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