1
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import axios from 'axios'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useAuthStore } from '../stores/auth.js'
|
||||
|
||||
const request = axios.create({
|
||||
timeout: 300000
|
||||
@@ -14,6 +15,10 @@ request.interceptors.request.use(config => {
|
||||
})
|
||||
|
||||
function redirectLogin() {
|
||||
// 同时清空 Pinia store,否则路由守卫仍视为已登录,会拦回首页形成死循环
|
||||
try {
|
||||
useAuthStore().logout()
|
||||
} catch { /* store 未初始化时忽略 */ }
|
||||
localStorage.removeItem('token')
|
||||
window.location.href = '/#/login'
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ const msgBox = ref(null)
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
datasets.value = await listDatasets()
|
||||
const d = await listDatasets()
|
||||
if (d && d.list) datasets.value = d.list
|
||||
if (datasets.value.length && !datasetId.value) {
|
||||
datasetId.value = datasets.value[0].id
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ArrowLeft, UploadFilled } from '@element-plus/icons-vue'
|
||||
@@ -123,21 +123,12 @@ function formatSize(bytes) {
|
||||
return (bytes / 1024 / 1024).toFixed(1) + ' MB'
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const ds = await listDatasets()
|
||||
const cur = ds.find(x => x.id === datasetId.value)
|
||||
datasetName.value = cur ? cur.name : '数据集'
|
||||
} catch { /* 忽略 */ }
|
||||
await load()
|
||||
})
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const d = await listDocuments({ dataset_id: datasetId.value, page: page.value, page_size: pageSize })
|
||||
documents.value = d.list
|
||||
total.value = d.total
|
||||
documents.value = d.list || []
|
||||
total.value = d.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -152,11 +143,39 @@ async function doUpload({ file }) {
|
||||
await uploadDocument(formData)
|
||||
ElMessage.success('上传成功,正在解析')
|
||||
await load()
|
||||
startPolling()
|
||||
} finally {
|
||||
uploading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 有待处理/解析中的文档时轮询刷新状态,全部完成即停止
|
||||
let pollTimer = null
|
||||
async function startPolling() {
|
||||
stopPolling()
|
||||
pollTimer = setInterval(async () => {
|
||||
await load()
|
||||
if (!documents.value.some(d => d.status === 0 || d.status === 1)) stopPolling()
|
||||
}, 3000)
|
||||
}
|
||||
function stopPolling() {
|
||||
if (pollTimer) {
|
||||
clearInterval(pollTimer)
|
||||
pollTimer = null
|
||||
}
|
||||
}
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const dsRes = await listDatasets()
|
||||
const ds = dsRes && dsRes.list ? dsRes.list : []
|
||||
const cur = ds.find(x => x.id === datasetId.value)
|
||||
datasetName.value = cur ? cur.name : '数据集'
|
||||
} catch { /* 忽略 */ }
|
||||
await load()
|
||||
if (documents.value.some(d => d.status === 0 || d.status === 1)) startPolling()
|
||||
})
|
||||
onUnmounted(stopPolling)
|
||||
|
||||
async function remove(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`删除文档「${row.filename}」?将同时删除分块、向量与全文索引。`, '删除确认', { type: 'warning' })
|
||||
|
||||
@@ -60,14 +60,16 @@ const form = ref({ id: 0, name: '', description: '', embedding_cfg_id: 0 })
|
||||
onMounted(async () => {
|
||||
await load()
|
||||
try {
|
||||
embedders.value = await listModelConfigs('embedding')
|
||||
const m = await listModelConfigs('embedding')
|
||||
if (m && m.list) embedders.value = m.list
|
||||
} catch { /* 忽略 */ }
|
||||
})
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
datasets.value = await listDatasets()
|
||||
const d = await listDatasets()
|
||||
if (d && d.list) datasets.value = d.list
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ const relationPageSize = 20
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
datasets.value = await listDatasets()
|
||||
const d = await listDatasets()
|
||||
if (d && d.list) datasets.value = d.list
|
||||
if (datasets.value.length) datasetId.value = datasets.value[0].id
|
||||
} catch { /* 忽略 */ }
|
||||
await load()
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="模型名" required>
|
||||
<el-input v-model="modelForm.model_name" placeholder="如:qwen2.5:7b" />
|
||||
<el-input v-model="modelForm.model_name" placeholder="如:qwen2.5:7b" @change="inheritFromExisting" />
|
||||
</el-form-item>
|
||||
<el-form-item label="接口地址">
|
||||
<el-input v-model="modelForm.endpoint_url" placeholder="如:http://localhost:11434/v1" />
|
||||
@@ -104,6 +104,7 @@ import { getSystemConfig, updateSystemConfig, regenerateToken, getToken } from '
|
||||
const tab = ref('models')
|
||||
const modelType = ref('chat')
|
||||
const models = ref([])
|
||||
const allModels = ref([])
|
||||
const modelLoading = ref(false)
|
||||
const testingId = ref(0)
|
||||
const chatModels = ref([])
|
||||
@@ -121,10 +122,11 @@ const tokenRegenerating = ref(false)
|
||||
|
||||
onMounted(async () => {
|
||||
await loadModels()
|
||||
try { chatModels.value = await listModelConfigs('chat') } catch { /* 忽略 */ }
|
||||
try { const all = await listModelConfigs(''); if (all && all.list) allModels.value = all.list } catch { /* 忽略 */ }
|
||||
try { const m = await listModelConfigs('chat'); if (m && m.list) chatModels.value = m.list } catch { /* 忽略 */ }
|
||||
try {
|
||||
const d = await listDatasets()
|
||||
datasets.value = d
|
||||
if (d && d.list) datasets.value = d.list
|
||||
} catch { /* 忽略 */ }
|
||||
await loadDefaults()
|
||||
await loadToken()
|
||||
@@ -133,7 +135,8 @@ onMounted(async () => {
|
||||
async function loadModels() {
|
||||
modelLoading.value = true
|
||||
try {
|
||||
models.value = await listModelConfigs(modelType.value)
|
||||
const m = await listModelConfigs(modelType.value)
|
||||
if (m && m.list) models.value = m.list
|
||||
} finally {
|
||||
modelLoading.value = false
|
||||
}
|
||||
@@ -161,6 +164,24 @@ function openModelDialog(row) {
|
||||
modelDialog.value = true
|
||||
}
|
||||
|
||||
// 输入模型名后,从表中已有同名配置带出接口地址与维度(仅填空字段,不覆盖手填值)
|
||||
function inheritFromExisting() {
|
||||
const name = modelForm.value.model_name.trim()
|
||||
if (!name) return
|
||||
const other = allModels.value.find(x => x.model_name === name && x.id !== modelForm.value.id)
|
||||
if (!other) return
|
||||
let filled = false
|
||||
if (!modelForm.value.endpoint_url && other.endpoint_url) {
|
||||
modelForm.value.endpoint_url = other.endpoint_url
|
||||
filled = true
|
||||
}
|
||||
if (modelForm.value.model_type === 'embedding' && (modelForm.value.dimension <= 0 || modelForm.value.dimension === 1024) && other.dimension > 0) {
|
||||
modelForm.value.dimension = other.dimension
|
||||
filled = true
|
||||
}
|
||||
if (filled) ElMessage.info(`已按已有配置「${other.name}」带出接口地址${modelForm.value.model_type === 'embedding' ? '与维度' : ''}`)
|
||||
}
|
||||
|
||||
async function saveModel() {
|
||||
if (!modelForm.value.name.trim() || !modelForm.value.model_name.trim()) {
|
||||
ElMessage.warning('请填写名称与模型名')
|
||||
@@ -172,7 +193,7 @@ async function saveModel() {
|
||||
ElMessage.success('保存成功')
|
||||
modelDialog.value = false
|
||||
await loadModels()
|
||||
if (modelType.value === 'chat') chatModels.value = await listModelConfigs('chat')
|
||||
if (modelType.value === 'chat') { const m = await listModelConfigs('chat'); if (m && m.list) chatModels.value = m.list }
|
||||
} finally {
|
||||
modelSaving.value = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user