知识库
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
This commit is contained in:
parent
2ac2d198a3
commit
a1bd2b850e
@ -44,7 +44,9 @@
|
|||||||
"ant-design-vue": "catalog:",
|
"ant-design-vue": "catalog:",
|
||||||
"cal-heatmap": "^4.2.4",
|
"cal-heatmap": "^4.2.4",
|
||||||
"dayjs": "catalog:",
|
"dayjs": "catalog:",
|
||||||
|
"dompurify": "^3.4.2",
|
||||||
"json-editor-vue": "^0.18.1",
|
"json-editor-vue": "^0.18.1",
|
||||||
|
"marked": "^18.0.3",
|
||||||
"pinia": "catalog:",
|
"pinia": "catalog:",
|
||||||
"pixi.js": "8.11.0-main.efa7feb",
|
"pixi.js": "8.11.0-main.efa7feb",
|
||||||
"prettier-eslint": "^16.4.2",
|
"prettier-eslint": "^16.4.2",
|
||||||
|
|||||||
@ -66,6 +66,10 @@
|
|||||||
"noChangesToSave": "No changes to save",
|
"noChangesToSave": "No changes to save",
|
||||||
"deleteSuccess": "Delete Success"
|
"deleteSuccess": "Delete Success"
|
||||||
},
|
},
|
||||||
|
"knowledge": {
|
||||||
|
"title": "Knowledge Base",
|
||||||
|
"chat": "Knowledge Q&A"
|
||||||
|
},
|
||||||
"operation": {
|
"operation": {
|
||||||
"title": "Operation",
|
"title": "Operation",
|
||||||
"apk": "Client APK",
|
"apk": "Client APK",
|
||||||
|
|||||||
@ -66,6 +66,10 @@
|
|||||||
"noChangesToSave": "没有需要保存的更改",
|
"noChangesToSave": "没有需要保存的更改",
|
||||||
"deleteSuccess": "删除成功"
|
"deleteSuccess": "删除成功"
|
||||||
},
|
},
|
||||||
|
"knowledge": {
|
||||||
|
"title": "知识库",
|
||||||
|
"chat": "知识问答"
|
||||||
|
},
|
||||||
"operation": {
|
"operation": {
|
||||||
"title": "运营管理",
|
"title": "运营管理",
|
||||||
"apk": "客户端 APK 下载",
|
"apk": "客户端 APK 下载",
|
||||||
|
|||||||
33
apps/web-antd/src/router/routes/modules/knowledge.ts
Normal file
33
apps/web-antd/src/router/routes/modules/knowledge.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import type { RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
|
import { BasicLayout } from '#/layouts';
|
||||||
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
const routes: RouteRecordRaw[] = [
|
||||||
|
{
|
||||||
|
component: BasicLayout,
|
||||||
|
meta: {
|
||||||
|
icon: 'lucide:book-open',
|
||||||
|
order: 1100,
|
||||||
|
title: $t('page.knowledge.title'),
|
||||||
|
authority: ['super'],
|
||||||
|
},
|
||||||
|
name: 'Knowledge',
|
||||||
|
path: '/knowledge',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'KnowledgeChat',
|
||||||
|
path: '/knowledge/chat',
|
||||||
|
component: () => import('#/views/knowledge/chat.vue'),
|
||||||
|
meta: {
|
||||||
|
affixTab: false,
|
||||||
|
icon: 'lucide:message-square-text',
|
||||||
|
title: $t('page.knowledge.chat'),
|
||||||
|
authority: ['super'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default routes;
|
||||||
913
apps/web-antd/src/views/knowledge/chat.vue
Normal file
913
apps/web-antd/src/views/knowledge/chat.vue
Normal file
@ -0,0 +1,913 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { nextTick, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
import { Page, VbenIcon } from '@vben/common-ui';
|
||||||
|
import { Button, Card, Tag } from 'ant-design-vue';
|
||||||
|
import { marked } from 'marked';
|
||||||
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
|
interface Source {
|
||||||
|
chunk_id: string;
|
||||||
|
score: number;
|
||||||
|
summary?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Msg {
|
||||||
|
role: 'bot' | 'err' | 'user';
|
||||||
|
text: string;
|
||||||
|
sources?: Source[];
|
||||||
|
streaming?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const accessStore = useAccessStore();
|
||||||
|
const messages = ref<Msg[]>([]);
|
||||||
|
const input = ref('');
|
||||||
|
const sending = ref(false);
|
||||||
|
const logEl = ref<HTMLDivElement>();
|
||||||
|
const logBottomEl = ref<HTMLDivElement>();
|
||||||
|
let logObserver: MutationObserver | null = null;
|
||||||
|
const quickQuestions = [
|
||||||
|
'AdGiftData 表里有哪些字段?',
|
||||||
|
'UserBaseData 里和等级相关的字段有哪些?',
|
||||||
|
'OrderData 表常用索引字段是什么?',
|
||||||
|
];
|
||||||
|
|
||||||
|
marked.setOptions({
|
||||||
|
breaks: true,
|
||||||
|
gfm: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
function scrollBottom() {
|
||||||
|
nextTick(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
logBottomEl.value?.scrollIntoView({
|
||||||
|
block: 'end',
|
||||||
|
});
|
||||||
|
logEl.value?.scrollTo({ top: logEl.value.scrollHeight });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!logEl.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logObserver = new MutationObserver(() => {
|
||||||
|
if (sending.value) {
|
||||||
|
scrollBottom();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
logObserver.observe(logEl.value, {
|
||||||
|
characterData: true,
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
logObserver?.disconnect();
|
||||||
|
logObserver = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
function extractStreamText(data: string) {
|
||||||
|
if (!data || data === '[DONE]') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(data);
|
||||||
|
if (typeof parsed === 'string') {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
if (typeof parsed === 'number' || typeof parsed === 'boolean') {
|
||||||
|
return String(parsed);
|
||||||
|
}
|
||||||
|
if (typeof parsed?.token === 'string') {
|
||||||
|
return parsed.token;
|
||||||
|
}
|
||||||
|
if (typeof parsed?.token === 'number' || typeof parsed?.token === 'boolean') {
|
||||||
|
return String(parsed.token);
|
||||||
|
}
|
||||||
|
if (typeof parsed?.content === 'string') {
|
||||||
|
return parsed.content;
|
||||||
|
}
|
||||||
|
if (typeof parsed?.content === 'number' || typeof parsed?.content === 'boolean') {
|
||||||
|
return String(parsed.content);
|
||||||
|
}
|
||||||
|
if (typeof parsed?.text === 'string') {
|
||||||
|
return parsed.text;
|
||||||
|
}
|
||||||
|
if (typeof parsed?.text === 'number' || typeof parsed?.text === 'boolean') {
|
||||||
|
return String(parsed.text);
|
||||||
|
}
|
||||||
|
if (typeof parsed?.answer === 'string') {
|
||||||
|
return parsed.answer;
|
||||||
|
}
|
||||||
|
if (typeof parsed?.answer === 'number' || typeof parsed?.answer === 'boolean') {
|
||||||
|
return String(parsed.answer);
|
||||||
|
}
|
||||||
|
if (typeof parsed?.delta === 'string') {
|
||||||
|
return parsed.delta;
|
||||||
|
}
|
||||||
|
if (typeof parsed?.delta === 'number' || typeof parsed?.delta === 'boolean') {
|
||||||
|
return String(parsed.delta);
|
||||||
|
}
|
||||||
|
if (typeof parsed?.choices?.[0]?.delta?.content === 'string') {
|
||||||
|
return parsed.choices[0].delta.content;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
typeof parsed?.choices?.[0]?.delta?.content === 'number'
|
||||||
|
|| typeof parsed?.choices?.[0]?.delta?.content === 'boolean'
|
||||||
|
) {
|
||||||
|
return String(parsed.choices[0].delta.content);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
} catch {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderMarkdown(text: string) {
|
||||||
|
const html = marked.parse(text, { async: false }) as string;
|
||||||
|
return DOMPurify.sanitize(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyStreamChunk(raw: string, botMsg: Msg) {
|
||||||
|
let evt = 'message';
|
||||||
|
let data = '';
|
||||||
|
|
||||||
|
for (const line of raw.split('\n')) {
|
||||||
|
if (line.startsWith('event:')) evt = line.slice(6).trim();
|
||||||
|
else if (line.startsWith('data:')) {
|
||||||
|
data += (data ? '\n' : '') + line.slice(5).replace(/^ /, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evt === 'sources') {
|
||||||
|
botMsg.sources = JSON.parse(data);
|
||||||
|
scrollBottom();
|
||||||
|
} else if (evt === 'token' || evt === 'message') {
|
||||||
|
const chunk = extractStreamText(data);
|
||||||
|
if (chunk) {
|
||||||
|
botMsg.text += chunk;
|
||||||
|
}
|
||||||
|
scrollBottom();
|
||||||
|
} else if (evt === 'error') {
|
||||||
|
botMsg.role = 'err';
|
||||||
|
botMsg.text = `流式失败: ${data}`;
|
||||||
|
} else if (evt === 'done') {
|
||||||
|
botMsg.streaming = false;
|
||||||
|
scrollBottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function send() {
|
||||||
|
const query = input.value.trim();
|
||||||
|
if (!query || sending.value) return;
|
||||||
|
|
||||||
|
messages.value.push({ role: 'user', text: query });
|
||||||
|
input.value = '';
|
||||||
|
sending.value = true;
|
||||||
|
|
||||||
|
const botMsg = reactive<Msg>({ role: 'bot', text: '', streaming: true });
|
||||||
|
messages.value.push(botMsg);
|
||||||
|
scrollBottom();
|
||||||
|
|
||||||
|
const token = accessStore.accessToken;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await fetch('/api/knowledge/chat', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: token ? `Bearer ${token}` : '',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ query, top_k: 30 }),
|
||||||
|
});
|
||||||
|
if (!resp.ok || !resp.body) {
|
||||||
|
throw new Error(`HTTP ${resp.status}: ${await resp.text()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSE 行解析:按 \n\n 分块;每块取 event: 与 data:
|
||||||
|
const reader = resp.body.pipeThrough(new TextDecoderStream()).getReader();
|
||||||
|
let buf = '';
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
const tail = buf.replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim();
|
||||||
|
if (tail) {
|
||||||
|
applyStreamChunk(tail, botMsg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf += value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
||||||
|
let idx;
|
||||||
|
while ((idx = buf.indexOf('\n\n')) >= 0) {
|
||||||
|
const raw = buf.slice(0, idx);
|
||||||
|
buf = buf.slice(idx + 2);
|
||||||
|
applyStreamChunk(raw, botMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
botMsg.streaming = false;
|
||||||
|
} catch (err: any) {
|
||||||
|
botMsg.role = 'err';
|
||||||
|
botMsg.text = `请求失败: ${err.message || err}`;
|
||||||
|
botMsg.streaming = false;
|
||||||
|
} finally {
|
||||||
|
sending.value = false;
|
||||||
|
scrollBottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKeydown(e: KeyboardEvent) {
|
||||||
|
if (e.key === 'Enter' && !e.shiftKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillQuestion(question: string) {
|
||||||
|
input.value = question;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page auto-content-height>
|
||||||
|
<div class="kb-chat-page">
|
||||||
|
<Card :bordered="false" class="kb-hero-card mb-5">
|
||||||
|
<div class="kb-hero">
|
||||||
|
<div class="kb-hero__content">
|
||||||
|
<div class="kb-hero__title">
|
||||||
|
<div class="kb-hero__icon">
|
||||||
|
<VbenIcon icon="solar:book-bookmark-bold" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="kb-hero__heading">配置表知识库问答</div>
|
||||||
|
<div class="kb-hero__subheading">
|
||||||
|
基于 BM25 检索与 DeepSeek 流式回答,适合快速查询配置字段、含义和上下游关系。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="kb-hero__tags">
|
||||||
|
<Tag color="blue" class="kb-hero__tag">
|
||||||
|
<VbenIcon icon="solar:database-bold" class="mr-1" />
|
||||||
|
配置检索
|
||||||
|
</Tag>
|
||||||
|
<Tag color="gold" class="kb-hero__tag">
|
||||||
|
<VbenIcon icon="solar:chat-round-dots-bold" class="mr-1" />
|
||||||
|
流式回答
|
||||||
|
</Tag>
|
||||||
|
<Tag color="green" class="kb-hero__tag">
|
||||||
|
<VbenIcon icon="solar:document-text-bold" class="mr-1" />
|
||||||
|
来源追踪
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="kb-hero__examples">
|
||||||
|
<div class="kb-hero__examples-title">试试这些问题</div>
|
||||||
|
<div class="kb-hero__examples-list">
|
||||||
|
<Button
|
||||||
|
v-for="question in quickQuestions"
|
||||||
|
:key="question"
|
||||||
|
class="kb-example-btn"
|
||||||
|
type="default"
|
||||||
|
@click="fillQuestion(question)"
|
||||||
|
>
|
||||||
|
{{ question }}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card :bordered="false" class="kb-chat-card">
|
||||||
|
<template #title>
|
||||||
|
<div class="kb-card-title">
|
||||||
|
<span class="kb-card-title__text">知识库对话</span>
|
||||||
|
<Tag color="processing" class="kb-card-title__tag">
|
||||||
|
{{ sending ? '回答中' : '就绪' }}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="kb-chat-shell">
|
||||||
|
<div ref="logEl" class="kb-log">
|
||||||
|
<div v-if="messages.length === 0" class="kb-empty-state">
|
||||||
|
<div class="kb-empty-state__icon">
|
||||||
|
<VbenIcon icon="solar:chat-round-line-line-duotone" />
|
||||||
|
</div>
|
||||||
|
<div class="kb-empty-state__title">开始一次配置检索问答</div>
|
||||||
|
<div class="kb-empty-state__hint">
|
||||||
|
例如:AdGiftData 表里有哪些字段?
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(m, i) in messages"
|
||||||
|
:key="i"
|
||||||
|
:class="['kb-msg', `kb-msg-${m.role}`]"
|
||||||
|
>
|
||||||
|
<div class="kb-msg__meta">
|
||||||
|
<div :class="['kb-msg__avatar', `kb-msg__avatar-${m.role}`]">
|
||||||
|
<VbenIcon
|
||||||
|
:icon="
|
||||||
|
m.role === 'user'
|
||||||
|
? 'solar:user-bold'
|
||||||
|
: m.role === 'err'
|
||||||
|
? 'solar:danger-circle-bold'
|
||||||
|
: 'solar:stars-bold'
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="kb-msg__role">
|
||||||
|
{{ m.role === 'user' ? '你' : m.role === 'err' ? '错误' : '助手' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div :class="['kb-body', `kb-body-${m.role}`, { 'kb-cursor': m.streaming }]">
|
||||||
|
<template v-if="m.role === 'user'">
|
||||||
|
{{ m.text }}
|
||||||
|
</template>
|
||||||
|
<div v-else class="kb-markdown" v-html="renderMarkdown(m.text)"></div>
|
||||||
|
</div>
|
||||||
|
<details v-if="m.sources && m.sources.length" class="kb-sources">
|
||||||
|
<summary>
|
||||||
|
<span>来源片段</span>
|
||||||
|
<Tag color="default">{{ m.sources.length }}</Tag>
|
||||||
|
</summary>
|
||||||
|
<ol>
|
||||||
|
<li v-for="(s, j) in m.sources" :key="j" class="kb-sources__item">
|
||||||
|
<span class="kb-score">{{ s.score.toFixed(2) }}</span>
|
||||||
|
<span class="kb-cid">{{ s.chunk_id }}</span>
|
||||||
|
<span v-if="s.summary" class="kb-summary">
|
||||||
|
{{ s.summary.slice(0, 60) }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
<div ref="logBottomEl" class="kb-log-bottom"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="kb-form" @submit.prevent="send">
|
||||||
|
<div class="kb-form__editor">
|
||||||
|
<textarea
|
||||||
|
v-model="input"
|
||||||
|
placeholder="输入问题,Enter 发送,Shift+Enter 换行"
|
||||||
|
:disabled="sending"
|
||||||
|
@keydown="onKeydown"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="kb-form__actions">
|
||||||
|
<Button
|
||||||
|
class="kb-send-btn"
|
||||||
|
type="primary"
|
||||||
|
:loading="sending"
|
||||||
|
:disabled="!input.trim()"
|
||||||
|
@click="send"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<VbenIcon icon="solar:arrow-up-linear" />
|
||||||
|
</template>
|
||||||
|
发送
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.kb-chat-page {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero-card,
|
||||||
|
.kb-chat-card {
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 24px;
|
||||||
|
background: rgb(255 255 255 / 96%);
|
||||||
|
box-shadow: 0 16px 34px rgb(15 23 42 / 8%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1.4fr) minmax(280px, 0.9fr);
|
||||||
|
gap: 24px;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__title {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 52px;
|
||||||
|
height: 52px;
|
||||||
|
border-radius: 18px;
|
||||||
|
background: linear-gradient(135deg, #fde68a 0%, #f59e0b 100%);
|
||||||
|
color: #78350f;
|
||||||
|
font-size: 24px;
|
||||||
|
box-shadow: 0 14px 28px rgb(245 158 11 / 22%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__heading {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #0f172a;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__subheading {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #64748b;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 999px;
|
||||||
|
padding-inline: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__examples {
|
||||||
|
border: 1px solid rgb(191 219 254 / 70%);
|
||||||
|
border-radius: 22px;
|
||||||
|
background: linear-gradient(180deg, rgb(255 255 255 / 98%) 0%, rgb(239 246 255 / 96%) 100%);
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__examples-title {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1e3a8a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-hero__examples-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-example-btn {
|
||||||
|
justify-content: flex-start;
|
||||||
|
min-height: 42px;
|
||||||
|
border-radius: 14px;
|
||||||
|
border-color: rgb(191 219 254 / 80%);
|
||||||
|
background: rgb(255 255 255 / 92%);
|
||||||
|
color: #1e293b;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-card-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-card-title__text {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-card-title__tag {
|
||||||
|
border-radius: 999px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-chat-shell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 680px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-log {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 8px 4px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-empty-state {
|
||||||
|
display: flex;
|
||||||
|
min-height: 420px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-empty-state__icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 68px;
|
||||||
|
height: 68px;
|
||||||
|
border-radius: 22px;
|
||||||
|
background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 30px;
|
||||||
|
box-shadow: 0 16px 28px rgb(59 130 246 / 16%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-empty-state__title {
|
||||||
|
margin-top: 18px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-empty-state__hint {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-msg {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-msg__meta {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-msg__avatar {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-msg__avatar-user {
|
||||||
|
background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
|
||||||
|
color: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-msg__avatar-bot {
|
||||||
|
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
||||||
|
color: #b45309;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-msg__avatar-err {
|
||||||
|
background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
|
||||||
|
color: #dc2626;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-msg__role {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-body {
|
||||||
|
padding: 14px 16px;
|
||||||
|
border-radius: 18px;
|
||||||
|
word-break: break-word;
|
||||||
|
border: 1px solid rgb(226 232 240 / 90%);
|
||||||
|
line-height: 1.75;
|
||||||
|
box-shadow: 0 10px 20px rgb(15 23 42 / 4%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-body-user {
|
||||||
|
background: linear-gradient(180deg, rgb(239 246 255 / 95%) 0%, rgb(219 234 254 / 96%) 100%);
|
||||||
|
border-color: rgb(147 197 253 / 80%);
|
||||||
|
color: #0f172a;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-body-bot {
|
||||||
|
background: linear-gradient(180deg, rgb(255 255 255 / 98%) 0%, rgb(248 250 252 / 98%) 100%);
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-body-err {
|
||||||
|
background: linear-gradient(180deg, rgb(254 242 242 / 98%) 0%, rgb(254 226 226 / 98%) 100%);
|
||||||
|
color: #b91c1c;
|
||||||
|
border-color: rgb(252 165 165 / 70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(*) {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(> :first-child) {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(> :last-child) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(p),
|
||||||
|
.kb-markdown :deep(ul),
|
||||||
|
.kb-markdown :deep(ol),
|
||||||
|
.kb-markdown :deep(pre),
|
||||||
|
.kb-markdown :deep(blockquote),
|
||||||
|
.kb-markdown :deep(table) {
|
||||||
|
margin: 0 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(h1),
|
||||||
|
.kb-markdown :deep(h2),
|
||||||
|
.kb-markdown :deep(h3),
|
||||||
|
.kb-markdown :deep(h4) {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
color: #0f172a;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(h1) {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(h2) {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(h3) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(ul),
|
||||||
|
.kb-markdown :deep(ol) {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(li + li) {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(code) {
|
||||||
|
border-radius: 6px;
|
||||||
|
background: rgb(226 232 240 / 75%);
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(pre) {
|
||||||
|
overflow-x: auto;
|
||||||
|
border: 1px solid rgb(226 232 240 / 90%);
|
||||||
|
border-radius: 14px;
|
||||||
|
background: #0f172a;
|
||||||
|
padding: 14px 16px;
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(pre code) {
|
||||||
|
background: transparent;
|
||||||
|
padding: 0;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(blockquote) {
|
||||||
|
border-left: 4px solid #93c5fd;
|
||||||
|
background: rgb(239 246 255 / 90%);
|
||||||
|
border-radius: 0 12px 12px 0;
|
||||||
|
padding: 10px 12px;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(a) {
|
||||||
|
color: #2563eb;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(table) {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(th),
|
||||||
|
.kb-markdown :deep(td) {
|
||||||
|
border: 1px solid rgb(226 232 240 / 90%);
|
||||||
|
padding: 8px 10px;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-markdown :deep(th) {
|
||||||
|
background: rgb(241 245 249 / 98%);
|
||||||
|
color: #0f172a;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-cursor::after {
|
||||||
|
content: '▍';
|
||||||
|
color: #2563eb;
|
||||||
|
animation: kb-blink 1s steps(2) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes kb-blink {
|
||||||
|
50% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-sources {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
background: rgb(248 250 252 / 98%);
|
||||||
|
border: 1px solid rgb(226 232 240 / 90%);
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-sources summary {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
color: #64748b;
|
||||||
|
font-weight: 600;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-sources[open] summary {
|
||||||
|
border-bottom: 1px solid rgb(226 232 240 / 90%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-sources ol {
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 14px 14px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-sources__item {
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-score {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 42px;
|
||||||
|
color: #2563eb;
|
||||||
|
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-cid {
|
||||||
|
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-summary {
|
||||||
|
color: #64748b;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-form {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: end;
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: 18px;
|
||||||
|
border-top: 1px solid rgb(226 232 240 / 90%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-form__editor {
|
||||||
|
border: 1px solid rgb(226 232 240 / 90%);
|
||||||
|
border-radius: 20px;
|
||||||
|
background: linear-gradient(180deg, rgb(255 255 255 / 100%) 0%, rgb(248 250 252 / 100%) 100%);
|
||||||
|
padding: 12px 14px;
|
||||||
|
box-shadow: inset 0 1px 0 rgb(255 255 255 / 60%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-form textarea {
|
||||||
|
flex: 1;
|
||||||
|
resize: none;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 86px;
|
||||||
|
max-height: 160px;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: #0f172a;
|
||||||
|
font: inherit;
|
||||||
|
outline: none;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-form textarea:focus {
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-form__actions {
|
||||||
|
display: flex;
|
||||||
|
min-width: 148px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.kb-send-btn) {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 120px;
|
||||||
|
height: 42px;
|
||||||
|
padding-inline: 18px;
|
||||||
|
border-radius: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 12px 24px rgb(37 99 235 / 18%);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.kb-send-btn .ant-btn-icon) {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-inline-end: 6px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.kb-send-btn .ant-btn-loading-icon) {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-inline-end: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.kb-send-btn > span) {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 960px) {
|
||||||
|
.kb-hero {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-chat-shell {
|
||||||
|
min-height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-form {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-form__actions {
|
||||||
|
min-width: 0;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-card-title {
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 640px) {
|
||||||
|
.kb-hero__title {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-log {
|
||||||
|
padding-inline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-body {
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -639,9 +639,15 @@ importers:
|
|||||||
dayjs:
|
dayjs:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 1.11.13
|
version: 1.11.13
|
||||||
|
dompurify:
|
||||||
|
specifier: ^3.4.2
|
||||||
|
version: 3.4.2
|
||||||
json-editor-vue:
|
json-editor-vue:
|
||||||
specifier: ^0.18.1
|
specifier: ^0.18.1
|
||||||
version: 0.18.1(vue@3.5.13(typescript@5.7.2))
|
version: 0.18.1(vue@3.5.13(typescript@5.7.2))
|
||||||
|
marked:
|
||||||
|
specifier: ^18.0.3
|
||||||
|
version: 18.0.3
|
||||||
pinia:
|
pinia:
|
||||||
specifier: 2.2.2
|
specifier: 2.2.2
|
||||||
version: 2.2.2(typescript@5.7.2)(vue@3.5.13(typescript@5.7.2))
|
version: 2.2.2(typescript@5.7.2)(vue@3.5.13(typescript@5.7.2))
|
||||||
@ -3608,8 +3614,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-bmsP4L2HqBF6i6uaMqJMcFBONVjKt+siGluRq4Ca4C0q7W2eMaVZr8iCgF9dKbcVXutftkC7D6z2SaSMmLiDyA==}
|
resolution: {integrity: sha512-bmsP4L2HqBF6i6uaMqJMcFBONVjKt+siGluRq4Ca4C0q7W2eMaVZr8iCgF9dKbcVXutftkC7D6z2SaSMmLiDyA==}
|
||||||
engines: {node: '>= 16'}
|
engines: {node: '>= 16'}
|
||||||
|
|
||||||
'@intlify/shared@11.3.0':
|
'@intlify/shared@11.4.2':
|
||||||
resolution: {integrity: sha512-LC6P/uay7rXL5zZ5+5iRJfLs/iUN8apu9tm8YqQVmW3Uq3X4A0dOFUIDuAmB7gAC29wTHOS3EiN/IosNSz0eNQ==}
|
resolution: {integrity: sha512-NzpHbguRCsOHDwxmlBa9qu/imc+/QWgsYUaK6FZeNC0wK8QfAbhqrktEp/haVzxU1aikH8IX4ytD+mfFEMi/9A==}
|
||||||
engines: {node: '>= 16'}
|
engines: {node: '>= 16'}
|
||||||
|
|
||||||
'@intlify/shared@12.0.0-alpha.3':
|
'@intlify/shared@12.0.0-alpha.3':
|
||||||
@ -6206,6 +6212,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
|
dompurify@3.4.2:
|
||||||
|
resolution: {integrity: sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==}
|
||||||
|
|
||||||
domutils@2.8.0:
|
domutils@2.8.0:
|
||||||
resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
|
resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
|
||||||
|
|
||||||
@ -7936,6 +7945,11 @@ packages:
|
|||||||
mark.js@8.11.1:
|
mark.js@8.11.1:
|
||||||
resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==}
|
resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==}
|
||||||
|
|
||||||
|
marked@18.0.3:
|
||||||
|
resolution: {integrity: sha512-7VT90JOkDeaRWpfjOReRGPEKn0ecdARBkDGL+tT1wZY0efPPqkUxLUSmzy/C7TIylQYJC9STISEsCHrqb/7VIA==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
math-intrinsics@1.1.0:
|
math-intrinsics@1.1.0:
|
||||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -13089,7 +13103,7 @@ snapshots:
|
|||||||
|
|
||||||
'@intlify/shared@10.0.5': {}
|
'@intlify/shared@10.0.5': {}
|
||||||
|
|
||||||
'@intlify/shared@11.3.0': {}
|
'@intlify/shared@11.4.2': {}
|
||||||
|
|
||||||
'@intlify/shared@12.0.0-alpha.3': {}
|
'@intlify/shared@12.0.0-alpha.3': {}
|
||||||
|
|
||||||
@ -13097,8 +13111,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.4.1(eslint@9.16.0(jiti@2.4.0))
|
'@eslint-community/eslint-utils': 4.4.1(eslint@9.16.0(jiti@2.4.0))
|
||||||
'@intlify/bundle-utils': 10.0.0(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))
|
'@intlify/bundle-utils': 10.0.0(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))
|
||||||
'@intlify/shared': 11.3.0
|
'@intlify/shared': 11.4.2
|
||||||
'@intlify/vue-i18n-extensions': 7.0.0(@intlify/shared@11.3.0)(@vue/compiler-dom@3.5.13)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
'@intlify/vue-i18n-extensions': 7.0.0(@intlify/shared@11.4.2)(@vue/compiler-dom@3.5.13)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
||||||
'@rollup/pluginutils': 5.1.3(rollup@4.28.0)
|
'@rollup/pluginutils': 5.1.3(rollup@4.28.0)
|
||||||
'@typescript-eslint/scope-manager': 8.17.0
|
'@typescript-eslint/scope-manager': 8.17.0
|
||||||
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2)
|
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2)
|
||||||
@ -13120,11 +13134,11 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
'@intlify/vue-i18n-extensions@7.0.0(@intlify/shared@11.3.0)(@vue/compiler-dom@3.5.13)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
'@intlify/vue-i18n-extensions@7.0.0(@intlify/shared@11.4.2)(@vue/compiler-dom@3.5.13)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.26.2
|
'@babel/parser': 7.26.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@intlify/shared': 11.3.0
|
'@intlify/shared': 11.4.2
|
||||||
'@vue/compiler-dom': 3.5.13
|
'@vue/compiler-dom': 3.5.13
|
||||||
vue: 3.5.13(typescript@5.7.2)
|
vue: 3.5.13(typescript@5.7.2)
|
||||||
vue-i18n: 10.0.5(vue@3.5.13(typescript@5.7.2))
|
vue-i18n: 10.0.5(vue@3.5.13(typescript@5.7.2))
|
||||||
@ -16104,6 +16118,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
domelementtype: 2.3.0
|
domelementtype: 2.3.0
|
||||||
|
|
||||||
|
dompurify@3.4.2:
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/trusted-types': 2.0.7
|
||||||
|
|
||||||
domutils@2.8.0:
|
domutils@2.8.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
dom-serializer: 1.4.1
|
dom-serializer: 1.4.1
|
||||||
@ -18039,6 +18057,8 @@ snapshots:
|
|||||||
|
|
||||||
mark.js@8.11.1: {}
|
mark.js@8.11.1: {}
|
||||||
|
|
||||||
|
marked@18.0.3: {}
|
||||||
|
|
||||||
math-intrinsics@1.1.0: {}
|
math-intrinsics@1.1.0: {}
|
||||||
|
|
||||||
mathml-tag-names@2.1.3: {}
|
mathml-tag-names@2.1.3: {}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user