4
This commit is contained in:
@@ -163,9 +163,12 @@ def kb_index_html(
|
|||||||
doc_url = f"/k/{token}/doc/{decrypt_token(doc.doc_token_encrypted) if doc.doc_token_encrypted else ''}"
|
doc_url = f"/k/{token}/doc/{decrypt_token(doc.doc_token_encrypted) if doc.doc_token_encrypted else ''}"
|
||||||
keywords_html = f'<span class="keywords">关键词:{doc.keywords}</span>' if doc.keywords else ""
|
keywords_html = f'<span class="keywords">关键词:{doc.keywords}</span>' if doc.keywords else ""
|
||||||
summary_html = f'<p class="summary">{doc.content_summary or ""}</p>' if doc.content_summary else ""
|
summary_html = f'<p class="summary">{doc.content_summary or ""}</p>' if doc.content_summary else ""
|
||||||
|
status_badge = ""
|
||||||
|
if doc.status != "READY":
|
||||||
|
status_badge = f' <span class="status-badge">[{doc.status}]</span>'
|
||||||
doc_rows += f"""
|
doc_rows += f"""
|
||||||
<div class="doc-item">
|
<div class="doc-item">
|
||||||
<h3><a href="{doc_url}">{doc.title or doc.original_filename}</a></h3>
|
<h3><a href="{doc_url}">{doc.title or doc.original_filename}</a>{status_badge}</h3>
|
||||||
<p class="meta">类型:{doc.file_ext} | 更新:{doc.updated_at}</p>
|
<p class="meta">类型:{doc.file_ext} | 更新:{doc.updated_at}</p>
|
||||||
{summary_html}
|
{summary_html}
|
||||||
{keywords_html}
|
{keywords_html}
|
||||||
@@ -195,6 +198,7 @@ def kb_index_html(
|
|||||||
.summary {{ color: #444; font-size: 0.95em; margin: 5px 0; }}
|
.summary {{ color: #444; font-size: 0.95em; margin: 5px 0; }}
|
||||||
.keywords {{ color: #888; font-size: 0.85em; }}
|
.keywords {{ color: #888; font-size: 0.85em; }}
|
||||||
.pagination {{ color: #666; font-size: 0.9em; text-align: center; }}
|
.pagination {{ color: #666; font-size: 0.9em; text-align: center; }}
|
||||||
|
.status-badge {{ color: #e67e22; font-size: 0.8em; font-weight: normal; }}
|
||||||
.footer {{ margin-top: 30px; padding-top: 15px; border-top: 1px solid #eee; color: #999; font-size: 0.85em; }}
|
.footer {{ margin-top: 30px; padding-top: 15px; border-top: 1px solid #eee; color: #999; font-size: 0.85em; }}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ class KbPublicService:
|
|||||||
def list_documents(
|
def list_documents(
|
||||||
self, kb: KnowledgeBase, *, page: int = 1, page_size: int = 50
|
self, kb: KnowledgeBase, *, page: int = 1, page_size: int = 50
|
||||||
) -> tuple[list[Document], int]:
|
) -> tuple[list[Document], int]:
|
||||||
"""获取知识库的文档列表(仅 READY 状态)。"""
|
"""获取知识库的文档列表(排除 DELETED)。"""
|
||||||
return self._doc_repo.list_by_knowledge_base(
|
return self._doc_repo.list_by_knowledge_base(
|
||||||
kb.id, page=page, page_size=page_size, status="READY"
|
kb.id, page=page, page_size=page_size
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_document_by_token(self, kb: KnowledgeBase, doc_token: str) -> Document:
|
def get_document_by_token(self, kb: KnowledgeBase, doc_token: str) -> Document:
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ python-multipart>=0.0.7
|
|||||||
# --- 文档解析 ---
|
# --- 文档解析 ---
|
||||||
# MIME 嗅探:纯 Python,Windows 无需 libmagic DLL
|
# MIME 嗅探:纯 Python,Windows 无需 libmagic DLL
|
||||||
filetype>=1.2
|
filetype>=1.2
|
||||||
# MarkItDown(MIT)
|
# MarkItDown(MIT)—— 含 docx/pdf 支持
|
||||||
markitdown>=0.1.0
|
markitdown[docx,pdf]>=0.1.0
|
||||||
# PDF fallback: PyMuPDF(AGPL-3.0)
|
# PDF fallback: PyMuPDF(AGPL-3.0)
|
||||||
# TODO: 商品化前替换为 pypdfium2(Apache-2.0/BSD),见 docs/technical-review.md R3
|
# TODO: 商品化前替换为 pypdfium2(Apache-2.0/BSD),见 docs/technical-review.md R3
|
||||||
PyMuPDF>=1.24.0
|
PyMuPDF>=1.24.0
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
| 11 | Markdown/TXT/JSON 输出 | ✅ 完成 |
|
| 11 | Markdown/TXT/JSON 输出 | ✅ 完成 |
|
||||||
| 12 | 搜索 | ✅ 完成(LIKE 搜索,可升级 FTS5) |
|
| 12 | 搜索 | ✅ 完成(LIKE 搜索,可升级 FTS5) |
|
||||||
| 13 | 安全 | 🔄 已实现:IDOR 防护、限流、XSS 防护、路径穿越防护、Session 安全 |
|
| 13 | 安全 | 🔄 已实现:IDOR 防护、限流、XSS 防护、路径穿越防护、Session 安全 |
|
||||||
| 14 | 前端完善 | ⬜ |
|
| 14 | 前端完善 | ✅ 完成 |
|
||||||
| 15 | 测试 | 🔄 后端 51/51 通过;前端测试待 Phase 14 |
|
| 15 | 测试 | 🔄 后端 51/51 通过;前端测试待 Phase 14 |
|
||||||
| 16 | Docker | 🔄 compose/Dockerfile 已写(Phase 1),待 Docker 环境验证 |
|
| 16 | Docker | 🔄 compose/Dockerfile 已写(Phase 1),待 Docker 环境验证 |
|
||||||
| 17 | Ubuntu 部署文档 | ⬜ |
|
| 17 | Ubuntu 部署文档 | ⬜ |
|
||||||
|
|||||||
Generated
+13
-40
@@ -9,7 +9,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3",
|
"@element-plus/icons-vue": "^2.3",
|
||||||
"axios": "^1.7",
|
"axios": "^1.7.9",
|
||||||
"element-plus": "^2.9",
|
"element-plus": "^2.9",
|
||||||
"pinia": "^2.2",
|
"pinia": "^2.2",
|
||||||
"vue": "^3.5",
|
"vue": "^3.5",
|
||||||
@@ -1809,18 +1809,6 @@
|
|||||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/agent-base": {
|
|
||||||
"version": "6.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
|
||||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "6.15.0",
|
"version": "6.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
|
||||||
@@ -1881,15 +1869,14 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.20.0",
|
"version": "1.7.9",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
|
||||||
"integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==",
|
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.16.0",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.6",
|
"form-data": "^4.0.0",
|
||||||
"https-proxy-agent": "^5.0.1",
|
"proxy-from-env": "^1.1.0"
|
||||||
"proxy-from-env": "^2.1.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
@@ -2052,6 +2039,7 @@
|
|||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "^2.1.3"
|
"ms": "^2.1.3"
|
||||||
@@ -2784,19 +2772,6 @@
|
|||||||
"he": "bin/he"
|
"he": "bin/he"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/https-proxy-agent": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"agent-base": "6",
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "7.0.8",
|
"version": "7.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz",
|
||||||
@@ -3043,6 +3018,7 @@
|
|||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/muggle-string": {
|
"node_modules/muggle-string": {
|
||||||
@@ -3296,13 +3272,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "2.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
|
|||||||
+12
-12
@@ -11,23 +11,23 @@
|
|||||||
"format": "prettier --write src/"
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vue": "^3.5",
|
"@element-plus/icons-vue": "^2.3",
|
||||||
"vue-router": "^4.4",
|
"axios": "^1.7.9",
|
||||||
"pinia": "^2.2",
|
|
||||||
"element-plus": "^2.9",
|
"element-plus": "^2.9",
|
||||||
"axios": "^1.7",
|
"pinia": "^2.2",
|
||||||
"@element-plus/icons-vue": "^2.3"
|
"vue": "^3.5",
|
||||||
|
"vue-router": "^4.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.2",
|
|
||||||
"vite": "^6.1",
|
|
||||||
"typescript": "^5.7",
|
|
||||||
"vue-tsc": "^2.2",
|
|
||||||
"@types/node": "^22.0",
|
"@types/node": "^22.0",
|
||||||
"eslint": "^9.0",
|
|
||||||
"eslint-plugin-vue": "^9.28",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^8.0",
|
"@typescript-eslint/eslint-plugin": "^8.0",
|
||||||
"@typescript-eslint/parser": "^8.0",
|
"@typescript-eslint/parser": "^8.0",
|
||||||
"prettier": "^3.4"
|
"@vitejs/plugin-vue": "^5.2",
|
||||||
|
"eslint": "^9.0",
|
||||||
|
"eslint-plugin-vue": "^9.28",
|
||||||
|
"prettier": "^3.4",
|
||||||
|
"typescript": "^5.7",
|
||||||
|
"vite": "^6.1",
|
||||||
|
"vue-tsc": "^2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import apiClient from '@/api/client'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const isCollapsed = ref(false)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get('/auth/me')
|
||||||
|
userStore.setUser(data)
|
||||||
|
} catch {
|
||||||
|
// 未登录,跳转登录页
|
||||||
|
if (router.currentRoute.value.path !== '/login' && router.currentRoute.value.path !== '/register') {
|
||||||
|
router.push('/login')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
async function handleLogout() {
|
||||||
|
try {
|
||||||
|
await apiClient.post('/auth/logout')
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
userStore.clearUser()
|
||||||
|
router.push('/login')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-container style="min-height: 100vh">
|
||||||
|
<el-aside :width="isCollapsed ? '64px' : '220px'" style="transition: width 0.3s">
|
||||||
|
<div style="padding: 20px; text-align: center; font-weight: bold; font-size: 18px; color: #409eff; white-space: nowrap; overflow: hidden">
|
||||||
|
<span v-if="!isCollapsed">AI Knowledge Link</span>
|
||||||
|
<span v-else>AKL</span>
|
||||||
|
</div>
|
||||||
|
<el-menu
|
||||||
|
:default-active="router.currentRoute.value.path"
|
||||||
|
:collapse="isCollapsed"
|
||||||
|
router
|
||||||
|
>
|
||||||
|
<el-menu-item index="/">
|
||||||
|
<el-icon><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"/></svg></el-icon>
|
||||||
|
<template #title>仪表盘</template>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/knowledge-bases">
|
||||||
|
<el-icon><svg viewBox="0 0 24 24" fill="currentColor"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9H9V9h10v2zm-4 4H9v-2h6v2zm4-8H9V5h10v2z"/></svg></el-icon>
|
||||||
|
<template #title>知识库</template>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/settings">
|
||||||
|
<el-icon><svg viewBox="0 0 24 24" fill="currentColor"><path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/></svg></el-icon>
|
||||||
|
<template #title>设置</template>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</el-aside>
|
||||||
|
<el-container>
|
||||||
|
<el-header style="display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #eee">
|
||||||
|
<el-button :icon="isCollapsed ? 'Expand' : 'Fold'" text @click="isCollapsed = !isCollapsed" />
|
||||||
|
<div style="display: flex; align-items: center; gap: 16px">
|
||||||
|
<span>{{ userStore.username }}</span>
|
||||||
|
<el-button type="danger" text @click="handleLogout">退出登录</el-button>
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-main style="padding: 20px">
|
||||||
|
<router-view />
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useUserStore } from '@/stores/user';
|
||||||
|
import apiClient from '@/api/client';
|
||||||
|
const router = useRouter();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const isCollapsed = ref(false);
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get('/auth/me');
|
||||||
|
userStore.setUser(data);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// 未登录,跳转登录页
|
||||||
|
if (router.currentRoute.value.path !== '/login' && router.currentRoute.value.path !== '/register') {
|
||||||
|
router.push('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
async function handleLogout() {
|
||||||
|
try {
|
||||||
|
await apiClient.post('/auth/logout');
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
userStore.clearUser();
|
||||||
|
router.push('/login');
|
||||||
|
}
|
||||||
|
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
||||||
|
const __VLS_ctx = {};
|
||||||
|
let __VLS_components;
|
||||||
|
let __VLS_directives;
|
||||||
|
const __VLS_0 = {}.ElContainer;
|
||||||
|
/** @type {[typeof __VLS_components.ElContainer, typeof __VLS_components.elContainer, typeof __VLS_components.ElContainer, typeof __VLS_components.elContainer, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_1 = __VLS_asFunctionalComponent(__VLS_0, new __VLS_0({
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_2 = __VLS_1({
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_1));
|
||||||
|
var __VLS_4 = {};
|
||||||
|
__VLS_3.slots.default;
|
||||||
|
const __VLS_5 = {}.ElAside;
|
||||||
|
/** @type {[typeof __VLS_components.ElAside, typeof __VLS_components.elAside, typeof __VLS_components.ElAside, typeof __VLS_components.elAside, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_6 = __VLS_asFunctionalComponent(__VLS_5, new __VLS_5({
|
||||||
|
width: (__VLS_ctx.isCollapsed ? '64px' : '220px'),
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_7 = __VLS_6({
|
||||||
|
width: (__VLS_ctx.isCollapsed ? '64px' : '220px'),
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_6));
|
||||||
|
__VLS_8.slots.default;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
if (!__VLS_ctx.isCollapsed) {
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
|
||||||
|
}
|
||||||
|
const __VLS_9 = {}.ElMenu;
|
||||||
|
/** @type {[typeof __VLS_components.ElMenu, typeof __VLS_components.elMenu, typeof __VLS_components.ElMenu, typeof __VLS_components.elMenu, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_10 = __VLS_asFunctionalComponent(__VLS_9, new __VLS_9({
|
||||||
|
defaultActive: (__VLS_ctx.router.currentRoute.value.path),
|
||||||
|
collapse: (__VLS_ctx.isCollapsed),
|
||||||
|
router: true,
|
||||||
|
}));
|
||||||
|
const __VLS_11 = __VLS_10({
|
||||||
|
defaultActive: (__VLS_ctx.router.currentRoute.value.path),
|
||||||
|
collapse: (__VLS_ctx.isCollapsed),
|
||||||
|
router: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_10));
|
||||||
|
__VLS_12.slots.default;
|
||||||
|
const __VLS_13 = {}.ElMenuItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElMenuItem, typeof __VLS_components.elMenuItem, typeof __VLS_components.ElMenuItem, typeof __VLS_components.elMenuItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_14 = __VLS_asFunctionalComponent(__VLS_13, new __VLS_13({
|
||||||
|
index: "/",
|
||||||
|
}));
|
||||||
|
const __VLS_15 = __VLS_14({
|
||||||
|
index: "/",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_14));
|
||||||
|
__VLS_16.slots.default;
|
||||||
|
const __VLS_17 = {}.ElIcon;
|
||||||
|
/** @type {[typeof __VLS_components.ElIcon, typeof __VLS_components.elIcon, typeof __VLS_components.ElIcon, typeof __VLS_components.elIcon, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_18 = __VLS_asFunctionalComponent(__VLS_17, new __VLS_17({}));
|
||||||
|
const __VLS_19 = __VLS_18({}, ...__VLS_functionalComponentArgsRest(__VLS_18));
|
||||||
|
__VLS_20.slots.default;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.svg, __VLS_intrinsicElements.svg)({
|
||||||
|
viewBox: "0 0 24 24",
|
||||||
|
fill: "currentColor",
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.path)({
|
||||||
|
d: "M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z",
|
||||||
|
});
|
||||||
|
var __VLS_20;
|
||||||
|
{
|
||||||
|
const { title: __VLS_thisSlot } = __VLS_16.slots;
|
||||||
|
}
|
||||||
|
var __VLS_16;
|
||||||
|
const __VLS_21 = {}.ElMenuItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElMenuItem, typeof __VLS_components.elMenuItem, typeof __VLS_components.ElMenuItem, typeof __VLS_components.elMenuItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_22 = __VLS_asFunctionalComponent(__VLS_21, new __VLS_21({
|
||||||
|
index: "/knowledge-bases",
|
||||||
|
}));
|
||||||
|
const __VLS_23 = __VLS_22({
|
||||||
|
index: "/knowledge-bases",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_22));
|
||||||
|
__VLS_24.slots.default;
|
||||||
|
const __VLS_25 = {}.ElIcon;
|
||||||
|
/** @type {[typeof __VLS_components.ElIcon, typeof __VLS_components.elIcon, typeof __VLS_components.ElIcon, typeof __VLS_components.elIcon, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_26 = __VLS_asFunctionalComponent(__VLS_25, new __VLS_25({}));
|
||||||
|
const __VLS_27 = __VLS_26({}, ...__VLS_functionalComponentArgsRest(__VLS_26));
|
||||||
|
__VLS_28.slots.default;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.svg, __VLS_intrinsicElements.svg)({
|
||||||
|
viewBox: "0 0 24 24",
|
||||||
|
fill: "currentColor",
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.path)({
|
||||||
|
d: "M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9H9V9h10v2zm-4 4H9v-2h6v2zm4-8H9V5h10v2z",
|
||||||
|
});
|
||||||
|
var __VLS_28;
|
||||||
|
{
|
||||||
|
const { title: __VLS_thisSlot } = __VLS_24.slots;
|
||||||
|
}
|
||||||
|
var __VLS_24;
|
||||||
|
const __VLS_29 = {}.ElMenuItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElMenuItem, typeof __VLS_components.elMenuItem, typeof __VLS_components.ElMenuItem, typeof __VLS_components.elMenuItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_30 = __VLS_asFunctionalComponent(__VLS_29, new __VLS_29({
|
||||||
|
index: "/settings",
|
||||||
|
}));
|
||||||
|
const __VLS_31 = __VLS_30({
|
||||||
|
index: "/settings",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_30));
|
||||||
|
__VLS_32.slots.default;
|
||||||
|
const __VLS_33 = {}.ElIcon;
|
||||||
|
/** @type {[typeof __VLS_components.ElIcon, typeof __VLS_components.elIcon, typeof __VLS_components.ElIcon, typeof __VLS_components.elIcon, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_34 = __VLS_asFunctionalComponent(__VLS_33, new __VLS_33({}));
|
||||||
|
const __VLS_35 = __VLS_34({}, ...__VLS_functionalComponentArgsRest(__VLS_34));
|
||||||
|
__VLS_36.slots.default;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.svg, __VLS_intrinsicElements.svg)({
|
||||||
|
viewBox: "0 0 24 24",
|
||||||
|
fill: "currentColor",
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.path)({
|
||||||
|
d: "M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z",
|
||||||
|
});
|
||||||
|
var __VLS_36;
|
||||||
|
{
|
||||||
|
const { title: __VLS_thisSlot } = __VLS_32.slots;
|
||||||
|
}
|
||||||
|
var __VLS_32;
|
||||||
|
var __VLS_12;
|
||||||
|
var __VLS_8;
|
||||||
|
const __VLS_37 = {}.ElContainer;
|
||||||
|
/** @type {[typeof __VLS_components.ElContainer, typeof __VLS_components.elContainer, typeof __VLS_components.ElContainer, typeof __VLS_components.elContainer, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_38 = __VLS_asFunctionalComponent(__VLS_37, new __VLS_37({}));
|
||||||
|
const __VLS_39 = __VLS_38({}, ...__VLS_functionalComponentArgsRest(__VLS_38));
|
||||||
|
__VLS_40.slots.default;
|
||||||
|
const __VLS_41 = {}.ElHeader;
|
||||||
|
/** @type {[typeof __VLS_components.ElHeader, typeof __VLS_components.elHeader, typeof __VLS_components.ElHeader, typeof __VLS_components.elHeader, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_42 = __VLS_asFunctionalComponent(__VLS_41, new __VLS_41({
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_43 = __VLS_42({
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_42));
|
||||||
|
__VLS_44.slots.default;
|
||||||
|
const __VLS_45 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_46 = __VLS_asFunctionalComponent(__VLS_45, new __VLS_45({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
icon: (__VLS_ctx.isCollapsed ? 'Expand' : 'Fold'),
|
||||||
|
text: true,
|
||||||
|
}));
|
||||||
|
const __VLS_47 = __VLS_46({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
icon: (__VLS_ctx.isCollapsed ? 'Expand' : 'Fold'),
|
||||||
|
text: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_46));
|
||||||
|
let __VLS_49;
|
||||||
|
let __VLS_50;
|
||||||
|
let __VLS_51;
|
||||||
|
const __VLS_52 = {
|
||||||
|
onClick: (...[$event]) => {
|
||||||
|
__VLS_ctx.isCollapsed = !__VLS_ctx.isCollapsed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var __VLS_48;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
|
||||||
|
(__VLS_ctx.userStore.username);
|
||||||
|
const __VLS_53 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_54 = __VLS_asFunctionalComponent(__VLS_53, new __VLS_53({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "danger",
|
||||||
|
text: true,
|
||||||
|
}));
|
||||||
|
const __VLS_55 = __VLS_54({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "danger",
|
||||||
|
text: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_54));
|
||||||
|
let __VLS_57;
|
||||||
|
let __VLS_58;
|
||||||
|
let __VLS_59;
|
||||||
|
const __VLS_60 = {
|
||||||
|
onClick: (__VLS_ctx.handleLogout)
|
||||||
|
};
|
||||||
|
__VLS_56.slots.default;
|
||||||
|
var __VLS_56;
|
||||||
|
var __VLS_44;
|
||||||
|
const __VLS_61 = {}.ElMain;
|
||||||
|
/** @type {[typeof __VLS_components.ElMain, typeof __VLS_components.elMain, typeof __VLS_components.ElMain, typeof __VLS_components.elMain, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_62 = __VLS_asFunctionalComponent(__VLS_61, new __VLS_61({
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_63 = __VLS_62({
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_62));
|
||||||
|
__VLS_64.slots.default;
|
||||||
|
const __VLS_65 = {}.RouterView;
|
||||||
|
/** @type {[typeof __VLS_components.RouterView, typeof __VLS_components.routerView, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_66 = __VLS_asFunctionalComponent(__VLS_65, new __VLS_65({}));
|
||||||
|
const __VLS_67 = __VLS_66({}, ...__VLS_functionalComponentArgsRest(__VLS_66));
|
||||||
|
var __VLS_64;
|
||||||
|
var __VLS_40;
|
||||||
|
var __VLS_3;
|
||||||
|
var __VLS_dollars;
|
||||||
|
const __VLS_self = (await import('vue')).defineComponent({
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
router: router,
|
||||||
|
userStore: userStore,
|
||||||
|
isCollapsed: isCollapsed,
|
||||||
|
handleLogout: handleLogout,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export default (await import('vue')).defineComponent({
|
||||||
|
setup() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
; /* PartiallyEnd: #4569/main.vue */
|
||||||
@@ -14,24 +14,30 @@ const router = createRouter({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
component: () => import('@/layouts/DefaultLayout.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
component: () => import('@/views/Dashboard.vue'),
|
component: () => import('@/views/Dashboard.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/knowledge-bases',
|
path: 'knowledge-bases',
|
||||||
name: 'KnowledgeBases',
|
name: 'KnowledgeBases',
|
||||||
component: () => import('@/views/KnowledgeBases.vue'),
|
component: () => import('@/views/KnowledgeBases.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/knowledge-bases/:id',
|
path: 'knowledge-bases/:id',
|
||||||
name: 'KbDetail',
|
name: 'KbDetail',
|
||||||
component: () => import('@/views/KbDetail.vue'),
|
component: () => import('@/views/KbDetail.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/settings',
|
path: 'settings',
|
||||||
name: 'Settings',
|
name: 'Settings',
|
||||||
component: () => import('@/views/Settings.vue'),
|
component: () => import('@/views/Settings.vue'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -15,25 +15,31 @@ const router = createRouter({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
component: () => import('@/layouts/DefaultLayout.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
component: () => import('@/views/Dashboard.vue'),
|
component: () => import('@/views/Dashboard.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/knowledge-bases',
|
path: 'knowledge-bases',
|
||||||
name: 'KnowledgeBases',
|
name: 'KnowledgeBases',
|
||||||
component: () => import('@/views/KnowledgeBases.vue'),
|
component: () => import('@/views/KnowledgeBases.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/knowledge-bases/:id',
|
path: 'knowledge-bases/:id',
|
||||||
name: 'KbDetail',
|
name: 'KbDetail',
|
||||||
component: () => import('@/views/KbDetail.vue'),
|
component: () => import('@/views/KbDetail.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/settings',
|
path: 'settings',
|
||||||
name: 'Settings',
|
name: 'Settings',
|
||||||
component: () => import('@/views/Settings.vue'),
|
component: () => import('@/views/Settings.vue'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
@@ -1,10 +1,87 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// Phase 14 完善仪表盘
|
import { ref, onMounted } from 'vue'
|
||||||
|
import apiClient from '@/api/client'
|
||||||
|
|
||||||
|
const stats = ref({
|
||||||
|
kb_count: 0,
|
||||||
|
doc_count: 0,
|
||||||
|
storage_used_mb: 0,
|
||||||
|
storage_quota_mb: 100,
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const [kbRes, storageRes] = await Promise.all([
|
||||||
|
apiClient.get('/knowledge-bases'),
|
||||||
|
apiClient.get('/auth/storage'),
|
||||||
|
])
|
||||||
|
stats.value.kb_count = kbRes.data.total
|
||||||
|
stats.value.storage_used_mb = storageRes.data.storage_used_mb
|
||||||
|
stats.value.storage_quota_mb = storageRes.data.storage_quota_mb
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="dashboard-page">
|
<div>
|
||||||
<h1>仪表盘</h1>
|
<h1>仪表盘</h1>
|
||||||
<p>Dashboard(Phase 14 完善)</p>
|
<el-row :gutter="20" style="margin-bottom: 20px">
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value">{{ stats.kb_count }}</div>
|
||||||
|
<div class="stat-label">知识库</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value">{{ stats.storage_used_mb }} MB</div>
|
||||||
|
<div class="stat-label">已用空间 / {{ stats.storage_quota_mb }} MB</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card>
|
||||||
|
<div class="stat-item">
|
||||||
|
<el-progress
|
||||||
|
:percentage="Math.min(100, Math.round(stats.storage_used_mb / stats.storage_quota_mb * 100))"
|
||||||
|
:stroke-width="20"
|
||||||
|
:text-inside="true"
|
||||||
|
/>
|
||||||
|
<div class="stat-label">存储用量</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||||
|
<span>快速开始</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-steps :active="0" direction="vertical">
|
||||||
|
<el-step title="创建知识库" description="点击左侧「知识库」菜单,创建你的第一个知识库" />
|
||||||
|
<el-step title="上传文档" description="支持 .docx 和 .pdf 文件" />
|
||||||
|
<el-step title="分享 AI 链接" description="复制知识库的 AI 专属链接,发送给任意 AI" />
|
||||||
|
</el-steps>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.stat-item {
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
.stat-value {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
.stat-label {
|
||||||
|
color: #999;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,17 +1,212 @@
|
|||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import apiClient from '@/api/client';
|
||||||
|
const stats = ref({
|
||||||
|
kb_count: 0,
|
||||||
|
doc_count: 0,
|
||||||
|
storage_used_mb: 0,
|
||||||
|
storage_quota_mb: 100,
|
||||||
|
});
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const [kbRes, storageRes] = await Promise.all([
|
||||||
|
apiClient.get('/knowledge-bases'),
|
||||||
|
apiClient.get('/auth/storage'),
|
||||||
|
]);
|
||||||
|
stats.value.kb_count = kbRes.data.total;
|
||||||
|
stats.value.storage_used_mb = storageRes.data.storage_used_mb;
|
||||||
|
stats.value.storage_quota_mb = storageRes.data.storage_quota_mb;
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
});
|
||||||
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
||||||
const __VLS_ctx = {};
|
const __VLS_ctx = {};
|
||||||
let __VLS_components;
|
let __VLS_components;
|
||||||
let __VLS_directives;
|
let __VLS_directives;
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
// CSS variable injection
|
||||||
...{ class: "dashboard-page" },
|
// CSS variable injection end
|
||||||
});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({});
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({});
|
const __VLS_0 = {}.ElRow;
|
||||||
/** @type {__VLS_StyleScopedClasses['dashboard-page']} */ ;
|
/** @type {[typeof __VLS_components.ElRow, typeof __VLS_components.elRow, typeof __VLS_components.ElRow, typeof __VLS_components.elRow, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_1 = __VLS_asFunctionalComponent(__VLS_0, new __VLS_0({
|
||||||
|
gutter: (20),
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_2 = __VLS_1({
|
||||||
|
gutter: (20),
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_1));
|
||||||
|
__VLS_3.slots.default;
|
||||||
|
const __VLS_4 = {}.ElCol;
|
||||||
|
/** @type {[typeof __VLS_components.ElCol, typeof __VLS_components.elCol, typeof __VLS_components.ElCol, typeof __VLS_components.elCol, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_5 = __VLS_asFunctionalComponent(__VLS_4, new __VLS_4({
|
||||||
|
span: (8),
|
||||||
|
}));
|
||||||
|
const __VLS_6 = __VLS_5({
|
||||||
|
span: (8),
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_5));
|
||||||
|
__VLS_7.slots.default;
|
||||||
|
const __VLS_8 = {}.ElCard;
|
||||||
|
/** @type {[typeof __VLS_components.ElCard, typeof __VLS_components.elCard, typeof __VLS_components.ElCard, typeof __VLS_components.elCard, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_9 = __VLS_asFunctionalComponent(__VLS_8, new __VLS_8({}));
|
||||||
|
const __VLS_10 = __VLS_9({}, ...__VLS_functionalComponentArgsRest(__VLS_9));
|
||||||
|
__VLS_11.slots.default;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ class: "stat-item" },
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ class: "stat-value" },
|
||||||
|
});
|
||||||
|
(__VLS_ctx.stats.kb_count);
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ class: "stat-label" },
|
||||||
|
});
|
||||||
|
var __VLS_11;
|
||||||
|
var __VLS_7;
|
||||||
|
const __VLS_12 = {}.ElCol;
|
||||||
|
/** @type {[typeof __VLS_components.ElCol, typeof __VLS_components.elCol, typeof __VLS_components.ElCol, typeof __VLS_components.elCol, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_13 = __VLS_asFunctionalComponent(__VLS_12, new __VLS_12({
|
||||||
|
span: (8),
|
||||||
|
}));
|
||||||
|
const __VLS_14 = __VLS_13({
|
||||||
|
span: (8),
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_13));
|
||||||
|
__VLS_15.slots.default;
|
||||||
|
const __VLS_16 = {}.ElCard;
|
||||||
|
/** @type {[typeof __VLS_components.ElCard, typeof __VLS_components.elCard, typeof __VLS_components.ElCard, typeof __VLS_components.elCard, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_17 = __VLS_asFunctionalComponent(__VLS_16, new __VLS_16({}));
|
||||||
|
const __VLS_18 = __VLS_17({}, ...__VLS_functionalComponentArgsRest(__VLS_17));
|
||||||
|
__VLS_19.slots.default;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ class: "stat-item" },
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ class: "stat-value" },
|
||||||
|
});
|
||||||
|
(__VLS_ctx.stats.storage_used_mb);
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ class: "stat-label" },
|
||||||
|
});
|
||||||
|
(__VLS_ctx.stats.storage_quota_mb);
|
||||||
|
var __VLS_19;
|
||||||
|
var __VLS_15;
|
||||||
|
const __VLS_20 = {}.ElCol;
|
||||||
|
/** @type {[typeof __VLS_components.ElCol, typeof __VLS_components.elCol, typeof __VLS_components.ElCol, typeof __VLS_components.elCol, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_21 = __VLS_asFunctionalComponent(__VLS_20, new __VLS_20({
|
||||||
|
span: (8),
|
||||||
|
}));
|
||||||
|
const __VLS_22 = __VLS_21({
|
||||||
|
span: (8),
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_21));
|
||||||
|
__VLS_23.slots.default;
|
||||||
|
const __VLS_24 = {}.ElCard;
|
||||||
|
/** @type {[typeof __VLS_components.ElCard, typeof __VLS_components.elCard, typeof __VLS_components.ElCard, typeof __VLS_components.elCard, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_25 = __VLS_asFunctionalComponent(__VLS_24, new __VLS_24({}));
|
||||||
|
const __VLS_26 = __VLS_25({}, ...__VLS_functionalComponentArgsRest(__VLS_25));
|
||||||
|
__VLS_27.slots.default;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ class: "stat-item" },
|
||||||
|
});
|
||||||
|
const __VLS_28 = {}.ElProgress;
|
||||||
|
/** @type {[typeof __VLS_components.ElProgress, typeof __VLS_components.elProgress, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_29 = __VLS_asFunctionalComponent(__VLS_28, new __VLS_28({
|
||||||
|
percentage: (Math.min(100, Math.round(__VLS_ctx.stats.storage_used_mb / __VLS_ctx.stats.storage_quota_mb * 100))),
|
||||||
|
strokeWidth: (20),
|
||||||
|
textInside: (true),
|
||||||
|
}));
|
||||||
|
const __VLS_30 = __VLS_29({
|
||||||
|
percentage: (Math.min(100, Math.round(__VLS_ctx.stats.storage_used_mb / __VLS_ctx.stats.storage_quota_mb * 100))),
|
||||||
|
strokeWidth: (20),
|
||||||
|
textInside: (true),
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_29));
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ class: "stat-label" },
|
||||||
|
});
|
||||||
|
var __VLS_27;
|
||||||
|
var __VLS_23;
|
||||||
|
var __VLS_3;
|
||||||
|
const __VLS_32 = {}.ElCard;
|
||||||
|
/** @type {[typeof __VLS_components.ElCard, typeof __VLS_components.elCard, typeof __VLS_components.ElCard, typeof __VLS_components.elCard, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_33 = __VLS_asFunctionalComponent(__VLS_32, new __VLS_32({}));
|
||||||
|
const __VLS_34 = __VLS_33({}, ...__VLS_functionalComponentArgsRest(__VLS_33));
|
||||||
|
__VLS_35.slots.default;
|
||||||
|
{
|
||||||
|
const { header: __VLS_thisSlot } = __VLS_35.slots;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
|
||||||
|
}
|
||||||
|
const __VLS_36 = {}.ElSteps;
|
||||||
|
/** @type {[typeof __VLS_components.ElSteps, typeof __VLS_components.elSteps, typeof __VLS_components.ElSteps, typeof __VLS_components.elSteps, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_37 = __VLS_asFunctionalComponent(__VLS_36, new __VLS_36({
|
||||||
|
active: (0),
|
||||||
|
direction: "vertical",
|
||||||
|
}));
|
||||||
|
const __VLS_38 = __VLS_37({
|
||||||
|
active: (0),
|
||||||
|
direction: "vertical",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_37));
|
||||||
|
__VLS_39.slots.default;
|
||||||
|
const __VLS_40 = {}.ElStep;
|
||||||
|
/** @type {[typeof __VLS_components.ElStep, typeof __VLS_components.elStep, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_41 = __VLS_asFunctionalComponent(__VLS_40, new __VLS_40({
|
||||||
|
title: "创建知识库",
|
||||||
|
description: "点击左侧「知识库」菜单,创建你的第一个知识库",
|
||||||
|
}));
|
||||||
|
const __VLS_42 = __VLS_41({
|
||||||
|
title: "创建知识库",
|
||||||
|
description: "点击左侧「知识库」菜单,创建你的第一个知识库",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_41));
|
||||||
|
const __VLS_44 = {}.ElStep;
|
||||||
|
/** @type {[typeof __VLS_components.ElStep, typeof __VLS_components.elStep, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_45 = __VLS_asFunctionalComponent(__VLS_44, new __VLS_44({
|
||||||
|
title: "上传文档",
|
||||||
|
description: "支持 .docx 和 .pdf 文件",
|
||||||
|
}));
|
||||||
|
const __VLS_46 = __VLS_45({
|
||||||
|
title: "上传文档",
|
||||||
|
description: "支持 .docx 和 .pdf 文件",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_45));
|
||||||
|
const __VLS_48 = {}.ElStep;
|
||||||
|
/** @type {[typeof __VLS_components.ElStep, typeof __VLS_components.elStep, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_49 = __VLS_asFunctionalComponent(__VLS_48, new __VLS_48({
|
||||||
|
title: "分享 AI 链接",
|
||||||
|
description: "复制知识库的 AI 专属链接,发送给任意 AI",
|
||||||
|
}));
|
||||||
|
const __VLS_50 = __VLS_49({
|
||||||
|
title: "分享 AI 链接",
|
||||||
|
description: "复制知识库的 AI 专属链接,发送给任意 AI",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_49));
|
||||||
|
var __VLS_39;
|
||||||
|
var __VLS_35;
|
||||||
|
/** @type {__VLS_StyleScopedClasses['stat-item']} */ ;
|
||||||
|
/** @type {__VLS_StyleScopedClasses['stat-value']} */ ;
|
||||||
|
/** @type {__VLS_StyleScopedClasses['stat-label']} */ ;
|
||||||
|
/** @type {__VLS_StyleScopedClasses['stat-item']} */ ;
|
||||||
|
/** @type {__VLS_StyleScopedClasses['stat-value']} */ ;
|
||||||
|
/** @type {__VLS_StyleScopedClasses['stat-label']} */ ;
|
||||||
|
/** @type {__VLS_StyleScopedClasses['stat-item']} */ ;
|
||||||
|
/** @type {__VLS_StyleScopedClasses['stat-label']} */ ;
|
||||||
var __VLS_dollars;
|
var __VLS_dollars;
|
||||||
const __VLS_self = (await import('vue')).defineComponent({
|
const __VLS_self = (await import('vue')).defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {
|
||||||
|
stats: stats,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default (await import('vue')).defineComponent({
|
export default (await import('vue')).defineComponent({
|
||||||
|
|||||||
@@ -1,10 +1,164 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// Phase 4 实现知识库详情
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import apiClient from '@/api/client'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const kbId = route.params.id as string
|
||||||
|
|
||||||
|
const kb = ref<any>(null)
|
||||||
|
const docs = ref<any[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const uploading = ref(false)
|
||||||
|
const aiUrl = ref('')
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadKb()
|
||||||
|
await loadDocs()
|
||||||
|
await loadLink()
|
||||||
|
})
|
||||||
|
|
||||||
|
async function loadKb() {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get(`/knowledge-bases/${kbId}`)
|
||||||
|
kb.value = data
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadDocs() {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get(`/documents?kb_id=${kbId}`)
|
||||||
|
docs.value = data.items
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadLink() {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get(`/knowledge-bases/${kbId}/link`)
|
||||||
|
aiUrl.value = `${window.location.origin}/k/${data.token}`
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleUpload(options: any) {
|
||||||
|
uploading.value = true
|
||||||
|
try {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('kb_id', kbId)
|
||||||
|
formData.append('file', options.file)
|
||||||
|
await apiClient.post('/documents/upload', formData, {
|
||||||
|
headers: { 'Content-Type': 'multipart/form-data' },
|
||||||
|
})
|
||||||
|
ElMessage.success('文档上传成功!')
|
||||||
|
loadDocs()
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
uploading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDeleteDoc(doc: any) {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(`确定删除文档「${doc.original_filename}」?`, '确认删除', { type: 'warning' })
|
||||||
|
await apiClient.delete(`/documents/${doc.id}`)
|
||||||
|
ElMessage.success('已删除。')
|
||||||
|
loadDocs()
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleReprocess(doc: any) {
|
||||||
|
try {
|
||||||
|
await apiClient.post(`/documents/${doc.id}/reprocess`)
|
||||||
|
ElMessage.success('重新解析已提交。')
|
||||||
|
loadDocs()
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCopyLink() {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(aiUrl.value)
|
||||||
|
ElMessage.success('AI 链接已复制!')
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleRegenerate() {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm('重新生成链接后,旧链接将立即失效。确定继续?', '确认', { type: 'warning' })
|
||||||
|
const { data } = await apiClient.post(`/knowledge-bases/${kbId}/regenerate-token`)
|
||||||
|
aiUrl.value = `${window.location.origin}/k/${data.token}`
|
||||||
|
ElMessage.success('链接已重新生成。')
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatSize(bytes: number) {
|
||||||
|
if (bytes < 1024) return bytes + ' B'
|
||||||
|
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
|
||||||
|
return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusType(status: string) {
|
||||||
|
if (status === 'READY') return 'success'
|
||||||
|
if (status === 'FAILED') return 'danger'
|
||||||
|
return 'warning'
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div v-if="kb">
|
||||||
<h1>知识库详情</h1>
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px">
|
||||||
<p>知识库详情(Phase 4 实现)</p>
|
<h1 style="margin: 0">{{ kb.name }}</h1>
|
||||||
|
<el-button type="primary" @click="handleCopyLink">复制 AI 链接</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-card style="margin-bottom: 20px">
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="描述">{{ kb.description || '无' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="状态">
|
||||||
|
<el-tag :type="kb.enabled ? 'success' : 'danger'">{{ kb.enabled ? '启用' : '禁用' }}</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="AI 链接">
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px">
|
||||||
|
<el-input :model-value="aiUrl" readonly size="small" style="flex: 1" />
|
||||||
|
<el-button size="small" @click="handleRegenerate">重新生成</el-button>
|
||||||
|
</div>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="文档数">{{ docs.length }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||||
|
<span>文档列表</span>
|
||||||
|
<el-upload
|
||||||
|
:show-file-list="false"
|
||||||
|
:http-request="handleUpload"
|
||||||
|
accept=".docx,.pdf"
|
||||||
|
>
|
||||||
|
<el-button type="primary" :loading="uploading">上传文档</el-button>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-table :data="docs" v-loading="loading" style="width: 100%">
|
||||||
|
<el-table-column prop="original_filename" label="文件名" min-width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column label="状态" width="120" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="statusType(row.status)" size="small">{{ row.status }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="大小" width="100" align="center">
|
||||||
|
<template #default="{ row }">{{ formatSize(row.file_size) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="title" label="标题" min-width="150" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="keywords" label="关键词" min-width="150" show-overflow-tooltip />
|
||||||
|
<el-table-column label="操作" width="200" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button size="small" @click="handleReprocess(row)">重新解析</el-button>
|
||||||
|
<el-button size="small" type="danger" @click="handleDeleteDoc(row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,14 +1,494 @@
|
|||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
import apiClient from '@/api/client';
|
||||||
|
const route = useRoute();
|
||||||
|
const kbId = route.params.id;
|
||||||
|
const kb = ref(null);
|
||||||
|
const docs = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
const uploading = ref(false);
|
||||||
|
const aiUrl = ref('');
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadKb();
|
||||||
|
await loadDocs();
|
||||||
|
await loadLink();
|
||||||
|
});
|
||||||
|
async function loadKb() {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get(`/knowledge-bases/${kbId}`);
|
||||||
|
kb.value = data;
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
async function loadDocs() {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get(`/documents?kb_id=${kbId}`);
|
||||||
|
docs.value = data.items;
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
async function loadLink() {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get(`/knowledge-bases/${kbId}/link`);
|
||||||
|
aiUrl.value = `${window.location.origin}/k/${data.token}`;
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
async function handleUpload(options) {
|
||||||
|
uploading.value = true;
|
||||||
|
try {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('kb_id', kbId);
|
||||||
|
formData.append('file', options.file);
|
||||||
|
await apiClient.post('/documents/upload', formData, {
|
||||||
|
headers: { 'Content-Type': 'multipart/form-data' },
|
||||||
|
});
|
||||||
|
ElMessage.success('文档上传成功!');
|
||||||
|
loadDocs();
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
uploading.value = false;
|
||||||
|
}
|
||||||
|
async function handleDeleteDoc(doc) {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(`确定删除文档「${doc.original_filename}」?`, '确认删除', { type: 'warning' });
|
||||||
|
await apiClient.delete(`/documents/${doc.id}`);
|
||||||
|
ElMessage.success('已删除。');
|
||||||
|
loadDocs();
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
async function handleReprocess(doc) {
|
||||||
|
try {
|
||||||
|
await apiClient.post(`/documents/${doc.id}/reprocess`);
|
||||||
|
ElMessage.success('重新解析已提交。');
|
||||||
|
loadDocs();
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
async function handleCopyLink() {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(aiUrl.value);
|
||||||
|
ElMessage.success('AI 链接已复制!');
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
async function handleRegenerate() {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm('重新生成链接后,旧链接将立即失效。确定继续?', '确认', { type: 'warning' });
|
||||||
|
const { data } = await apiClient.post(`/knowledge-bases/${kbId}/regenerate-token`);
|
||||||
|
aiUrl.value = `${window.location.origin}/k/${data.token}`;
|
||||||
|
ElMessage.success('链接已重新生成。');
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
function formatSize(bytes) {
|
||||||
|
if (bytes < 1024)
|
||||||
|
return bytes + ' B';
|
||||||
|
if (bytes < 1024 * 1024)
|
||||||
|
return (bytes / 1024).toFixed(1) + ' KB';
|
||||||
|
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
||||||
|
}
|
||||||
|
function statusType(status) {
|
||||||
|
if (status === 'READY')
|
||||||
|
return 'success';
|
||||||
|
if (status === 'FAILED')
|
||||||
|
return 'danger';
|
||||||
|
return 'warning';
|
||||||
|
}
|
||||||
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
||||||
const __VLS_ctx = {};
|
const __VLS_ctx = {};
|
||||||
let __VLS_components;
|
let __VLS_components;
|
||||||
let __VLS_directives;
|
let __VLS_directives;
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
|
if (__VLS_ctx.kb) {
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
(__VLS_ctx.kb.name);
|
||||||
|
const __VLS_0 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_1 = __VLS_asFunctionalComponent(__VLS_0, new __VLS_0({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "primary",
|
||||||
|
}));
|
||||||
|
const __VLS_2 = __VLS_1({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "primary",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_1));
|
||||||
|
let __VLS_4;
|
||||||
|
let __VLS_5;
|
||||||
|
let __VLS_6;
|
||||||
|
const __VLS_7 = {
|
||||||
|
onClick: (__VLS_ctx.handleCopyLink)
|
||||||
|
};
|
||||||
|
__VLS_3.slots.default;
|
||||||
|
var __VLS_3;
|
||||||
|
const __VLS_8 = {}.ElCard;
|
||||||
|
/** @type {[typeof __VLS_components.ElCard, typeof __VLS_components.elCard, typeof __VLS_components.ElCard, typeof __VLS_components.elCard, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_9 = __VLS_asFunctionalComponent(__VLS_8, new __VLS_8({
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_10 = __VLS_9({
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_9));
|
||||||
|
__VLS_11.slots.default;
|
||||||
|
const __VLS_12 = {}.ElDescriptions;
|
||||||
|
/** @type {[typeof __VLS_components.ElDescriptions, typeof __VLS_components.elDescriptions, typeof __VLS_components.ElDescriptions, typeof __VLS_components.elDescriptions, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_13 = __VLS_asFunctionalComponent(__VLS_12, new __VLS_12({
|
||||||
|
column: (2),
|
||||||
|
border: true,
|
||||||
|
}));
|
||||||
|
const __VLS_14 = __VLS_13({
|
||||||
|
column: (2),
|
||||||
|
border: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_13));
|
||||||
|
__VLS_15.slots.default;
|
||||||
|
const __VLS_16 = {}.ElDescriptionsItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElDescriptionsItem, typeof __VLS_components.elDescriptionsItem, typeof __VLS_components.ElDescriptionsItem, typeof __VLS_components.elDescriptionsItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_17 = __VLS_asFunctionalComponent(__VLS_16, new __VLS_16({
|
||||||
|
label: "描述",
|
||||||
|
}));
|
||||||
|
const __VLS_18 = __VLS_17({
|
||||||
|
label: "描述",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_17));
|
||||||
|
__VLS_19.slots.default;
|
||||||
|
(__VLS_ctx.kb.description || '无');
|
||||||
|
var __VLS_19;
|
||||||
|
const __VLS_20 = {}.ElDescriptionsItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElDescriptionsItem, typeof __VLS_components.elDescriptionsItem, typeof __VLS_components.ElDescriptionsItem, typeof __VLS_components.elDescriptionsItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_21 = __VLS_asFunctionalComponent(__VLS_20, new __VLS_20({
|
||||||
|
label: "状态",
|
||||||
|
}));
|
||||||
|
const __VLS_22 = __VLS_21({
|
||||||
|
label: "状态",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_21));
|
||||||
|
__VLS_23.slots.default;
|
||||||
|
const __VLS_24 = {}.ElTag;
|
||||||
|
/** @type {[typeof __VLS_components.ElTag, typeof __VLS_components.elTag, typeof __VLS_components.ElTag, typeof __VLS_components.elTag, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_25 = __VLS_asFunctionalComponent(__VLS_24, new __VLS_24({
|
||||||
|
type: (__VLS_ctx.kb.enabled ? 'success' : 'danger'),
|
||||||
|
}));
|
||||||
|
const __VLS_26 = __VLS_25({
|
||||||
|
type: (__VLS_ctx.kb.enabled ? 'success' : 'danger'),
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_25));
|
||||||
|
__VLS_27.slots.default;
|
||||||
|
(__VLS_ctx.kb.enabled ? '启用' : '禁用');
|
||||||
|
var __VLS_27;
|
||||||
|
var __VLS_23;
|
||||||
|
const __VLS_28 = {}.ElDescriptionsItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElDescriptionsItem, typeof __VLS_components.elDescriptionsItem, typeof __VLS_components.ElDescriptionsItem, typeof __VLS_components.elDescriptionsItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_29 = __VLS_asFunctionalComponent(__VLS_28, new __VLS_28({
|
||||||
|
label: "AI 链接",
|
||||||
|
}));
|
||||||
|
const __VLS_30 = __VLS_29({
|
||||||
|
label: "AI 链接",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_29));
|
||||||
|
__VLS_31.slots.default;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
const __VLS_32 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_33 = __VLS_asFunctionalComponent(__VLS_32, new __VLS_32({
|
||||||
|
modelValue: (__VLS_ctx.aiUrl),
|
||||||
|
readonly: true,
|
||||||
|
size: "small",
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_34 = __VLS_33({
|
||||||
|
modelValue: (__VLS_ctx.aiUrl),
|
||||||
|
readonly: true,
|
||||||
|
size: "small",
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_33));
|
||||||
|
const __VLS_36 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_37 = __VLS_asFunctionalComponent(__VLS_36, new __VLS_36({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
}));
|
||||||
|
const __VLS_38 = __VLS_37({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_37));
|
||||||
|
let __VLS_40;
|
||||||
|
let __VLS_41;
|
||||||
|
let __VLS_42;
|
||||||
|
const __VLS_43 = {
|
||||||
|
onClick: (__VLS_ctx.handleRegenerate)
|
||||||
|
};
|
||||||
|
__VLS_39.slots.default;
|
||||||
|
var __VLS_39;
|
||||||
|
var __VLS_31;
|
||||||
|
const __VLS_44 = {}.ElDescriptionsItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElDescriptionsItem, typeof __VLS_components.elDescriptionsItem, typeof __VLS_components.ElDescriptionsItem, typeof __VLS_components.elDescriptionsItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_45 = __VLS_asFunctionalComponent(__VLS_44, new __VLS_44({
|
||||||
|
label: "文档数",
|
||||||
|
}));
|
||||||
|
const __VLS_46 = __VLS_45({
|
||||||
|
label: "文档数",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_45));
|
||||||
|
__VLS_47.slots.default;
|
||||||
|
(__VLS_ctx.docs.length);
|
||||||
|
var __VLS_47;
|
||||||
|
var __VLS_15;
|
||||||
|
var __VLS_11;
|
||||||
|
const __VLS_48 = {}.ElCard;
|
||||||
|
/** @type {[typeof __VLS_components.ElCard, typeof __VLS_components.elCard, typeof __VLS_components.ElCard, typeof __VLS_components.elCard, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_49 = __VLS_asFunctionalComponent(__VLS_48, new __VLS_48({}));
|
||||||
|
const __VLS_50 = __VLS_49({}, ...__VLS_functionalComponentArgsRest(__VLS_49));
|
||||||
|
__VLS_51.slots.default;
|
||||||
|
{
|
||||||
|
const { header: __VLS_thisSlot } = __VLS_51.slots;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
|
||||||
|
const __VLS_52 = {}.ElUpload;
|
||||||
|
/** @type {[typeof __VLS_components.ElUpload, typeof __VLS_components.elUpload, typeof __VLS_components.ElUpload, typeof __VLS_components.elUpload, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_53 = __VLS_asFunctionalComponent(__VLS_52, new __VLS_52({
|
||||||
|
showFileList: (false),
|
||||||
|
httpRequest: (__VLS_ctx.handleUpload),
|
||||||
|
accept: ".docx,.pdf",
|
||||||
|
}));
|
||||||
|
const __VLS_54 = __VLS_53({
|
||||||
|
showFileList: (false),
|
||||||
|
httpRequest: (__VLS_ctx.handleUpload),
|
||||||
|
accept: ".docx,.pdf",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_53));
|
||||||
|
__VLS_55.slots.default;
|
||||||
|
const __VLS_56 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_57 = __VLS_asFunctionalComponent(__VLS_56, new __VLS_56({
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.uploading),
|
||||||
|
}));
|
||||||
|
const __VLS_58 = __VLS_57({
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.uploading),
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_57));
|
||||||
|
__VLS_59.slots.default;
|
||||||
|
var __VLS_59;
|
||||||
|
var __VLS_55;
|
||||||
|
}
|
||||||
|
const __VLS_60 = {}.ElTable;
|
||||||
|
/** @type {[typeof __VLS_components.ElTable, typeof __VLS_components.elTable, typeof __VLS_components.ElTable, typeof __VLS_components.elTable, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_61 = __VLS_asFunctionalComponent(__VLS_60, new __VLS_60({
|
||||||
|
data: (__VLS_ctx.docs),
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_62 = __VLS_61({
|
||||||
|
data: (__VLS_ctx.docs),
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_61));
|
||||||
|
__VLS_asFunctionalDirective(__VLS_directives.vLoading)(null, { ...__VLS_directiveBindingRestFields, value: (__VLS_ctx.loading) }, null, null);
|
||||||
|
__VLS_63.slots.default;
|
||||||
|
const __VLS_64 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_65 = __VLS_asFunctionalComponent(__VLS_64, new __VLS_64({
|
||||||
|
prop: "original_filename",
|
||||||
|
label: "文件名",
|
||||||
|
minWidth: "200",
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
}));
|
||||||
|
const __VLS_66 = __VLS_65({
|
||||||
|
prop: "original_filename",
|
||||||
|
label: "文件名",
|
||||||
|
minWidth: "200",
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_65));
|
||||||
|
const __VLS_68 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_69 = __VLS_asFunctionalComponent(__VLS_68, new __VLS_68({
|
||||||
|
label: "状态",
|
||||||
|
width: "120",
|
||||||
|
align: "center",
|
||||||
|
}));
|
||||||
|
const __VLS_70 = __VLS_69({
|
||||||
|
label: "状态",
|
||||||
|
width: "120",
|
||||||
|
align: "center",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_69));
|
||||||
|
__VLS_71.slots.default;
|
||||||
|
{
|
||||||
|
const { default: __VLS_thisSlot } = __VLS_71.slots;
|
||||||
|
const [{ row }] = __VLS_getSlotParams(__VLS_thisSlot);
|
||||||
|
const __VLS_72 = {}.ElTag;
|
||||||
|
/** @type {[typeof __VLS_components.ElTag, typeof __VLS_components.elTag, typeof __VLS_components.ElTag, typeof __VLS_components.elTag, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_73 = __VLS_asFunctionalComponent(__VLS_72, new __VLS_72({
|
||||||
|
type: (__VLS_ctx.statusType(row.status)),
|
||||||
|
size: "small",
|
||||||
|
}));
|
||||||
|
const __VLS_74 = __VLS_73({
|
||||||
|
type: (__VLS_ctx.statusType(row.status)),
|
||||||
|
size: "small",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_73));
|
||||||
|
__VLS_75.slots.default;
|
||||||
|
(row.status);
|
||||||
|
var __VLS_75;
|
||||||
|
}
|
||||||
|
var __VLS_71;
|
||||||
|
const __VLS_76 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_77 = __VLS_asFunctionalComponent(__VLS_76, new __VLS_76({
|
||||||
|
label: "大小",
|
||||||
|
width: "100",
|
||||||
|
align: "center",
|
||||||
|
}));
|
||||||
|
const __VLS_78 = __VLS_77({
|
||||||
|
label: "大小",
|
||||||
|
width: "100",
|
||||||
|
align: "center",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_77));
|
||||||
|
__VLS_79.slots.default;
|
||||||
|
{
|
||||||
|
const { default: __VLS_thisSlot } = __VLS_79.slots;
|
||||||
|
const [{ row }] = __VLS_getSlotParams(__VLS_thisSlot);
|
||||||
|
(__VLS_ctx.formatSize(row.file_size));
|
||||||
|
}
|
||||||
|
var __VLS_79;
|
||||||
|
const __VLS_80 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_81 = __VLS_asFunctionalComponent(__VLS_80, new __VLS_80({
|
||||||
|
prop: "title",
|
||||||
|
label: "标题",
|
||||||
|
minWidth: "150",
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
}));
|
||||||
|
const __VLS_82 = __VLS_81({
|
||||||
|
prop: "title",
|
||||||
|
label: "标题",
|
||||||
|
minWidth: "150",
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_81));
|
||||||
|
const __VLS_84 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_85 = __VLS_asFunctionalComponent(__VLS_84, new __VLS_84({
|
||||||
|
prop: "keywords",
|
||||||
|
label: "关键词",
|
||||||
|
minWidth: "150",
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
}));
|
||||||
|
const __VLS_86 = __VLS_85({
|
||||||
|
prop: "keywords",
|
||||||
|
label: "关键词",
|
||||||
|
minWidth: "150",
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_85));
|
||||||
|
const __VLS_88 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_89 = __VLS_asFunctionalComponent(__VLS_88, new __VLS_88({
|
||||||
|
label: "操作",
|
||||||
|
width: "200",
|
||||||
|
align: "center",
|
||||||
|
}));
|
||||||
|
const __VLS_90 = __VLS_89({
|
||||||
|
label: "操作",
|
||||||
|
width: "200",
|
||||||
|
align: "center",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_89));
|
||||||
|
__VLS_91.slots.default;
|
||||||
|
{
|
||||||
|
const { default: __VLS_thisSlot } = __VLS_91.slots;
|
||||||
|
const [{ row }] = __VLS_getSlotParams(__VLS_thisSlot);
|
||||||
|
const __VLS_92 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_93 = __VLS_asFunctionalComponent(__VLS_92, new __VLS_92({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
}));
|
||||||
|
const __VLS_94 = __VLS_93({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_93));
|
||||||
|
let __VLS_96;
|
||||||
|
let __VLS_97;
|
||||||
|
let __VLS_98;
|
||||||
|
const __VLS_99 = {
|
||||||
|
onClick: (...[$event]) => {
|
||||||
|
if (!(__VLS_ctx.kb))
|
||||||
|
return;
|
||||||
|
__VLS_ctx.handleReprocess(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
__VLS_95.slots.default;
|
||||||
|
var __VLS_95;
|
||||||
|
const __VLS_100 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_101 = __VLS_asFunctionalComponent(__VLS_100, new __VLS_100({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
type: "danger",
|
||||||
|
}));
|
||||||
|
const __VLS_102 = __VLS_101({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
type: "danger",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_101));
|
||||||
|
let __VLS_104;
|
||||||
|
let __VLS_105;
|
||||||
|
let __VLS_106;
|
||||||
|
const __VLS_107 = {
|
||||||
|
onClick: (...[$event]) => {
|
||||||
|
if (!(__VLS_ctx.kb))
|
||||||
|
return;
|
||||||
|
__VLS_ctx.handleDeleteDoc(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
__VLS_103.slots.default;
|
||||||
|
var __VLS_103;
|
||||||
|
}
|
||||||
|
var __VLS_91;
|
||||||
|
var __VLS_63;
|
||||||
|
var __VLS_51;
|
||||||
|
}
|
||||||
var __VLS_dollars;
|
var __VLS_dollars;
|
||||||
const __VLS_self = (await import('vue')).defineComponent({
|
const __VLS_self = (await import('vue')).defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {
|
||||||
|
kb: kb,
|
||||||
|
docs: docs,
|
||||||
|
loading: loading,
|
||||||
|
uploading: uploading,
|
||||||
|
aiUrl: aiUrl,
|
||||||
|
handleUpload: handleUpload,
|
||||||
|
handleDeleteDoc: handleDeleteDoc,
|
||||||
|
handleReprocess: handleReprocess,
|
||||||
|
handleCopyLink: handleCopyLink,
|
||||||
|
handleRegenerate: handleRegenerate,
|
||||||
|
formatSize: formatSize,
|
||||||
|
statusType: statusType,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default (await import('vue')).defineComponent({
|
export default (await import('vue')).defineComponent({
|
||||||
|
|||||||
@@ -1,10 +1,120 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// Phase 4 实现知识库列表
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import apiClient from '@/api/client'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const kbs = ref<any[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const showCreate = ref(false)
|
||||||
|
const createForm = ref({ name: '', description: '' })
|
||||||
|
const createLoading = ref(false)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadKbs()
|
||||||
|
})
|
||||||
|
|
||||||
|
async function loadKbs() {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get('/knowledge-bases')
|
||||||
|
kbs.value = data.items
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCreate() {
|
||||||
|
if (!createForm.value.name.trim()) {
|
||||||
|
ElMessage.warning('请输入知识库名称。')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
createLoading.value = true
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.post('/knowledge-bases', createForm.value)
|
||||||
|
ElMessage.success('知识库创建成功!')
|
||||||
|
showCreate.value = false
|
||||||
|
createForm.value = { name: '', description: '' }
|
||||||
|
router.push(`/knowledge-bases/${data.id}`)
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
createLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete(kb: any) {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(`确定删除知识库「${kb.name}」?`, '确认删除', { type: 'warning' })
|
||||||
|
await apiClient.delete(`/knowledge-bases/${kb.id}`)
|
||||||
|
ElMessage.success('已删除。')
|
||||||
|
loadKbs()
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleToggle(kb: any) {
|
||||||
|
const action = kb.enabled ? 'disable' : 'enable'
|
||||||
|
await apiClient.post(`/knowledge-bases/${kb.id}/${action}`)
|
||||||
|
ElMessage.success(kb.enabled ? '已禁用。' : '已启用。')
|
||||||
|
loadKbs()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCopyLink(kb: any) {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get(`/knowledge-bases/${kb.id}/link`)
|
||||||
|
const url = `${window.location.origin}${data.ai_url}`
|
||||||
|
await navigator.clipboard.writeText(url)
|
||||||
|
ElMessage.success('AI 链接已复制到剪贴板!')
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h1>知识库</h1>
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px">
|
||||||
<p>知识库列表(Phase 4 实现)</p>
|
<h1 style="margin: 0">知识库</h1>
|
||||||
|
<el-button type="primary" @click="showCreate = true">创建知识库</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table :data="kbs" v-loading="loading" style="width: 100%">
|
||||||
|
<el-table-column prop="name" label="名称" min-width="200">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<router-link :to="`/knowledge-bases/${row.id}`" style="color: #409eff; text-decoration: none">
|
||||||
|
{{ row.name }}
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="document_count" label="文档数" width="100" align="center" />
|
||||||
|
<el-table-column label="状态" width="100" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="row.enabled ? 'success' : 'danger'" size="small">
|
||||||
|
{{ row.enabled ? '启用' : '禁用' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="300" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button size="small" @click="handleCopyLink(row)">复制链接</el-button>
|
||||||
|
<el-button size="small" @click="handleToggle(row)">
|
||||||
|
{{ row.enabled ? '禁用' : '启用' }}
|
||||||
|
</el-button>
|
||||||
|
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 创建对话框 -->
|
||||||
|
<el-dialog v-model="showCreate" title="创建知识库" width="500px">
|
||||||
|
<el-form :model="createForm" label-position="top">
|
||||||
|
<el-form-item label="名称" required>
|
||||||
|
<el-input v-model="createForm.name" placeholder="例如:公司知识库" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="描述">
|
||||||
|
<el-input v-model="createForm.description" type="textarea" :rows="3" placeholder="可选描述" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="showCreate = false">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="createLoading" @click="handleCreate">创建</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,14 +1,427 @@
|
|||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
import apiClient from '@/api/client';
|
||||||
|
const router = useRouter();
|
||||||
|
const kbs = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
const showCreate = ref(false);
|
||||||
|
const createForm = ref({ name: '', description: '' });
|
||||||
|
const createLoading = ref(false);
|
||||||
|
onMounted(() => {
|
||||||
|
loadKbs();
|
||||||
|
});
|
||||||
|
async function loadKbs() {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get('/knowledge-bases');
|
||||||
|
kbs.value = data.items;
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
async function handleCreate() {
|
||||||
|
if (!createForm.value.name.trim()) {
|
||||||
|
ElMessage.warning('请输入知识库名称。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
createLoading.value = true;
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.post('/knowledge-bases', createForm.value);
|
||||||
|
ElMessage.success('知识库创建成功!');
|
||||||
|
showCreate.value = false;
|
||||||
|
createForm.value = { name: '', description: '' };
|
||||||
|
router.push(`/knowledge-bases/${data.id}`);
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
createLoading.value = false;
|
||||||
|
}
|
||||||
|
async function handleDelete(kb) {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(`确定删除知识库「${kb.name}」?`, '确认删除', { type: 'warning' });
|
||||||
|
await apiClient.delete(`/knowledge-bases/${kb.id}`);
|
||||||
|
ElMessage.success('已删除。');
|
||||||
|
loadKbs();
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
async function handleToggle(kb) {
|
||||||
|
const action = kb.enabled ? 'disable' : 'enable';
|
||||||
|
await apiClient.post(`/knowledge-bases/${kb.id}/${action}`);
|
||||||
|
ElMessage.success(kb.enabled ? '已禁用。' : '已启用。');
|
||||||
|
loadKbs();
|
||||||
|
}
|
||||||
|
async function handleCopyLink(kb) {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get(`/knowledge-bases/${kb.id}/link`);
|
||||||
|
const url = `${window.location.origin}${data.ai_url}`;
|
||||||
|
await navigator.clipboard.writeText(url);
|
||||||
|
ElMessage.success('AI 链接已复制到剪贴板!');
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
||||||
const __VLS_ctx = {};
|
const __VLS_ctx = {};
|
||||||
let __VLS_components;
|
let __VLS_components;
|
||||||
let __VLS_directives;
|
let __VLS_directives;
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({});
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
const __VLS_0 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_1 = __VLS_asFunctionalComponent(__VLS_0, new __VLS_0({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "primary",
|
||||||
|
}));
|
||||||
|
const __VLS_2 = __VLS_1({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "primary",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_1));
|
||||||
|
let __VLS_4;
|
||||||
|
let __VLS_5;
|
||||||
|
let __VLS_6;
|
||||||
|
const __VLS_7 = {
|
||||||
|
onClick: (...[$event]) => {
|
||||||
|
__VLS_ctx.showCreate = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
__VLS_3.slots.default;
|
||||||
|
var __VLS_3;
|
||||||
|
const __VLS_8 = {}.ElTable;
|
||||||
|
/** @type {[typeof __VLS_components.ElTable, typeof __VLS_components.elTable, typeof __VLS_components.ElTable, typeof __VLS_components.elTable, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_9 = __VLS_asFunctionalComponent(__VLS_8, new __VLS_8({
|
||||||
|
data: (__VLS_ctx.kbs),
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_10 = __VLS_9({
|
||||||
|
data: (__VLS_ctx.kbs),
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_9));
|
||||||
|
__VLS_asFunctionalDirective(__VLS_directives.vLoading)(null, { ...__VLS_directiveBindingRestFields, value: (__VLS_ctx.loading) }, null, null);
|
||||||
|
__VLS_11.slots.default;
|
||||||
|
const __VLS_12 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_13 = __VLS_asFunctionalComponent(__VLS_12, new __VLS_12({
|
||||||
|
prop: "name",
|
||||||
|
label: "名称",
|
||||||
|
minWidth: "200",
|
||||||
|
}));
|
||||||
|
const __VLS_14 = __VLS_13({
|
||||||
|
prop: "name",
|
||||||
|
label: "名称",
|
||||||
|
minWidth: "200",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_13));
|
||||||
|
__VLS_15.slots.default;
|
||||||
|
{
|
||||||
|
const { default: __VLS_thisSlot } = __VLS_15.slots;
|
||||||
|
const [{ row }] = __VLS_getSlotParams(__VLS_thisSlot);
|
||||||
|
const __VLS_16 = {}.RouterLink;
|
||||||
|
/** @type {[typeof __VLS_components.RouterLink, typeof __VLS_components.routerLink, typeof __VLS_components.RouterLink, typeof __VLS_components.routerLink, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_17 = __VLS_asFunctionalComponent(__VLS_16, new __VLS_16({
|
||||||
|
to: (`/knowledge-bases/${row.id}`),
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_18 = __VLS_17({
|
||||||
|
to: (`/knowledge-bases/${row.id}`),
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_17));
|
||||||
|
__VLS_19.slots.default;
|
||||||
|
(row.name);
|
||||||
|
var __VLS_19;
|
||||||
|
}
|
||||||
|
var __VLS_15;
|
||||||
|
const __VLS_20 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_21 = __VLS_asFunctionalComponent(__VLS_20, new __VLS_20({
|
||||||
|
prop: "description",
|
||||||
|
label: "描述",
|
||||||
|
minWidth: "200",
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
}));
|
||||||
|
const __VLS_22 = __VLS_21({
|
||||||
|
prop: "description",
|
||||||
|
label: "描述",
|
||||||
|
minWidth: "200",
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_21));
|
||||||
|
const __VLS_24 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_25 = __VLS_asFunctionalComponent(__VLS_24, new __VLS_24({
|
||||||
|
prop: "document_count",
|
||||||
|
label: "文档数",
|
||||||
|
width: "100",
|
||||||
|
align: "center",
|
||||||
|
}));
|
||||||
|
const __VLS_26 = __VLS_25({
|
||||||
|
prop: "document_count",
|
||||||
|
label: "文档数",
|
||||||
|
width: "100",
|
||||||
|
align: "center",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_25));
|
||||||
|
const __VLS_28 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_29 = __VLS_asFunctionalComponent(__VLS_28, new __VLS_28({
|
||||||
|
label: "状态",
|
||||||
|
width: "100",
|
||||||
|
align: "center",
|
||||||
|
}));
|
||||||
|
const __VLS_30 = __VLS_29({
|
||||||
|
label: "状态",
|
||||||
|
width: "100",
|
||||||
|
align: "center",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_29));
|
||||||
|
__VLS_31.slots.default;
|
||||||
|
{
|
||||||
|
const { default: __VLS_thisSlot } = __VLS_31.slots;
|
||||||
|
const [{ row }] = __VLS_getSlotParams(__VLS_thisSlot);
|
||||||
|
const __VLS_32 = {}.ElTag;
|
||||||
|
/** @type {[typeof __VLS_components.ElTag, typeof __VLS_components.elTag, typeof __VLS_components.ElTag, typeof __VLS_components.elTag, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_33 = __VLS_asFunctionalComponent(__VLS_32, new __VLS_32({
|
||||||
|
type: (row.enabled ? 'success' : 'danger'),
|
||||||
|
size: "small",
|
||||||
|
}));
|
||||||
|
const __VLS_34 = __VLS_33({
|
||||||
|
type: (row.enabled ? 'success' : 'danger'),
|
||||||
|
size: "small",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_33));
|
||||||
|
__VLS_35.slots.default;
|
||||||
|
(row.enabled ? '启用' : '禁用');
|
||||||
|
var __VLS_35;
|
||||||
|
}
|
||||||
|
var __VLS_31;
|
||||||
|
const __VLS_36 = {}.ElTableColumn;
|
||||||
|
/** @type {[typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, typeof __VLS_components.ElTableColumn, typeof __VLS_components.elTableColumn, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_37 = __VLS_asFunctionalComponent(__VLS_36, new __VLS_36({
|
||||||
|
label: "操作",
|
||||||
|
width: "300",
|
||||||
|
align: "center",
|
||||||
|
}));
|
||||||
|
const __VLS_38 = __VLS_37({
|
||||||
|
label: "操作",
|
||||||
|
width: "300",
|
||||||
|
align: "center",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_37));
|
||||||
|
__VLS_39.slots.default;
|
||||||
|
{
|
||||||
|
const { default: __VLS_thisSlot } = __VLS_39.slots;
|
||||||
|
const [{ row }] = __VLS_getSlotParams(__VLS_thisSlot);
|
||||||
|
const __VLS_40 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_41 = __VLS_asFunctionalComponent(__VLS_40, new __VLS_40({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
}));
|
||||||
|
const __VLS_42 = __VLS_41({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_41));
|
||||||
|
let __VLS_44;
|
||||||
|
let __VLS_45;
|
||||||
|
let __VLS_46;
|
||||||
|
const __VLS_47 = {
|
||||||
|
onClick: (...[$event]) => {
|
||||||
|
__VLS_ctx.handleCopyLink(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
__VLS_43.slots.default;
|
||||||
|
var __VLS_43;
|
||||||
|
const __VLS_48 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_49 = __VLS_asFunctionalComponent(__VLS_48, new __VLS_48({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
}));
|
||||||
|
const __VLS_50 = __VLS_49({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_49));
|
||||||
|
let __VLS_52;
|
||||||
|
let __VLS_53;
|
||||||
|
let __VLS_54;
|
||||||
|
const __VLS_55 = {
|
||||||
|
onClick: (...[$event]) => {
|
||||||
|
__VLS_ctx.handleToggle(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
__VLS_51.slots.default;
|
||||||
|
(row.enabled ? '禁用' : '启用');
|
||||||
|
var __VLS_51;
|
||||||
|
const __VLS_56 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_57 = __VLS_asFunctionalComponent(__VLS_56, new __VLS_56({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
type: "danger",
|
||||||
|
}));
|
||||||
|
const __VLS_58 = __VLS_57({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
size: "small",
|
||||||
|
type: "danger",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_57));
|
||||||
|
let __VLS_60;
|
||||||
|
let __VLS_61;
|
||||||
|
let __VLS_62;
|
||||||
|
const __VLS_63 = {
|
||||||
|
onClick: (...[$event]) => {
|
||||||
|
__VLS_ctx.handleDelete(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
__VLS_59.slots.default;
|
||||||
|
var __VLS_59;
|
||||||
|
}
|
||||||
|
var __VLS_39;
|
||||||
|
var __VLS_11;
|
||||||
|
const __VLS_64 = {}.ElDialog;
|
||||||
|
/** @type {[typeof __VLS_components.ElDialog, typeof __VLS_components.elDialog, typeof __VLS_components.ElDialog, typeof __VLS_components.elDialog, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_65 = __VLS_asFunctionalComponent(__VLS_64, new __VLS_64({
|
||||||
|
modelValue: (__VLS_ctx.showCreate),
|
||||||
|
title: "创建知识库",
|
||||||
|
width: "500px",
|
||||||
|
}));
|
||||||
|
const __VLS_66 = __VLS_65({
|
||||||
|
modelValue: (__VLS_ctx.showCreate),
|
||||||
|
title: "创建知识库",
|
||||||
|
width: "500px",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_65));
|
||||||
|
__VLS_67.slots.default;
|
||||||
|
const __VLS_68 = {}.ElForm;
|
||||||
|
/** @type {[typeof __VLS_components.ElForm, typeof __VLS_components.elForm, typeof __VLS_components.ElForm, typeof __VLS_components.elForm, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_69 = __VLS_asFunctionalComponent(__VLS_68, new __VLS_68({
|
||||||
|
model: (__VLS_ctx.createForm),
|
||||||
|
labelPosition: "top",
|
||||||
|
}));
|
||||||
|
const __VLS_70 = __VLS_69({
|
||||||
|
model: (__VLS_ctx.createForm),
|
||||||
|
labelPosition: "top",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_69));
|
||||||
|
__VLS_71.slots.default;
|
||||||
|
const __VLS_72 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_73 = __VLS_asFunctionalComponent(__VLS_72, new __VLS_72({
|
||||||
|
label: "名称",
|
||||||
|
required: true,
|
||||||
|
}));
|
||||||
|
const __VLS_74 = __VLS_73({
|
||||||
|
label: "名称",
|
||||||
|
required: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_73));
|
||||||
|
__VLS_75.slots.default;
|
||||||
|
const __VLS_76 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_77 = __VLS_asFunctionalComponent(__VLS_76, new __VLS_76({
|
||||||
|
modelValue: (__VLS_ctx.createForm.name),
|
||||||
|
placeholder: "例如:公司知识库",
|
||||||
|
}));
|
||||||
|
const __VLS_78 = __VLS_77({
|
||||||
|
modelValue: (__VLS_ctx.createForm.name),
|
||||||
|
placeholder: "例如:公司知识库",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_77));
|
||||||
|
var __VLS_75;
|
||||||
|
const __VLS_80 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_81 = __VLS_asFunctionalComponent(__VLS_80, new __VLS_80({
|
||||||
|
label: "描述",
|
||||||
|
}));
|
||||||
|
const __VLS_82 = __VLS_81({
|
||||||
|
label: "描述",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_81));
|
||||||
|
__VLS_83.slots.default;
|
||||||
|
const __VLS_84 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_85 = __VLS_asFunctionalComponent(__VLS_84, new __VLS_84({
|
||||||
|
modelValue: (__VLS_ctx.createForm.description),
|
||||||
|
type: "textarea",
|
||||||
|
rows: (3),
|
||||||
|
placeholder: "可选描述",
|
||||||
|
}));
|
||||||
|
const __VLS_86 = __VLS_85({
|
||||||
|
modelValue: (__VLS_ctx.createForm.description),
|
||||||
|
type: "textarea",
|
||||||
|
rows: (3),
|
||||||
|
placeholder: "可选描述",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_85));
|
||||||
|
var __VLS_83;
|
||||||
|
var __VLS_71;
|
||||||
|
{
|
||||||
|
const { footer: __VLS_thisSlot } = __VLS_67.slots;
|
||||||
|
const __VLS_88 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_89 = __VLS_asFunctionalComponent(__VLS_88, new __VLS_88({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
}));
|
||||||
|
const __VLS_90 = __VLS_89({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_89));
|
||||||
|
let __VLS_92;
|
||||||
|
let __VLS_93;
|
||||||
|
let __VLS_94;
|
||||||
|
const __VLS_95 = {
|
||||||
|
onClick: (...[$event]) => {
|
||||||
|
__VLS_ctx.showCreate = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
__VLS_91.slots.default;
|
||||||
|
var __VLS_91;
|
||||||
|
const __VLS_96 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_97 = __VLS_asFunctionalComponent(__VLS_96, new __VLS_96({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.createLoading),
|
||||||
|
}));
|
||||||
|
const __VLS_98 = __VLS_97({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.createLoading),
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_97));
|
||||||
|
let __VLS_100;
|
||||||
|
let __VLS_101;
|
||||||
|
let __VLS_102;
|
||||||
|
const __VLS_103 = {
|
||||||
|
onClick: (__VLS_ctx.handleCreate)
|
||||||
|
};
|
||||||
|
__VLS_99.slots.default;
|
||||||
|
var __VLS_99;
|
||||||
|
}
|
||||||
|
var __VLS_67;
|
||||||
var __VLS_dollars;
|
var __VLS_dollars;
|
||||||
const __VLS_self = (await import('vue')).defineComponent({
|
const __VLS_self = (await import('vue')).defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {
|
||||||
|
kbs: kbs,
|
||||||
|
loading: loading,
|
||||||
|
showCreate: showCreate,
|
||||||
|
createForm: createForm,
|
||||||
|
createLoading: createLoading,
|
||||||
|
handleCreate: handleCreate,
|
||||||
|
handleDelete: handleDelete,
|
||||||
|
handleToggle: handleToggle,
|
||||||
|
handleCopyLink: handleCopyLink,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default (await import('vue')).defineComponent({
|
export default (await import('vue')).defineComponent({
|
||||||
|
|||||||
@@ -1,14 +1,54 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// Phase 3 实现登录逻辑
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import apiClient from '@/api/client'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
username_or_email: '',
|
||||||
|
password: '',
|
||||||
|
})
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
async function handleLogin() {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.post('/auth/login', form.value)
|
||||||
|
userStore.setUser(data)
|
||||||
|
router.push('/')
|
||||||
|
} catch {
|
||||||
|
// 错误由拦截器处理
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="login-page">
|
<div class="login-page">
|
||||||
<el-card class="login-card">
|
<el-card class="login-card">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h2>AI Knowledge Link</h2>
|
<h2 style="text-align: center; margin: 0">AI Knowledge Link</h2>
|
||||||
</template>
|
</template>
|
||||||
<p>登录页面(Phase 3 实现)</p>
|
<el-form :model="form" label-position="top" @submit.prevent="handleLogin">
|
||||||
|
<el-form-item label="用户名或邮箱">
|
||||||
|
<el-input v-model="form.username_or_email" placeholder="请输入用户名或邮箱" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码">
|
||||||
|
<el-input v-model="form.password" type="password" placeholder="请输入密码" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :loading="loading" style="width: 100%" native-type="submit">
|
||||||
|
登录
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div style="text-align: center">
|
||||||
|
<router-link to="/register">没有账号?立即注册</router-link>
|
||||||
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,3 +1,28 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useUserStore } from '@/stores/user';
|
||||||
|
import apiClient from '@/api/client';
|
||||||
|
const router = useRouter();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const form = ref({
|
||||||
|
username_or_email: '',
|
||||||
|
password: '',
|
||||||
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
async function handleLogin() {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.post('/auth/login', form.value);
|
||||||
|
userStore.setUser(data);
|
||||||
|
router.push('/');
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// 错误由拦截器处理
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
||||||
const __VLS_ctx = {};
|
const __VLS_ctx = {};
|
||||||
let __VLS_components;
|
let __VLS_components;
|
||||||
@@ -19,16 +44,128 @@ const __VLS_2 = __VLS_1({
|
|||||||
__VLS_3.slots.default;
|
__VLS_3.slots.default;
|
||||||
{
|
{
|
||||||
const { header: __VLS_thisSlot } = __VLS_3.slots;
|
const { header: __VLS_thisSlot } = __VLS_3.slots;
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({});
|
const __VLS_4 = {}.ElForm;
|
||||||
|
/** @type {[typeof __VLS_components.ElForm, typeof __VLS_components.elForm, typeof __VLS_components.ElForm, typeof __VLS_components.elForm, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_5 = __VLS_asFunctionalComponent(__VLS_4, new __VLS_4({
|
||||||
|
...{ 'onSubmit': {} },
|
||||||
|
model: (__VLS_ctx.form),
|
||||||
|
labelPosition: "top",
|
||||||
|
}));
|
||||||
|
const __VLS_6 = __VLS_5({
|
||||||
|
...{ 'onSubmit': {} },
|
||||||
|
model: (__VLS_ctx.form),
|
||||||
|
labelPosition: "top",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_5));
|
||||||
|
let __VLS_8;
|
||||||
|
let __VLS_9;
|
||||||
|
let __VLS_10;
|
||||||
|
const __VLS_11 = {
|
||||||
|
onSubmit: (__VLS_ctx.handleLogin)
|
||||||
|
};
|
||||||
|
__VLS_7.slots.default;
|
||||||
|
const __VLS_12 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_13 = __VLS_asFunctionalComponent(__VLS_12, new __VLS_12({
|
||||||
|
label: "用户名或邮箱",
|
||||||
|
}));
|
||||||
|
const __VLS_14 = __VLS_13({
|
||||||
|
label: "用户名或邮箱",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_13));
|
||||||
|
__VLS_15.slots.default;
|
||||||
|
const __VLS_16 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_17 = __VLS_asFunctionalComponent(__VLS_16, new __VLS_16({
|
||||||
|
modelValue: (__VLS_ctx.form.username_or_email),
|
||||||
|
placeholder: "请输入用户名或邮箱",
|
||||||
|
}));
|
||||||
|
const __VLS_18 = __VLS_17({
|
||||||
|
modelValue: (__VLS_ctx.form.username_or_email),
|
||||||
|
placeholder: "请输入用户名或邮箱",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_17));
|
||||||
|
var __VLS_15;
|
||||||
|
const __VLS_20 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_21 = __VLS_asFunctionalComponent(__VLS_20, new __VLS_20({
|
||||||
|
label: "密码",
|
||||||
|
}));
|
||||||
|
const __VLS_22 = __VLS_21({
|
||||||
|
label: "密码",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_21));
|
||||||
|
__VLS_23.slots.default;
|
||||||
|
const __VLS_24 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_25 = __VLS_asFunctionalComponent(__VLS_24, new __VLS_24({
|
||||||
|
modelValue: (__VLS_ctx.form.password),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "请输入密码",
|
||||||
|
showPassword: true,
|
||||||
|
}));
|
||||||
|
const __VLS_26 = __VLS_25({
|
||||||
|
modelValue: (__VLS_ctx.form.password),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "请输入密码",
|
||||||
|
showPassword: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_25));
|
||||||
|
var __VLS_23;
|
||||||
|
const __VLS_28 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_29 = __VLS_asFunctionalComponent(__VLS_28, new __VLS_28({}));
|
||||||
|
const __VLS_30 = __VLS_29({}, ...__VLS_functionalComponentArgsRest(__VLS_29));
|
||||||
|
__VLS_31.slots.default;
|
||||||
|
const __VLS_32 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_33 = __VLS_asFunctionalComponent(__VLS_32, new __VLS_32({
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.loading),
|
||||||
|
...{ style: {} },
|
||||||
|
nativeType: "submit",
|
||||||
|
}));
|
||||||
|
const __VLS_34 = __VLS_33({
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.loading),
|
||||||
|
...{ style: {} },
|
||||||
|
nativeType: "submit",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_33));
|
||||||
|
__VLS_35.slots.default;
|
||||||
|
var __VLS_35;
|
||||||
|
var __VLS_31;
|
||||||
|
var __VLS_7;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
const __VLS_36 = {}.RouterLink;
|
||||||
|
/** @type {[typeof __VLS_components.RouterLink, typeof __VLS_components.routerLink, typeof __VLS_components.RouterLink, typeof __VLS_components.routerLink, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_37 = __VLS_asFunctionalComponent(__VLS_36, new __VLS_36({
|
||||||
|
to: "/register",
|
||||||
|
}));
|
||||||
|
const __VLS_38 = __VLS_37({
|
||||||
|
to: "/register",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_37));
|
||||||
|
__VLS_39.slots.default;
|
||||||
|
var __VLS_39;
|
||||||
var __VLS_3;
|
var __VLS_3;
|
||||||
/** @type {__VLS_StyleScopedClasses['login-page']} */ ;
|
/** @type {__VLS_StyleScopedClasses['login-page']} */ ;
|
||||||
/** @type {__VLS_StyleScopedClasses['login-card']} */ ;
|
/** @type {__VLS_StyleScopedClasses['login-card']} */ ;
|
||||||
var __VLS_dollars;
|
var __VLS_dollars;
|
||||||
const __VLS_self = (await import('vue')).defineComponent({
|
const __VLS_self = (await import('vue')).defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {
|
||||||
|
form: form,
|
||||||
|
loading: loading,
|
||||||
|
handleLogin: handleLogin,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default (await import('vue')).defineComponent({
|
export default (await import('vue')).defineComponent({
|
||||||
|
|||||||
@@ -1,14 +1,72 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// Phase 3 实现注册逻辑
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import apiClient from '@/api/client'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
username: '',
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
})
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
async function handleRegister() {
|
||||||
|
if (form.value.password !== form.value.confirmPassword) {
|
||||||
|
ElMessage.error('两次输入的密码不一致。')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.post('/auth/register', {
|
||||||
|
username: form.value.username,
|
||||||
|
email: form.value.email,
|
||||||
|
password: form.value.password,
|
||||||
|
})
|
||||||
|
userStore.setUser(data)
|
||||||
|
router.push('/')
|
||||||
|
} catch {
|
||||||
|
// 错误由拦截器处理
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="register-page">
|
<div class="register-page">
|
||||||
<el-card class="register-card">
|
<el-card class="register-card">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h2>注册</h2>
|
<h2 style="text-align: center; margin: 0">注册</h2>
|
||||||
</template>
|
</template>
|
||||||
<p>注册页面(Phase 3 实现)</p>
|
<el-form :model="form" label-position="top" @submit.prevent="handleRegister">
|
||||||
|
<el-form-item label="用户名">
|
||||||
|
<el-input v-model="form.username" placeholder="2-32 位字母、数字、下划线" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="邮箱">
|
||||||
|
<el-input v-model="form.email" placeholder="your@email.com" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码">
|
||||||
|
<el-input v-model="form.password" type="password" placeholder="至少 8 位" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="确认密码">
|
||||||
|
<el-input v-model="form.confirmPassword" type="password" placeholder="再次输入密码" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :loading="loading" style="width: 100%" native-type="submit">
|
||||||
|
注册
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div style="text-align: center">
|
||||||
|
<router-link to="/login">已有账号?立即登录</router-link>
|
||||||
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,3 +1,39 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useUserStore } from '@/stores/user';
|
||||||
|
import apiClient from '@/api/client';
|
||||||
|
const router = useRouter();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const form = ref({
|
||||||
|
username: '',
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
async function handleRegister() {
|
||||||
|
if (form.value.password !== form.value.confirmPassword) {
|
||||||
|
ElMessage.error('两次输入的密码不一致。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.post('/auth/register', {
|
||||||
|
username: form.value.username,
|
||||||
|
email: form.value.email,
|
||||||
|
password: form.value.password,
|
||||||
|
});
|
||||||
|
userStore.setUser(data);
|
||||||
|
router.push('/');
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// 错误由拦截器处理
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
||||||
const __VLS_ctx = {};
|
const __VLS_ctx = {};
|
||||||
let __VLS_components;
|
let __VLS_components;
|
||||||
@@ -19,16 +55,176 @@ const __VLS_2 = __VLS_1({
|
|||||||
__VLS_3.slots.default;
|
__VLS_3.slots.default;
|
||||||
{
|
{
|
||||||
const { header: __VLS_thisSlot } = __VLS_3.slots;
|
const { header: __VLS_thisSlot } = __VLS_3.slots;
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({});
|
const __VLS_4 = {}.ElForm;
|
||||||
|
/** @type {[typeof __VLS_components.ElForm, typeof __VLS_components.elForm, typeof __VLS_components.ElForm, typeof __VLS_components.elForm, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_5 = __VLS_asFunctionalComponent(__VLS_4, new __VLS_4({
|
||||||
|
...{ 'onSubmit': {} },
|
||||||
|
model: (__VLS_ctx.form),
|
||||||
|
labelPosition: "top",
|
||||||
|
}));
|
||||||
|
const __VLS_6 = __VLS_5({
|
||||||
|
...{ 'onSubmit': {} },
|
||||||
|
model: (__VLS_ctx.form),
|
||||||
|
labelPosition: "top",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_5));
|
||||||
|
let __VLS_8;
|
||||||
|
let __VLS_9;
|
||||||
|
let __VLS_10;
|
||||||
|
const __VLS_11 = {
|
||||||
|
onSubmit: (__VLS_ctx.handleRegister)
|
||||||
|
};
|
||||||
|
__VLS_7.slots.default;
|
||||||
|
const __VLS_12 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_13 = __VLS_asFunctionalComponent(__VLS_12, new __VLS_12({
|
||||||
|
label: "用户名",
|
||||||
|
}));
|
||||||
|
const __VLS_14 = __VLS_13({
|
||||||
|
label: "用户名",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_13));
|
||||||
|
__VLS_15.slots.default;
|
||||||
|
const __VLS_16 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_17 = __VLS_asFunctionalComponent(__VLS_16, new __VLS_16({
|
||||||
|
modelValue: (__VLS_ctx.form.username),
|
||||||
|
placeholder: "2-32 位字母、数字、下划线",
|
||||||
|
}));
|
||||||
|
const __VLS_18 = __VLS_17({
|
||||||
|
modelValue: (__VLS_ctx.form.username),
|
||||||
|
placeholder: "2-32 位字母、数字、下划线",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_17));
|
||||||
|
var __VLS_15;
|
||||||
|
const __VLS_20 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_21 = __VLS_asFunctionalComponent(__VLS_20, new __VLS_20({
|
||||||
|
label: "邮箱",
|
||||||
|
}));
|
||||||
|
const __VLS_22 = __VLS_21({
|
||||||
|
label: "邮箱",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_21));
|
||||||
|
__VLS_23.slots.default;
|
||||||
|
const __VLS_24 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_25 = __VLS_asFunctionalComponent(__VLS_24, new __VLS_24({
|
||||||
|
modelValue: (__VLS_ctx.form.email),
|
||||||
|
placeholder: "your@email.com",
|
||||||
|
}));
|
||||||
|
const __VLS_26 = __VLS_25({
|
||||||
|
modelValue: (__VLS_ctx.form.email),
|
||||||
|
placeholder: "your@email.com",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_25));
|
||||||
|
var __VLS_23;
|
||||||
|
const __VLS_28 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_29 = __VLS_asFunctionalComponent(__VLS_28, new __VLS_28({
|
||||||
|
label: "密码",
|
||||||
|
}));
|
||||||
|
const __VLS_30 = __VLS_29({
|
||||||
|
label: "密码",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_29));
|
||||||
|
__VLS_31.slots.default;
|
||||||
|
const __VLS_32 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_33 = __VLS_asFunctionalComponent(__VLS_32, new __VLS_32({
|
||||||
|
modelValue: (__VLS_ctx.form.password),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "至少 8 位",
|
||||||
|
showPassword: true,
|
||||||
|
}));
|
||||||
|
const __VLS_34 = __VLS_33({
|
||||||
|
modelValue: (__VLS_ctx.form.password),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "至少 8 位",
|
||||||
|
showPassword: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_33));
|
||||||
|
var __VLS_31;
|
||||||
|
const __VLS_36 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_37 = __VLS_asFunctionalComponent(__VLS_36, new __VLS_36({
|
||||||
|
label: "确认密码",
|
||||||
|
}));
|
||||||
|
const __VLS_38 = __VLS_37({
|
||||||
|
label: "确认密码",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_37));
|
||||||
|
__VLS_39.slots.default;
|
||||||
|
const __VLS_40 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_41 = __VLS_asFunctionalComponent(__VLS_40, new __VLS_40({
|
||||||
|
modelValue: (__VLS_ctx.form.confirmPassword),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "再次输入密码",
|
||||||
|
showPassword: true,
|
||||||
|
}));
|
||||||
|
const __VLS_42 = __VLS_41({
|
||||||
|
modelValue: (__VLS_ctx.form.confirmPassword),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "再次输入密码",
|
||||||
|
showPassword: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_41));
|
||||||
|
var __VLS_39;
|
||||||
|
const __VLS_44 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_45 = __VLS_asFunctionalComponent(__VLS_44, new __VLS_44({}));
|
||||||
|
const __VLS_46 = __VLS_45({}, ...__VLS_functionalComponentArgsRest(__VLS_45));
|
||||||
|
__VLS_47.slots.default;
|
||||||
|
const __VLS_48 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_49 = __VLS_asFunctionalComponent(__VLS_48, new __VLS_48({
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.loading),
|
||||||
|
...{ style: {} },
|
||||||
|
nativeType: "submit",
|
||||||
|
}));
|
||||||
|
const __VLS_50 = __VLS_49({
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.loading),
|
||||||
|
...{ style: {} },
|
||||||
|
nativeType: "submit",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_49));
|
||||||
|
__VLS_51.slots.default;
|
||||||
|
var __VLS_51;
|
||||||
|
var __VLS_47;
|
||||||
|
var __VLS_7;
|
||||||
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
|
||||||
|
...{ style: {} },
|
||||||
|
});
|
||||||
|
const __VLS_52 = {}.RouterLink;
|
||||||
|
/** @type {[typeof __VLS_components.RouterLink, typeof __VLS_components.routerLink, typeof __VLS_components.RouterLink, typeof __VLS_components.routerLink, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_53 = __VLS_asFunctionalComponent(__VLS_52, new __VLS_52({
|
||||||
|
to: "/login",
|
||||||
|
}));
|
||||||
|
const __VLS_54 = __VLS_53({
|
||||||
|
to: "/login",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_53));
|
||||||
|
__VLS_55.slots.default;
|
||||||
|
var __VLS_55;
|
||||||
var __VLS_3;
|
var __VLS_3;
|
||||||
/** @type {__VLS_StyleScopedClasses['register-page']} */ ;
|
/** @type {__VLS_StyleScopedClasses['register-page']} */ ;
|
||||||
/** @type {__VLS_StyleScopedClasses['register-card']} */ ;
|
/** @type {__VLS_StyleScopedClasses['register-card']} */ ;
|
||||||
var __VLS_dollars;
|
var __VLS_dollars;
|
||||||
const __VLS_self = (await import('vue')).defineComponent({
|
const __VLS_self = (await import('vue')).defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {
|
||||||
|
form: form,
|
||||||
|
loading: loading,
|
||||||
|
handleRegister: handleRegister,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default (await import('vue')).defineComponent({
|
export default (await import('vue')).defineComponent({
|
||||||
|
|||||||
@@ -1,10 +1,49 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// Phase 14 实现设置页
|
import { ref } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import apiClient from '@/api/client'
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
})
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
async function handleChangePassword() {
|
||||||
|
if (form.value.password !== form.value.confirmPassword) {
|
||||||
|
ElMessage.error('两次输入的密码不一致。')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (form.value.password.length < 8) {
|
||||||
|
ElMessage.error('密码长度不能少于 8 位。')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
await apiClient.patch('/auth/me', { password: form.value.password })
|
||||||
|
ElMessage.success('密码修改成功。')
|
||||||
|
form.value = { password: '', confirmPassword: '' }
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h1>设置</h1>
|
<h1>设置</h1>
|
||||||
<p>设置页面(Phase 14 实现)</p>
|
<el-card>
|
||||||
|
<template #header>修改密码</template>
|
||||||
|
<el-form :model="form" label-position="top" style="max-width: 400px">
|
||||||
|
<el-form-item label="新密码">
|
||||||
|
<el-input v-model="form.password" type="password" placeholder="至少 8 位" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="确认新密码">
|
||||||
|
<el-input v-model="form.confirmPassword" type="password" placeholder="再次输入新密码" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :loading="loading" @click="handleChangePassword">修改密码</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,14 +1,148 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import apiClient from '@/api/client';
|
||||||
|
const form = ref({
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
async function handleChangePassword() {
|
||||||
|
if (form.value.password !== form.value.confirmPassword) {
|
||||||
|
ElMessage.error('两次输入的密码不一致。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (form.value.password.length < 8) {
|
||||||
|
ElMessage.error('密码长度不能少于 8 位。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
await apiClient.patch('/auth/me', { password: form.value.password });
|
||||||
|
ElMessage.success('密码修改成功。');
|
||||||
|
form.value = { password: '', confirmPassword: '' };
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
|
||||||
const __VLS_ctx = {};
|
const __VLS_ctx = {};
|
||||||
let __VLS_components;
|
let __VLS_components;
|
||||||
let __VLS_directives;
|
let __VLS_directives;
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({});
|
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({});
|
||||||
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({});
|
const __VLS_0 = {}.ElCard;
|
||||||
|
/** @type {[typeof __VLS_components.ElCard, typeof __VLS_components.elCard, typeof __VLS_components.ElCard, typeof __VLS_components.elCard, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_1 = __VLS_asFunctionalComponent(__VLS_0, new __VLS_0({}));
|
||||||
|
const __VLS_2 = __VLS_1({}, ...__VLS_functionalComponentArgsRest(__VLS_1));
|
||||||
|
__VLS_3.slots.default;
|
||||||
|
{
|
||||||
|
const { header: __VLS_thisSlot } = __VLS_3.slots;
|
||||||
|
}
|
||||||
|
const __VLS_4 = {}.ElForm;
|
||||||
|
/** @type {[typeof __VLS_components.ElForm, typeof __VLS_components.elForm, typeof __VLS_components.ElForm, typeof __VLS_components.elForm, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_5 = __VLS_asFunctionalComponent(__VLS_4, new __VLS_4({
|
||||||
|
model: (__VLS_ctx.form),
|
||||||
|
labelPosition: "top",
|
||||||
|
...{ style: {} },
|
||||||
|
}));
|
||||||
|
const __VLS_6 = __VLS_5({
|
||||||
|
model: (__VLS_ctx.form),
|
||||||
|
labelPosition: "top",
|
||||||
|
...{ style: {} },
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_5));
|
||||||
|
__VLS_7.slots.default;
|
||||||
|
const __VLS_8 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_9 = __VLS_asFunctionalComponent(__VLS_8, new __VLS_8({
|
||||||
|
label: "新密码",
|
||||||
|
}));
|
||||||
|
const __VLS_10 = __VLS_9({
|
||||||
|
label: "新密码",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_9));
|
||||||
|
__VLS_11.slots.default;
|
||||||
|
const __VLS_12 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_13 = __VLS_asFunctionalComponent(__VLS_12, new __VLS_12({
|
||||||
|
modelValue: (__VLS_ctx.form.password),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "至少 8 位",
|
||||||
|
showPassword: true,
|
||||||
|
}));
|
||||||
|
const __VLS_14 = __VLS_13({
|
||||||
|
modelValue: (__VLS_ctx.form.password),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "至少 8 位",
|
||||||
|
showPassword: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_13));
|
||||||
|
var __VLS_11;
|
||||||
|
const __VLS_16 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_17 = __VLS_asFunctionalComponent(__VLS_16, new __VLS_16({
|
||||||
|
label: "确认新密码",
|
||||||
|
}));
|
||||||
|
const __VLS_18 = __VLS_17({
|
||||||
|
label: "确认新密码",
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_17));
|
||||||
|
__VLS_19.slots.default;
|
||||||
|
const __VLS_20 = {}.ElInput;
|
||||||
|
/** @type {[typeof __VLS_components.ElInput, typeof __VLS_components.elInput, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_21 = __VLS_asFunctionalComponent(__VLS_20, new __VLS_20({
|
||||||
|
modelValue: (__VLS_ctx.form.confirmPassword),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "再次输入新密码",
|
||||||
|
showPassword: true,
|
||||||
|
}));
|
||||||
|
const __VLS_22 = __VLS_21({
|
||||||
|
modelValue: (__VLS_ctx.form.confirmPassword),
|
||||||
|
type: "password",
|
||||||
|
placeholder: "再次输入新密码",
|
||||||
|
showPassword: true,
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_21));
|
||||||
|
var __VLS_19;
|
||||||
|
const __VLS_24 = {}.ElFormItem;
|
||||||
|
/** @type {[typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, typeof __VLS_components.ElFormItem, typeof __VLS_components.elFormItem, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_25 = __VLS_asFunctionalComponent(__VLS_24, new __VLS_24({}));
|
||||||
|
const __VLS_26 = __VLS_25({}, ...__VLS_functionalComponentArgsRest(__VLS_25));
|
||||||
|
__VLS_27.slots.default;
|
||||||
|
const __VLS_28 = {}.ElButton;
|
||||||
|
/** @type {[typeof __VLS_components.ElButton, typeof __VLS_components.elButton, typeof __VLS_components.ElButton, typeof __VLS_components.elButton, ]} */ ;
|
||||||
|
// @ts-ignore
|
||||||
|
const __VLS_29 = __VLS_asFunctionalComponent(__VLS_28, new __VLS_28({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.loading),
|
||||||
|
}));
|
||||||
|
const __VLS_30 = __VLS_29({
|
||||||
|
...{ 'onClick': {} },
|
||||||
|
type: "primary",
|
||||||
|
loading: (__VLS_ctx.loading),
|
||||||
|
}, ...__VLS_functionalComponentArgsRest(__VLS_29));
|
||||||
|
let __VLS_32;
|
||||||
|
let __VLS_33;
|
||||||
|
let __VLS_34;
|
||||||
|
const __VLS_35 = {
|
||||||
|
onClick: (__VLS_ctx.handleChangePassword)
|
||||||
|
};
|
||||||
|
__VLS_31.slots.default;
|
||||||
|
var __VLS_31;
|
||||||
|
var __VLS_27;
|
||||||
|
var __VLS_7;
|
||||||
|
var __VLS_3;
|
||||||
var __VLS_dollars;
|
var __VLS_dollars;
|
||||||
const __VLS_self = (await import('vue')).defineComponent({
|
const __VLS_self = (await import('vue')).defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {
|
||||||
|
form: form,
|
||||||
|
loading: loading,
|
||||||
|
handleChangePassword: handleChangePassword,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default (await import('vue')).defineComponent({
|
export default (await import('vue')).defineComponent({
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"root":["./src/env.d.ts","./src/main.ts","./src/api/client.ts","./src/router/index.ts","./src/stores/user.ts","./src/app.vue","./src/views/dashboard.vue","./src/views/kbdetail.vue","./src/views/knowledgebases.vue","./src/views/login.vue","./src/views/register.vue","./src/views/settings.vue"],"version":"5.9.3"}
|
{"root":["./src/env.d.ts","./src/main.ts","./src/api/client.ts","./src/router/index.ts","./src/stores/user.ts","./src/app.vue","./src/layouts/defaultlayout.vue","./src/views/dashboard.vue","./src/views/kbdetail.vue","./src/views/knowledgebases.vue","./src/views/login.vue","./src/views/register.vue","./src/views/settings.vue"],"version":"5.9.3"}
|
||||||
Reference in New Issue
Block a user