feat(文档管理): 添加文档状态更新和向量生成功能
refactor(话术管理): 重构话术列表和编辑界面,调整API路径 fix(请求拦截器): 移除调试日志并优化错误处理 style(分页组件): 格式化代码并添加初始化标记 feat(知识库): 实现文档状态切换和向量生成功能
This commit is contained in:
@@ -3,7 +3,7 @@ import request from '/@/utils/request';
|
||||
//获取话术列表
|
||||
export function getscriptList(data: object) {
|
||||
return request({
|
||||
url: '/customer-server/speechcraft/list',
|
||||
url: '/customer-server/scripted/speech/list',
|
||||
method: 'get',
|
||||
params: data,
|
||||
});
|
||||
@@ -12,7 +12,7 @@ export function getscriptList(data: object) {
|
||||
//增加话术
|
||||
export function addScript(data: object) {
|
||||
return request({
|
||||
url: '/customer-server/speechcraft/add',
|
||||
url: '/customer-server/scripted/speech/add',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
@@ -21,7 +21,7 @@ export function addScript(data: object) {
|
||||
//删除话术列表
|
||||
export function deleteScript(data: object) {
|
||||
return request({
|
||||
url: '/customer-server/speechcraft/delete',
|
||||
url: '/customer-server/scripted/speech/delete',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
@@ -30,8 +30,17 @@ export function deleteScript(data: object) {
|
||||
//更新话术列表
|
||||
export function updateScript(data: object) {
|
||||
return request({
|
||||
url: '/customer-server/speechcraft/update',
|
||||
url: '/customer-server/scripted/speech/update',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
//获取话术详情
|
||||
export function getScriptDetail(data: object) {
|
||||
return request({
|
||||
url: '/customer-server/scripted/speech/getOne',
|
||||
method: 'get',
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface UpdateDocumentParams {
|
||||
fileSize?: number;
|
||||
format?: string;
|
||||
title?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
// 文档分段查询参数
|
||||
@@ -184,3 +185,12 @@ export function getDocumentProcess(id: string) {
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 生成向量
|
||||
export function generateVector(id: string, datasetId: string) {
|
||||
return request({
|
||||
url: '/rag/document/vectorization',
|
||||
method: 'post',
|
||||
data: { id, datasetId },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,100 +1,113 @@
|
||||
<template>
|
||||
<div :class="{'hidden':hidden}" class="pagination-container">
|
||||
<el-pagination
|
||||
:background="background"
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:layout="layout"
|
||||
:page-sizes="pageSizes"
|
||||
:pager-count="pagerCount"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
<div :class="{ hidden: hidden }" class="pagination-container">
|
||||
<el-pagination
|
||||
:background="background"
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:layout="layout"
|
||||
:page-sizes="pageSizes"
|
||||
:pager-count="pagerCount"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, defineComponent,computed } from 'vue';
|
||||
import { toRefs, defineComponent, computed, ref, onMounted } from 'vue';
|
||||
const props = {
|
||||
total: {
|
||||
required: true,
|
||||
type: Number
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [10, 20, 30, 50]
|
||||
}
|
||||
},
|
||||
// 移动端页码按钮的数量端默认值5
|
||||
pagerCount: {
|
||||
type: Number,
|
||||
default: document.body.clientWidth < 992 ? 5 : 7
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
default: 'total, sizes, prev, pager, next, jumper'
|
||||
},
|
||||
background: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
hidden: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
total: {
|
||||
required: true,
|
||||
type: Number,
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 20,
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [10, 20, 30, 50];
|
||||
},
|
||||
},
|
||||
// 移动端页码按钮的数量端默认值5
|
||||
pagerCount: {
|
||||
type: Number,
|
||||
default: document.body.clientWidth < 992 ? 5 : 7,
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
default: 'total, sizes, prev, pager, next, jumper',
|
||||
},
|
||||
background: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
hidden: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
};
|
||||
export default defineComponent({
|
||||
name: 'pagination',
|
||||
props: props,
|
||||
setup(props,{emit}){
|
||||
const { page,limit,pageSizes } = toRefs(props);
|
||||
const currentPage = computed({
|
||||
get() {
|
||||
return page.value;
|
||||
},
|
||||
set(val) {
|
||||
emit('update:page', val)
|
||||
}
|
||||
});
|
||||
const pageSize = computed({
|
||||
get() {
|
||||
return limit.value
|
||||
},
|
||||
set(val) {
|
||||
emit('update:limit', val)
|
||||
}
|
||||
});
|
||||
const handleSizeChange = (val:number) => {
|
||||
emit('pagination', { page: currentPage.value, limit: val })
|
||||
};
|
||||
const handleCurrentChange=(val:number) => {
|
||||
emit('pagination', { page: val, limit: pageSizes.value })
|
||||
}
|
||||
return {
|
||||
currentPage,
|
||||
pageSize,
|
||||
handleSizeChange,
|
||||
handleCurrentChange
|
||||
}
|
||||
}
|
||||
name: 'pagination',
|
||||
props: props,
|
||||
setup(props, { emit }) {
|
||||
const { page, limit } = toRefs(props);
|
||||
const isInitialized = ref(false);
|
||||
|
||||
const currentPage = computed({
|
||||
get() {
|
||||
return page.value;
|
||||
},
|
||||
set(val) {
|
||||
emit('update:page', val);
|
||||
},
|
||||
});
|
||||
const pageSize = computed({
|
||||
get() {
|
||||
return limit.value;
|
||||
},
|
||||
set(val) {
|
||||
emit('update:limit', val);
|
||||
},
|
||||
});
|
||||
|
||||
const handleSizeChange = (val: number) => {
|
||||
if (isInitialized.value) {
|
||||
emit('pagination', { page: currentPage.value, limit: val });
|
||||
}
|
||||
};
|
||||
const handleCurrentChange = (val: number) => {
|
||||
if (isInitialized.value) {
|
||||
emit('pagination', { page: val, limit: pageSize.value });
|
||||
}
|
||||
};
|
||||
|
||||
// 组件挂载后标记为已初始化
|
||||
onMounted(() => {
|
||||
isInitialized.value = true;
|
||||
});
|
||||
|
||||
return {
|
||||
currentPage,
|
||||
pageSize,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pagination-container {
|
||||
padding: 32px 16px;
|
||||
padding: 32px 16px;
|
||||
}
|
||||
.pagination-container.hidden {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -108,8 +108,6 @@ const requestInterceptor = (config: InternalAxiosRequestConfig) => {
|
||||
// 没有变化,只传递 id
|
||||
config.data = { id: idField };
|
||||
}
|
||||
|
||||
console.log('[最小化传参] 原始字段数:', Object.keys(currentData).length, '-> 传递字段数:', Object.keys(config.data).length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +153,6 @@ const responseInterceptor = (response: AxiosResponse) => {
|
||||
if (code === 402 && !requestUrl.includes('/assets/asset/sku/')) {
|
||||
// 获取当前路由路径
|
||||
const currentPath = window.location.hash.replace('#', '') || window.location.pathname;
|
||||
console.log('[request.ts] 检测到403错误,当前路径:', currentPath);
|
||||
handleModuleNotEnabled(currentPath);
|
||||
// 直接返回,不再显示错误消息
|
||||
return Promise.reject(new Error('模块未开通'));
|
||||
@@ -173,8 +170,6 @@ const responseInterceptor = (response: AxiosResponse) => {
|
||||
|
||||
// 响应错误拦截器
|
||||
const responseErrorHandler = (error: any) => {
|
||||
console.error('API请求错误:', error);
|
||||
|
||||
if (error.code === 'ECONNABORTED' && error.message.includes('timeout')) {
|
||||
showErrorMessage('请求超时,请检查网络连接');
|
||||
return Promise.reject(new Error('请求超时'));
|
||||
@@ -206,13 +201,11 @@ const responseErrorHandler = (error: any) => {
|
||||
const lastSubscribeTime = sessionStorage.getItem('lastSubscribeTime');
|
||||
const now = Date.now();
|
||||
if (lastSubscribeTime && now - parseInt(lastSubscribeTime) < 5000) {
|
||||
console.log('[responseErrorHandler] 刚完成开通,跳过402处理');
|
||||
showErrorMessage(responseMessage || '服务开通中,请稍后刷新页面');
|
||||
return Promise.reject(new Error('模块开通中'));
|
||||
}
|
||||
|
||||
const currentPath = window.location.hash.replace('#', '') || window.location.pathname;
|
||||
console.log('[responseErrorHandler] 检测到HTTP 402错误,当前路径:', currentPath);
|
||||
handleModuleNotEnabled(currentPath);
|
||||
return Promise.reject(new Error('模块未开通'));
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,14 +4,18 @@
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" size="default" label-width="90px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="标签" prop="tag">
|
||||
<el-input v-model="formData.tag" placeholder="请输入标签" clearable />
|
||||
<el-form-item label="数据集">
|
||||
<el-input v-model="formData.datasetName" placeholder="数据集" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="场景类型">
|
||||
<el-input v-model="formData.sceneType" placeholder="场景类型" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 富文本编辑器 -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="话术" prop="content">
|
||||
<Editor v-model="formData.content" height="400px" :key="editorKey" placeholder="请输入产品详情" :disableExceptEmotion="true" />
|
||||
<el-form-item label="话术内容" prop="questionContent">
|
||||
<Editor v-model="formData.questionContent" height="400px" :key="editorKey" placeholder="请输入话术内容" :disableExceptEmotion="true" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -29,18 +33,19 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, toRefs, nextTick } from 'vue';
|
||||
import { ref, reactive, toRefs, nextTick, onMounted } from 'vue';
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
|
||||
import Editor from '/@/components/editor/index.vue';
|
||||
import { addScript, updateScript } from '/@/api/customerService/script';
|
||||
import { addScript, updateScript, getScriptDetail } from '/@/api/customerService/script';
|
||||
import { listknowledges } from '/@/api/knowledge/dataset';
|
||||
|
||||
// 定义类型接口
|
||||
interface DialogRow {
|
||||
id?: number | string;
|
||||
tag: string;
|
||||
creator: string;
|
||||
content: string;
|
||||
modifier: string;
|
||||
id?: number;
|
||||
datasetId: string | number;
|
||||
datasetName?: string;
|
||||
sceneType: number;
|
||||
questionContent: string;
|
||||
}
|
||||
|
||||
// 定义事件
|
||||
@@ -48,30 +53,30 @@ const emit = defineEmits<{
|
||||
(e: 'refresh'): void;
|
||||
}>();
|
||||
|
||||
// 定义数据集选项类型
|
||||
interface DatasetOption {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
// 响应式数据
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
isShowDialog: false,
|
||||
datasets: [] as DatasetOption[], // 数据集列表
|
||||
editorKey: 0, // 用于强制重新渲染编辑器
|
||||
formData: {
|
||||
id: 0,
|
||||
tag: '',
|
||||
content: '',
|
||||
creator: '',
|
||||
modifier: '',
|
||||
datasetId: 0,
|
||||
datasetName: '',
|
||||
sceneType: 0,
|
||||
questionContent: '',
|
||||
} as DialogRow,
|
||||
});
|
||||
|
||||
// 表单验证规则
|
||||
const rules: FormRules = {
|
||||
tag: [
|
||||
{ required: true, message: '标签名称不能为空', trigger: 'blur' },
|
||||
{ max: 64, message: '标签长度最多 64 个字符', trigger: 'blur' },
|
||||
],
|
||||
content: [
|
||||
{ required: true, message: '产品详情不能为空', trigger: 'blur' },
|
||||
{ max: 8126, message: '产品名称长度最多 8126 个字符', trigger: 'blur' },
|
||||
],
|
||||
questionContent: [{ required: true, message: '话术内容不能为空', trigger: 'blur' }],
|
||||
};
|
||||
|
||||
// 模板引用
|
||||
@@ -80,28 +85,74 @@ const formRef = ref<FormInstance>();
|
||||
// 解构状态数据
|
||||
const { loading, isShowDialog, formData, editorKey } = toRefs(state);
|
||||
|
||||
/**
|
||||
* 加载数据集列表
|
||||
*/
|
||||
const loadDatasets = async () => {
|
||||
try {
|
||||
const response = await listknowledges({ pageNum: 1, pageSize: 100 });
|
||||
if (response.data && response.data.list) {
|
||||
state.datasets = response.data.list.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('加载数据集列表失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
loadDatasets();
|
||||
});
|
||||
|
||||
/**
|
||||
* 打开对话框
|
||||
* @param row - 可选的编辑数据
|
||||
*/
|
||||
const openDialog = (row?: DialogRow) => {
|
||||
const openDialog = async (row?: DialogRow) => {
|
||||
resetForm();
|
||||
|
||||
if (row) {
|
||||
// 深拷贝数据,避免引用问题
|
||||
state.formData = { ...row };
|
||||
// 重新加载数据集列表,确保数据是最新的
|
||||
await loadDatasets();
|
||||
|
||||
if (row && row.id) {
|
||||
try {
|
||||
// 加载话术详情
|
||||
const response = await getScriptDetail({ id: row.id });
|
||||
if (response.data) {
|
||||
// 确保datasetId是字符串类型,与datasets选项的value类型一致
|
||||
const detailData = {
|
||||
...response.data,
|
||||
datasetId: String(response.data.datasetId),
|
||||
datasetName: '',
|
||||
};
|
||||
|
||||
// 查找对应的数据集名称
|
||||
const dataset = state.datasets.find((d) => d.value === detailData.datasetId);
|
||||
if (dataset) {
|
||||
detailData.datasetName = dataset.label;
|
||||
}
|
||||
|
||||
state.formData = detailData;
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取话术详情失败');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 新增模式,确保清空数据
|
||||
state.formData = {
|
||||
id: 0,
|
||||
tag: '',
|
||||
content: '',
|
||||
creator: '',
|
||||
modifier: '',
|
||||
datasetId: 0,
|
||||
datasetName: '',
|
||||
sceneType: 0,
|
||||
questionContent: '',
|
||||
};
|
||||
}
|
||||
|
||||
// 更新编辑器 key 强制重新渲染
|
||||
// 强制重新渲染编辑器
|
||||
state.editorKey++;
|
||||
|
||||
state.isShowDialog = true;
|
||||
@@ -139,21 +190,22 @@ const onSubmit = async () => {
|
||||
const valid = await formRef.value.validate();
|
||||
if (!valid) return;
|
||||
|
||||
// 额外验证话术内容
|
||||
if (!state.formData.content || state.formData.content === '<p><br></p>' || state.formData.content.trim() === '<p><br></p>') {
|
||||
ElMessage.warning('话术内容不能为空');
|
||||
return;
|
||||
}
|
||||
// 确保数据类型正确
|
||||
const submitData = {
|
||||
...state.formData,
|
||||
datasetId: String(state.formData.datasetId),
|
||||
sceneType: Number(state.formData.sceneType),
|
||||
};
|
||||
|
||||
state.loading = true;
|
||||
|
||||
if (state.formData.id === 0) {
|
||||
// 新增模式
|
||||
await addScript(state.formData);
|
||||
await addScript(submitData);
|
||||
ElMessage.success('添加成功');
|
||||
} else {
|
||||
// 编辑模式
|
||||
await updateScript(state.formData);
|
||||
await updateScript(submitData);
|
||||
ElMessage.success('修改成功');
|
||||
}
|
||||
|
||||
@@ -161,7 +213,6 @@ const onSubmit = async () => {
|
||||
state.isShowDialog = false;
|
||||
emit('refresh');
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error);
|
||||
// 错误已由请求拦截器统一处理
|
||||
} finally {
|
||||
state.loading = false;
|
||||
@@ -174,10 +225,10 @@ const onSubmit = async () => {
|
||||
const resetForm = () => {
|
||||
state.formData = {
|
||||
id: 0,
|
||||
tag: '',
|
||||
content: '',
|
||||
creator: '',
|
||||
modifier: '',
|
||||
datasetId: 0,
|
||||
datasetName: '',
|
||||
sceneType: 0,
|
||||
questionContent: '',
|
||||
};
|
||||
|
||||
// 重置表单验证状态
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
<el-button size="default" type="success" @click="handleAdd">
|
||||
<el-button size="default" type="success" @click="handleAdd">
|
||||
<el-icon><FolderAdd /></el-icon>
|
||||
新增话术
|
||||
</el-button>
|
||||
@@ -31,9 +31,10 @@
|
||||
<!-- 数据表格 -->
|
||||
<el-table :data="tableData.data" v-loading="tableData.loading" style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="tag" label="标签" show-overflow-tooltip min-width="120" />
|
||||
<el-table-column prop="creator" label="创建人" show-overflow-tooltip min-width="100" />
|
||||
<el-table-column prop="updater" label="修改人" show-overflow-tooltip min-width="100" />
|
||||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||||
<el-table-column prop="datasetId" label="数据集ID" width="120" align="center" />
|
||||
<el-table-column prop="sceneType" label="场景类型" width="120" align="center" />
|
||||
<el-table-column prop="questionContent" label="问题内容" show-overflow-tooltip min-width="200" />
|
||||
<el-table-column prop="createdAt" label="创建时间" show-overflow-tooltip min-width="140">
|
||||
<template #default="{ row }">
|
||||
{{ formatTime(row.createdAt) }}
|
||||
@@ -81,13 +82,12 @@ import { getscriptList, deleteScript } from '/@/api/customerService/script';
|
||||
|
||||
// ==================== 类型定义 ====================
|
||||
interface ScriptItem {
|
||||
id: string;
|
||||
tag: string;
|
||||
creator: string;
|
||||
modifier: string;
|
||||
createdAt: string; // 保持原字段不变
|
||||
updatedAt: string; // 保持原字段不变
|
||||
content?: string;
|
||||
id: number;
|
||||
datasetId: number;
|
||||
sceneType: number;
|
||||
questionContent: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
interface TableParams {
|
||||
@@ -176,7 +176,6 @@ const formatTime = (time: string | number | Date): string => {
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
} catch (error) {
|
||||
console.error('时间格式化错误:', error);
|
||||
return String(time);
|
||||
}
|
||||
};
|
||||
@@ -196,8 +195,6 @@ const loadTableData = async () => {
|
||||
tableData.data = list;
|
||||
tableData.total = total;
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error);
|
||||
// 错误已由请求拦截器统一处理
|
||||
tableData.data = [];
|
||||
tableData.total = 0;
|
||||
} finally {
|
||||
@@ -215,8 +212,8 @@ const handleAdd = () => {
|
||||
/**
|
||||
* 编辑话术
|
||||
*/
|
||||
const handleEdit = (row: ScriptItem) => {
|
||||
editRoleRef.value?.openDialog(row as any);
|
||||
const handleEdit = async (row: ScriptItem) => {
|
||||
await editRoleRef.value?.openDialog(row as any);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -224,7 +221,7 @@ const handleEdit = (row: ScriptItem) => {
|
||||
*/
|
||||
const handleDelete = async (row: ScriptItem) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定要删除话术「${row.tag}」吗?此操作不可恢复。`, '提示', {
|
||||
await ElMessageBox.confirm(`确定要删除话术「${row.questionContent}」吗?此操作不可恢复。`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
@@ -237,19 +234,11 @@ const handleDelete = async (row: ScriptItem) => {
|
||||
await loadTableData();
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除失败:', error);
|
||||
// 错误已由请求拦截器统一处理
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 操作成功回调
|
||||
*/
|
||||
const handleSuccess = () => {
|
||||
loadTableData();
|
||||
};
|
||||
|
||||
// ==================== 生命周期 ====================
|
||||
onMounted(() => {
|
||||
loadTableData();
|
||||
|
||||
@@ -127,32 +127,37 @@
|
||||
</div>
|
||||
<div class="file-table" v-loading="fileLoading">
|
||||
<el-table :data="fileList" style="width: 100%" row-key="id" border>
|
||||
<el-table-column prop="Title" label="名称" min-width="200">
|
||||
<el-table-column prop="title" label="名称" min-width="200">
|
||||
<template #default="scope">
|
||||
<span class="file-link" @click="onViewDocumentDetail(scope.row)" style="cursor: pointer; color: #409eff">{{
|
||||
scope.row.Title
|
||||
scope.row.title
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="chunkCount" label="分块数" width="80" align="center" />
|
||||
<el-table-column prop="status" label="状态" width="90" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === 1 ? 'success' : 'info'" size="small">
|
||||
{{ scope.row.status === 1 ? '正常' : '禁用' }}
|
||||
</el-tag>
|
||||
<el-switch
|
||||
v-model="scope.row.statusEnabled"
|
||||
inline-prompt
|
||||
active-text="启"
|
||||
inactive-text="停"
|
||||
@change="onFileStatusChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="vectorStatus" label="向量化" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.vectorStatus === 'done' ? 'success' : 'warning'" size="small">
|
||||
{{ scope.row.vectorStatus || '未处理' }}
|
||||
<el-tag :type="scope.row.vectorStatus === 2 ? 'success' : 'warning'" size="small">
|
||||
{{ scope.row.vectorStatus === 2 ? '已完成' : '未完成' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdAt" label="上传日期" width="180" />
|
||||
<el-table-column label="动作" width="120" align="center">
|
||||
<el-table-column label="动作" width="180" align="center">
|
||||
<template #default="scope">
|
||||
<el-button text size="small" @click="onPreviewFile(scope.row)">预览</el-button>
|
||||
<el-button text size="small" type="primary" @click="onGenerateVector(scope.row)">生成向量</el-button>
|
||||
<el-button text size="small" type="danger" @click="onDeleteFile(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -286,7 +291,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import type { FormInstance, FormRules, UploadFile } from 'element-plus';
|
||||
import DocumentDetailDialog from './component/documentDetailDialog.vue';
|
||||
import { listknowledges, createknowledge, updateknowledge, deleteknowledge } from '/@/api/knowledge/dataset';
|
||||
import { listDocuments, uploadFile, createDocument, deleteDocument } from '/@/api/knowledge/document';
|
||||
import { listDocuments, uploadFile, createDocument, deleteDocument, updateDocument, generateVector, getDocument } from '/@/api/knowledge/document';
|
||||
|
||||
// 数据集相关
|
||||
const knowledgeLoading = ref(false);
|
||||
@@ -497,7 +502,10 @@ const getFileList = async () => {
|
||||
pageNum: 1,
|
||||
pageSize: 100,
|
||||
});
|
||||
fileList.value = response.data?.list || [];
|
||||
fileList.value = (response.data?.list || []).map((item: any) => ({
|
||||
...item,
|
||||
statusEnabled: item.status === 1,
|
||||
}));
|
||||
} catch (_error) {
|
||||
ElMessage.error('获取文件列表失败');
|
||||
} finally {
|
||||
@@ -578,14 +586,47 @@ const onConfirmUpload = async () => {
|
||||
};
|
||||
|
||||
// 文件状态变化
|
||||
const _onFileStatusChange = (row: any) => {
|
||||
ElMessage.success(row.enabled ? '已启用' : '已禁用');
|
||||
const onFileStatusChange = async (row: any) => {
|
||||
const newStatus = row.statusEnabled ? 1 : 0;
|
||||
try {
|
||||
// 调用后端API来更新文件状态
|
||||
await updateDocument({
|
||||
id: row.id,
|
||||
status: newStatus,
|
||||
});
|
||||
ElMessage.success(row.statusEnabled ? '已启用' : '已禁用');
|
||||
} catch (error) {
|
||||
// 失败时恢复原状态
|
||||
row.statusEnabled = !row.statusEnabled;
|
||||
ElMessage.error('状态更新失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 生成向量
|
||||
const onGenerateVector = async (row: any) => {
|
||||
try {
|
||||
// 调用后端API来生成向量,传递id和datasetId
|
||||
await generateVector(row.id, currentknowledge.value.id);
|
||||
ElMessage.success('生成向量任务已提交');
|
||||
// 模拟更新状态
|
||||
setTimeout(() => {
|
||||
getFileList();
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
ElMessage.error('生成向量失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 查看文档详情
|
||||
const onViewDocumentDetail = (row: any) => {
|
||||
currentDocument.value = row;
|
||||
showDocumentDetailDialog.value = true;
|
||||
const onViewDocumentDetail = async (row: any) => {
|
||||
try {
|
||||
// 调用getDocument接口获取最新的文件详情
|
||||
const response = await getDocument(row.id);
|
||||
currentDocument.value = response.data;
|
||||
showDocumentDetailDialog.value = true;
|
||||
} catch (error) {
|
||||
ElMessage.error('获取文件详情失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 预览文件
|
||||
|
||||
Reference in New Issue
Block a user