重构知识库相关接口,更新数据结构和命名,移除示例文件,调整组件和视图以支持新命名,优化文档和数据集管理功能。
This commit is contained in:
111
src/api/cid/apis/index.ts
Normal file
111
src/api/cid/apis/index.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { newService } from '/@/utils/request';
|
||||
|
||||
// 接口查询参数
|
||||
export interface ApiInterfaceQueryParams {
|
||||
keyword?: string;
|
||||
platformId?: string;
|
||||
status?: string;
|
||||
method?: string;
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
// 创建接口参数
|
||||
export interface CreateApiInterfaceParams {
|
||||
platformId: string | number;
|
||||
name: string;
|
||||
code: string;
|
||||
url: string;
|
||||
method: string;
|
||||
status?: string;
|
||||
authType?: string;
|
||||
requestConfig?: Record<string, any>;
|
||||
responseConfig?: Record<string, any>;
|
||||
limitConfig?: Record<string, any>;
|
||||
}
|
||||
|
||||
// 更新接口参数
|
||||
export interface UpdateApiInterfaceParams extends Partial<CreateApiInterfaceParams> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
// 更新接口状态参数
|
||||
export interface UpdateApiInterfaceStatusParams {
|
||||
id: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
// 接口信息(响应字段)
|
||||
export interface ApiInterfaceInfo {
|
||||
id: string;
|
||||
platformId: string | number;
|
||||
platformName?: string;
|
||||
name: string;
|
||||
code: string;
|
||||
url: string;
|
||||
method: string;
|
||||
status: string;
|
||||
statusName?: string;
|
||||
authType?: string;
|
||||
requestConfig?: Record<string, any>;
|
||||
responseConfig?: Record<string, any>;
|
||||
limitConfig?: Record<string, any>;
|
||||
createdBy?: string;
|
||||
createdAt?: number;
|
||||
updatedBy?: string;
|
||||
updatedAt?: number;
|
||||
}
|
||||
|
||||
// 获取接口列表
|
||||
export function listApiInterfaces(params: ApiInterfaceQueryParams) {
|
||||
return newService({
|
||||
url: '/api/interface/controller/listApiInterfaces',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 获取接口详情
|
||||
export function getApiInterface(id: string) {
|
||||
return newService({
|
||||
url: '/api/interface/controller/getApiInterface',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 创建接口
|
||||
export function createApiInterface(data: CreateApiInterfaceParams) {
|
||||
return newService({
|
||||
url: '/api/interface/controller/createApiInterface',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 修改接口
|
||||
export function updateApiInterface(data: UpdateApiInterfaceParams) {
|
||||
return newService({
|
||||
url: '/api/interface/controller/updateApiInterface',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新接口状态
|
||||
export function updateApiInterfaceStatus(data: UpdateApiInterfaceStatusParams) {
|
||||
return newService({
|
||||
url: '/api/interface/controller/updateApiInterfaceStatus',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除接口
|
||||
export function deleteApiInterface(id: string) {
|
||||
return newService({
|
||||
url: '/api/interface/controller/deleteApiInterface',
|
||||
method: 'delete',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
130
src/api/cid/datasource/index.ts
Normal file
130
src/api/cid/datasource/index.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import { newService } from '/@/utils/request';
|
||||
|
||||
// 平台查询参数
|
||||
export interface DatasourcePlatformQueryParams {
|
||||
keyword?: string;
|
||||
status?: string;
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
// 创建平台参数
|
||||
export interface CreateDatasourcePlatformParams {
|
||||
platformCode: string;
|
||||
platformName: string;
|
||||
description?: string;
|
||||
apiBaseUrl: string;
|
||||
authType: string;
|
||||
status?: string;
|
||||
token?: string;
|
||||
apiKey?: string;
|
||||
clientId?: string;
|
||||
clientSecret?: string;
|
||||
rateLimitPerMinute?: number;
|
||||
rateLimitPerHour?: number;
|
||||
concurrencyLimit?: number;
|
||||
requestTimeoutMs?: number;
|
||||
maxRetries?: number;
|
||||
retryDelayMs?: number;
|
||||
createdBy?: string;
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
// 更新平台参数
|
||||
export interface UpdateDatasourcePlatformParams extends Partial<CreateDatasourcePlatformParams> {
|
||||
id: string;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
// 更新平台状态参数
|
||||
export interface UpdateDatasourcePlatformStatusParams {
|
||||
id: string;
|
||||
Status: string;
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
// 平台信息
|
||||
export interface DatasourcePlatformInfo {
|
||||
id: string;
|
||||
platformCode: string;
|
||||
platformName: string;
|
||||
description?: string;
|
||||
status: string;
|
||||
statusName: string;
|
||||
apiBaseUrl: string;
|
||||
authType: string;
|
||||
authTypeName: string;
|
||||
rateLimitPerMinute?: number;
|
||||
rateLimitPerHour?: number;
|
||||
concurrencyLimit?: number;
|
||||
requestTimeoutMs?: number;
|
||||
maxRetries?: number;
|
||||
retryDelayMs?: number;
|
||||
createdBy?: string;
|
||||
createdAt?: number;
|
||||
updatedBy?: string;
|
||||
updatedAt?: number;
|
||||
}
|
||||
|
||||
// 获取平台列表
|
||||
export function listDatasourcePlatforms(params: DatasourcePlatformQueryParams) {
|
||||
return newService({
|
||||
url: '/datasource/platform/controller/listDatasourcePlatforms',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 创建平台
|
||||
export function createDatasourcePlatform(data: CreateDatasourcePlatformParams) {
|
||||
return newService({
|
||||
url: '/datasource/platform/controller/createDatasourcePlatform',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新平台
|
||||
export function updateDatasourcePlatform(data: UpdateDatasourcePlatformParams) {
|
||||
return newService({
|
||||
url: '/datasource/platform/controller/updateDatasourcePlatform',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除平台
|
||||
export function deleteDatasourcePlatform(id: string) {
|
||||
return newService({
|
||||
url: '/datasource/platform/controller/deleteDatasourcePlatform',
|
||||
method: 'delete',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 获取平台详情
|
||||
export function getDatasourcePlatform(id: string) {
|
||||
return newService({
|
||||
url: '/datasource/platform/controller/getDatasourcePlatform',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 根据编码获取平台信息
|
||||
export function getPlatformByCode(platformCode: string) {
|
||||
return newService({
|
||||
url: '/datasource/platform/controller/getPlatformByCode',
|
||||
method: 'get',
|
||||
params: { platformCode },
|
||||
});
|
||||
}
|
||||
|
||||
// 更新平台状态
|
||||
export function updateDatasourcePlatformStatus(data: UpdateDatasourcePlatformStatusParams) {
|
||||
return newService({
|
||||
url: '/datasource/platform/controller/updateDatasourcePlatformStatus',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
162
src/api/cid/field/index.ts
Normal file
162
src/api/cid/field/index.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
import { newService } from '/@/utils/request';
|
||||
|
||||
// 字典映射查询参数
|
||||
export interface FieldMappingQueryParams {
|
||||
configName?: string;
|
||||
vendorName?: string;
|
||||
apiName?: string;
|
||||
businessDomain?: string;
|
||||
isActive?: boolean;
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
// 创建字典映射参数
|
||||
export interface CreateFieldMappingParams {
|
||||
configName: string;
|
||||
vendorName: string;
|
||||
apiName: string;
|
||||
apiVersion?: string;
|
||||
sourceField: string;
|
||||
sourceFieldType?: string;
|
||||
sourceFieldDesc?: string;
|
||||
targetField: string;
|
||||
targetFieldType?: string;
|
||||
targetFieldDesc?: string;
|
||||
transformType?: string;
|
||||
transformParams?: any;
|
||||
validationRules?: any;
|
||||
defaultValue?: string;
|
||||
isRequired?: boolean;
|
||||
isActive?: boolean;
|
||||
priority?: number;
|
||||
businessDomain?: string;
|
||||
fieldGroup?: string;
|
||||
configVersion?: number;
|
||||
effectiveDate?: string;
|
||||
expiryDate?: string;
|
||||
createdBy?: string;
|
||||
}
|
||||
|
||||
// 更新字典映射参数
|
||||
export interface UpdateFieldMappingParams extends Partial<CreateFieldMappingParams> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
// 字典映射信息(响应字段)
|
||||
export interface FieldMappingInfo {
|
||||
id: string;
|
||||
configName: string;
|
||||
vendorName: string;
|
||||
apiName: string;
|
||||
apiVersion?: string;
|
||||
sourceField: string;
|
||||
sourceFieldType?: string;
|
||||
sourceFieldDesc?: string;
|
||||
targetField: string;
|
||||
targetFieldType?: string;
|
||||
targetFieldDesc?: string;
|
||||
transformType?: string;
|
||||
transformTypeName?: string;
|
||||
transformParams?: any;
|
||||
validationRules?: any;
|
||||
defaultValue?: string;
|
||||
isRequired?: boolean;
|
||||
isActive?: boolean;
|
||||
priority?: number;
|
||||
businessDomain?: string;
|
||||
businessDomainName?: string;
|
||||
fieldGroup?: string;
|
||||
configVersion?: number;
|
||||
effectiveDate?: string;
|
||||
expiryDate?: string;
|
||||
createdBy?: string;
|
||||
createdTime?: string;
|
||||
updatedBy?: string;
|
||||
updatedTime?: string;
|
||||
}
|
||||
|
||||
// 查询字典映射列表
|
||||
export function listFieldMappingConfigs(params: FieldMappingQueryParams) {
|
||||
return newService({
|
||||
url: '/field/mapping/config/controller/field-mapping-configs',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 创建字典映射
|
||||
export function createFieldMappingConfig(data: CreateFieldMappingParams) {
|
||||
return newService({
|
||||
url: '/field/mapping/config/controller/field-mapping-configs',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 根据ID查询字典映射详情
|
||||
export function getFieldMappingConfig(id: string) {
|
||||
return newService({
|
||||
url: `/field/mapping/config/controller/field-mapping-configs/${id}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
// 根据ID修改字典映射
|
||||
export function updateFieldMappingConfig(id: string, data: UpdateFieldMappingParams) {
|
||||
return newService({
|
||||
url: `/field/mapping/config/controller/field-mapping-configs/${id}`,
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 根据ID修改字典映射状态
|
||||
export function updateFieldMappingConfigStatus(id: string, isActive: boolean) {
|
||||
return newService({
|
||||
url: `/field/mapping/config/controller/field-mapping-configs/${id}/status`,
|
||||
method: 'put',
|
||||
data: { id, isActive },
|
||||
});
|
||||
}
|
||||
|
||||
// 根据ID删除字典映射
|
||||
export function deleteFieldMappingConfig(id: string) {
|
||||
return newService({
|
||||
url: `/field/mapping/config/controller/field-mapping-configs/${id}`,
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
|
||||
// 根据厂商和接口查询字段映射(过滤过期)
|
||||
export interface QueryFieldMappingParams {
|
||||
vendorName: string;
|
||||
apiName: string;
|
||||
apiVersion?: string;
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
export function queryFieldMappingConfigs(params: QueryFieldMappingParams) {
|
||||
return newService({
|
||||
url: '/field/mapping/config/controller/field-mapping-configs/query',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 验证字段映射配置的有效性
|
||||
export interface ValidateFieldMappingParams {
|
||||
configName: string;
|
||||
vendorName: string;
|
||||
apiName: string;
|
||||
sourceField: string;
|
||||
targetField: string;
|
||||
}
|
||||
|
||||
export function validateFieldMappingConfig(data: ValidateFieldMappingParams) {
|
||||
return newService({
|
||||
url: '/field/mapping/config/controller/field-mapping-configs/validate',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
// ⚠️ 示例文件:仅用于接口调用演示,不参与生产运行。
|
||||
// 知识库接口使用示例
|
||||
import {
|
||||
createKnowledgeBase,
|
||||
CreateDatasetParams,
|
||||
updateKnowledgeBase,
|
||||
UpdateDatasetParams
|
||||
} from '/@/api/knowledge/dataset';
|
||||
|
||||
// 示例1:创建带描述的知识库
|
||||
const createKnowledgeBaseWithDescription = async () => {
|
||||
const params: CreateDatasetParams = {
|
||||
name: '客服知识库',
|
||||
description: '包含常见问题和答案的知识库'
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await createKnowledgeBase(params);
|
||||
console.log('知识库创建成功:', response.data);
|
||||
} catch (error) {
|
||||
console.error('创建失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 示例2:创建仅包含名称的知识库
|
||||
const createKnowledgeBaseOnly = async () => {
|
||||
const params: CreateDatasetParams = {
|
||||
name: '产品知识库'
|
||||
// description 是可选的,可以不传
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await createKnowledgeBase(params);
|
||||
console.log('知识库创建成功:', response.data);
|
||||
} catch (error) {
|
||||
console.error('创建失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 示例3:更新知识库名称和描述
|
||||
const updateKnowledgeBaseInfo = async () => {
|
||||
const params: UpdateDatasetParams = {
|
||||
id: '1234567890', // 必传
|
||||
name: '更新后的知识库名称',
|
||||
description: '更新后的描述信息'
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await updateKnowledgeBase(params);
|
||||
console.log('知识库更新成功:', response.data);
|
||||
} catch (error) {
|
||||
console.error('更新失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 示例4:仅更新知识库名称
|
||||
const updateKnowledgeBaseName = async () => {
|
||||
const params: UpdateDatasetParams = {
|
||||
id: '1234567890', // 必传
|
||||
name: '仅更新名称'
|
||||
// description 是可选的,可以不传
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await updateKnowledgeBase(params);
|
||||
console.log('知识库名称更新成功:', response.data);
|
||||
} catch (error) {
|
||||
console.error('更新失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 在Vue组件中使用
|
||||
/*
|
||||
import { ref } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { createKnowledgeBase, CreateDatasetParams } from '/@/api/knowledge/dataset';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const formData = ref<CreateDatasetParams>({
|
||||
name: '',
|
||||
description: ''
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formData.value.name.trim()) {
|
||||
ElMessage.error('知识库名称不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
await createKnowledgeBase(formData.value);
|
||||
ElMessage.success('知识库创建成功');
|
||||
// 重置表单或跳转到列表页
|
||||
formData.value = { name: '', description: '' };
|
||||
} catch (error) {
|
||||
ElMessage.error('创建失败,请重试');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
formData,
|
||||
loading,
|
||||
handleSubmit
|
||||
};
|
||||
}
|
||||
});
|
||||
*/
|
||||
@@ -1,108 +1,68 @@
|
||||
import { newService } from '/@/utils/request';
|
||||
|
||||
// 数据集查询参数
|
||||
export interface DatasetQueryParams {
|
||||
export interface knowledgeQueryParams {
|
||||
keyword?: string;
|
||||
status?: string;
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
// 创建知识库参数
|
||||
export interface CreateDatasetParams {
|
||||
export interface CreateknowledgeParams {
|
||||
name: string; // 必传
|
||||
description?: string; // 可选
|
||||
}
|
||||
|
||||
// 更新知识库参数
|
||||
export interface UpdateDatasetParams {
|
||||
export interface UpdateknowledgeParams {
|
||||
id: string; // 必传
|
||||
name?: string; // 可选
|
||||
description?: string; // 可选
|
||||
}
|
||||
|
||||
// 数据集信息
|
||||
export interface DatasetInfo {
|
||||
export interface knowledgeInfo {
|
||||
id?: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
type: string; // text, qa, table
|
||||
documentCount?: number;
|
||||
charCount?: number;
|
||||
status: string; // enable, disable
|
||||
embeddingModel?: string;
|
||||
fileCount?: number;
|
||||
totalSize?: number;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
// 获取数据集列表
|
||||
export function listDatasets(params: DatasetQueryParams) {
|
||||
// 获取知识库列表
|
||||
export function listknowledges(params: knowledgeQueryParams) {
|
||||
return newService({
|
||||
url: '/rag-knowledge/knowledge/listKnowledge',
|
||||
url: '/rag-knowledge/dataset/listDataset',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 获取数据集详情
|
||||
export function getDataset(id: string) {
|
||||
// 创建知识库
|
||||
export function createknowledge(data: CreateknowledgeParams) {
|
||||
return newService({
|
||||
url: '/knowledge/dataset/detail',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 创建数据集(简化版)
|
||||
export function createKnowledgeBase(data: CreateDatasetParams) {
|
||||
return newService({
|
||||
url: '/rag-knowledge/knowledge/createKnowledge',
|
||||
url: '/rag-knowledge/dataset/createDataset',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 创建数据集(完整版)
|
||||
export function createDataset(data: DatasetInfo) {
|
||||
// 更新知识库
|
||||
export function updateknowledge(data: UpdateknowledgeParams) {
|
||||
return newService({
|
||||
url: '/knowledge/dataset/create',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新知识库(简化版)
|
||||
export function updateKnowledgeBase(data: UpdateDatasetParams) {
|
||||
return newService({
|
||||
url: '/rag-knowledge/knowledge/updateKnowledge',
|
||||
url: '/rag-knowledge/dataset/updateDataset',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新数据集(完整版)
|
||||
export function updateDataset(data: DatasetInfo) {
|
||||
// 删除知识库
|
||||
export function deleteknowledge(id: string) {
|
||||
return newService({
|
||||
url: '/knowledge/dataset/update',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除数据集
|
||||
export function deleteDataset(id: string) {
|
||||
return newService({
|
||||
url: '/rag-knowledge/knowledge/deleteKnowledge',
|
||||
url: '/rag-knowledge/dataset/deleteDataset',
|
||||
method: 'delete',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 更新数据集状态
|
||||
export function updateDatasetStatus(data: { id: string; status: string }) {
|
||||
return newService({
|
||||
url: '/knowledge/dataset/updateStatus',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
// ⚠️ 示例文件:仅用于接口调用演示,不参与生产运行。
|
||||
// 文档接口使用示例
|
||||
import {
|
||||
createDocument,
|
||||
CreateDocumentParams,
|
||||
updateDocument,
|
||||
UpdateDocumentParams,
|
||||
uploadDocument,
|
||||
deleteDocument,
|
||||
listDocuments,
|
||||
DocumentQueryParams
|
||||
} from '/@/api/knowledge/document';
|
||||
|
||||
// 示例1:创建文档(JSON格式)
|
||||
const createDocumentExample = async () => {
|
||||
const params: CreateDocumentParams = {
|
||||
KnowledgeId: 12345, // 知识库ID,必传
|
||||
filePath: '/path/to/document.pdf', // 文件路径,必传
|
||||
fileSize: 1024000, // 文件大小(字节),必传
|
||||
format: 'pdf', // 文件格式,必传
|
||||
title: '产品使用手册' // 文档标题,必传
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await createDocument(params);
|
||||
console.log('文档创建成功:', response.data);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('创建失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 示例2:上传文档(FormData格式)
|
||||
const uploadDocumentExample = async (file: File, knowledgeId: string) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('datasetId', knowledgeId);
|
||||
|
||||
try {
|
||||
const response = await uploadDocument(formData);
|
||||
console.log('文档上传成功:', response.data);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('上传失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 示例3:获取文档列表
|
||||
const getDocumentList = async (knowledgeId: string) => {
|
||||
const params: DocumentQueryParams = {
|
||||
datasetId: knowledgeId,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
keyword: '', // 可选搜索关键字
|
||||
status: '', // 可选状态筛选
|
||||
fileType: '' // 可选文件类型筛选
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await listDocuments(params);
|
||||
console.log('文档列表:', response.data);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('获取列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 示例4:更新文档
|
||||
const updateDocumentExample = async () => {
|
||||
const params: UpdateDocumentParams = {
|
||||
id: '1234567890', // 必传
|
||||
title: '更新后的文档标题' // 可选,只更新标题
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await updateDocument(params);
|
||||
console.log('文档更新成功:', response.data);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('更新失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 示例5:完整更新文档
|
||||
const updateDocumentFull = async () => {
|
||||
const params: UpdateDocumentParams = {
|
||||
id: '1234567890', // 必传
|
||||
KnowledgeId: 67890, // 可选
|
||||
filePath: '/new/path/document.pdf', // 可选
|
||||
fileSize: 2048000, // 可选
|
||||
format: 'pdf', // 可选
|
||||
title: '完全更新的文档' // 可选
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await updateDocument(params);
|
||||
console.log('文档完整更新成功:', response.data);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('更新失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 示例6:删除文档
|
||||
const deleteDocumentExample = async (documentId: string) => {
|
||||
try {
|
||||
await deleteDocument(documentId);
|
||||
console.log('文档删除成功');
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 在Vue组件中使用
|
||||
/*
|
||||
import { ref } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import {
|
||||
createDocument,
|
||||
CreateDocumentParams,
|
||||
uploadDocument,
|
||||
deleteDocument,
|
||||
listDocuments,
|
||||
DocumentQueryParams
|
||||
} from '/@/api/knowledge/document';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const formData = ref<CreateDocumentParams>({
|
||||
KnowledgeId: 0,
|
||||
filePath: '',
|
||||
fileSize: 0,
|
||||
format: '',
|
||||
title: ''
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
const documentList = ref([]);
|
||||
|
||||
// 创建文档
|
||||
const handleCreate = async () => {
|
||||
// 验证必填字段
|
||||
if (!formData.value.KnowledgeId || !formData.value.filePath ||
|
||||
!formData.value.fileSize || !formData.value.format || !formData.value.title) {
|
||||
ElMessage.error('请填写所有必填字段');
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
await createDocument(formData.value);
|
||||
ElMessage.success('文档创建成功');
|
||||
// 重置表单
|
||||
formData.value = {
|
||||
KnowledgeId: 0,
|
||||
filePath: '',
|
||||
fileSize: 0,
|
||||
format: '',
|
||||
title: ''
|
||||
};
|
||||
// 刷新列表
|
||||
await getDocuments();
|
||||
} catch (error) {
|
||||
ElMessage.error('创建失败,请重试');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 文件上传
|
||||
const handleFileUpload = async (event: Event, knowledgeId: string) => {
|
||||
const file = (event.target as HTMLInputElement).files?.[0];
|
||||
if (!file) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('datasetId', knowledgeId);
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
await uploadDocument(formData);
|
||||
ElMessage.success('文档上传成功');
|
||||
await getDocuments();
|
||||
} catch (error) {
|
||||
ElMessage.error('上传失败,请重试');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 删除文档
|
||||
const handleDelete = async (id: string) => {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除这个文档吗?', '提示', {
|
||||
type: 'warning',
|
||||
});
|
||||
|
||||
await deleteDocument(id);
|
||||
ElMessage.success('删除成功');
|
||||
await getDocuments();
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 获取文档列表
|
||||
const getDocuments = async () => {
|
||||
try {
|
||||
const response = await listDocuments({
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
});
|
||||
documentList.value = response.data.list;
|
||||
} catch (error) {
|
||||
console.error('获取列表失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
formData,
|
||||
loading,
|
||||
documentList,
|
||||
handleCreate,
|
||||
handleFileUpload,
|
||||
handleDelete,
|
||||
getDocuments
|
||||
};
|
||||
}
|
||||
});
|
||||
*/
|
||||
@@ -4,15 +4,13 @@ import { newService } from '/@/utils/request';
|
||||
export interface DocumentQueryParams {
|
||||
keyword?: string;
|
||||
datasetId?: string;
|
||||
status?: string;
|
||||
fileType?: string;
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
// 创建文档参数
|
||||
export interface CreateDocumentParams {
|
||||
KnowledgeId: number; // 必传
|
||||
datasetId: string; // 必传
|
||||
filePath: string; // 必传
|
||||
fileSize: number; // 必传
|
||||
format: string; // 必传
|
||||
@@ -22,11 +20,11 @@ export interface CreateDocumentParams {
|
||||
// 更新文档参数
|
||||
export interface UpdateDocumentParams {
|
||||
id: string; // 必传
|
||||
KnowledgeId?: number; // 可选
|
||||
filePath?: string; // 可选
|
||||
fileSize?: number; // 可选
|
||||
format?: string; // 可选
|
||||
title?: string; // 可选
|
||||
datasetId?: string;
|
||||
filePath?: string;
|
||||
fileSize?: number;
|
||||
format?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
// 文档信息
|
||||
@@ -34,35 +32,20 @@ export interface DocumentInfo {
|
||||
id?: string;
|
||||
name: string;
|
||||
datasetId: string;
|
||||
datasetName?: string;
|
||||
fileType: string; // pdf, docx, txt, md, html
|
||||
fileType: string;
|
||||
fileSize?: number;
|
||||
filePath?: string;
|
||||
charCount?: number;
|
||||
chunkCount?: number;
|
||||
status: string; // pending, processing, completed, failed
|
||||
indexStatus?: string; // not_indexed, indexing, indexed, failed
|
||||
errorMessage?: string;
|
||||
parseStatus?: string;
|
||||
enabled?: boolean;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
// 文档分段信息
|
||||
export interface DocumentChunk {
|
||||
id: string;
|
||||
documentId: string;
|
||||
content: string;
|
||||
chunkIndex: number;
|
||||
charCount: number;
|
||||
tokenCount?: number;
|
||||
embedding?: number[];
|
||||
createdAt?: string;
|
||||
}
|
||||
|
||||
// 获取文档列表
|
||||
export function listDocuments(params: DocumentQueryParams) {
|
||||
return newService({
|
||||
url: '/knowledge/document/list',
|
||||
url: '/rag-knowledge/document/listDocument',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
@@ -71,16 +54,16 @@ export function listDocuments(params: DocumentQueryParams) {
|
||||
// 获取文档详情
|
||||
export function getDocument(id: string) {
|
||||
return newService({
|
||||
url: '/knowledge/document/detail',
|
||||
url: '/rag-knowledge/document/getDocument',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 创建文档(JSON格式)
|
||||
// 创建文档
|
||||
export function createDocument(data: CreateDocumentParams) {
|
||||
return newService({
|
||||
url: '/knowledge/document/create',
|
||||
url: '/rag-knowledge/document/createDocument',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
@@ -89,16 +72,28 @@ export function createDocument(data: CreateDocumentParams) {
|
||||
// 更新文档
|
||||
export function updateDocument(data: UpdateDocumentParams) {
|
||||
return newService({
|
||||
url: '/knowledge/document/update',
|
||||
url: '/rag-knowledge/document/updateDocument',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 公共文件上传(OSS),返回文件路径
|
||||
export function uploadFile(file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
return newService({
|
||||
url: '/oss/file/uploadFile',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
});
|
||||
}
|
||||
|
||||
// 上传文档
|
||||
export function uploadDocument(data: FormData) {
|
||||
return newService({
|
||||
url: '/knowledge/document/upload',
|
||||
url: '/rag-knowledge/document/createDocument',
|
||||
method: 'post',
|
||||
data,
|
||||
headers: {
|
||||
@@ -110,61 +105,16 @@ export function uploadDocument(data: FormData) {
|
||||
// 删除文档
|
||||
export function deleteDocument(id: string) {
|
||||
return newService({
|
||||
url: '/knowledge/document/delete',
|
||||
url: '/rag-knowledge/document/deleteDocument',
|
||||
method: 'delete',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 批量删除文档
|
||||
export function batchDeleteDocuments(ids: string[]) {
|
||||
// 获取文件向量化处理进度
|
||||
export function getDocumentProcess(id: string) {
|
||||
return newService({
|
||||
url: '/knowledge/document/batchDelete',
|
||||
method: 'delete',
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
||||
// 重新处理文档
|
||||
export function reprocessDocument(id: string) {
|
||||
return newService({
|
||||
url: '/knowledge/document/reprocess',
|
||||
method: 'post',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 获取文档分段列表
|
||||
export function listDocumentChunks(params: { documentId: string; pageNum: number; pageSize: number }) {
|
||||
return newService({
|
||||
url: '/knowledge/document/chunks',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新文档分段
|
||||
export function updateDocumentChunk(data: { id: string; content: string }) {
|
||||
return newService({
|
||||
url: '/knowledge/document/chunk/update',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除文档分段
|
||||
export function deleteDocumentChunk(id: string) {
|
||||
return newService({
|
||||
url: '/knowledge/document/chunk/delete',
|
||||
method: 'delete',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
// 预览文档内容
|
||||
export function previewDocument(id: string) {
|
||||
return newService({
|
||||
url: '/knowledge/document/preview',
|
||||
url: '/rag-knowledge/document/getProcess',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
});
|
||||
|
||||
@@ -76,7 +76,7 @@ export const lazyImg = (el: any, arr: any) => {
|
||||
const io = new IntersectionObserver((res) => {
|
||||
res.forEach((v: any) => {
|
||||
if (v.isIntersecting) {
|
||||
const { img, key } = v.target.dataset;
|
||||
const { img, key } = v.target.knowledge;
|
||||
v.target.src = img;
|
||||
v.target.onload = () => {
|
||||
io.unobserve(v.target);
|
||||
|
||||
219
src/views/cid/apis/index.vue
Normal file
219
src/views/cid/apis/index.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<div class="cid-apis-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="68px">
|
||||
<el-form-item label="关键字" prop="keyword">
|
||||
<el-input
|
||||
v-model="tableData.param.keyword"
|
||||
placeholder="请输入接口名称"
|
||||
clearable
|
||||
size="default"
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="getList"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" @click="getList">
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="default" @click="resetQuery(queryRef)">
|
||||
<el-icon><ele-Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
<el-button size="default" type="success" @click="onOpenAdd">
|
||||
<el-icon><ele-FolderAdd /></el-icon>
|
||||
新增接口
|
||||
</el-button>
|
||||
<el-button size="default" type="danger" @click="onRowDel(null)">
|
||||
<el-icon><ele-Delete /></el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="name" label="接口名称" show-overflow-tooltip />
|
||||
<el-table-column prop="path" label="接口路径" show-overflow-tooltip />
|
||||
<el-table-column prop="method" label="请求方式" width="100" align="center" />
|
||||
<el-table-column prop="datasourceName" label="所属平台" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'" size="small">
|
||||
{{ scope.row.status === 1 ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdAt" label="创建时间" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary" @click="onOpenEdit(scope.row)">修改</el-button>
|
||||
<el-button size="small" text type="danger" @click="onRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" :close-on-click-modal="false">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="90px">
|
||||
<el-form-item label="接口名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入接口名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="接口路径" prop="path">
|
||||
<el-input v-model="form.path" placeholder="请输入接口路径" />
|
||||
</el-form-item>
|
||||
<el-form-item label="请求方式" prop="method">
|
||||
<el-select v-model="form.method" style="width: 100%">
|
||||
<el-option label="GET" value="GET" />
|
||||
<el-option label="POST" value="POST" />
|
||||
<el-option label="PUT" value="PUT" />
|
||||
<el-option label="DELETE" value="DELETE" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属平台" prop="datasourceId">
|
||||
<el-input v-model="form.datasourceId" placeholder="请输入所属平台ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="form.status" style="width: 100%">
|
||||
<el-option label="启用" :value="1" />
|
||||
<el-option label="禁用" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialog.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :loading="dialog.saving">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default { name: 'cidApis' };
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
|
||||
|
||||
const queryRef = ref<FormInstance>();
|
||||
const formRef = ref<FormInstance>();
|
||||
const ids = ref<string[]>([]);
|
||||
|
||||
const tableData = reactive({
|
||||
data: [] as any[],
|
||||
total: 0,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
keyword: '',
|
||||
},
|
||||
});
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
saving: false,
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
id: '',
|
||||
name: '',
|
||||
path: '',
|
||||
method: 'GET',
|
||||
datasourceId: '',
|
||||
description: '',
|
||||
status: 1,
|
||||
});
|
||||
|
||||
const rules = {
|
||||
name: [{ required: true, message: '请输入接口名称', trigger: 'blur' }],
|
||||
path: [{ required: true, message: '请输入接口路径', trigger: 'blur' }],
|
||||
method: [{ required: true, message: '请选择请求方式', trigger: 'change' }],
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
// TODO: 调用列表接口
|
||||
};
|
||||
|
||||
const resetQuery = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
getList();
|
||||
};
|
||||
|
||||
const handleSelectionChange = (selection: any[]) => {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
};
|
||||
|
||||
const onOpenAdd = () => {
|
||||
dialog.title = '新增接口';
|
||||
dialog.visible = true;
|
||||
form.id = '';
|
||||
form.name = '';
|
||||
form.path = '';
|
||||
form.method = 'GET';
|
||||
form.datasourceId = '';
|
||||
form.description = '';
|
||||
form.status = 1;
|
||||
};
|
||||
|
||||
const onOpenEdit = (row: any) => {
|
||||
dialog.title = '修改接口';
|
||||
dialog.visible = true;
|
||||
form.id = row.id;
|
||||
form.name = row.name;
|
||||
form.path = row.path;
|
||||
form.method = row.method;
|
||||
form.datasourceId = row.datasourceId;
|
||||
form.description = row.description;
|
||||
form.status = row.status;
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value.validate((valid) => {
|
||||
if (!valid) return;
|
||||
dialog.saving = true;
|
||||
// TODO: 调用新增/编辑接口
|
||||
dialog.saving = false;
|
||||
dialog.visible = false;
|
||||
getList();
|
||||
});
|
||||
};
|
||||
|
||||
const onRowDel = (row: any) => {
|
||||
const delIds = row ? [row.id] : ids.value;
|
||||
if (delIds.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(`确定要删除选中的接口吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
// TODO: 调用删除接口
|
||||
ElMessage.success('删除成功');
|
||||
getList();
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
355
src/views/cid/datasource/index.vue
Normal file
355
src/views/cid/datasource/index.vue
Normal file
@@ -0,0 +1,355 @@
|
||||
<template>
|
||||
<div class="cid-datasource-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="68px">
|
||||
<el-form-item label="关键字" prop="keyword">
|
||||
<el-input
|
||||
v-model="tableData.param.keyword"
|
||||
placeholder="请输入平台名称"
|
||||
clearable
|
||||
size="default"
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="getList"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="tableData.param.status" placeholder="平台状态" clearable size="default" style="width: 160px">
|
||||
<el-option label="启用" value="ACTIVE" />
|
||||
<el-option label="禁用" value="INACTIVE" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" @click="getList">
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="default" @click="resetQuery(queryRef)">
|
||||
<el-icon><ele-Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
<el-button size="default" type="success" @click="onOpenAdd">
|
||||
<el-icon><ele-FolderAdd /></el-icon>
|
||||
新增平台
|
||||
</el-button>
|
||||
<el-button size="default" type="danger" @click="onRowDel(null)">
|
||||
<el-icon><ele-Delete /></el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="platformName" label="平台名称" show-overflow-tooltip />
|
||||
<el-table-column prop="platformCode" label="平台编码" show-overflow-tooltip />
|
||||
<el-table-column prop="apiBaseUrl" label="接口基础URL" show-overflow-tooltip />
|
||||
<el-table-column prop="authTypeName" label="认证方式" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="rateLimitPerMinute" label="限频(次/分)" width="110" align="center" />
|
||||
<el-table-column prop="statusName" label="状态" width="90" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === 'ACTIVE' ? 'success' : 'danger'" size="small">
|
||||
{{ scope.row.status === 'ACTIVE' ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="description" label="描述" show-overflow-tooltip />
|
||||
<el-table-column label="创建时间" width="160">
|
||||
<template #default="scope">
|
||||
{{ scope.row.createdAt ? formatTime(scope.row.createdAt) : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary" @click="onOpenEdit(scope.row)">修改</el-button>
|
||||
<el-button size="small" text type="danger" @click="onRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" :close-on-click-modal="false">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
|
||||
<el-form-item label="平台名称" prop="platformName">
|
||||
<el-input v-model="form.platformName" placeholder="请输入平台名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="平台编码" prop="platformCode">
|
||||
<el-input v-model="form.platformCode" placeholder="请输入平台编码,如 ALIYUN_API" />
|
||||
</el-form-item>
|
||||
<el-form-item label="接口基础URL" prop="apiBaseUrl">
|
||||
<el-input v-model="form.apiBaseUrl" placeholder="请输入接口基础URL" />
|
||||
</el-form-item>
|
||||
<el-form-item label="认证方式" prop="authType">
|
||||
<el-select v-model="form.authType" placeholder="请选择认证方式" style="width: 100%">
|
||||
<el-option label="API Key认证" value="API_KEY" />
|
||||
<el-option label="OAuth2" value="OAUTH2" />
|
||||
<el-option label="Bearer Token" value="BEARER_TOKEN" />
|
||||
<el-option label="无认证" value="NONE" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="API Key" prop="apiKey" v-if="form.authType === 'API_KEY'">
|
||||
<el-input v-model="form.apiKey" placeholder="请输入 API Key" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label="Token" prop="token" v-if="form.authType === 'BEARER_TOKEN'">
|
||||
<el-input v-model="form.token" placeholder="请输入 Bearer Token" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label="Client ID" prop="clientId" v-if="form.authType === 'OAUTH2'">
|
||||
<el-input v-model="form.clientId" placeholder="请输入 Client ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="Client Secret" prop="clientSecret" v-if="form.authType === 'OAUTH2'">
|
||||
<el-input v-model="form.clientSecret" placeholder="请输入 Client Secret" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="form.status" style="width: 100%">
|
||||
<el-option label="启用" value="ACTIVE" />
|
||||
<el-option label="禁用" value="INACTIVE" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="限频(次/分)" prop="rateLimitPerMinute">
|
||||
<el-input-number v-model="form.rateLimitPerMinute" :min="0" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="限频(次/时)" prop="rateLimitPerHour">
|
||||
<el-input-number v-model="form.rateLimitPerHour" :min="0" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="并发限制" prop="concurrencyLimit">
|
||||
<el-input-number v-model="form.concurrencyLimit" :min="0" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="超时(ms)" prop="requestTimeoutMs">
|
||||
<el-input-number v-model="form.requestTimeoutMs" :min="0" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最大重试次数" prop="maxRetries">
|
||||
<el-input-number v-model="form.maxRetries" :min="0" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="重试延迟(ms)" prop="retryDelayMs">
|
||||
<el-input-number v-model="form.retryDelayMs" :min="0" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialog.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :loading="dialog.saving">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default { name: 'cidDatasource' };
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
|
||||
import { listDatasourcePlatforms, createDatasourcePlatform, updateDatasourcePlatform, deleteDatasourcePlatform } from '/@/api/cid/datasource';
|
||||
|
||||
const queryRef = ref<FormInstance>();
|
||||
const formRef = ref<FormInstance>();
|
||||
const ids = ref<string[]>([]);
|
||||
|
||||
const tableData = reactive({
|
||||
data: [] as any[],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
keyword: '',
|
||||
status: '',
|
||||
},
|
||||
});
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
saving: false,
|
||||
isEdit: false,
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
id: '',
|
||||
platformName: '',
|
||||
platformCode: '',
|
||||
apiBaseUrl: '',
|
||||
authType: 'API_KEY',
|
||||
status: 'ACTIVE',
|
||||
description: '',
|
||||
token: '',
|
||||
apiKey: '',
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
rateLimitPerMinute: 200,
|
||||
rateLimitPerHour: 10000,
|
||||
concurrencyLimit: 50,
|
||||
requestTimeoutMs: 15000,
|
||||
maxRetries: 3,
|
||||
retryDelayMs: 300,
|
||||
});
|
||||
|
||||
const rules = {
|
||||
platformName: [{ required: true, message: '请输入平台名称', trigger: 'blur' }],
|
||||
platformCode: [{ required: true, message: '请输入平台编码', trigger: 'blur' }],
|
||||
apiBaseUrl: [{ required: true, message: '请输入接口基础URL', trigger: 'blur' }],
|
||||
authType: [{ required: true, message: '请选择认证方式', trigger: 'change' }],
|
||||
};
|
||||
|
||||
const formatTime = (ts: number) => {
|
||||
if (!ts) return '';
|
||||
const d = new Date(ts * 1000);
|
||||
return d.toLocaleString('zh-CN', { hour12: false });
|
||||
};
|
||||
|
||||
const getList = async () => {
|
||||
tableData.loading = true;
|
||||
try {
|
||||
const res = await listDatasourcePlatforms({
|
||||
pageNum: tableData.param.pageNum,
|
||||
pageSize: tableData.param.pageSize,
|
||||
...(tableData.param.keyword ? { keyword: tableData.param.keyword } : {}),
|
||||
...(tableData.param.status ? { status: tableData.param.status } : {}),
|
||||
});
|
||||
tableData.data = res.data?.list || [];
|
||||
tableData.total = res.data?.total || 0;
|
||||
} catch (_e) {
|
||||
ElMessage.error('获取平台列表失败');
|
||||
} finally {
|
||||
tableData.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
const resetQuery = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
getList();
|
||||
};
|
||||
|
||||
const handleSelectionChange = (selection: any[]) => {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
form.id = '';
|
||||
form.platformName = '';
|
||||
form.platformCode = '';
|
||||
form.apiBaseUrl = '';
|
||||
form.authType = 'API_KEY';
|
||||
form.status = 'ACTIVE';
|
||||
form.description = '';
|
||||
form.token = '';
|
||||
form.apiKey = '';
|
||||
form.clientId = '';
|
||||
form.clientSecret = '';
|
||||
form.rateLimitPerMinute = 200;
|
||||
form.rateLimitPerHour = 10000;
|
||||
form.concurrencyLimit = 50;
|
||||
form.requestTimeoutMs = 15000;
|
||||
form.maxRetries = 3;
|
||||
form.retryDelayMs = 300;
|
||||
};
|
||||
|
||||
const onOpenAdd = () => {
|
||||
resetForm();
|
||||
dialog.title = '新增平台';
|
||||
dialog.isEdit = false;
|
||||
dialog.visible = true;
|
||||
};
|
||||
|
||||
const onOpenEdit = (row: any) => {
|
||||
dialog.title = '修改平台';
|
||||
dialog.isEdit = true;
|
||||
dialog.visible = true;
|
||||
form.id = row.id;
|
||||
form.platformName = row.platformName;
|
||||
form.platformCode = row.platformCode;
|
||||
form.apiBaseUrl = row.apiBaseUrl;
|
||||
form.authType = row.authType;
|
||||
form.status = row.status;
|
||||
form.description = row.description || '';
|
||||
form.token = row.token || '';
|
||||
form.apiKey = row.apiKey || '';
|
||||
form.clientId = row.clientId || '';
|
||||
form.clientSecret = row.clientSecret || '';
|
||||
form.rateLimitPerMinute = row.rateLimitPerMinute ?? 200;
|
||||
form.rateLimitPerHour = row.rateLimitPerHour ?? 10000;
|
||||
form.concurrencyLimit = row.concurrencyLimit ?? 50;
|
||||
form.requestTimeoutMs = row.requestTimeoutMs ?? 15000;
|
||||
form.maxRetries = row.maxRetries ?? 3;
|
||||
form.retryDelayMs = row.retryDelayMs ?? 300;
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
dialog.saving = true;
|
||||
try {
|
||||
if (dialog.isEdit) {
|
||||
await updateDatasourcePlatform({ ...form });
|
||||
ElMessage.success('修改成功');
|
||||
} else {
|
||||
const { id: _id, ...createParams } = form;
|
||||
await createDatasourcePlatform(createParams);
|
||||
ElMessage.success('创建成功');
|
||||
}
|
||||
dialog.visible = false;
|
||||
getList();
|
||||
} catch (_e) {
|
||||
ElMessage.error(dialog.isEdit ? '修改失败' : '创建失败');
|
||||
} finally {
|
||||
dialog.saving = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onRowDel = (row: any) => {
|
||||
const delIds = row ? [row.id] : ids.value;
|
||||
if (delIds.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据');
|
||||
return;
|
||||
}
|
||||
const msg = row ? `确定要删除平台「${row.platformName}」吗?` : `确定要删除选中的 ${delIds.length} 个平台吗?`;
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
try {
|
||||
for (const id of delIds) {
|
||||
await deleteDatasourcePlatform(id);
|
||||
}
|
||||
ElMessage.success('删除成功');
|
||||
getList();
|
||||
} catch (_e) {
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
198
src/views/cid/field/index.vue
Normal file
198
src/views/cid/field/index.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<div class="cid-field-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="system-user-search mb15">
|
||||
<el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="68px">
|
||||
<el-form-item label="关键字" prop="keyword">
|
||||
<el-input
|
||||
v-model="tableData.param.keyword"
|
||||
placeholder="请输入字段名称"
|
||||
clearable
|
||||
size="default"
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="getList"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" @click="getList">
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button size="default" @click="resetQuery(queryRef)">
|
||||
<el-icon><ele-Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
<el-button size="default" type="success" @click="onOpenAdd">
|
||||
<el-icon><ele-FolderAdd /></el-icon>
|
||||
新增映射
|
||||
</el-button>
|
||||
<el-button size="default" type="danger" @click="onRowDel(null)">
|
||||
<el-icon><ele-Delete /></el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="sourceField" label="源字段" show-overflow-tooltip />
|
||||
<el-table-column prop="targetField" label="目标字段" show-overflow-tooltip />
|
||||
<el-table-column prop="datasourceName" label="所属平台" show-overflow-tooltip />
|
||||
<el-table-column prop="apiName" label="所属接口" show-overflow-tooltip />
|
||||
<el-table-column prop="description" label="描述" show-overflow-tooltip />
|
||||
<el-table-column prop="createdAt" label="创建时间" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary" @click="onOpenEdit(scope.row)">修改</el-button>
|
||||
<el-button size="small" text type="danger" @click="onRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" :close-on-click-modal="false">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="90px">
|
||||
<el-form-item label="源字段" prop="sourceField">
|
||||
<el-input v-model="form.sourceField" placeholder="请输入源字段名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="目标字段" prop="targetField">
|
||||
<el-input v-model="form.targetField" placeholder="请输入目标字段名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属平台" prop="datasourceId">
|
||||
<el-input v-model="form.datasourceId" placeholder="请输入所属平台ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属接口" prop="apiId">
|
||||
<el-input v-model="form.apiId" placeholder="请输入所属接口ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialog.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :loading="dialog.saving">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default { name: 'cidField' };
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
|
||||
|
||||
const queryRef = ref<FormInstance>();
|
||||
const formRef = ref<FormInstance>();
|
||||
const ids = ref<string[]>([]);
|
||||
|
||||
const tableData = reactive({
|
||||
data: [] as any[],
|
||||
total: 0,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
keyword: '',
|
||||
},
|
||||
});
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
saving: false,
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
id: '',
|
||||
sourceField: '',
|
||||
targetField: '',
|
||||
datasourceId: '',
|
||||
apiId: '',
|
||||
description: '',
|
||||
});
|
||||
|
||||
const rules = {
|
||||
sourceField: [{ required: true, message: '请输入源字段名', trigger: 'blur' }],
|
||||
targetField: [{ required: true, message: '请输入目标字段名', trigger: 'blur' }],
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
// TODO: 调用列表接口
|
||||
};
|
||||
|
||||
const resetQuery = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
getList();
|
||||
};
|
||||
|
||||
const handleSelectionChange = (selection: any[]) => {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
};
|
||||
|
||||
const onOpenAdd = () => {
|
||||
dialog.title = '新增字典映射';
|
||||
dialog.visible = true;
|
||||
form.id = '';
|
||||
form.sourceField = '';
|
||||
form.targetField = '';
|
||||
form.datasourceId = '';
|
||||
form.apiId = '';
|
||||
form.description = '';
|
||||
};
|
||||
|
||||
const onOpenEdit = (row: any) => {
|
||||
dialog.title = '修改字典映射';
|
||||
dialog.visible = true;
|
||||
form.id = row.id;
|
||||
form.sourceField = row.sourceField;
|
||||
form.targetField = row.targetField;
|
||||
form.datasourceId = row.datasourceId;
|
||||
form.apiId = row.apiId;
|
||||
form.description = row.description;
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value.validate((valid) => {
|
||||
if (!valid) return;
|
||||
dialog.saving = true;
|
||||
// TODO: 调用新增/编辑接口
|
||||
dialog.saving = false;
|
||||
dialog.visible = false;
|
||||
getList();
|
||||
});
|
||||
};
|
||||
|
||||
const onRowDel = (row: any) => {
|
||||
const delIds = row ? [row.id] : ids.value;
|
||||
if (delIds.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(`确定要删除选中的字典映射吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
// TODO: 调用删除接口
|
||||
ElMessage.success('删除成功');
|
||||
getList();
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
@@ -13,9 +13,7 @@
|
||||
<div class="document-content">
|
||||
<div class="content-header">
|
||||
<h2>{{ documentInfo.name }}</h2>
|
||||
<div class="content-meta">
|
||||
Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}
|
||||
</div>
|
||||
<div class="content-meta">Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}</div>
|
||||
</div>
|
||||
<div class="content-body" v-loading="contentLoading">
|
||||
<pre class="document-text">{{ documentContent }}</pre>
|
||||
@@ -37,13 +35,7 @@
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<el-input
|
||||
v-model="chunkSearch"
|
||||
placeholder="搜索"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 120px"
|
||||
>
|
||||
<el-input v-model="chunkSearch" placeholder="搜索" clearable size="small" style="width: 120px">
|
||||
<template #prefix>
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
</template>
|
||||
@@ -59,11 +51,7 @@
|
||||
<el-checkbox v-model="selectAll" @change="onSelectAllChange">选择所有</el-checkbox>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="chunk-item"
|
||||
v-for="chunk in filteredChunks"
|
||||
:key="chunk.id"
|
||||
>
|
||||
<div class="chunk-item" v-for="chunk in filteredChunks" :key="chunk.id">
|
||||
<div class="chunk-checkbox">
|
||||
<el-checkbox v-model="chunk.selected" />
|
||||
</div>
|
||||
@@ -112,8 +100,8 @@ import { ElMessage } from 'element-plus';
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean;
|
||||
datasetId: string;
|
||||
datasetName: string;
|
||||
knowledgeId: string;
|
||||
knowledgeName: string;
|
||||
document: any;
|
||||
}>();
|
||||
|
||||
@@ -150,9 +138,7 @@ const selectAll = ref(false);
|
||||
// 过滤后的切片列表
|
||||
const filteredChunks = computed(() => {
|
||||
if (!chunkSearch.value) return chunkList.value;
|
||||
return chunkList.value.filter((chunk) =>
|
||||
(chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase())
|
||||
);
|
||||
return chunkList.value.filter((chunk) => (chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase()));
|
||||
});
|
||||
|
||||
// 格式化文件大小
|
||||
@@ -215,7 +201,7 @@ const getChunkList = async () => {
|
||||
|
||||
// 全选变化
|
||||
const onSelectAllChange = (val: boolean) => {
|
||||
chunkList.value.forEach(chunk => {
|
||||
chunkList.value.forEach((chunk) => {
|
||||
chunk.selected = val;
|
||||
});
|
||||
};
|
||||
@@ -231,12 +217,15 @@ const onAddChunk = () => {
|
||||
};
|
||||
|
||||
// 监听弹窗打开
|
||||
watch(() => props.modelValue, (val) => {
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (val && props.document) {
|
||||
getDocumentDetail();
|
||||
getChunkList();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="isEdit ? '编辑数据集' : '新增数据集'"
|
||||
v-model="isShowDialog"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
@close="onCancel"
|
||||
>
|
||||
<el-dialog :title="isEdit ? '编辑数据集' : '新增数据集'" v-model="isShowDialog" width="600px" :close-on-click-modal="false" @close="onCancel">
|
||||
<el-form ref="formRef" :model="ruleForm" :rules="rules" label-width="100px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
@@ -67,7 +61,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'editDataset',
|
||||
name: 'editknowledge',
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -75,10 +69,10 @@ export default {
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { createDataset, updateDataset, getDataset } from '/@/api/knowledge/dataset';
|
||||
import { createknowledge, updateknowledge, getknowledge } from '/@/api/knowledge/knowledge';
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['getDatasetList']);
|
||||
const emit = defineEmits(['getknowledgeList']);
|
||||
|
||||
// 表单ref
|
||||
const formRef = ref<FormInstance>();
|
||||
@@ -124,7 +118,7 @@ const openDialog = async (row?: any) => {
|
||||
|
||||
if (row) {
|
||||
try {
|
||||
const res: any = await getDataset(row.id);
|
||||
const res: any = await getknowledge(row.id);
|
||||
const data = res.data || row;
|
||||
ruleForm.id = data.id || '';
|
||||
ruleForm.name = data.name || '';
|
||||
@@ -174,15 +168,15 @@ const onSubmit = async () => {
|
||||
};
|
||||
|
||||
if (isEdit.value) {
|
||||
await updateDataset(data);
|
||||
await updateknowledge(data);
|
||||
ElMessage.success('保存成功');
|
||||
} else {
|
||||
await createDataset(data);
|
||||
await createknowledge(data);
|
||||
ElMessage.success('创建成功');
|
||||
}
|
||||
|
||||
isShowDialog.value = false;
|
||||
emit('getDatasetList');
|
||||
emit('getknowledgeList');
|
||||
} catch (_error) {
|
||||
ElMessage.error(isEdit.value ? '保存失败,请重试' : '创建失败,请重试');
|
||||
} finally {
|
||||
@@ -198,5 +192,4 @@ defineExpose({
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="knowledge-dataset-page">
|
||||
<div class="knowledge-dataset-container">
|
||||
<div class="knowledge-knowledge-page">
|
||||
<div class="knowledge-knowledge-container">
|
||||
<el-card shadow="hover">
|
||||
<div class="knowledge-dataset-search mb15">
|
||||
<div class="knowledge-knowledge-search mb15">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="数据集名称">
|
||||
<el-input size="default" v-model="tableData.param.keyword" placeholder="请输入数据集名称" clearable style="width: 200px" />
|
||||
@@ -21,7 +21,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" @click="getDatasetList">
|
||||
<el-button size="default" type="primary" @click="getknowledgeList">
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
@@ -29,7 +29,7 @@
|
||||
<el-icon><ele-Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
<el-button size="default" type="success" @click="onOpenAdd" v-auth="'api/v1/knowledge/dataset/create'">
|
||||
<el-button size="default" type="success" @click="onOpenAdd" v-auth="'api/v1/knowledge/knowledge/create'">
|
||||
<el-icon><ele-Plus /></el-icon>
|
||||
新增
|
||||
</el-button>
|
||||
@@ -63,7 +63,7 @@
|
||||
active-text="启"
|
||||
inactive-text="停"
|
||||
@change="onStatusChange(scope.row)"
|
||||
v-auth="'api/v1/knowledge/dataset/updateStatus'"
|
||||
v-auth="'api/v1/knowledge/knowledge/updateStatus'"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -71,9 +71,9 @@
|
||||
<el-table-column prop="updatedAt" label="更新时间" width="170" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary" @click="onEdit(scope.row)" v-auth="'api/v1/knowledge/dataset/update'">编辑</el-button>
|
||||
<el-button size="small" text type="primary" @click="onEdit(scope.row)" v-auth="'api/v1/knowledge/knowledge/update'">编辑</el-button>
|
||||
<el-button size="small" text type="success" @click="onManageDocuments(scope.row)">文档</el-button>
|
||||
<el-button size="small" text type="danger" @click="onRowDel(scope.row)" v-auth="'api/v1/knowledge/dataset/delete'">删除</el-button>
|
||||
<el-button size="small" text type="danger" @click="onRowDel(scope.row)" v-auth="'api/v1/knowledge/knowledge/delete'">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -91,13 +91,13 @@
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<EditDataset ref="editDatasetRef" @getDatasetList="getDatasetList" />
|
||||
<Editknowledge ref="editknowledgeRef" @getknowledgeList="getknowledgeList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'knowledgeDataset',
|
||||
name: 'knowledgeknowledge',
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -105,8 +105,8 @@ export default {
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { listDatasets, deleteDataset, updateDatasetStatus } from '/@/api/knowledge/dataset';
|
||||
import EditDataset from './component/editDataset.vue';
|
||||
import { listknowledges, deleteknowledge, updateknowledgeStatus } from '/@/api/knowledge/knowledge';
|
||||
import Editknowledge from './component/editknowledge.vue';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -125,13 +125,13 @@ const tableData = reactive({
|
||||
});
|
||||
|
||||
// 编辑弹窗ref
|
||||
const editDatasetRef = ref();
|
||||
const editknowledgeRef = ref();
|
||||
|
||||
// 获取数据集列表
|
||||
const getDatasetList = async () => {
|
||||
const getknowledgeList = async () => {
|
||||
tableData.loading = true;
|
||||
try {
|
||||
const res: any = await listDatasets(tableData.param);
|
||||
const res: any = await listknowledges(tableData.param);
|
||||
const list = res.data?.list || [];
|
||||
tableData.data = list.map((item: any) => ({
|
||||
...item,
|
||||
@@ -190,27 +190,27 @@ const onResetQuery = () => {
|
||||
tableData.param.type = '';
|
||||
tableData.param.status = undefined;
|
||||
tableData.param.pageNum = 1;
|
||||
getDatasetList();
|
||||
getknowledgeList();
|
||||
};
|
||||
|
||||
// 打开新增弹窗
|
||||
const onOpenAdd = () => {
|
||||
editDatasetRef.value.openDialog();
|
||||
editknowledgeRef.value.openDialog();
|
||||
};
|
||||
|
||||
// 打开编辑弹窗
|
||||
const onEdit = (row: any) => {
|
||||
editDatasetRef.value.openDialog(row);
|
||||
editknowledgeRef.value.openDialog(row);
|
||||
};
|
||||
|
||||
// 查看详情
|
||||
const onViewDetail = (row: any) => {
|
||||
router.push({ path: '/knowledge/document', query: { datasetId: row.id, datasetName: row.name } });
|
||||
router.push({ path: '/knowledge/document', query: { knowledgeId: row.id, knowledgeName: row.name } });
|
||||
};
|
||||
|
||||
// 管理文档
|
||||
const onManageDocuments = (row: any) => {
|
||||
router.push({ path: '/knowledge/document', query: { datasetId: row.id, datasetName: row.name } });
|
||||
router.push({ path: '/knowledge/document', query: { knowledgeId: row.id, knowledgeName: row.name } });
|
||||
};
|
||||
|
||||
// 状态切换
|
||||
@@ -218,7 +218,7 @@ const onStatusChange = async (row: any) => {
|
||||
const newStatus = row.statusEnabled ? 'enable' : 'disable';
|
||||
const statusText = row.statusEnabled ? '启用' : '禁用';
|
||||
try {
|
||||
await updateDatasetStatus({ id: row.id, status: newStatus });
|
||||
await updateknowledgeStatus({ id: row.id, status: newStatus });
|
||||
ElMessage.success(`${statusText}成功`);
|
||||
} catch (_error) {
|
||||
row.statusEnabled = !row.statusEnabled;
|
||||
@@ -232,40 +232,42 @@ const onRowDel = (row: any) => {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await deleteDataset(row.id);
|
||||
await deleteknowledge(row.id);
|
||||
ElMessage.success('删除成功');
|
||||
getDatasetList();
|
||||
getknowledgeList();
|
||||
} catch (_error) {
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 分页大小改变
|
||||
const onSizeChange = (size: number) => {
|
||||
tableData.param.pageSize = size;
|
||||
getDatasetList();
|
||||
getknowledgeList();
|
||||
};
|
||||
|
||||
// 当前页改变
|
||||
const onCurrentChange = (page: number) => {
|
||||
tableData.param.pageNum = page;
|
||||
getDatasetList();
|
||||
getknowledgeList();
|
||||
};
|
||||
|
||||
// 页面加载时获取数据
|
||||
onMounted(() => {
|
||||
getDatasetList();
|
||||
getknowledgeList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.knowledge-dataset-page {
|
||||
.knowledge-knowledge-page {
|
||||
padding: 15px;
|
||||
.knowledge-dataset-container {
|
||||
.knowledge-dataset-search {
|
||||
.knowledge-knowledge-container {
|
||||
.knowledge-knowledge-search {
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="isShowDrawer"
|
||||
title="文档分段管理"
|
||||
size="70%"
|
||||
:close-on-click-modal="true"
|
||||
>
|
||||
<el-drawer v-model="isShowDrawer" title="文档分段管理" size="70%" :close-on-click-modal="true">
|
||||
<div class="chunks-container" v-loading="loading">
|
||||
<div class="chunks-header">
|
||||
<div class="doc-info">
|
||||
@@ -12,13 +7,7 @@
|
||||
<el-tag size="small" type="info">共 {{ tableData.total }} 个分段</el-tag>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<el-input
|
||||
v-model="searchKeyword"
|
||||
placeholder="搜索分段内容"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter="onSearch"
|
||||
>
|
||||
<el-input v-model="searchKeyword" placeholder="搜索分段内容" clearable style="width: 200px" @keyup.enter="onSearch">
|
||||
<template #append>
|
||||
<el-button @click="onSearch">
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
@@ -29,11 +18,7 @@
|
||||
</div>
|
||||
|
||||
<div class="chunks-list">
|
||||
<div
|
||||
class="chunk-item"
|
||||
v-for="chunk in tableData.data"
|
||||
:key="chunk.id"
|
||||
>
|
||||
<div class="chunk-item" v-for="chunk in tableData.data" :key="chunk.id">
|
||||
<div class="chunk-header">
|
||||
<div class="chunk-index">
|
||||
<el-tag size="small"># {{ chunk.chunkIndex + 1 }}</el-tag>
|
||||
@@ -55,12 +40,7 @@
|
||||
{{ chunk.content }}
|
||||
</div>
|
||||
<div class="chunk-edit" v-else>
|
||||
<el-input
|
||||
v-model="chunk.editContent"
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
placeholder="请输入分段内容"
|
||||
/>
|
||||
<el-input v-model="chunk.editContent" type="textarea" :rows="6" placeholder="请输入分段内容" />
|
||||
<div class="edit-actions">
|
||||
<el-button size="small" @click="onCancelEdit(chunk)">取消</el-button>
|
||||
<el-button size="small" type="primary" @click="onSaveChunk(chunk)" :loading="chunk.saving">保存</el-button>
|
||||
@@ -186,7 +166,8 @@ const onDeleteChunk = (chunk: any) => {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await deleteDocumentChunk(chunk.id);
|
||||
ElMessage.success('删除成功');
|
||||
@@ -194,7 +175,8 @@ const onDeleteChunk = (chunk: any) => {
|
||||
} catch (_error) {
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 分页大小改变
|
||||
@@ -277,7 +259,8 @@ defineExpose({
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.char-count, .token-count {
|
||||
.char-count,
|
||||
.token-count {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="isShowDrawer"
|
||||
title="文档预览"
|
||||
size="60%"
|
||||
:close-on-click-modal="true"
|
||||
>
|
||||
<el-drawer v-model="isShowDrawer" title="文档预览" size="60%" :close-on-click-modal="true">
|
||||
<div class="preview-container" v-loading="loading">
|
||||
<div class="preview-header">
|
||||
<div class="file-info">
|
||||
@@ -37,7 +32,7 @@
|
||||
<el-tab-pane label="文档信息" name="info">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="文档名称">{{ documentInfo.name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所属数据集">{{ documentInfo.datasetName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所属数据集">{{ documentInfo.knowledgeName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="文件类型">{{ documentInfo.fileType?.toUpperCase() }}</el-descriptions-item>
|
||||
<el-descriptions-item label="文件大小">{{ formatFileSize(documentInfo.fileSize) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="字符数">{{ documentInfo.charCount }}</el-descriptions-item>
|
||||
@@ -81,8 +76,8 @@ const activeTab = ref('content');
|
||||
const documentInfo = reactive({
|
||||
id: '',
|
||||
name: '',
|
||||
datasetId: '',
|
||||
datasetName: '',
|
||||
knowledgeId: '',
|
||||
knowledgeName: '',
|
||||
fileType: '',
|
||||
fileSize: 0,
|
||||
filePath: '',
|
||||
@@ -211,10 +206,7 @@ const openDialog = async (row: any) => {
|
||||
// 获取文档详情和内容
|
||||
loading.value = true;
|
||||
try {
|
||||
const [detailRes, contentRes] = await Promise.all([
|
||||
getDocument(row.id),
|
||||
previewDocument(row.id),
|
||||
]);
|
||||
const [detailRes, contentRes] = await Promise.all([getDocument(row.id), previewDocument(row.id)]);
|
||||
|
||||
if (detailRes.data) {
|
||||
Object.assign(documentInfo, detailRes.data);
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="上传文档"
|
||||
v-model="isShowDialog"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
@close="onCancel"
|
||||
>
|
||||
<el-dialog title="上传文档" v-model="isShowDialog" width="600px" :close-on-click-modal="false" @close="onCancel">
|
||||
<el-form ref="formRef" :model="ruleForm" :rules="rules" label-width="100px">
|
||||
<el-form-item label="所属数据集" prop="datasetId">
|
||||
<el-select v-model="ruleForm.datasetId" placeholder="请选择数据集" clearable style="width: 100%" :disabled="!!currentDatasetId">
|
||||
<el-option v-for="item in datasetOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
<el-form-item label="所属数据集" prop="knowledgeId">
|
||||
<el-select v-model="ruleForm.datasetId" placeholder="请选择数据集" clearable style="width: 100%" :disabled="!!currentknowledgeId">
|
||||
<el-option v-for="item in knowledgeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传文件" prop="files">
|
||||
@@ -25,13 +19,9 @@
|
||||
accept=".pdf,.docx,.doc,.txt,.md,.html"
|
||||
>
|
||||
<el-icon class="el-icon--upload"><ele-UploadFilled /></el-icon>
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或<em>点击上传</em>
|
||||
</div>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
支持 PDF、Word、TXT、Markdown、HTML 格式,单个文件不超过 20MB
|
||||
</div>
|
||||
<div class="el-upload__tip">支持 PDF、Word、TXT、Markdown、HTML 格式,单个文件不超过 20MB</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
@@ -81,8 +71,8 @@ import { uploadDocument } from '/@/api/knowledge/document';
|
||||
|
||||
// 定义props
|
||||
const props = defineProps<{
|
||||
datasetOptions: any[];
|
||||
currentDatasetId?: string;
|
||||
knowledgeOptions: any[];
|
||||
currentknowledgeId?: string;
|
||||
}>();
|
||||
|
||||
// 定义事件
|
||||
@@ -115,7 +105,7 @@ const rules = reactive<FormRules>({
|
||||
|
||||
// 监听当前数据集ID
|
||||
watch(
|
||||
() => props.currentDatasetId,
|
||||
() => props.currentknowledgeId,
|
||||
(val) => {
|
||||
if (val) {
|
||||
ruleForm.datasetId = val;
|
||||
@@ -126,7 +116,7 @@ watch(
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
if (!props.currentDatasetId) {
|
||||
if (!props.currentknowledgeId) {
|
||||
ruleForm.datasetId = '';
|
||||
}
|
||||
ruleForm.chunkSize = 500;
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<div class="page-header">
|
||||
<el-breadcrumb separator=">">
|
||||
<el-breadcrumb-item>
|
||||
<span class="back-link" @click="onBackToKnowledge">知识库</span>
|
||||
<span class="back-link" @click="onBackToknowledge">知识库</span>
|
||||
</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>
|
||||
<span class="back-link" @click="onBackToDataset">{{ datasetName }}</span>
|
||||
<span class="back-link" @click="onBackToknowledge">{{ knowledgeName }}</span>
|
||||
</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>{{ documentInfo.name }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
@@ -18,9 +18,7 @@
|
||||
<div class="document-content">
|
||||
<div class="content-header">
|
||||
<h2>{{ documentInfo.name }}</h2>
|
||||
<div class="content-meta">
|
||||
Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}
|
||||
</div>
|
||||
<div class="content-meta">Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}</div>
|
||||
</div>
|
||||
<div class="content-body" v-loading="contentLoading">
|
||||
<pre class="document-text">{{ documentContent }}</pre>
|
||||
@@ -42,13 +40,7 @@
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<el-input
|
||||
v-model="chunkSearch"
|
||||
placeholder="搜索"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 120px"
|
||||
>
|
||||
<el-input v-model="chunkSearch" placeholder="搜索" clearable size="small" style="width: 120px">
|
||||
<template #prefix>
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
</template>
|
||||
@@ -64,11 +56,7 @@
|
||||
<el-checkbox v-model="selectAll" @change="onSelectAllChange">选择所有</el-checkbox>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="chunk-item"
|
||||
v-for="chunk in filteredChunks"
|
||||
:key="chunk.id"
|
||||
>
|
||||
<div class="chunk-item" v-for="chunk in filteredChunks" :key="chunk.id">
|
||||
<div class="chunk-checkbox">
|
||||
<el-checkbox v-model="chunk.selected" />
|
||||
</div>
|
||||
@@ -121,8 +109,8 @@ const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
// 路由参数
|
||||
const datasetId = ref('');
|
||||
const datasetName = ref('');
|
||||
const knowledgeId = ref('');
|
||||
const knowledgeName = ref('');
|
||||
const documentId = ref('');
|
||||
|
||||
// 文档信息
|
||||
@@ -151,9 +139,7 @@ const selectAll = ref(false);
|
||||
// 过滤后的切片列表
|
||||
const filteredChunks = computed(() => {
|
||||
if (!chunkSearch.value) return chunkList.value;
|
||||
return chunkList.value.filter((chunk) =>
|
||||
(chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase())
|
||||
);
|
||||
return chunkList.value.filter((chunk) => (chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase()));
|
||||
});
|
||||
|
||||
// 格式化文件大小
|
||||
@@ -171,15 +157,15 @@ const truncateText = (text: string, maxLength: number) => {
|
||||
};
|
||||
|
||||
// 返回知识库列表
|
||||
const onBackToKnowledge = () => {
|
||||
router.push('/knowledge/dataset');
|
||||
const onBackToknowledge = () => {
|
||||
router.push('/knowledge/knowledge');
|
||||
};
|
||||
|
||||
// 返回数据集详情
|
||||
const onBackToDataset = () => {
|
||||
const onBackToknowledge = () => {
|
||||
router.push({
|
||||
path: '/knowledge/document',
|
||||
query: { datasetId: datasetId.value, datasetName: datasetName.value },
|
||||
query: { knowledgeId: knowledgeId.value, knowledgeName: knowledgeName.value },
|
||||
});
|
||||
};
|
||||
|
||||
@@ -195,8 +181,7 @@ const getDocumentDetail = async () => {
|
||||
documentInfo.fileSize = detail.fileSize || 0;
|
||||
documentInfo.createdAt = detail.createdAt || '';
|
||||
const contentData = contentRes.data;
|
||||
documentContent.value =
|
||||
typeof contentData === 'string' ? contentData : contentData?.content || contentData?.text || '';
|
||||
documentContent.value = typeof contentData === 'string' ? contentData : contentData?.content || contentData?.text || '';
|
||||
} catch (_error) {
|
||||
ElMessage.error('获取文档详情失败');
|
||||
documentContent.value = '';
|
||||
@@ -248,12 +233,12 @@ const onAddChunk = () => {
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
datasetId.value = (route.query.datasetId as string) || '';
|
||||
datasetName.value = (route.query.datasetName as string) || '';
|
||||
knowledgeId.value = (route.query.knowledgeId as string) || '';
|
||||
knowledgeName.value = (route.query.knowledgeName as string) || '';
|
||||
documentId.value = (route.query.docId as string) || '';
|
||||
if (!documentId.value) {
|
||||
ElMessage.warning('缺少文档ID,无法查看详情');
|
||||
onBackToDataset();
|
||||
onBackToknowledge();
|
||||
return;
|
||||
}
|
||||
getDocumentDetail();
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
<div class="knowledge-document-container">
|
||||
<el-card shadow="hover">
|
||||
<!-- 面包屑导航 -->
|
||||
<div class="breadcrumb-nav mb15" v-if="currentDataset.id">
|
||||
<div class="breadcrumb-nav mb15" v-if="currentknowledge.id">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item :to="{ path: '/knowledge/dataset' }">数据集管理</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>{{ currentDataset.name }}</el-breadcrumb-item>
|
||||
<el-breadcrumb-item :to="{ path: '/knowledge/knowledge' }">数据集管理</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>{{ currentknowledge.name }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
|
||||
<div class="knowledge-document-search mb15">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="所属数据集" v-if="!currentDataset.id">
|
||||
<el-select size="default" v-model="tableData.param.datasetId" placeholder="请选择数据集" clearable style="width: 180px">
|
||||
<el-option v-for="item in datasetOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
<el-form-item label="所属数据集" v-if="!currentknowledge.id">
|
||||
<el-select size="default" v-model="tableData.param.knowledgeId" placeholder="请选择数据集" clearable style="width: 180px">
|
||||
<el-option v-for="item in knowledgeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="文档名称">
|
||||
@@ -50,20 +50,20 @@
|
||||
<el-icon><ele-Upload /></el-icon>
|
||||
上传文档
|
||||
</el-button>
|
||||
<el-button size="default" type="danger" @click="onBatchDelete" :disabled="selectedIds.length === 0" v-auth="'api/v1/knowledge/document/batchDelete'">
|
||||
<el-button
|
||||
size="default"
|
||||
type="danger"
|
||||
@click="onBatchDelete"
|
||||
:disabled="selectedIds.length === 0"
|
||||
v-auth="'api/v1/knowledge/document/batchDelete'"
|
||||
>
|
||||
<el-icon><ele-Delete /></el-icon>
|
||||
批量删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
v-loading="tableData.loading"
|
||||
border
|
||||
@selection-change="onSelectionChange"
|
||||
>
|
||||
<el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading" border @selection-change="onSelectionChange">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="name" label="文档名称" min-width="200" show-overflow-tooltip>
|
||||
@@ -76,7 +76,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="datasetName" label="所属数据集" width="150" show-overflow-tooltip v-if="!currentDataset.id" />
|
||||
<el-table-column prop="knowledgeName" label="所属数据集" width="150" show-overflow-tooltip v-if="!currentknowledge.id" />
|
||||
<el-table-column prop="fileType" label="文件类型" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag size="small">{{ scope.row.fileType?.toUpperCase() }}</el-tag>
|
||||
@@ -103,8 +103,18 @@
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary" @click="onPreview(scope.row)">预览</el-button>
|
||||
<el-button size="small" text type="success" @click="onViewChunks(scope.row)" v-auth="'api/v1/knowledge/document/chunks'">分段</el-button>
|
||||
<el-button size="small" text type="warning" @click="onReprocess(scope.row)" v-if="scope.row.status === 'failed'" v-auth="'api/v1/knowledge/document/reprocess'">重试</el-button>
|
||||
<el-button size="small" text type="success" @click="onViewChunks(scope.row)" v-auth="'api/v1/knowledge/document/chunks'"
|
||||
>分段</el-button
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
text
|
||||
type="warning"
|
||||
@click="onReprocess(scope.row)"
|
||||
v-if="scope.row.status === 'failed'"
|
||||
v-auth="'api/v1/knowledge/document/reprocess'"
|
||||
>重试</el-button
|
||||
>
|
||||
<el-button size="small" text type="danger" @click="onRowDel(scope.row)" v-auth="'api/v1/knowledge/document/delete'">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -125,7 +135,12 @@
|
||||
</div>
|
||||
|
||||
<!-- 上传文档弹窗 -->
|
||||
<UploadDocument ref="uploadDocumentRef" :datasetOptions="datasetOptions" :currentDatasetId="currentDataset.id" @getDocumentList="getDocumentList" />
|
||||
<UploadDocument
|
||||
ref="uploadDocumentRef"
|
||||
:knowledgeOptions="knowledgeOptions"
|
||||
:currentknowledgeId="currentknowledge.id"
|
||||
@getDocumentList="getDocumentList"
|
||||
/>
|
||||
|
||||
<!-- 文档预览弹窗 -->
|
||||
<PreviewDocument ref="previewDocumentRef" />
|
||||
@@ -146,7 +161,7 @@ import { ref, reactive, onMounted, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { listDocuments, deleteDocument, batchDeleteDocuments, reprocessDocument } from '/@/api/knowledge/document';
|
||||
import { listDatasets } from '/@/api/knowledge/dataset';
|
||||
import { listknowledges } from '/@/api/knowledge/knowledge';
|
||||
import UploadDocument from './component/uploadDocument.vue';
|
||||
import PreviewDocument from './component/previewDocument.vue';
|
||||
import DocumentChunks from './component/documentChunks.vue';
|
||||
@@ -154,13 +169,13 @@ import DocumentChunks from './component/documentChunks.vue';
|
||||
const route = useRoute();
|
||||
|
||||
// 当前数据集
|
||||
const currentDataset = reactive({
|
||||
const currentknowledge = reactive({
|
||||
id: '',
|
||||
name: '',
|
||||
});
|
||||
|
||||
// 数据集选项
|
||||
const datasetOptions = ref<any[]>([]);
|
||||
const knowledgeOptions = ref<any[]>([]);
|
||||
|
||||
// 选中的文档ID
|
||||
const selectedIds = ref<string[]>([]);
|
||||
@@ -172,7 +187,7 @@ const tableData = reactive({
|
||||
loading: false,
|
||||
param: {
|
||||
keyword: '',
|
||||
datasetId: '',
|
||||
knowledgeId: '',
|
||||
fileType: '',
|
||||
status: undefined as string | undefined,
|
||||
pageNum: 1,
|
||||
@@ -186,12 +201,12 @@ const previewDocumentRef = ref();
|
||||
const documentChunksRef = ref();
|
||||
|
||||
// 获取数据集列表
|
||||
const getDatasetOptions = async () => {
|
||||
const getknowledgeOptions = async () => {
|
||||
try {
|
||||
const res: any = await listDatasets({ pageNum: 1, pageSize: 1000 });
|
||||
datasetOptions.value = res.data?.list || [];
|
||||
const res: any = await listknowledges({ pageNum: 1, pageSize: 1000 });
|
||||
knowledgeOptions.value = res.data?.list || [];
|
||||
} catch (_error) {
|
||||
datasetOptions.value = [];
|
||||
knowledgeOptions.value = [];
|
||||
ElMessage.error('获取数据集列表失败');
|
||||
}
|
||||
};
|
||||
@@ -201,8 +216,8 @@ const getDocumentList = async () => {
|
||||
tableData.loading = true;
|
||||
try {
|
||||
const params = { ...tableData.param };
|
||||
if (currentDataset.id) {
|
||||
params.datasetId = currentDataset.id;
|
||||
if (currentknowledge.id) {
|
||||
params.knowledgeId = currentknowledge.id;
|
||||
}
|
||||
const res: any = await listDocuments(params);
|
||||
tableData.data = res.data?.list || [];
|
||||
@@ -309,8 +324,8 @@ const getIndexStatusText = (status: string) => {
|
||||
// 重置查询
|
||||
const onResetQuery = () => {
|
||||
tableData.param.keyword = '';
|
||||
if (!currentDataset.id) {
|
||||
tableData.param.datasetId = '';
|
||||
if (!currentknowledge.id) {
|
||||
tableData.param.knowledgeId = '';
|
||||
}
|
||||
tableData.param.fileType = '';
|
||||
tableData.param.status = undefined;
|
||||
@@ -346,7 +361,7 @@ const onReprocess = async (row: any) => {
|
||||
|
||||
// 选择变化
|
||||
const onSelectionChange = (selection: any[]) => {
|
||||
selectedIds.value = selection.map(item => item.id);
|
||||
selectedIds.value = selection.map((item) => item.id);
|
||||
};
|
||||
|
||||
// 批量删除
|
||||
@@ -355,7 +370,8 @@ const onBatchDelete = () => {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await batchDeleteDocuments(selectedIds.value);
|
||||
ElMessage.success('删除成功');
|
||||
@@ -363,7 +379,8 @@ const onBatchDelete = () => {
|
||||
} catch (_error) {
|
||||
ElMessage.error('批量删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 删除文档
|
||||
@@ -372,7 +389,8 @@ const onRowDel = (row: any) => {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await deleteDocument(row.id);
|
||||
ElMessage.success('删除成功');
|
||||
@@ -380,7 +398,8 @@ const onRowDel = (row: any) => {
|
||||
} catch (_error) {
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 分页大小改变
|
||||
@@ -399,13 +418,13 @@ const onCurrentChange = (page: number) => {
|
||||
watch(
|
||||
() => route.query,
|
||||
(query) => {
|
||||
if (query.datasetId) {
|
||||
currentDataset.id = query.datasetId as string;
|
||||
currentDataset.name = query.datasetName as string || '';
|
||||
tableData.param.datasetId = currentDataset.id;
|
||||
if (query.knowledgeId) {
|
||||
currentknowledge.id = query.knowledgeId as string;
|
||||
currentknowledge.name = (query.knowledgeName as string) || '';
|
||||
tableData.param.knowledgeId = currentknowledge.id;
|
||||
} else {
|
||||
currentDataset.id = '';
|
||||
currentDataset.name = '';
|
||||
currentknowledge.id = '';
|
||||
currentknowledge.name = '';
|
||||
}
|
||||
getDocumentList();
|
||||
},
|
||||
@@ -414,7 +433,7 @@ watch(
|
||||
|
||||
// 页面加载时获取数据
|
||||
onMounted(() => {
|
||||
getDatasetOptions();
|
||||
getknowledgeOptions();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
<template>
|
||||
<div class="knowledge-page">
|
||||
<!-- 数据集列表页 -->
|
||||
<div class="dataset-list-view" v-if="!currentDataset">
|
||||
<div class="knowledge-list-view" v-if="!currentknowledge">
|
||||
<div class="page-header">
|
||||
<div class="header-left">
|
||||
<el-icon class="header-icon"><ele-Folder /></el-icon>
|
||||
<span class="header-title">知识库</span>
|
||||
</div>
|
||||
<el-button type="primary" @click="onAddDataset">
|
||||
<el-button type="primary" @click="onAddknowledge">
|
||||
<el-icon><ele-Plus /></el-icon>
|
||||
新建知识库
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="dataset-cards" v-loading="datasetLoading">
|
||||
<div class="knowledge-cards" v-loading="knowledgeLoading">
|
||||
<!-- 数据集卡片 -->
|
||||
<div
|
||||
class="dataset-card"
|
||||
v-for="item in datasetList"
|
||||
class="knowledge-card"
|
||||
v-for="item in knowledgeList"
|
||||
:key="item.id"
|
||||
@click="onSelectDataset(item)"
|
||||
@click="onSelectknowledge(item)"
|
||||
@contextmenu.prevent="onCardContextMenu($event, item)"
|
||||
>
|
||||
<div class="card-icon">
|
||||
@@ -33,12 +33,12 @@
|
||||
<!-- 悬停操作按钮 -->
|
||||
<div class="card-actions" @click.stop>
|
||||
<el-tooltip content="重命名" placement="top">
|
||||
<el-button text size="small" @click="onRenameDataset(item)">
|
||||
<el-button text size="small" @click="onRenameknowledge(item)">
|
||||
<el-icon><ele-Edit /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button text size="small" type="danger" @click="onDeleteDataset(item)">
|
||||
<el-button text size="small" type="danger" @click="onDeleteknowledge(item)">
|
||||
<el-icon><ele-Delete /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
@@ -46,17 +46,17 @@
|
||||
</div>
|
||||
|
||||
<!-- 查看全部卡片 -->
|
||||
<div class="see-all-card" v-if="datasetList.length > 0">
|
||||
<div class="see-all-card" v-if="knowledgeList.length > 0">
|
||||
<span>See All</span>
|
||||
<el-icon><ele-ArrowRight /></el-icon>
|
||||
</div>
|
||||
|
||||
<el-empty v-if="datasetList.length === 0 && !datasetLoading" description="暂无知识库,点击上方按钮创建" :image-size="100" />
|
||||
<el-empty v-if="knowledgeList.length === 0 && !knowledgeLoading" description="暂无知识库,点击上方按钮创建" :image-size="100" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 数据集详情页 -->
|
||||
<div class="dataset-detail-view" v-else>
|
||||
<div class="knowledge-detail-view" v-else>
|
||||
<!-- 顶部导航 -->
|
||||
<div class="detail-header">
|
||||
<div class="header-left">
|
||||
@@ -64,7 +64,7 @@
|
||||
<el-breadcrumb-item>
|
||||
<span class="back-link" @click="onBackToList">知识库</span>
|
||||
</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>{{ currentDataset.name }}</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>{{ currentknowledge.name }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,48 +72,32 @@
|
||||
<div class="detail-body">
|
||||
<!-- 左侧信息面板 -->
|
||||
<div class="info-sidebar">
|
||||
<div class="dataset-profile">
|
||||
<div class="knowledge-profile">
|
||||
<div class="profile-icon">
|
||||
<span class="icon-text">{{ currentDataset.name?.charAt(0)?.toUpperCase() || 'D' }}</span>
|
||||
<span class="icon-text">{{ currentknowledge.name?.charAt(0)?.toUpperCase() || 'D' }}</span>
|
||||
</div>
|
||||
<div class="profile-info">
|
||||
<div class="profile-name">{{ currentDataset.name }}</div>
|
||||
<div class="profile-meta">{{ currentDataset.fileCount || 0 }} 个文件 · {{ formatFileSize(currentDataset.totalSize || 0) }}</div>
|
||||
<div class="profile-time">创建于 {{ currentDataset.createdAt }}</div>
|
||||
<div class="profile-name">{{ currentknowledge.name }}</div>
|
||||
<div class="profile-meta">{{ currentknowledge.fileCount || 0 }} 个文件 · {{ formatFileSize(currentknowledge.totalSize || 0) }}</div>
|
||||
<div class="profile-time">创建于 {{ currentknowledge.createdAt }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 功能菜单 -->
|
||||
<div class="func-menu">
|
||||
<div
|
||||
class="menu-item"
|
||||
:class="{ active: activeMenu === 'files' }"
|
||||
@click="activeMenu = 'files'"
|
||||
>
|
||||
<div class="menu-item" :class="{ active: activeMenu === 'files' }" @click="activeMenu = 'files'">
|
||||
<el-icon><ele-Document /></el-icon>
|
||||
<span>文件列表</span>
|
||||
</div>
|
||||
<div
|
||||
class="menu-item"
|
||||
:class="{ active: activeMenu === 'search' }"
|
||||
@click="activeMenu = 'search'"
|
||||
>
|
||||
<div class="menu-item" :class="{ active: activeMenu === 'search' }" @click="activeMenu = 'search'">
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
<span>检索测试</span>
|
||||
</div>
|
||||
<div
|
||||
class="menu-item"
|
||||
:class="{ active: activeMenu === 'logs' }"
|
||||
@click="activeMenu = 'logs'"
|
||||
>
|
||||
<div class="menu-item" :class="{ active: activeMenu === 'logs' }" @click="activeMenu = 'logs'">
|
||||
<el-icon><ele-List /></el-icon>
|
||||
<span>日志</span>
|
||||
</div>
|
||||
<div
|
||||
class="menu-item"
|
||||
:class="{ active: activeMenu === 'settings' }"
|
||||
@click="activeMenu = 'settings'"
|
||||
>
|
||||
<div class="menu-item" :class="{ active: activeMenu === 'settings' }" @click="activeMenu = 'settings'">
|
||||
<el-icon><ele-Setting /></el-icon>
|
||||
<span>配置</span>
|
||||
</div>
|
||||
@@ -130,13 +114,7 @@
|
||||
<span class="subtitle">解析成功后才能问答哦。</span>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<el-input
|
||||
v-model="searchKeyword"
|
||||
placeholder="搜索文件"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter="getFileList"
|
||||
>
|
||||
<el-input v-model="searchKeyword" placeholder="搜索文件" clearable style="width: 200px" @keyup.enter="getFileList">
|
||||
<template #prefix>
|
||||
<el-icon><ele-Search /></el-icon>
|
||||
</template>
|
||||
@@ -149,51 +127,33 @@
|
||||
</div>
|
||||
<div class="file-table" v-loading="fileLoading">
|
||||
<el-table :data="fileList" style="width: 100%" row-key="id" border>
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column prop="name" label="名称" min-width="200" sortable>
|
||||
<el-table-column prop="Title" label="名称" min-width="200">
|
||||
<template #default="scope">
|
||||
<div class="file-name" @click="onViewDocumentDetail(scope.row)">
|
||||
<el-icon class="file-icon" :style="{ color: getFileIconColor(scope.row.fileType) }">
|
||||
<ele-Document />
|
||||
</el-icon>
|
||||
<span class="file-link">{{ scope.row.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdAt" label="上传日期" width="180" sortable />
|
||||
<el-table-column prop="source" label="来源" width="80" align="center">
|
||||
<template #default>
|
||||
<el-icon><ele-Monitor /></el-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="enabled" label="启用" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.enabled"
|
||||
size="small"
|
||||
@change="onFileStatusChange(scope.row)"
|
||||
/>
|
||||
<span class="file-link" @click="onViewDocumentDetail(scope.row)" style="cursor: pointer; color: #409eff">{{
|
||||
scope.row.Title
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="chunkCount" label="分块数" width="80" align="center" />
|
||||
<el-table-column prop="parseStatus" label="解析" width="100" align="center">
|
||||
<el-table-column prop="status" label="状态" width="90" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getParseStatusType(scope.row.parseStatus)" size="small">
|
||||
{{ scope.row.parseStatus }}
|
||||
<el-tag :type="scope.row.status === 1 ? 'success' : 'info'" size="small">
|
||||
{{ scope.row.status === 1 ? '正常' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="动作" width="140" align="center">
|
||||
<el-table-column prop="vectorStatus" label="向量化" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-button text size="small" @click="onPreviewFile(scope.row)">
|
||||
<el-icon><ele-View /></el-icon>
|
||||
</el-button>
|
||||
<el-button text size="small" @click="onDownloadFile(scope.row)">
|
||||
<el-icon><ele-Download /></el-icon>
|
||||
</el-button>
|
||||
<el-button text size="small" type="danger" @click="onDeleteFile(scope.row)">
|
||||
<el-icon><ele-Delete /></el-icon>
|
||||
</el-button>
|
||||
<el-tag :type="scope.row.vectorStatus === 'done' ? 'success' : 'warning'" size="small">
|
||||
{{ scope.row.vectorStatus || '未处理' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdAt" label="上传日期" width="180" />
|
||||
<el-table-column label="动作" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-button text size="small" @click="onPreviewFile(scope.row)">预览</el-button>
|
||||
<el-button text size="small" type="danger" @click="onDeleteFile(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -205,12 +165,7 @@
|
||||
<template v-if="activeMenu === 'search'">
|
||||
<div class="panel-card">
|
||||
<h3>检索测试</h3>
|
||||
<el-input
|
||||
v-model="searchQuery"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="输入问题进行检索测试..."
|
||||
/>
|
||||
<el-input v-model="searchQuery" type="textarea" :rows="3" placeholder="输入问题进行检索测试..." />
|
||||
<el-button type="primary" class="mt15" @click="onSearchTest">测试检索</el-button>
|
||||
<div class="search-results mt15" v-if="searchResults.length > 0">
|
||||
<h4>检索结果</h4>
|
||||
@@ -227,12 +182,7 @@
|
||||
<div class="panel-card">
|
||||
<h3>操作日志</h3>
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="(log, index) in logList"
|
||||
:key="index"
|
||||
:timestamp="log.time"
|
||||
placement="top"
|
||||
>
|
||||
<el-timeline-item v-for="(log, index) in logList" :key="index" :timestamp="log.time" placement="top">
|
||||
<span>{{ log.content }}</span>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
@@ -246,7 +196,7 @@
|
||||
<h3>数据集配置</h3>
|
||||
<el-form label-width="120px" style="max-width: 500px">
|
||||
<el-form-item label="数据集名称">
|
||||
<el-input v-model="currentDataset.name" disabled />
|
||||
<el-input v-model="currentknowledge.name" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="向量模型">
|
||||
<el-select v-model="settingsForm.embeddingModel" style="width: 100%">
|
||||
@@ -272,33 +222,23 @@
|
||||
</div>
|
||||
|
||||
<!-- 新增/编辑数据集弹窗 -->
|
||||
<el-dialog
|
||||
:title="datasetForm.id ? '编辑知识库' : '新建知识库'"
|
||||
v-model="showDatasetDialog"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form ref="datasetFormRef" :model="datasetForm" :rules="datasetRules" label-width="100px">
|
||||
<el-dialog :title="knowledgeForm.id ? '编辑知识库' : '新建知识库'" v-model="showknowledgeDialog" width="500px" :close-on-click-modal="false">
|
||||
<el-form ref="knowledgeFormRef" :model="knowledgeForm" :rules="knowledgeRules" label-width="100px">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="datasetForm.name" placeholder="请输入知识库名称" />
|
||||
<el-input v-model="knowledgeForm.name" placeholder="请输入知识库名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="datasetForm.description" type="textarea" :rows="3" placeholder="请输入描述" />
|
||||
<el-input v-model="knowledgeForm.description" type="textarea" :rows="3" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showDatasetDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="onSaveDataset" :loading="datasetSaving">确定</el-button>
|
||||
<el-button @click="showknowledgeDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="onSaveknowledge" :loading="knowledgeSaving">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 上传文件弹窗 -->
|
||||
<el-dialog
|
||||
title="上传文件"
|
||||
v-model="showUploadDialog"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-dialog title="上传文件" v-model="showUploadDialog" width="600px" :close-on-click-modal="false">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
class="upload-area"
|
||||
@@ -327,8 +267,8 @@
|
||||
<!-- 文档详情弹窗 -->
|
||||
<DocumentDetailDialog
|
||||
v-model="showDocumentDetailDialog"
|
||||
:datasetId="currentDataset?.id || ''"
|
||||
:datasetName="currentDataset?.name || ''"
|
||||
:knowledgeId="currentknowledge?.id || ''"
|
||||
:knowledgeName="currentknowledge?.name || ''"
|
||||
:document="currentDocument"
|
||||
/>
|
||||
</div>
|
||||
@@ -345,24 +285,37 @@ import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import type { FormInstance, FormRules, UploadFile } from 'element-plus';
|
||||
import DocumentDetailDialog from './component/documentDetailDialog.vue';
|
||||
import { listDatasets, createKnowledgeBase, updateKnowledgeBase, deleteDataset } from '/@/api/knowledge/dataset';
|
||||
import { listknowledges, createknowledge, updateknowledge, deleteknowledge } from '/@/api/knowledge/dataset';
|
||||
import { listDocuments, uploadFile, createDocument, deleteDocument } from '/@/api/knowledge/document';
|
||||
|
||||
// 数据集相关
|
||||
const datasetLoading = ref(false);
|
||||
const datasetList = ref<any[]>([]);
|
||||
const currentDataset = ref<any>(null);
|
||||
const showDatasetDialog = ref(false);
|
||||
const datasetSaving = ref(false);
|
||||
const datasetFormRef = ref<FormInstance>();
|
||||
const datasetForm = reactive({
|
||||
const knowledgeLoading = ref(false);
|
||||
const knowledgeList = ref<any[]>([]);
|
||||
const currentknowledge = ref<any>(null);
|
||||
const showknowledgeDialog = ref(false);
|
||||
const knowledgeSaving = ref(false);
|
||||
const knowledgeFormRef = ref<FormInstance>();
|
||||
const knowledgeForm = reactive({
|
||||
id: '',
|
||||
name: '',
|
||||
description: '',
|
||||
});
|
||||
const datasetRules = reactive<FormRules>({
|
||||
const knowledgeRules = reactive<FormRules>({
|
||||
name: [{ required: true, message: '请输入知识库名称', trigger: 'blur' }],
|
||||
});
|
||||
|
||||
// 文件列表(含OSS上传结果)
|
||||
interface UploadFileItem {
|
||||
file: UploadFile;
|
||||
filePath: string;
|
||||
fileSize: number;
|
||||
fileFormat: string;
|
||||
fileName: string;
|
||||
uploading: boolean;
|
||||
error: boolean;
|
||||
}
|
||||
const uploadFileItems = ref<UploadFileItem[]>([]);
|
||||
|
||||
// 文件相关
|
||||
const fileLoading = ref(false);
|
||||
const fileList = ref<any[]>([]);
|
||||
@@ -401,7 +354,7 @@ const formatFileSize = (size: number) => {
|
||||
};
|
||||
|
||||
// 获取文件图标颜色
|
||||
const getFileIconColor = (fileType: string) => {
|
||||
const _getFileIconColor = (fileType: string) => {
|
||||
const colors: Record<string, string> = {
|
||||
pdf: '#f56c6c',
|
||||
docx: '#409eff',
|
||||
@@ -415,7 +368,7 @@ const getFileIconColor = (fileType: string) => {
|
||||
};
|
||||
|
||||
// 获取解析状态类型
|
||||
const getParseStatusType = (status: string) => {
|
||||
const _getParseStatusType = (status: string) => {
|
||||
const types: Record<string, string> = {
|
||||
general: 'success',
|
||||
pending: 'warning',
|
||||
@@ -425,40 +378,40 @@ const getParseStatusType = (status: string) => {
|
||||
};
|
||||
|
||||
// 获取数据集列表
|
||||
const getDatasetList = async () => {
|
||||
datasetLoading.value = true;
|
||||
const getknowledgeList = async () => {
|
||||
knowledgeLoading.value = true;
|
||||
try {
|
||||
const response = await listDatasets({
|
||||
const response = await listknowledges({
|
||||
pageNum: 1,
|
||||
pageSize: 100
|
||||
pageSize: 100,
|
||||
});
|
||||
datasetList.value = response.data.list || [];
|
||||
knowledgeList.value = response.data.list || [];
|
||||
} catch (_error) {
|
||||
ElMessage.error('获取知识库列表失败');
|
||||
} finally {
|
||||
datasetLoading.value = false;
|
||||
knowledgeLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 选择数据集
|
||||
const onSelectDataset = (item: any) => {
|
||||
currentDataset.value = item;
|
||||
const onSelectknowledge = (item: any) => {
|
||||
currentknowledge.value = item;
|
||||
activeMenu.value = 'files';
|
||||
getFileList();
|
||||
getLogList();
|
||||
};
|
||||
|
||||
// 新增数据集
|
||||
const onAddDataset = () => {
|
||||
datasetForm.id = '';
|
||||
datasetForm.name = '';
|
||||
datasetForm.description = '';
|
||||
showDatasetDialog.value = true;
|
||||
const onAddknowledge = () => {
|
||||
knowledgeForm.id = '';
|
||||
knowledgeForm.name = '';
|
||||
knowledgeForm.description = '';
|
||||
showknowledgeDialog.value = true;
|
||||
};
|
||||
|
||||
// 返回列表
|
||||
const onBackToList = () => {
|
||||
currentDataset.value = null;
|
||||
currentknowledge.value = null;
|
||||
};
|
||||
|
||||
// 右键菜单
|
||||
@@ -467,64 +420,66 @@ const onCardContextMenu = (event: MouseEvent, item: any) => {
|
||||
};
|
||||
|
||||
// 重命名数据集
|
||||
const onRenameDataset = (item: any) => {
|
||||
datasetForm.id = item.id;
|
||||
datasetForm.name = item.name;
|
||||
datasetForm.description = item.description || '';
|
||||
showDatasetDialog.value = true;
|
||||
const onRenameknowledge = (item: any) => {
|
||||
knowledgeForm.id = item.id;
|
||||
knowledgeForm.name = item.name;
|
||||
knowledgeForm.description = item.description || '';
|
||||
showknowledgeDialog.value = true;
|
||||
};
|
||||
|
||||
// 删除数据集
|
||||
const onDeleteDataset = (item: any) => {
|
||||
const onDeleteknowledge = (item: any) => {
|
||||
ElMessageBox.confirm(`确定要删除知识库【${item.name}】吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await deleteDataset(item.id);
|
||||
await deleteknowledge(item.id);
|
||||
ElMessage.success('删除成功');
|
||||
if (currentDataset.value?.id === item.id) {
|
||||
currentDataset.value = null;
|
||||
if (currentknowledge.value?.id === item.id) {
|
||||
currentknowledge.value = null;
|
||||
}
|
||||
getDatasetList();
|
||||
getknowledgeList();
|
||||
} catch (_error) {
|
||||
ElMessage.error('删除失败,请重试');
|
||||
}
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 保存数据集
|
||||
const onSaveDataset = async () => {
|
||||
const form = datasetFormRef.value;
|
||||
const onSaveknowledge = async () => {
|
||||
const form = knowledgeFormRef.value;
|
||||
if (!form) return;
|
||||
|
||||
form.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
datasetSaving.value = true;
|
||||
knowledgeSaving.value = true;
|
||||
try {
|
||||
if (datasetForm.id) {
|
||||
if (knowledgeForm.id) {
|
||||
// 更新知识库
|
||||
await updateKnowledgeBase({
|
||||
id: datasetForm.id,
|
||||
name: datasetForm.name,
|
||||
description: datasetForm.description
|
||||
await updateknowledge({
|
||||
id: knowledgeForm.id,
|
||||
name: knowledgeForm.name,
|
||||
description: knowledgeForm.description,
|
||||
});
|
||||
} else {
|
||||
// 创建知识库
|
||||
await createKnowledgeBase({
|
||||
name: datasetForm.name,
|
||||
description: datasetForm.description
|
||||
await createknowledge({
|
||||
name: knowledgeForm.name,
|
||||
description: knowledgeForm.description,
|
||||
});
|
||||
}
|
||||
|
||||
ElMessage.success(datasetForm.id ? '保存成功' : '创建成功');
|
||||
showDatasetDialog.value = false;
|
||||
getDatasetList();
|
||||
ElMessage.success(knowledgeForm.id ? '保存成功' : '创建成功');
|
||||
showknowledgeDialog.value = false;
|
||||
getknowledgeList();
|
||||
} catch (_error) {
|
||||
ElMessage.error('保存失败,请重试');
|
||||
} finally {
|
||||
datasetSaving.value = false;
|
||||
knowledgeSaving.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -532,40 +487,17 @@ const onSaveDataset = async () => {
|
||||
|
||||
// 获取文件列表
|
||||
const getFileList = async () => {
|
||||
if (!currentDataset.value) return;
|
||||
if (!currentknowledge.value) return;
|
||||
|
||||
fileLoading.value = true;
|
||||
try {
|
||||
// 模拟数据
|
||||
fileList.value = [
|
||||
{
|
||||
id: '1',
|
||||
name: '456_product(1).txt',
|
||||
fileType: 'txt',
|
||||
createdAt: '21/01/2026 16:53:32',
|
||||
enabled: true,
|
||||
chunkCount: 1,
|
||||
parseStatus: 'general',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '123_speech(1).txt',
|
||||
fileType: 'txt',
|
||||
createdAt: '21/01/2026 16:53:26',
|
||||
enabled: true,
|
||||
chunkCount: 1,
|
||||
parseStatus: 'general',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: '123_product.txt',
|
||||
fileType: 'txt',
|
||||
createdAt: '21/01/2026 14:39:41',
|
||||
enabled: true,
|
||||
chunkCount: 1,
|
||||
parseStatus: 'general',
|
||||
},
|
||||
];
|
||||
const response = await listDocuments({
|
||||
datasetId: currentknowledge.value.id,
|
||||
...(searchKeyword.value ? { keyword: searchKeyword.value } : {}),
|
||||
pageNum: 1,
|
||||
pageSize: 100,
|
||||
});
|
||||
fileList.value = response.data?.list || [];
|
||||
} catch (_error) {
|
||||
ElMessage.error('获取文件列表失败');
|
||||
} finally {
|
||||
@@ -575,36 +507,78 @@ const getFileList = async () => {
|
||||
|
||||
// 上传文件
|
||||
const onUploadFile = () => {
|
||||
uploadFileItems.value = [];
|
||||
uploadFileList.value = [];
|
||||
showUploadDialog.value = true;
|
||||
};
|
||||
|
||||
// 上传文件变化
|
||||
const onUploadChange = (file: UploadFile, files: UploadFile[]) => {
|
||||
// 选择文件时立即上传到OSS
|
||||
const onUploadChange = async (file: UploadFile, files: UploadFile[]) => {
|
||||
uploadFileList.value = files;
|
||||
// 找出新增的文件(还没有对应的 item)
|
||||
const exists = uploadFileItems.value.some((i) => i.file.uid === file.uid);
|
||||
if (exists || !file.raw) return;
|
||||
const item: UploadFileItem = {
|
||||
file,
|
||||
filePath: '',
|
||||
fileSize: 0,
|
||||
fileFormat: '',
|
||||
fileName: file.name,
|
||||
uploading: true,
|
||||
error: false,
|
||||
};
|
||||
uploadFileItems.value.push(item);
|
||||
try {
|
||||
const ossRes = await uploadFile(file.raw as File);
|
||||
item.filePath = ossRes.data?.fileURL || '';
|
||||
item.fileSize = ossRes.data?.fileSize || file.size || 0;
|
||||
item.fileFormat = ossRes.data?.fileFormat || file.name.split('.').pop() || '';
|
||||
item.fileName = ossRes.data?.fileName || file.name;
|
||||
item.uploading = false;
|
||||
} catch (_e) {
|
||||
item.uploading = false;
|
||||
item.error = true;
|
||||
ElMessage.error(`${file.name} 上传失败`);
|
||||
}
|
||||
};
|
||||
|
||||
// 移除上传文件
|
||||
const onUploadRemove = (file: UploadFile, files: UploadFile[]) => {
|
||||
uploadFileList.value = files;
|
||||
uploadFileItems.value = uploadFileItems.value.filter((i) => i.file.uid !== file.uid);
|
||||
};
|
||||
|
||||
// 确认上传
|
||||
// 确认上传:所有文件已上传OSS,直接创建文档
|
||||
const onConfirmUpload = async () => {
|
||||
const readyItems = uploadFileItems.value.filter((i) => !i.uploading && !i.error && i.filePath);
|
||||
if (readyItems.length === 0) {
|
||||
ElMessage.warning('请等待文件上传完成或移除上传失败的文件');
|
||||
return;
|
||||
}
|
||||
uploading.value = true;
|
||||
try {
|
||||
ElMessage.success(`成功上传 ${uploadFileList.value.length} 个文件`);
|
||||
for (const item of readyItems) {
|
||||
const ext = item.file.name.split('.').pop() || '';
|
||||
await createDocument({
|
||||
datasetId: currentknowledge.value.id,
|
||||
filePath: item.filePath,
|
||||
fileSize: item.fileSize || item.file.size || 0,
|
||||
format: item.fileFormat || ext,
|
||||
title: item.fileName || item.file.name,
|
||||
});
|
||||
}
|
||||
ElMessage.success(`成功创建 ${readyItems.length} 个文件`);
|
||||
showUploadDialog.value = false;
|
||||
getFileList();
|
||||
} catch (_error) {
|
||||
ElMessage.error('上传失败,请重试');
|
||||
ElMessage.error('创建文档失败,请重试');
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 文件状态变化
|
||||
const onFileStatusChange = (row: any) => {
|
||||
const _onFileStatusChange = (row: any) => {
|
||||
ElMessage.success(row.enabled ? '已启用' : '已禁用');
|
||||
};
|
||||
|
||||
@@ -620,7 +594,7 @@ const onPreviewFile = (row: any) => {
|
||||
};
|
||||
|
||||
// 下载文件
|
||||
const onDownloadFile = (row: any) => {
|
||||
const _onDownloadFile = (row: any) => {
|
||||
ElMessage.info(`下载文件: ${row.name}`);
|
||||
};
|
||||
|
||||
@@ -630,10 +604,17 @@ const onDeleteFile = (row: any) => {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await deleteDocument(row.id);
|
||||
ElMessage.success('删除成功');
|
||||
getFileList();
|
||||
}).catch(() => {});
|
||||
} catch (_error) {
|
||||
ElMessage.error('删除失败,请重试');
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 检索测试
|
||||
@@ -656,7 +637,7 @@ const getLogList = () => {
|
||||
{ time: '2026-01-21 16:53:32', content: '上传文件 456_product(1).txt' },
|
||||
{ time: '2026-01-21 16:53:26', content: '上传文件 123_speech(1).txt' },
|
||||
{ time: '2026-01-21 14:39:41', content: '上传文件 123_product.txt' },
|
||||
{ time: '2026-01-17 10:00:00', content: '创建知识库 dataset_tenant_1' },
|
||||
{ time: '2026-01-17 10:00:00', content: '创建知识库 knowledge_tenant_1' },
|
||||
];
|
||||
};
|
||||
|
||||
@@ -667,7 +648,7 @@ const onSaveSettings = () => {
|
||||
|
||||
// 页面加载
|
||||
onMounted(() => {
|
||||
getDatasetList();
|
||||
getknowledgeList();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -678,7 +659,7 @@ onMounted(() => {
|
||||
box-sizing: border-box;
|
||||
|
||||
// 数据集列表页
|
||||
.dataset-list-view {
|
||||
.knowledge-list-view {
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -703,12 +684,12 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.dataset-cards {
|
||||
.knowledge-cards {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
|
||||
.dataset-card {
|
||||
.knowledge-card {
|
||||
width: 200px;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
@@ -804,7 +785,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
// 数据集详情页
|
||||
.dataset-detail-view {
|
||||
.knowledge-detail-view {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -840,7 +821,7 @@ onMounted(() => {
|
||||
flex-direction: column;
|
||||
background: #fafafa;
|
||||
|
||||
.dataset-profile {
|
||||
.knowledge-profile {
|
||||
padding: 20px 16px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ export default defineComponent({
|
||||
draggable: '.workflow-left-item',
|
||||
forceFallback: true,
|
||||
onEnd: function (evt: any) {
|
||||
const { name, icon, id } = evt.clone.dataset;
|
||||
const { name, icon, id } = evt.clone.knowledge;
|
||||
const { layerX, layerY, clientX, clientY } = evt.originalEvent;
|
||||
const el = state.workflowRightRef!;
|
||||
const { x, y, width, height } = el.getBoundingClientRect();
|
||||
@@ -617,8 +617,8 @@ export default defineComponent({
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
background-image: linear-gradient(90deg, rgb(156 214 255 / 15%) 10%, rgba(0, 0, 0, 0) 10%),
|
||||
linear-gradient(rgb(156 214 255 / 15%) 10%, rgba(0, 0, 0, 0) 10%);
|
||||
background-image:
|
||||
linear-gradient(90deg, rgb(156 214 255 / 15%) 10%, rgba(0, 0, 0, 0) 10%), linear-gradient(rgb(156 214 255 / 15%) 10%, rgba(0, 0, 0, 0) 10%);
|
||||
background-size: 10px 10px;
|
||||
.workflow-right-clone {
|
||||
position: absolute;
|
||||
|
||||
@@ -707,7 +707,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
],
|
||||
dataset: {
|
||||
knowledge: {
|
||||
source: [
|
||||
{ status: '已签收', value1: 33, value2: 93 },
|
||||
{ status: '配送中', value1: 53, value2: 32 },
|
||||
|
||||
Reference in New Issue
Block a user