mirror of https://github.com/certd/certd
perf: 支持AI分析报错
parent
abf015f485
commit
aa96859798
|
@ -35,3 +35,7 @@ networks:
|
|||
- subnet: 2001:db8::/64
|
||||
|
||||
```
|
||||
|
||||
## 3. SSL_CERT_NOT_MATCH_DOMAIN_ERROR
|
||||
部署证书任务报类似 `SSL_CERT_NOT_MATCH_DOMAIN_ERROR`错误
|
||||
这是由于当前流水线的证书域名与要部署的目标站点的域名不匹配导致的,在申请证书任务中,增加目标站点域名,重新运行流水线即可
|
File diff suppressed because one or more lines are too long
|
@ -1,151 +0,0 @@
|
|||
function embedChatbot() {
|
||||
const chatBtnId = "fastgpt-chatbot-button";
|
||||
const chatWindowId = "fastgpt-chatbot-window";
|
||||
const script = document.getElementById("chatbot-iframe");
|
||||
const botSrc = script?.getAttribute("data-bot-src");
|
||||
const defaultOpen = script?.getAttribute("data-default-open") === "true";
|
||||
const canDrag = script?.getAttribute("data-drag") === "true";
|
||||
const MessageIcon =
|
||||
script?.getAttribute("data-open-icon") ||
|
||||
`data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTMyNzg1NjY0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQxMzIiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDMyQzI0Ny4wNCAzMiAzMiAyMjQgMzIgNDY0QTQxMC4yNCA0MTAuMjQgMCAwIDAgMTcyLjQ4IDc2OEwxNjAgOTY1LjEyYTI1LjI4IDI1LjI4IDAgMCAwIDM5LjA0IDIyLjRsMTY4LTExMkE1MjguNjQgNTI4LjY0IDAgMCAwIDUxMiA4OTZjMjY0Ljk2IDAgNDgwLTE5MiA0ODAtNDMyUzc3Ni45NiAzMiA1MTIgMzJ6IG0yNDQuOCA0MTZsLTM2MS42IDMwMS43NmExMi40OCAxMi40OCAwIDAgMS0xOS44NC0xMi40OGw1OS4yLTIzMy45MmgtMTYwYTEyLjQ4IDEyLjQ4IDAgMCAxLTcuMzYtMjMuMzZsMzYxLjYtMzAxLjc2YTEyLjQ4IDEyLjQ4IDAgMCAxIDE5Ljg0IDEyLjQ4bC01OS4yIDIzMy45MmgxNjBhMTIuNDggMTIuNDggMCAwIDEgOCAyMi4wOHoiIGZpbGw9IiM0ZTgzZmQiIHAtaWQ9IjQxMzMiPjwvcGF0aD48L3N2Zz4=`;
|
||||
const CloseIcon =
|
||||
script?.getAttribute("data-close-icon") ||
|
||||
"data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTM1NDQxNTI2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjYzNjciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDEwMjRBNTEyIDUxMiAwIDEgMSA1MTIgMGE1MTIgNTEyIDAgMCAxIDAgMTAyNHpNMzA1Ljk1NjU3MSAzNzAuMzk1NDI5TDQ0Ny40ODggNTEyIDMwNS45NTY1NzEgNjUzLjYwNDU3MWE0NS41NjggNDUuNTY4IDAgMSAwIDY0LjQzODg1OCA2NC40Mzg4NThMNTEyIDU3Ni41MTJsMTQxLjYwNDU3MSAxNDEuNTMxNDI5YTQ1LjU2OCA0NS41NjggMCAwIDAgNjQuNDM4ODU4LTY0LjQzODg1OEw1NzYuNTEyIDUxMmwxNDEuNTMxNDI5LTE0MS42MDQ1NzFhNDUuNTY4IDQ1LjU2OCAwIDEgMC02NC40Mzg4NTgtNjQuNDM4ODU4TDUxMiA0NDcuNDg4IDM3MC4zOTU0MjkgMzA1Ljk1NjU3MWE0NS41NjggNDUuNTY4IDAgMCAwLTY0LjQzODg1OCA2NC40Mzg4NTh6IiBmaWxsPSIjNGU4M2ZkIiBwLWlkPSI2MzY4Ij48L3BhdGg+PC9zdmc+";
|
||||
|
||||
if (!botSrc) {
|
||||
console.error(`Can't find appid`);
|
||||
return;
|
||||
}
|
||||
if (document.getElementById(chatBtnId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ChatBtn = document.createElement("div");
|
||||
ChatBtn.id = chatBtnId;
|
||||
ChatBtn.style.cssText = "position: fixed; bottom: 30px; right: 60px; width: 40px; height: 40px; cursor: pointer; z-index: 2147483647; transition: 0;";
|
||||
|
||||
const ChatBtnDiv = document.createElement("img");
|
||||
ChatBtnDiv.src = defaultOpen ? CloseIcon : MessageIcon;
|
||||
ChatBtnDiv.setAttribute("width", "100%");
|
||||
ChatBtnDiv.setAttribute("height", "100%");
|
||||
ChatBtnDiv.draggable = false;
|
||||
|
||||
const parent = document.createElement("div");
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.allow = "*";
|
||||
iframe.referrerPolicy = "no-referrer";
|
||||
iframe.title = "FastGPT Chat Window";
|
||||
parent.id = chatWindowId;
|
||||
iframe.src = botSrc;
|
||||
parent.style.cssText =
|
||||
"border: none; position: fixed; flex-direction: column; justify-content: space-between; box-shadow: rgba(150, 150, 150, 0.2) 0px 10px 30px 0px, rgba(150, 150, 150, 0.2) 0px 0px 0px 1px; width: 375px; height: 667px; max-width: 90vw; max-height: 85vh; border-radius: 0.75rem; display: flex; z-index: 2147483647; overflow: hidden; left: unset; background-color: #F3F4F6;";
|
||||
parent.style.visibility = defaultOpen ? "unset" : "hidden";
|
||||
iframe.style.cssText = "border: none;width:100%;height:100%";
|
||||
|
||||
document.body.appendChild(parent);
|
||||
parent.appendChild(iframe);
|
||||
|
||||
const tips = document.createElement("div");
|
||||
tips.innerText = "内容由AI生成,仅供参考";
|
||||
tips.style.cssText = "padding:5px;font-size:10px;display:flex; justify-content:center;border-top: 1px solid #ddd;";
|
||||
parent.appendChild(tips);
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
mutations.forEach(mutation => {
|
||||
if (mutation.type === "attributes" && mutation.attributeName === "data-bot-src") {
|
||||
const newBotSrc = script.getAttribute("data-bot-src");
|
||||
if (newBotSrc) {
|
||||
iframe.src = newBotSrc;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(script, {
|
||||
attributes: true,
|
||||
attributeFilter: ["data-bot-src"],
|
||||
});
|
||||
|
||||
let chatBtnDragged = false;
|
||||
let chatBtnDown = false;
|
||||
let chatBtnMouseX;
|
||||
let chatBtnMouseY;
|
||||
|
||||
const updateChatWindowPosition = () => {
|
||||
const chatWindow = document.getElementById(chatWindowId);
|
||||
const btn = ChatBtn.getBoundingClientRect();
|
||||
const [vw, vh, ww, wh] = [window.innerWidth, window.innerHeight, chatWindow.offsetWidth, chatWindow.offsetHeight];
|
||||
|
||||
let right = 0;
|
||||
if (btn.left >= ww) {
|
||||
right = vw - btn.left + 10; // 左侧有空间则放在左侧,间距 10
|
||||
} else if (vw - btn.right >= ww) {
|
||||
right = vw - btn.right - ww - 10; // 右侧有空间则放在右侧
|
||||
}
|
||||
|
||||
let bottom = Math.max(30, vh - btn.bottom); // 聊天窗口底部和按钮对齐,最少 30
|
||||
if (btn.top < wh) {
|
||||
bottom = Math.min(bottom, vh - wh - 30); // 确保聊天窗口不超出顶部
|
||||
}
|
||||
|
||||
chatWindow.style.right = `${right}px`;
|
||||
chatWindow.style.bottom = `${bottom}px`;
|
||||
};
|
||||
|
||||
ChatBtn.addEventListener("click", function () {
|
||||
if (chatBtnDragged) {
|
||||
chatBtnDragged = false;
|
||||
return;
|
||||
}
|
||||
const chatWindow = document.getElementById(chatWindowId);
|
||||
|
||||
if (!chatWindow) return;
|
||||
const visibilityVal = chatWindow.style.visibility;
|
||||
if (visibilityVal === "hidden") {
|
||||
chatWindow.style.visibility = "unset";
|
||||
ChatBtnDiv.src = CloseIcon;
|
||||
} else {
|
||||
chatWindow.style.visibility = "hidden";
|
||||
ChatBtnDiv.src = MessageIcon;
|
||||
}
|
||||
});
|
||||
|
||||
ChatBtn.addEventListener("mousedown", e => {
|
||||
e.stopPropagation();
|
||||
chatBtnMouseX = e.clientX;
|
||||
chatBtnMouseY = e.clientY;
|
||||
chatBtnDown = true;
|
||||
|
||||
ChatBtn.initialRight = parseInt(ChatBtn.style.right) || 60;
|
||||
ChatBtn.initialBottom = parseInt(ChatBtn.style.bottom) || 30;
|
||||
});
|
||||
|
||||
window.addEventListener("mousemove", e => {
|
||||
e.stopPropagation();
|
||||
if (!canDrag || !chatBtnDown) return;
|
||||
|
||||
chatBtnDragged = true;
|
||||
|
||||
const deltaX = e.clientX - chatBtnMouseX;
|
||||
const deltaY = e.clientY - chatBtnMouseY;
|
||||
|
||||
let newRight = ChatBtn.initialRight - deltaX;
|
||||
let newBottom = ChatBtn.initialBottom - deltaY;
|
||||
|
||||
newRight = Math.max(20, Math.min(window.innerWidth - 60, newRight));
|
||||
newBottom = Math.max(30, Math.min(window.innerHeight - 70, newBottom));
|
||||
|
||||
ChatBtn.style.right = `${newRight}px`;
|
||||
ChatBtn.style.bottom = `${newBottom}px`;
|
||||
|
||||
updateChatWindowPosition();
|
||||
});
|
||||
|
||||
window.addEventListener("mouseup", e => {
|
||||
chatBtnDown = false;
|
||||
});
|
||||
|
||||
ChatBtn.appendChild(ChatBtnDiv);
|
||||
document.body.appendChild(ChatBtn);
|
||||
updateChatWindowPosition();
|
||||
}
|
||||
window.addEventListener("load", embedChatbot);
|
|
@ -74,8 +74,12 @@ const tokenTheme = computed(() => {
|
|||
// settingStore.init();
|
||||
|
||||
const chatBox = ref();
|
||||
onMounted(async () => {
|
||||
// await util.sleep(5000);
|
||||
// await chatBox.value.openChat({ q: "hello" });
|
||||
});
|
||||
// onMounted(async () => {
|
||||
// await util.sleep(2000);
|
||||
// await chatBox.value.openChat({ q: "hello" });
|
||||
// });
|
||||
const openChat = (q: string) => {
|
||||
chatBox.value.openChat({ q });
|
||||
};
|
||||
provide("fn:ai.open", openChat);
|
||||
</script>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
</div>
|
||||
|
||||
<!-- 聊天按钮 -->
|
||||
<div v-show="!chatVisible" class="maxkb-chat-button" :style="buttonPosition" @click="toggleChat">
|
||||
<div v-show="!chatVisible" class="maxkb-chat-button" @click="toggleChat">
|
||||
<img src="https://maxkb.handfree.work/ui/MaxKB.gif" />
|
||||
</div>
|
||||
|
||||
|
@ -123,7 +123,7 @@ onMounted(() => {
|
|||
});
|
||||
|
||||
async function openChat(req: { q: string }) {
|
||||
showGuide.value = true;
|
||||
chatVisible.value = true;
|
||||
|
||||
const iframeId = "maxkb-chat";
|
||||
|
||||
|
@ -227,10 +227,10 @@ defineExpose({
|
|||
#maxkb .maxkb-tips .maxkb-button button::after {
|
||||
border: none;
|
||||
}
|
||||
#maxkb .maxkb-tips . {
|
||||
#maxkb .maxkb-tips {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
//top: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
#maxkb-chat-container {
|
||||
|
@ -248,7 +248,7 @@ defineExpose({
|
|||
|
||||
#maxkb .maxkb-chat-button {
|
||||
position: fixed;
|
||||
right: 0px;
|
||||
right: 10px;
|
||||
bottom: 30px;
|
||||
cursor: pointer;
|
||||
z-index: 10000;
|
||||
|
|
|
@ -21,7 +21,7 @@ async function batchUpdateGroupRequest(groupId: number) {
|
|||
const pipelineGroupDictRef = dict({
|
||||
url: "/pi/pipeline/group/all",
|
||||
value: "id",
|
||||
label: "name"
|
||||
label: "name",
|
||||
});
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
|
||||
|
@ -33,9 +33,9 @@ async function openGroupSelectDialog() {
|
|||
type: "dict-select",
|
||||
dict: pipelineGroupDictRef,
|
||||
form: {
|
||||
rules: [{ required: true, message: "请选择分组" }]
|
||||
}
|
||||
}
|
||||
rules: [{ required: true, message: "请选择分组" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
form: {
|
||||
mode: "edit",
|
||||
|
@ -44,18 +44,18 @@ async function openGroupSelectDialog() {
|
|||
await batchUpdateGroupRequest(form.groupId);
|
||||
},
|
||||
col: {
|
||||
span: 22
|
||||
span: 22,
|
||||
},
|
||||
labelCol: {
|
||||
style: {
|
||||
width: "100px"
|
||||
}
|
||||
width: "100px",
|
||||
},
|
||||
},
|
||||
wrapper: {
|
||||
title: "批量修改分组",
|
||||
width: 600
|
||||
}
|
||||
}
|
||||
width: 600,
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
await openCrudFormDialog({ crudOptions });
|
||||
}
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<template #footer>
|
||||
<fs-button key="aiChat" type="primary" icon="ion:color-wand-outline" @click="taskModal.onAiChat">AI分析</fs-button>
|
||||
<fs-button key="cancel" icon="ion:close-circle-outline" @click="taskModal.onOk">关闭</fs-button>
|
||||
<fs-button key="submit" icon="ion:checkmark-circle-outline" type="primary" @click="taskModal.onOk">确定</fs-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
|
@ -37,11 +42,15 @@ export default {
|
|||
props: {},
|
||||
emits: ["run"],
|
||||
setup(props: any, ctx: any) {
|
||||
const openAiChat: any = inject("fn:ai.open", (q: string) => {});
|
||||
const taskModal = ref({
|
||||
open: false,
|
||||
onOk() {
|
||||
taskViewClose();
|
||||
},
|
||||
onAiChat() {
|
||||
onAiChat();
|
||||
},
|
||||
cancelText: "关闭",
|
||||
});
|
||||
const { isMobile } = usePreferences();
|
||||
|
@ -52,6 +61,22 @@ export default {
|
|||
return "left";
|
||||
});
|
||||
|
||||
function onAiChat() {
|
||||
debugger;
|
||||
const logs = currentHistory.value?.logs[activeKey.value];
|
||||
let logText = "";
|
||||
for (let log of logs) {
|
||||
logText += log + "\n";
|
||||
}
|
||||
const maxLength = 5000;
|
||||
if (logText.length > maxLength) {
|
||||
logText = logText.substring(logText.length - maxLength);
|
||||
}
|
||||
if (openAiChat) {
|
||||
openAiChat(logText);
|
||||
}
|
||||
}
|
||||
|
||||
const detail = ref({ nodes: [] });
|
||||
const activeKey = ref();
|
||||
const currentHistory: Ref<RunHistory> | undefined = inject("currentHistory");
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
<a-col :span="6">
|
||||
<statistic-card title="用户总数" :count="count.userCount">
|
||||
<template #footer>
|
||||
<router-link to="/sys/authority/user" class="flex"><fs-icon icon="ion:settings-outline" class="mr-5 fs-16" /> 管理用户</router-link>
|
||||
<router-link to="/sys/authority/user" class="flex">
|
||||
<fs-icon icon="ion:settings-outline" class="mr-5 fs-16" />
|
||||
管理用户
|
||||
</router-link>
|
||||
</template>
|
||||
</statistic-card>
|
||||
</a-col>
|
||||
|
@ -21,7 +24,10 @@
|
|||
<a-col :span="6">
|
||||
<statistic-card title="全站流水线总数" :count="count.pipelineCount">
|
||||
<template #footer>
|
||||
<router-link to="/certd/pipeline" class="flex"><fs-icon icon="ion:settings-outline" class="mr-5 fs-16" /> 管理流水线</router-link>
|
||||
<router-link to="/certd/pipeline" class="flex">
|
||||
<fs-icon icon="ion:settings-outline" class="mr-5 fs-16" />
|
||||
管理流水线
|
||||
</router-link>
|
||||
</template>
|
||||
</statistic-card>
|
||||
</a-col>
|
||||
|
@ -42,21 +48,23 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted, ref, Ref } from "vue";
|
||||
import { FsIcon } from "@fast-crud/fast-crud";
|
||||
import StatisticCard from "/@/views/framework/home/dashboard/statistic-card.vue";
|
||||
import DayCount from "/@/views/framework/home/dashboard/charts/day-count.vue";
|
||||
import { GetStatisticCount } from "./api";
|
||||
|
||||
const count = ref({});
|
||||
function transformCountPerDayToChartData(key) {
|
||||
count.value[key] = count.value[key].map((item) => {
|
||||
const count: Ref = ref({});
|
||||
|
||||
function transformCountPerDayToChartData(key: string) {
|
||||
count.value[key] = count.value[key].map((item:any) => {
|
||||
return {
|
||||
name: item.date,
|
||||
value: item.count
|
||||
value: item.count,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function loadCount() {
|
||||
count.value = await GetStatisticCount();
|
||||
transformCountPerDayToChartData("userRegisterCountPerDay");
|
||||
|
|
Loading…
Reference in New Issue