重构知识库相关接口,更新数据结构和命名,移除示例文件,调整组件和视图以支持新命名,优化文档和数据集管理功能。
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';
|
import { newService } from '/@/utils/request';
|
||||||
|
|
||||||
// 数据集查询参数
|
// 数据集查询参数
|
||||||
export interface DatasetQueryParams {
|
export interface knowledgeQueryParams {
|
||||||
keyword?: string;
|
keyword?: string;
|
||||||
status?: string;
|
|
||||||
pageNum: number;
|
pageNum: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建知识库参数
|
// 创建知识库参数
|
||||||
export interface CreateDatasetParams {
|
export interface CreateknowledgeParams {
|
||||||
name: string; // 必传
|
name: string; // 必传
|
||||||
description?: string; // 可选
|
description?: string; // 可选
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新知识库参数
|
// 更新知识库参数
|
||||||
export interface UpdateDatasetParams {
|
export interface UpdateknowledgeParams {
|
||||||
id: string; // 必传
|
id: string; // 必传
|
||||||
name?: string; // 可选
|
name?: string; // 可选
|
||||||
description?: string; // 可选
|
description?: string; // 可选
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数据集信息
|
// 数据集信息
|
||||||
export interface DatasetInfo {
|
export interface knowledgeInfo {
|
||||||
id?: string;
|
id?: string;
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
type: string; // text, qa, table
|
fileCount?: number;
|
||||||
documentCount?: number;
|
totalSize?: number;
|
||||||
charCount?: number;
|
|
||||||
status: string; // enable, disable
|
|
||||||
embeddingModel?: string;
|
|
||||||
createdAt?: string;
|
createdAt?: string;
|
||||||
updatedAt?: string;
|
updatedAt?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取数据集列表
|
// 获取知识库列表
|
||||||
export function listDatasets(params: DatasetQueryParams) {
|
export function listknowledges(params: knowledgeQueryParams) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/rag-knowledge/knowledge/listKnowledge',
|
url: '/rag-knowledge/dataset/listDataset',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取数据集详情
|
// 创建知识库
|
||||||
export function getDataset(id: string) {
|
export function createknowledge(data: CreateknowledgeParams) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/dataset/detail',
|
url: '/rag-knowledge/dataset/createDataset',
|
||||||
method: 'get',
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建数据集(简化版)
|
|
||||||
export function createKnowledgeBase(data: CreateDatasetParams) {
|
|
||||||
return newService({
|
|
||||||
url: '/rag-knowledge/knowledge/createKnowledge',
|
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建数据集(完整版)
|
// 更新知识库
|
||||||
export function createDataset(data: DatasetInfo) {
|
export function updateknowledge(data: UpdateknowledgeParams) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/dataset/create',
|
url: '/rag-knowledge/dataset/updateDataset',
|
||||||
method: 'post',
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新知识库(简化版)
|
|
||||||
export function updateKnowledgeBase(data: UpdateDatasetParams) {
|
|
||||||
return newService({
|
|
||||||
url: '/rag-knowledge/knowledge/updateKnowledge',
|
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新数据集(完整版)
|
// 删除知识库
|
||||||
export function updateDataset(data: DatasetInfo) {
|
export function deleteknowledge(id: string) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/dataset/update',
|
url: '/rag-knowledge/dataset/deleteDataset',
|
||||||
method: 'put',
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除数据集
|
|
||||||
export function deleteDataset(id: string) {
|
|
||||||
return newService({
|
|
||||||
url: '/rag-knowledge/knowledge/deleteKnowledge',
|
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
params: { id },
|
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,29 +4,27 @@ import { newService } from '/@/utils/request';
|
|||||||
export interface DocumentQueryParams {
|
export interface DocumentQueryParams {
|
||||||
keyword?: string;
|
keyword?: string;
|
||||||
datasetId?: string;
|
datasetId?: string;
|
||||||
status?: string;
|
|
||||||
fileType?: string;
|
|
||||||
pageNum: number;
|
pageNum: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建文档参数
|
// 创建文档参数
|
||||||
export interface CreateDocumentParams {
|
export interface CreateDocumentParams {
|
||||||
KnowledgeId: number; // 必传
|
datasetId: string; // 必传
|
||||||
filePath: string; // 必传
|
filePath: string; // 必传
|
||||||
fileSize: number; // 必传
|
fileSize: number; // 必传
|
||||||
format: string; // 必传
|
format: string; // 必传
|
||||||
title: string; // 必传
|
title: string; // 必传
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新文档参数
|
// 更新文档参数
|
||||||
export interface UpdateDocumentParams {
|
export interface UpdateDocumentParams {
|
||||||
id: string; // 必传
|
id: string; // 必传
|
||||||
KnowledgeId?: number; // 可选
|
datasetId?: string;
|
||||||
filePath?: string; // 可选
|
filePath?: string;
|
||||||
fileSize?: number; // 可选
|
fileSize?: number;
|
||||||
format?: string; // 可选
|
format?: string;
|
||||||
title?: string; // 可选
|
title?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文档信息
|
// 文档信息
|
||||||
@@ -34,35 +32,20 @@ export interface DocumentInfo {
|
|||||||
id?: string;
|
id?: string;
|
||||||
name: string;
|
name: string;
|
||||||
datasetId: string;
|
datasetId: string;
|
||||||
datasetName?: string;
|
fileType: string;
|
||||||
fileType: string; // pdf, docx, txt, md, html
|
|
||||||
fileSize?: number;
|
fileSize?: number;
|
||||||
filePath?: string;
|
filePath?: string;
|
||||||
charCount?: number;
|
|
||||||
chunkCount?: number;
|
chunkCount?: number;
|
||||||
status: string; // pending, processing, completed, failed
|
parseStatus?: string;
|
||||||
indexStatus?: string; // not_indexed, indexing, indexed, failed
|
enabled?: boolean;
|
||||||
errorMessage?: string;
|
|
||||||
createdAt?: string;
|
createdAt?: string;
|
||||||
updatedAt?: 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) {
|
export function listDocuments(params: DocumentQueryParams) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/document/list',
|
url: '/rag-knowledge/document/listDocument',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
@@ -71,16 +54,16 @@ export function listDocuments(params: DocumentQueryParams) {
|
|||||||
// 获取文档详情
|
// 获取文档详情
|
||||||
export function getDocument(id: string) {
|
export function getDocument(id: string) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/document/detail',
|
url: '/rag-knowledge/document/getDocument',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: { id },
|
params: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建文档(JSON格式)
|
// 创建文档
|
||||||
export function createDocument(data: CreateDocumentParams) {
|
export function createDocument(data: CreateDocumentParams) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/document/create',
|
url: '/rag-knowledge/document/createDocument',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
@@ -89,16 +72,28 @@ export function createDocument(data: CreateDocumentParams) {
|
|||||||
// 更新文档
|
// 更新文档
|
||||||
export function updateDocument(data: UpdateDocumentParams) {
|
export function updateDocument(data: UpdateDocumentParams) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/document/update',
|
url: '/rag-knowledge/document/updateDocument',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data,
|
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) {
|
export function uploadDocument(data: FormData) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/document/upload',
|
url: '/rag-knowledge/document/createDocument',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -110,61 +105,16 @@ export function uploadDocument(data: FormData) {
|
|||||||
// 删除文档
|
// 删除文档
|
||||||
export function deleteDocument(id: string) {
|
export function deleteDocument(id: string) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/document/delete',
|
url: '/rag-knowledge/document/deleteDocument',
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
params: { id },
|
params: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量删除文档
|
// 获取文件向量化处理进度
|
||||||
export function batchDeleteDocuments(ids: string[]) {
|
export function getDocumentProcess(id: string) {
|
||||||
return newService({
|
return newService({
|
||||||
url: '/knowledge/document/batchDelete',
|
url: '/rag-knowledge/document/getProcess',
|
||||||
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',
|
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: { id },
|
params: { id },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export const lazyImg = (el: any, arr: any) => {
|
|||||||
const io = new IntersectionObserver((res) => {
|
const io = new IntersectionObserver((res) => {
|
||||||
res.forEach((v: any) => {
|
res.forEach((v: any) => {
|
||||||
if (v.isIntersecting) {
|
if (v.isIntersecting) {
|
||||||
const { img, key } = v.target.dataset;
|
const { img, key } = v.target.knowledge;
|
||||||
v.target.src = img;
|
v.target.src = img;
|
||||||
v.target.onload = () => {
|
v.target.onload = () => {
|
||||||
io.unobserve(v.target);
|
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,22 +13,20 @@
|
|||||||
<div class="document-content">
|
<div class="document-content">
|
||||||
<div class="content-header">
|
<div class="content-header">
|
||||||
<h2>{{ documentInfo.name }}</h2>
|
<h2>{{ documentInfo.name }}</h2>
|
||||||
<div class="content-meta">
|
<div class="content-meta">Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}</div>
|
||||||
Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="content-body" v-loading="contentLoading">
|
<div class="content-body" v-loading="contentLoading">
|
||||||
<pre class="document-text">{{ documentContent }}</pre>
|
<pre class="document-text">{{ documentContent }}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 右侧:切片结果 -->
|
<!-- 右侧:切片结果 -->
|
||||||
<div class="chunk-panel">
|
<div class="chunk-panel">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<h3>切片结果</h3>
|
<h3>切片结果</h3>
|
||||||
<div class="panel-subtitle">查看用于嵌入和召回的切片段落。</div>
|
<div class="panel-subtitle">查看用于嵌入和召回的切片段落。</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-toolbar">
|
<div class="panel-toolbar">
|
||||||
<div class="toolbar-tabs">
|
<div class="toolbar-tabs">
|
||||||
<el-radio-group v-model="viewMode" size="small">
|
<el-radio-group v-model="viewMode" size="small">
|
||||||
@@ -37,13 +35,7 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-actions">
|
<div class="toolbar-actions">
|
||||||
<el-input
|
<el-input v-model="chunkSearch" placeholder="搜索" clearable size="small" style="width: 120px">
|
||||||
v-model="chunkSearch"
|
|
||||||
placeholder="搜索"
|
|
||||||
clearable
|
|
||||||
size="small"
|
|
||||||
style="width: 120px"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<el-icon><ele-Search /></el-icon>
|
<el-icon><ele-Search /></el-icon>
|
||||||
</template>
|
</template>
|
||||||
@@ -53,17 +45,13 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chunk-list" v-loading="chunkLoading">
|
<div class="chunk-list" v-loading="chunkLoading">
|
||||||
<div class="select-all">
|
<div class="select-all">
|
||||||
<el-checkbox v-model="selectAll" @change="onSelectAllChange">选择所有</el-checkbox>
|
<el-checkbox v-model="selectAll" @change="onSelectAllChange">选择所有</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="chunk-item" v-for="chunk in filteredChunks" :key="chunk.id">
|
||||||
class="chunk-item"
|
|
||||||
v-for="chunk in filteredChunks"
|
|
||||||
:key="chunk.id"
|
|
||||||
>
|
|
||||||
<div class="chunk-checkbox">
|
<div class="chunk-checkbox">
|
||||||
<el-checkbox v-model="chunk.selected" />
|
<el-checkbox v-model="chunk.selected" />
|
||||||
</div>
|
</div>
|
||||||
@@ -74,10 +62,10 @@
|
|||||||
<el-switch v-model="chunk.enabled" size="small" @change="onChunkStatusChange(chunk)" />
|
<el-switch v-model="chunk.enabled" size="small" @change="onChunkStatusChange(chunk)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-empty v-if="filteredChunks.length === 0 && !chunkLoading" description="暂无切片" :image-size="60" />
|
<el-empty v-if="filteredChunks.length === 0 && !chunkLoading" description="暂无切片" :image-size="60" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
<span class="total-info">总共 {{ chunkTotal }} 条</span>
|
<span class="total-info">总共 {{ chunkTotal }} 条</span>
|
||||||
@@ -112,8 +100,8 @@ import { ElMessage } from 'element-plus';
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: boolean;
|
modelValue: boolean;
|
||||||
datasetId: string;
|
knowledgeId: string;
|
||||||
datasetName: string;
|
knowledgeName: string;
|
||||||
document: any;
|
document: any;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
@@ -150,9 +138,7 @@ const selectAll = ref(false);
|
|||||||
// 过滤后的切片列表
|
// 过滤后的切片列表
|
||||||
const filteredChunks = computed(() => {
|
const filteredChunks = computed(() => {
|
||||||
if (!chunkSearch.value) return chunkList.value;
|
if (!chunkSearch.value) return chunkList.value;
|
||||||
return chunkList.value.filter((chunk) =>
|
return chunkList.value.filter((chunk) => (chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase()));
|
||||||
(chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase())
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 格式化文件大小
|
// 格式化文件大小
|
||||||
@@ -179,7 +165,7 @@ const getDocumentDetail = async () => {
|
|||||||
documentInfo.fileType = props.document?.fileType || 'txt';
|
documentInfo.fileType = props.document?.fileType || 'txt';
|
||||||
documentInfo.fileSize = props.document?.fileSize || 10;
|
documentInfo.fileSize = props.document?.fileSize || 10;
|
||||||
documentInfo.createdAt = props.document?.createdAt || '22/01/2026 00:53:32';
|
documentInfo.createdAt = props.document?.createdAt || '22/01/2026 00:53:32';
|
||||||
|
|
||||||
// 模拟文档内容
|
// 模拟文档内容
|
||||||
documentContent.value = '<p>123</p>';
|
documentContent.value = '<p>123</p>';
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
@@ -215,7 +201,7 @@ const getChunkList = async () => {
|
|||||||
|
|
||||||
// 全选变化
|
// 全选变化
|
||||||
const onSelectAllChange = (val: boolean) => {
|
const onSelectAllChange = (val: boolean) => {
|
||||||
chunkList.value.forEach(chunk => {
|
chunkList.value.forEach((chunk) => {
|
||||||
chunk.selected = val;
|
chunk.selected = val;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -231,12 +217,15 @@ const onAddChunk = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 监听弹窗打开
|
// 监听弹窗打开
|
||||||
watch(() => props.modelValue, (val) => {
|
watch(
|
||||||
if (val && props.document) {
|
() => props.modelValue,
|
||||||
getDocumentDetail();
|
(val) => {
|
||||||
getChunkList();
|
if (val && props.document) {
|
||||||
|
getDocumentDetail();
|
||||||
|
getChunkList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -250,7 +239,7 @@ watch(() => props.modelValue, (val) => {
|
|||||||
.drawer-content {
|
.drawer-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
// 左侧文档内容
|
// 左侧文档内容
|
||||||
.document-content {
|
.document-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -258,30 +247,30 @@ watch(() => props.modelValue, (val) => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-right: 1px solid #ebeef5;
|
border-right: 1px solid #ebeef5;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.content-header {
|
.content-header {
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 0 0 8px 0;
|
margin: 0 0 8px 0;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-meta {
|
.content-meta {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-body {
|
.content-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
|
|
||||||
.document-text {
|
.document-text {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||||
@@ -293,53 +282,53 @@ watch(() => props.modelValue, (val) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 右侧切片面板
|
// 右侧切片面板
|
||||||
.chunk-panel {
|
.chunk-panel {
|
||||||
width: 420px;
|
width: 420px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
.panel-header {
|
.panel-header {
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
margin: 0 0 4px 0;
|
margin: 0 0 4px 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-subtitle {
|
.panel-subtitle {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-toolbar {
|
.panel-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
.toolbar-actions {
|
.toolbar-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-list {
|
.chunk-list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
|
|
||||||
.select-all {
|
.select-all {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-item {
|
.chunk-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@@ -348,16 +337,16 @@ watch(() => props.modelValue, (val) => {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
border: 1px solid #ebeef5;
|
border: 1px solid #ebeef5;
|
||||||
|
|
||||||
.chunk-checkbox {
|
.chunk-checkbox {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-content {
|
.chunk-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
.chunk-text {
|
.chunk-text {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
@@ -365,14 +354,14 @@ watch(() => props.modelValue, (val) => {
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-actions {
|
.chunk-actions {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-footer {
|
.panel-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -380,7 +369,7 @@ watch(() => props.modelValue, (val) => {
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
border-top: 1px solid #ebeef5;
|
border-top: 1px solid #ebeef5;
|
||||||
|
|
||||||
.total-info {
|
.total-info {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog :title="isEdit ? '编辑数据集' : '新增数据集'" v-model="isShowDialog" width="600px" :close-on-click-modal="false" @close="onCancel">
|
||||||
: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-form ref="formRef" :model="ruleForm" :rules="rules" label-width="100px">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
@@ -67,7 +61,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'editDataset',
|
name: 'editknowledge',
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -75,10 +69,10 @@ export default {
|
|||||||
import { ref, reactive } from 'vue';
|
import { ref, reactive } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import type { FormInstance, FormRules } 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
|
// 表单ref
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
@@ -121,10 +115,10 @@ const resetForm = () => {
|
|||||||
const openDialog = async (row?: any) => {
|
const openDialog = async (row?: any) => {
|
||||||
resetForm();
|
resetForm();
|
||||||
isEdit.value = !!row;
|
isEdit.value = !!row;
|
||||||
|
|
||||||
if (row) {
|
if (row) {
|
||||||
try {
|
try {
|
||||||
const res: any = await getDataset(row.id);
|
const res: any = await getknowledge(row.id);
|
||||||
const data = res.data || row;
|
const data = res.data || row;
|
||||||
ruleForm.id = data.id || '';
|
ruleForm.id = data.id || '';
|
||||||
ruleForm.name = data.name || '';
|
ruleForm.name = data.name || '';
|
||||||
@@ -145,7 +139,7 @@ const openDialog = async (row?: any) => {
|
|||||||
ruleForm.charCount = row.charCount || 0;
|
ruleForm.charCount = row.charCount || 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isShowDialog.value = true;
|
isShowDialog.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -159,7 +153,7 @@ const onCancel = () => {
|
|||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
const form = formRef.value;
|
const form = formRef.value;
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
|
|
||||||
form.validate(async (valid: boolean) => {
|
form.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
submitLoading.value = true;
|
submitLoading.value = true;
|
||||||
@@ -172,17 +166,17 @@ const onSubmit = async () => {
|
|||||||
embeddingModel: ruleForm.embeddingModel,
|
embeddingModel: ruleForm.embeddingModel,
|
||||||
status: 'enable',
|
status: 'enable',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isEdit.value) {
|
if (isEdit.value) {
|
||||||
await updateDataset(data);
|
await updateknowledge(data);
|
||||||
ElMessage.success('保存成功');
|
ElMessage.success('保存成功');
|
||||||
} else {
|
} else {
|
||||||
await createDataset(data);
|
await createknowledge(data);
|
||||||
ElMessage.success('创建成功');
|
ElMessage.success('创建成功');
|
||||||
}
|
}
|
||||||
|
|
||||||
isShowDialog.value = false;
|
isShowDialog.value = false;
|
||||||
emit('getDatasetList');
|
emit('getknowledgeList');
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
ElMessage.error(isEdit.value ? '保存失败,请重试' : '创建失败,请重试');
|
ElMessage.error(isEdit.value ? '保存失败,请重试' : '创建失败,请重试');
|
||||||
} finally {
|
} finally {
|
||||||
@@ -198,5 +192,4 @@ defineExpose({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss"></style>
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="knowledge-dataset-page">
|
<div class="knowledge-knowledge-page">
|
||||||
<div class="knowledge-dataset-container">
|
<div class="knowledge-knowledge-container">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<div class="knowledge-dataset-search mb15">
|
<div class="knowledge-knowledge-search mb15">
|
||||||
<el-form :inline="true">
|
<el-form :inline="true">
|
||||||
<el-form-item label="数据集名称">
|
<el-form-item label="数据集名称">
|
||||||
<el-input size="default" v-model="tableData.param.keyword" placeholder="请输入数据集名称" clearable style="width: 200px" />
|
<el-input size="default" v-model="tableData.param.keyword" placeholder="请输入数据集名称" clearable style="width: 200px" />
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<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-icon><ele-Search /></el-icon>
|
||||||
查询
|
查询
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<el-icon><ele-Refresh /></el-icon>
|
<el-icon><ele-Refresh /></el-icon>
|
||||||
重置
|
重置
|
||||||
</el-button>
|
</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-icon><ele-Plus /></el-icon>
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
active-text="启"
|
active-text="启"
|
||||||
inactive-text="停"
|
inactive-text="停"
|
||||||
@change="onStatusChange(scope.row)"
|
@change="onStatusChange(scope.row)"
|
||||||
v-auth="'api/v1/knowledge/dataset/updateStatus'"
|
v-auth="'api/v1/knowledge/knowledge/updateStatus'"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -71,9 +71,9 @@
|
|||||||
<el-table-column prop="updatedAt" label="更新时间" width="170" show-overflow-tooltip />
|
<el-table-column prop="updatedAt" label="更新时间" width="170" show-overflow-tooltip />
|
||||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||||
<template #default="scope">
|
<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="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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -91,13 +91,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
<EditDataset ref="editDatasetRef" @getDatasetList="getDatasetList" />
|
<Editknowledge ref="editknowledgeRef" @getknowledgeList="getknowledgeList" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'knowledgeDataset',
|
name: 'knowledgeknowledge',
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -105,8 +105,8 @@ export default {
|
|||||||
import { ref, reactive, onMounted } from 'vue';
|
import { ref, reactive, onMounted } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { listDatasets, deleteDataset, updateDatasetStatus } from '/@/api/knowledge/dataset';
|
import { listknowledges, deleteknowledge, updateknowledgeStatus } from '/@/api/knowledge/knowledge';
|
||||||
import EditDataset from './component/editDataset.vue';
|
import Editknowledge from './component/editknowledge.vue';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@@ -125,13 +125,13 @@ const tableData = reactive({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 编辑弹窗ref
|
// 编辑弹窗ref
|
||||||
const editDatasetRef = ref();
|
const editknowledgeRef = ref();
|
||||||
|
|
||||||
// 获取数据集列表
|
// 获取数据集列表
|
||||||
const getDatasetList = async () => {
|
const getknowledgeList = async () => {
|
||||||
tableData.loading = true;
|
tableData.loading = true;
|
||||||
try {
|
try {
|
||||||
const res: any = await listDatasets(tableData.param);
|
const res: any = await listknowledges(tableData.param);
|
||||||
const list = res.data?.list || [];
|
const list = res.data?.list || [];
|
||||||
tableData.data = list.map((item: any) => ({
|
tableData.data = list.map((item: any) => ({
|
||||||
...item,
|
...item,
|
||||||
@@ -190,27 +190,27 @@ const onResetQuery = () => {
|
|||||||
tableData.param.type = '';
|
tableData.param.type = '';
|
||||||
tableData.param.status = undefined;
|
tableData.param.status = undefined;
|
||||||
tableData.param.pageNum = 1;
|
tableData.param.pageNum = 1;
|
||||||
getDatasetList();
|
getknowledgeList();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开新增弹窗
|
// 打开新增弹窗
|
||||||
const onOpenAdd = () => {
|
const onOpenAdd = () => {
|
||||||
editDatasetRef.value.openDialog();
|
editknowledgeRef.value.openDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开编辑弹窗
|
// 打开编辑弹窗
|
||||||
const onEdit = (row: any) => {
|
const onEdit = (row: any) => {
|
||||||
editDatasetRef.value.openDialog(row);
|
editknowledgeRef.value.openDialog(row);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
const onViewDetail = (row: any) => {
|
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) => {
|
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 newStatus = row.statusEnabled ? 'enable' : 'disable';
|
||||||
const statusText = row.statusEnabled ? '启用' : '禁用';
|
const statusText = row.statusEnabled ? '启用' : '禁用';
|
||||||
try {
|
try {
|
||||||
await updateDatasetStatus({ id: row.id, status: newStatus });
|
await updateknowledgeStatus({ id: row.id, status: newStatus });
|
||||||
ElMessage.success(`${statusText}成功`);
|
ElMessage.success(`${statusText}成功`);
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
row.statusEnabled = !row.statusEnabled;
|
row.statusEnabled = !row.statusEnabled;
|
||||||
@@ -232,40 +232,42 @@ const onRowDel = (row: any) => {
|
|||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(async () => {
|
})
|
||||||
try {
|
.then(async () => {
|
||||||
await deleteDataset(row.id);
|
try {
|
||||||
ElMessage.success('删除成功');
|
await deleteknowledge(row.id);
|
||||||
getDatasetList();
|
ElMessage.success('删除成功');
|
||||||
} catch (_error) {
|
getknowledgeList();
|
||||||
ElMessage.error('删除失败');
|
} catch (_error) {
|
||||||
}
|
ElMessage.error('删除失败');
|
||||||
}).catch(() => {});
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 分页大小改变
|
// 分页大小改变
|
||||||
const onSizeChange = (size: number) => {
|
const onSizeChange = (size: number) => {
|
||||||
tableData.param.pageSize = size;
|
tableData.param.pageSize = size;
|
||||||
getDatasetList();
|
getknowledgeList();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 当前页改变
|
// 当前页改变
|
||||||
const onCurrentChange = (page: number) => {
|
const onCurrentChange = (page: number) => {
|
||||||
tableData.param.pageNum = page;
|
tableData.param.pageNum = page;
|
||||||
getDatasetList();
|
getknowledgeList();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面加载时获取数据
|
// 页面加载时获取数据
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDatasetList();
|
getknowledgeList();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.knowledge-dataset-page {
|
.knowledge-knowledge-page {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
.knowledge-dataset-container {
|
.knowledge-knowledge-container {
|
||||||
.knowledge-dataset-search {
|
.knowledge-knowledge-search {
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-drawer
|
<el-drawer v-model="isShowDrawer" title="文档分段管理" size="70%" :close-on-click-modal="true">
|
||||||
v-model="isShowDrawer"
|
|
||||||
title="文档分段管理"
|
|
||||||
size="70%"
|
|
||||||
:close-on-click-modal="true"
|
|
||||||
>
|
|
||||||
<div class="chunks-container" v-loading="loading">
|
<div class="chunks-container" v-loading="loading">
|
||||||
<div class="chunks-header">
|
<div class="chunks-header">
|
||||||
<div class="doc-info">
|
<div class="doc-info">
|
||||||
@@ -12,13 +7,7 @@
|
|||||||
<el-tag size="small" type="info">共 {{ tableData.total }} 个分段</el-tag>
|
<el-tag size="small" type="info">共 {{ tableData.total }} 个分段</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<el-input
|
<el-input v-model="searchKeyword" placeholder="搜索分段内容" clearable style="width: 200px" @keyup.enter="onSearch">
|
||||||
v-model="searchKeyword"
|
|
||||||
placeholder="搜索分段内容"
|
|
||||||
clearable
|
|
||||||
style="width: 200px"
|
|
||||||
@keyup.enter="onSearch"
|
|
||||||
>
|
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-button @click="onSearch">
|
<el-button @click="onSearch">
|
||||||
<el-icon><ele-Search /></el-icon>
|
<el-icon><ele-Search /></el-icon>
|
||||||
@@ -27,13 +16,9 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chunks-list">
|
<div class="chunks-list">
|
||||||
<div
|
<div class="chunk-item" v-for="chunk in tableData.data" :key="chunk.id">
|
||||||
class="chunk-item"
|
|
||||||
v-for="chunk in tableData.data"
|
|
||||||
:key="chunk.id"
|
|
||||||
>
|
|
||||||
<div class="chunk-header">
|
<div class="chunk-header">
|
||||||
<div class="chunk-index">
|
<div class="chunk-index">
|
||||||
<el-tag size="small"># {{ chunk.chunkIndex + 1 }}</el-tag>
|
<el-tag size="small"># {{ chunk.chunkIndex + 1 }}</el-tag>
|
||||||
@@ -55,22 +40,17 @@
|
|||||||
{{ chunk.content }}
|
{{ chunk.content }}
|
||||||
</div>
|
</div>
|
||||||
<div class="chunk-edit" v-else>
|
<div class="chunk-edit" v-else>
|
||||||
<el-input
|
<el-input v-model="chunk.editContent" type="textarea" :rows="6" placeholder="请输入分段内容" />
|
||||||
v-model="chunk.editContent"
|
|
||||||
type="textarea"
|
|
||||||
:rows="6"
|
|
||||||
placeholder="请输入分段内容"
|
|
||||||
/>
|
|
||||||
<div class="edit-actions">
|
<div class="edit-actions">
|
||||||
<el-button size="small" @click="onCancelEdit(chunk)">取消</el-button>
|
<el-button size="small" @click="onCancelEdit(chunk)">取消</el-button>
|
||||||
<el-button size="small" type="primary" @click="onSaveChunk(chunk)" :loading="chunk.saving">保存</el-button>
|
<el-button size="small" type="primary" @click="onSaveChunk(chunk)" :loading="chunk.saving">保存</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-empty v-if="tableData.data.length === 0" description="暂无分段数据" />
|
<el-empty v-if="tableData.data.length === 0" description="暂无分段数据" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
<div class="chunks-pagination" v-if="tableData.total > 0">
|
<div class="chunks-pagination" v-if="tableData.total > 0">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
@@ -165,7 +145,7 @@ const onSaveChunk = async (chunk: any) => {
|
|||||||
ElMessage.warning('分段内容不能为空');
|
ElMessage.warning('分段内容不能为空');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk.saving = true;
|
chunk.saving = true;
|
||||||
try {
|
try {
|
||||||
await updateDocumentChunk({ id: chunk.id, content: chunk.editContent });
|
await updateDocumentChunk({ id: chunk.id, content: chunk.editContent });
|
||||||
@@ -186,15 +166,17 @@ const onDeleteChunk = (chunk: any) => {
|
|||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(async () => {
|
})
|
||||||
try {
|
.then(async () => {
|
||||||
await deleteDocumentChunk(chunk.id);
|
try {
|
||||||
ElMessage.success('删除成功');
|
await deleteDocumentChunk(chunk.id);
|
||||||
getChunkList();
|
ElMessage.success('删除成功');
|
||||||
} catch (_error) {
|
getChunkList();
|
||||||
ElMessage.error('删除失败');
|
} catch (_error) {
|
||||||
}
|
ElMessage.error('删除失败');
|
||||||
}).catch(() => {});
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 分页大小改变
|
// 分页大小改变
|
||||||
@@ -231,66 +213,67 @@ defineExpose({
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.chunks-header {
|
.chunks-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
|
||||||
.doc-info {
|
.doc-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
|
||||||
.doc-name {
|
.doc-name {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunks-list {
|
.chunks-list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
.chunk-item {
|
.chunk-item {
|
||||||
border: 1px solid #ebeef5;
|
border: 1px solid #ebeef5;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: #409eff;
|
border-color: #409eff;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-header {
|
.chunk-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
|
||||||
.chunk-index {
|
.chunk-index {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
|
||||||
.char-count, .token-count {
|
.char-count,
|
||||||
|
.token-count {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-content {
|
.chunk-content {
|
||||||
color: #606266;
|
color: #606266;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-edit {
|
.chunk-edit {
|
||||||
.edit-actions {
|
.edit-actions {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
@@ -299,7 +282,7 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunks-pagination {
|
.chunks-pagination {
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
border-top: 1px solid #ebeef5;
|
border-top: 1px solid #ebeef5;
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-drawer
|
<el-drawer v-model="isShowDrawer" title="文档预览" size="60%" :close-on-click-modal="true">
|
||||||
v-model="isShowDrawer"
|
|
||||||
title="文档预览"
|
|
||||||
size="60%"
|
|
||||||
:close-on-click-modal="true"
|
|
||||||
>
|
|
||||||
<div class="preview-container" v-loading="loading">
|
<div class="preview-container" v-loading="loading">
|
||||||
<div class="preview-header">
|
<div class="preview-header">
|
||||||
<div class="file-info">
|
<div class="file-info">
|
||||||
@@ -37,7 +32,7 @@
|
|||||||
<el-tab-pane label="文档信息" name="info">
|
<el-tab-pane label="文档信息" name="info">
|
||||||
<el-descriptions :column="2" border>
|
<el-descriptions :column="2" border>
|
||||||
<el-descriptions-item label="文档名称">{{ documentInfo.name }}</el-descriptions-item>
|
<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="文件类型">{{ documentInfo.fileType?.toUpperCase() }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="文件大小">{{ formatFileSize(documentInfo.fileSize) }}</el-descriptions-item>
|
<el-descriptions-item label="文件大小">{{ formatFileSize(documentInfo.fileSize) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="字符数">{{ documentInfo.charCount }}</el-descriptions-item>
|
<el-descriptions-item label="字符数">{{ documentInfo.charCount }}</el-descriptions-item>
|
||||||
@@ -81,8 +76,8 @@ const activeTab = ref('content');
|
|||||||
const documentInfo = reactive({
|
const documentInfo = reactive({
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
name: '',
|
||||||
datasetId: '',
|
knowledgeId: '',
|
||||||
datasetName: '',
|
knowledgeName: '',
|
||||||
fileType: '',
|
fileType: '',
|
||||||
fileSize: 0,
|
fileSize: 0,
|
||||||
filePath: '',
|
filePath: '',
|
||||||
@@ -207,15 +202,12 @@ const openDialog = async (row: any) => {
|
|||||||
documentContent.value = '';
|
documentContent.value = '';
|
||||||
activeTab.value = 'content';
|
activeTab.value = 'content';
|
||||||
isShowDrawer.value = true;
|
isShowDrawer.value = true;
|
||||||
|
|
||||||
// 获取文档详情和内容
|
// 获取文档详情和内容
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const [detailRes, contentRes] = await Promise.all([
|
const [detailRes, contentRes] = await Promise.all([getDocument(row.id), previewDocument(row.id)]);
|
||||||
getDocument(row.id),
|
|
||||||
previewDocument(row.id),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (detailRes.data) {
|
if (detailRes.data) {
|
||||||
Object.assign(documentInfo, detailRes.data);
|
Object.assign(documentInfo, detailRes.data);
|
||||||
}
|
}
|
||||||
@@ -250,31 +242,31 @@ defineExpose({
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.preview-header {
|
.preview-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.file-info {
|
.file-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.file-icon {
|
.file-icon {
|
||||||
font-size: 48px;
|
font-size: 48px;
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-detail {
|
.file-detail {
|
||||||
h3 {
|
h3 {
|
||||||
margin: 0 0 8px 0;
|
margin: 0 0 8px 0;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.meta {
|
.meta {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
@@ -282,11 +274,11 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-content {
|
.preview-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
.content-area {
|
.content-area {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background: #f5f7fa;
|
background: #f5f7fa;
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog title="上传文档" v-model="isShowDialog" width="600px" :close-on-click-modal="false" @close="onCancel">
|
||||||
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 ref="formRef" :model="ruleForm" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="所属数据集" prop="datasetId">
|
<el-form-item label="所属数据集" prop="knowledgeId">
|
||||||
<el-select v-model="ruleForm.datasetId" placeholder="请选择数据集" clearable style="width: 100%" :disabled="!!currentDatasetId">
|
<el-select v-model="ruleForm.datasetId" placeholder="请选择数据集" clearable style="width: 100%" :disabled="!!currentknowledgeId">
|
||||||
<el-option v-for="item in datasetOptions" :key="item.id" :label="item.name" :value="item.id" />
|
<el-option v-for="item in knowledgeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="上传文件" prop="files">
|
<el-form-item label="上传文件" prop="files">
|
||||||
@@ -25,13 +19,9 @@
|
|||||||
accept=".pdf,.docx,.doc,.txt,.md,.html"
|
accept=".pdf,.docx,.doc,.txt,.md,.html"
|
||||||
>
|
>
|
||||||
<el-icon class="el-icon--upload"><ele-UploadFilled /></el-icon>
|
<el-icon class="el-icon--upload"><ele-UploadFilled /></el-icon>
|
||||||
<div class="el-upload__text">
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
将文件拖到此处,或<em>点击上传</em>
|
|
||||||
</div>
|
|
||||||
<template #tip>
|
<template #tip>
|
||||||
<div class="el-upload__tip">
|
<div class="el-upload__tip">支持 PDF、Word、TXT、Markdown、HTML 格式,单个文件不超过 20MB</div>
|
||||||
支持 PDF、Word、TXT、Markdown、HTML 格式,单个文件不超过 20MB
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -81,8 +71,8 @@ import { uploadDocument } from '/@/api/knowledge/document';
|
|||||||
|
|
||||||
// 定义props
|
// 定义props
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
datasetOptions: any[];
|
knowledgeOptions: any[];
|
||||||
currentDatasetId?: string;
|
currentknowledgeId?: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 定义事件
|
// 定义事件
|
||||||
@@ -115,7 +105,7 @@ const rules = reactive<FormRules>({
|
|||||||
|
|
||||||
// 监听当前数据集ID
|
// 监听当前数据集ID
|
||||||
watch(
|
watch(
|
||||||
() => props.currentDatasetId,
|
() => props.currentknowledgeId,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
ruleForm.datasetId = val;
|
ruleForm.datasetId = val;
|
||||||
@@ -126,7 +116,7 @@ watch(
|
|||||||
|
|
||||||
// 重置表单
|
// 重置表单
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
if (!props.currentDatasetId) {
|
if (!props.currentknowledgeId) {
|
||||||
ruleForm.datasetId = '';
|
ruleForm.datasetId = '';
|
||||||
}
|
}
|
||||||
ruleForm.chunkSize = 500;
|
ruleForm.chunkSize = 500;
|
||||||
@@ -169,14 +159,14 @@ const onCancel = () => {
|
|||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
const form = formRef.value;
|
const form = formRef.value;
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
|
|
||||||
form.validate(async (valid: boolean) => {
|
form.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (fileList.value.length === 0) {
|
if (fileList.value.length === 0) {
|
||||||
ElMessage.warning('请选择要上传的文件');
|
ElMessage.warning('请选择要上传的文件');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
submitLoading.value = true;
|
submitLoading.value = true;
|
||||||
try {
|
try {
|
||||||
// 逐个上传文件
|
// 逐个上传文件
|
||||||
@@ -188,10 +178,10 @@ const onSubmit = async () => {
|
|||||||
formData.append('chunkOverlap', ruleForm.chunkOverlap.toString());
|
formData.append('chunkOverlap', ruleForm.chunkOverlap.toString());
|
||||||
formData.append('cleanWhitespace', ruleForm.cleanWhitespace.toString());
|
formData.append('cleanWhitespace', ruleForm.cleanWhitespace.toString());
|
||||||
formData.append('removeHeaders', ruleForm.removeHeaders.toString());
|
formData.append('removeHeaders', ruleForm.removeHeaders.toString());
|
||||||
|
|
||||||
await uploadDocument(formData);
|
await uploadDocument(formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElMessage.success(`成功上传 ${fileList.value.length} 个文件`);
|
ElMessage.success(`成功上传 ${fileList.value.length} 个文件`);
|
||||||
isShowDialog.value = false;
|
isShowDialog.value = false;
|
||||||
emit('getDocumentList');
|
emit('getDocumentList');
|
||||||
|
|||||||
@@ -4,36 +4,34 @@
|
|||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<el-breadcrumb separator=">">
|
<el-breadcrumb separator=">">
|
||||||
<el-breadcrumb-item>
|
<el-breadcrumb-item>
|
||||||
<span class="back-link" @click="onBackToKnowledge">知识库</span>
|
<span class="back-link" @click="onBackToknowledge">知识库</span>
|
||||||
</el-breadcrumb-item>
|
</el-breadcrumb-item>
|
||||||
<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>
|
||||||
<el-breadcrumb-item>{{ documentInfo.name }}</el-breadcrumb-item>
|
<el-breadcrumb-item>{{ documentInfo.name }}</el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="page-content">
|
<div class="page-content">
|
||||||
<!-- 左侧:文档原文 -->
|
<!-- 左侧:文档原文 -->
|
||||||
<div class="document-content">
|
<div class="document-content">
|
||||||
<div class="content-header">
|
<div class="content-header">
|
||||||
<h2>{{ documentInfo.name }}</h2>
|
<h2>{{ documentInfo.name }}</h2>
|
||||||
<div class="content-meta">
|
<div class="content-meta">Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}</div>
|
||||||
Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="content-body" v-loading="contentLoading">
|
<div class="content-body" v-loading="contentLoading">
|
||||||
<pre class="document-text">{{ documentContent }}</pre>
|
<pre class="document-text">{{ documentContent }}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 右侧:切片结果 -->
|
<!-- 右侧:切片结果 -->
|
||||||
<div class="chunk-panel">
|
<div class="chunk-panel">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<h3>切片结果</h3>
|
<h3>切片结果</h3>
|
||||||
<div class="panel-subtitle">查看用于嵌入和召回的切片段落。</div>
|
<div class="panel-subtitle">查看用于嵌入和召回的切片段落。</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-toolbar">
|
<div class="panel-toolbar">
|
||||||
<div class="toolbar-tabs">
|
<div class="toolbar-tabs">
|
||||||
<el-radio-group v-model="viewMode" size="small">
|
<el-radio-group v-model="viewMode" size="small">
|
||||||
@@ -42,13 +40,7 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-actions">
|
<div class="toolbar-actions">
|
||||||
<el-input
|
<el-input v-model="chunkSearch" placeholder="搜索" clearable size="small" style="width: 120px">
|
||||||
v-model="chunkSearch"
|
|
||||||
placeholder="搜索"
|
|
||||||
clearable
|
|
||||||
size="small"
|
|
||||||
style="width: 120px"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<el-icon><ele-Search /></el-icon>
|
<el-icon><ele-Search /></el-icon>
|
||||||
</template>
|
</template>
|
||||||
@@ -58,17 +50,13 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chunk-list" v-loading="chunkLoading">
|
<div class="chunk-list" v-loading="chunkLoading">
|
||||||
<div class="select-all">
|
<div class="select-all">
|
||||||
<el-checkbox v-model="selectAll" @change="onSelectAllChange">选择所有</el-checkbox>
|
<el-checkbox v-model="selectAll" @change="onSelectAllChange">选择所有</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="chunk-item" v-for="chunk in filteredChunks" :key="chunk.id">
|
||||||
class="chunk-item"
|
|
||||||
v-for="chunk in filteredChunks"
|
|
||||||
:key="chunk.id"
|
|
||||||
>
|
|
||||||
<div class="chunk-checkbox">
|
<div class="chunk-checkbox">
|
||||||
<el-checkbox v-model="chunk.selected" />
|
<el-checkbox v-model="chunk.selected" />
|
||||||
</div>
|
</div>
|
||||||
@@ -79,10 +67,10 @@
|
|||||||
<el-switch v-model="chunk.enabled" size="small" @change="onChunkStatusChange(chunk)" />
|
<el-switch v-model="chunk.enabled" size="small" @change="onChunkStatusChange(chunk)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-empty v-if="filteredChunks.length === 0 && !chunkLoading" description="暂无切片" :image-size="60" />
|
<el-empty v-if="filteredChunks.length === 0 && !chunkLoading" description="暂无切片" :image-size="60" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
<span class="total-info">总共 {{ chunkTotal }} 条</span>
|
<span class="total-info">总共 {{ chunkTotal }} 条</span>
|
||||||
@@ -121,8 +109,8 @@ const route = useRoute();
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
// 路由参数
|
// 路由参数
|
||||||
const datasetId = ref('');
|
const knowledgeId = ref('');
|
||||||
const datasetName = ref('');
|
const knowledgeName = ref('');
|
||||||
const documentId = ref('');
|
const documentId = ref('');
|
||||||
|
|
||||||
// 文档信息
|
// 文档信息
|
||||||
@@ -151,9 +139,7 @@ const selectAll = ref(false);
|
|||||||
// 过滤后的切片列表
|
// 过滤后的切片列表
|
||||||
const filteredChunks = computed(() => {
|
const filteredChunks = computed(() => {
|
||||||
if (!chunkSearch.value) return chunkList.value;
|
if (!chunkSearch.value) return chunkList.value;
|
||||||
return chunkList.value.filter((chunk) =>
|
return chunkList.value.filter((chunk) => (chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase()));
|
||||||
(chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase())
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 格式化文件大小
|
// 格式化文件大小
|
||||||
@@ -171,15 +157,15 @@ const truncateText = (text: string, maxLength: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 返回知识库列表
|
// 返回知识库列表
|
||||||
const onBackToKnowledge = () => {
|
const onBackToknowledge = () => {
|
||||||
router.push('/knowledge/dataset');
|
router.push('/knowledge/knowledge');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 返回数据集详情
|
// 返回数据集详情
|
||||||
const onBackToDataset = () => {
|
const onBackToknowledge = () => {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/knowledge/document',
|
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.fileSize = detail.fileSize || 0;
|
||||||
documentInfo.createdAt = detail.createdAt || '';
|
documentInfo.createdAt = detail.createdAt || '';
|
||||||
const contentData = contentRes.data;
|
const contentData = contentRes.data;
|
||||||
documentContent.value =
|
documentContent.value = typeof contentData === 'string' ? contentData : contentData?.content || contentData?.text || '';
|
||||||
typeof contentData === 'string' ? contentData : contentData?.content || contentData?.text || '';
|
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
ElMessage.error('获取文档详情失败');
|
ElMessage.error('获取文档详情失败');
|
||||||
documentContent.value = '';
|
documentContent.value = '';
|
||||||
@@ -248,12 +233,12 @@ const onAddChunk = () => {
|
|||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
datasetId.value = (route.query.datasetId as string) || '';
|
knowledgeId.value = (route.query.knowledgeId as string) || '';
|
||||||
datasetName.value = (route.query.datasetName as string) || '';
|
knowledgeName.value = (route.query.knowledgeName as string) || '';
|
||||||
documentId.value = (route.query.docId as string) || '';
|
documentId.value = (route.query.docId as string) || '';
|
||||||
if (!documentId.value) {
|
if (!documentId.value) {
|
||||||
ElMessage.warning('缺少文档ID,无法查看详情');
|
ElMessage.warning('缺少文档ID,无法查看详情');
|
||||||
onBackToDataset();
|
onBackToknowledge();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getDocumentDetail();
|
getDocumentDetail();
|
||||||
@@ -267,29 +252,29 @@ onMounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: #f5f7fa;
|
background: #f5f7fa;
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
.back-link {
|
.back-link {
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-content {
|
.page-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
|
|
||||||
// 左侧文档内容
|
// 左侧文档内容
|
||||||
.document-content {
|
.document-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -299,30 +284,30 @@ onMounted(() => {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.content-header {
|
.content-header {
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 0 0 8px 0;
|
margin: 0 0 8px 0;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-meta {
|
.content-meta {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-body {
|
.content-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
|
|
||||||
.document-text {
|
.document-text {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||||
@@ -334,7 +319,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 右侧切片面板
|
// 右侧切片面板
|
||||||
.chunk-panel {
|
.chunk-panel {
|
||||||
width: 420px;
|
width: 420px;
|
||||||
@@ -343,46 +328,46 @@ onMounted(() => {
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
.panel-header {
|
.panel-header {
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
margin: 0 0 4px 0;
|
margin: 0 0 4px 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-subtitle {
|
.panel-subtitle {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-toolbar {
|
.panel-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
.toolbar-actions {
|
.toolbar-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-list {
|
.chunk-list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
|
|
||||||
.select-all {
|
.select-all {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-item {
|
.chunk-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@@ -391,16 +376,16 @@ onMounted(() => {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
border: 1px solid #ebeef5;
|
border: 1px solid #ebeef5;
|
||||||
|
|
||||||
.chunk-checkbox {
|
.chunk-checkbox {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-content {
|
.chunk-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
.chunk-text {
|
.chunk-text {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
@@ -408,14 +393,14 @@ onMounted(() => {
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chunk-actions {
|
.chunk-actions {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-footer {
|
.panel-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -423,7 +408,7 @@ onMounted(() => {
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
border-top: 1px solid #ebeef5;
|
border-top: 1px solid #ebeef5;
|
||||||
|
|
||||||
.total-info {
|
.total-info {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
|
|||||||
@@ -3,18 +3,18 @@
|
|||||||
<div class="knowledge-document-container">
|
<div class="knowledge-document-container">
|
||||||
<el-card shadow="hover">
|
<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 separator="/">
|
||||||
<el-breadcrumb-item :to="{ path: '/knowledge/dataset' }">数据集管理</el-breadcrumb-item>
|
<el-breadcrumb-item :to="{ path: '/knowledge/knowledge' }">数据集管理</el-breadcrumb-item>
|
||||||
<el-breadcrumb-item>{{ currentDataset.name }}</el-breadcrumb-item>
|
<el-breadcrumb-item>{{ currentknowledge.name }}</el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="knowledge-document-search mb15">
|
<div class="knowledge-document-search mb15">
|
||||||
<el-form :inline="true">
|
<el-form :inline="true">
|
||||||
<el-form-item label="所属数据集" v-if="!currentDataset.id">
|
<el-form-item label="所属数据集" v-if="!currentknowledge.id">
|
||||||
<el-select size="default" v-model="tableData.param.datasetId" placeholder="请选择数据集" clearable style="width: 180px">
|
<el-select size="default" v-model="tableData.param.knowledgeId" placeholder="请选择数据集" clearable style="width: 180px">
|
||||||
<el-option v-for="item in datasetOptions" :key="item.id" :label="item.name" :value="item.id" />
|
<el-option v-for="item in knowledgeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="文档名称">
|
<el-form-item label="文档名称">
|
||||||
@@ -50,20 +50,20 @@
|
|||||||
<el-icon><ele-Upload /></el-icon>
|
<el-icon><ele-Upload /></el-icon>
|
||||||
上传文档
|
上传文档
|
||||||
</el-button>
|
</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-icon><ele-Delete /></el-icon>
|
||||||
批量删除
|
批量删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<el-table
|
<el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading" border @selection-change="onSelectionChange">
|
||||||
: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="selection" width="50" align="center" />
|
||||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
<el-table-column prop="name" label="文档名称" min-width="200" show-overflow-tooltip>
|
<el-table-column prop="name" label="文档名称" min-width="200" show-overflow-tooltip>
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</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">
|
<el-table-column prop="fileType" label="文件类型" width="100" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag size="small">{{ scope.row.fileType?.toUpperCase() }}</el-tag>
|
<el-tag size="small">{{ scope.row.fileType?.toUpperCase() }}</el-tag>
|
||||||
@@ -103,8 +103,18 @@
|
|||||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button size="small" text type="primary" @click="onPreview(scope.row)">预览</el-button>
|
<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="success" @click="onViewChunks(scope.row)" v-auth="'api/v1/knowledge/document/chunks'"
|
||||||
<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
|
||||||
|
>
|
||||||
|
<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>
|
<el-button size="small" text type="danger" @click="onRowDel(scope.row)" v-auth="'api/v1/knowledge/document/delete'">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -123,13 +133,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 上传文档弹窗 -->
|
<!-- 上传文档弹窗 -->
|
||||||
<UploadDocument ref="uploadDocumentRef" :datasetOptions="datasetOptions" :currentDatasetId="currentDataset.id" @getDocumentList="getDocumentList" />
|
<UploadDocument
|
||||||
|
ref="uploadDocumentRef"
|
||||||
|
:knowledgeOptions="knowledgeOptions"
|
||||||
|
:currentknowledgeId="currentknowledge.id"
|
||||||
|
@getDocumentList="getDocumentList"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 文档预览弹窗 -->
|
<!-- 文档预览弹窗 -->
|
||||||
<PreviewDocument ref="previewDocumentRef" />
|
<PreviewDocument ref="previewDocumentRef" />
|
||||||
|
|
||||||
<!-- 文档分段弹窗 -->
|
<!-- 文档分段弹窗 -->
|
||||||
<DocumentChunks ref="documentChunksRef" />
|
<DocumentChunks ref="documentChunksRef" />
|
||||||
</div>
|
</div>
|
||||||
@@ -146,7 +161,7 @@ import { ref, reactive, onMounted, watch } from 'vue';
|
|||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { listDocuments, deleteDocument, batchDeleteDocuments, reprocessDocument } from '/@/api/knowledge/document';
|
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 UploadDocument from './component/uploadDocument.vue';
|
||||||
import PreviewDocument from './component/previewDocument.vue';
|
import PreviewDocument from './component/previewDocument.vue';
|
||||||
import DocumentChunks from './component/documentChunks.vue';
|
import DocumentChunks from './component/documentChunks.vue';
|
||||||
@@ -154,13 +169,13 @@ import DocumentChunks from './component/documentChunks.vue';
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
// 当前数据集
|
// 当前数据集
|
||||||
const currentDataset = reactive({
|
const currentknowledge = reactive({
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
name: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
// 数据集选项
|
// 数据集选项
|
||||||
const datasetOptions = ref<any[]>([]);
|
const knowledgeOptions = ref<any[]>([]);
|
||||||
|
|
||||||
// 选中的文档ID
|
// 选中的文档ID
|
||||||
const selectedIds = ref<string[]>([]);
|
const selectedIds = ref<string[]>([]);
|
||||||
@@ -172,7 +187,7 @@ const tableData = reactive({
|
|||||||
loading: false,
|
loading: false,
|
||||||
param: {
|
param: {
|
||||||
keyword: '',
|
keyword: '',
|
||||||
datasetId: '',
|
knowledgeId: '',
|
||||||
fileType: '',
|
fileType: '',
|
||||||
status: undefined as string | undefined,
|
status: undefined as string | undefined,
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@@ -186,12 +201,12 @@ const previewDocumentRef = ref();
|
|||||||
const documentChunksRef = ref();
|
const documentChunksRef = ref();
|
||||||
|
|
||||||
// 获取数据集列表
|
// 获取数据集列表
|
||||||
const getDatasetOptions = async () => {
|
const getknowledgeOptions = async () => {
|
||||||
try {
|
try {
|
||||||
const res: any = await listDatasets({ pageNum: 1, pageSize: 1000 });
|
const res: any = await listknowledges({ pageNum: 1, pageSize: 1000 });
|
||||||
datasetOptions.value = res.data?.list || [];
|
knowledgeOptions.value = res.data?.list || [];
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
datasetOptions.value = [];
|
knowledgeOptions.value = [];
|
||||||
ElMessage.error('获取数据集列表失败');
|
ElMessage.error('获取数据集列表失败');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -201,8 +216,8 @@ const getDocumentList = async () => {
|
|||||||
tableData.loading = true;
|
tableData.loading = true;
|
||||||
try {
|
try {
|
||||||
const params = { ...tableData.param };
|
const params = { ...tableData.param };
|
||||||
if (currentDataset.id) {
|
if (currentknowledge.id) {
|
||||||
params.datasetId = currentDataset.id;
|
params.knowledgeId = currentknowledge.id;
|
||||||
}
|
}
|
||||||
const res: any = await listDocuments(params);
|
const res: any = await listDocuments(params);
|
||||||
tableData.data = res.data?.list || [];
|
tableData.data = res.data?.list || [];
|
||||||
@@ -309,8 +324,8 @@ const getIndexStatusText = (status: string) => {
|
|||||||
// 重置查询
|
// 重置查询
|
||||||
const onResetQuery = () => {
|
const onResetQuery = () => {
|
||||||
tableData.param.keyword = '';
|
tableData.param.keyword = '';
|
||||||
if (!currentDataset.id) {
|
if (!currentknowledge.id) {
|
||||||
tableData.param.datasetId = '';
|
tableData.param.knowledgeId = '';
|
||||||
}
|
}
|
||||||
tableData.param.fileType = '';
|
tableData.param.fileType = '';
|
||||||
tableData.param.status = undefined;
|
tableData.param.status = undefined;
|
||||||
@@ -346,7 +361,7 @@ const onReprocess = async (row: any) => {
|
|||||||
|
|
||||||
// 选择变化
|
// 选择变化
|
||||||
const onSelectionChange = (selection: any[]) => {
|
const onSelectionChange = (selection: any[]) => {
|
||||||
selectedIds.value = selection.map(item => item.id);
|
selectedIds.value = selection.map((item) => item.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 批量删除
|
// 批量删除
|
||||||
@@ -355,15 +370,17 @@ const onBatchDelete = () => {
|
|||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(async () => {
|
})
|
||||||
try {
|
.then(async () => {
|
||||||
await batchDeleteDocuments(selectedIds.value);
|
try {
|
||||||
ElMessage.success('删除成功');
|
await batchDeleteDocuments(selectedIds.value);
|
||||||
getDocumentList();
|
ElMessage.success('删除成功');
|
||||||
} catch (_error) {
|
getDocumentList();
|
||||||
ElMessage.error('批量删除失败');
|
} catch (_error) {
|
||||||
}
|
ElMessage.error('批量删除失败');
|
||||||
}).catch(() => {});
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 删除文档
|
// 删除文档
|
||||||
@@ -372,15 +389,17 @@ const onRowDel = (row: any) => {
|
|||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(async () => {
|
})
|
||||||
try {
|
.then(async () => {
|
||||||
await deleteDocument(row.id);
|
try {
|
||||||
ElMessage.success('删除成功');
|
await deleteDocument(row.id);
|
||||||
getDocumentList();
|
ElMessage.success('删除成功');
|
||||||
} catch (_error) {
|
getDocumentList();
|
||||||
ElMessage.error('删除失败');
|
} catch (_error) {
|
||||||
}
|
ElMessage.error('删除失败');
|
||||||
}).catch(() => {});
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 分页大小改变
|
// 分页大小改变
|
||||||
@@ -399,13 +418,13 @@ const onCurrentChange = (page: number) => {
|
|||||||
watch(
|
watch(
|
||||||
() => route.query,
|
() => route.query,
|
||||||
(query) => {
|
(query) => {
|
||||||
if (query.datasetId) {
|
if (query.knowledgeId) {
|
||||||
currentDataset.id = query.datasetId as string;
|
currentknowledge.id = query.knowledgeId as string;
|
||||||
currentDataset.name = query.datasetName as string || '';
|
currentknowledge.name = (query.knowledgeName as string) || '';
|
||||||
tableData.param.datasetId = currentDataset.id;
|
tableData.param.knowledgeId = currentknowledge.id;
|
||||||
} else {
|
} else {
|
||||||
currentDataset.id = '';
|
currentknowledge.id = '';
|
||||||
currentDataset.name = '';
|
currentknowledge.name = '';
|
||||||
}
|
}
|
||||||
getDocumentList();
|
getDocumentList();
|
||||||
},
|
},
|
||||||
@@ -414,7 +433,7 @@ watch(
|
|||||||
|
|
||||||
// 页面加载时获取数据
|
// 页面加载时获取数据
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDatasetOptions();
|
getknowledgeOptions();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -212,7 +212,7 @@ export default defineComponent({
|
|||||||
draggable: '.workflow-left-item',
|
draggable: '.workflow-left-item',
|
||||||
forceFallback: true,
|
forceFallback: true,
|
||||||
onEnd: function (evt: any) {
|
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 { layerX, layerY, clientX, clientY } = evt.originalEvent;
|
||||||
const el = state.workflowRightRef!;
|
const el = state.workflowRightRef!;
|
||||||
const { x, y, width, height } = el.getBoundingClientRect();
|
const { x, y, width, height } = el.getBoundingClientRect();
|
||||||
@@ -617,8 +617,8 @@ export default defineComponent({
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-image: linear-gradient(90deg, rgb(156 214 255 / 15%) 10%, rgba(0, 0, 0, 0) 10%),
|
background-image:
|
||||||
linear-gradient(rgb(156 214 255 / 15%) 10%, rgba(0, 0, 0, 0) 10%);
|
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;
|
background-size: 10px 10px;
|
||||||
.workflow-right-clone {
|
.workflow-right-clone {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="visualizing-demo1">
|
<div class="visualizing-demo1">
|
||||||
<baidumap src="https://hm.baidu.com/hm.js?d9c8b87d10717013641458b300c552e4"></baidumap>
|
<baidumap src="https://hm.baidu.com/hm.js?d9c8b87d10717013641458b300c552e4"></baidumap>
|
||||||
<baidumap src="https://api.map.baidu.com/api?v=3.0&ak=wsijQt8sLXrCW71YesmispvYHitfG9gv&s=1"></baidumap>
|
<baidumap src="https://api.map.baidu.com/api?v=3.0&ak=wsijQt8sLXrCW71YesmispvYHitfG9gv&s=1"></baidumap>
|
||||||
<!-- 地图 -->
|
<!-- 地图 -->
|
||||||
<div ref="visualizingDemo1" style="height: 100%"></div>
|
<div ref="visualizingDemo1" style="height: 100%"></div>
|
||||||
<div class="visualizing-container">
|
<div class="visualizing-container">
|
||||||
@@ -117,7 +117,7 @@ interface Demo1State {
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'visualizingLinkDemo1',
|
name: 'visualizingLinkDemo1',
|
||||||
components:{baidumap},
|
components: { baidumap },
|
||||||
setup() {
|
setup() {
|
||||||
const { proxy } = <any>getCurrentInstance();
|
const { proxy } = <any>getCurrentInstance();
|
||||||
const state = reactive<Demo1State>({
|
const state = reactive<Demo1State>({
|
||||||
@@ -707,7 +707,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
dataset: {
|
knowledge: {
|
||||||
source: [
|
source: [
|
||||||
{ status: '已签收', value1: 33, value2: 93 },
|
{ status: '已签收', value1: 33, value2: 93 },
|
||||||
{ status: '配送中', value1: 53, value2: 32 },
|
{ status: '配送中', value1: 53, value2: 32 },
|
||||||
|
|||||||
Reference in New Issue
Block a user