feat: 样本管理
This commit is contained in:
83
src/pages/ai/sample-tag/components/tag-manager.tsx
Normal file
83
src/pages/ai/sample-tag/components/tag-manager.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
// 使用示例 - App.tsx
|
||||
|
||||
import { Modal, message, Space } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import RenameRule, {
|
||||
type FileItem,
|
||||
type RenameResult,
|
||||
} from '@/components/RenameRule';
|
||||
import { updateSamples } from '@/services/ai/sample';
|
||||
|
||||
const TagManager: React.FC<{
|
||||
visible: boolean;
|
||||
files: FileItem[];
|
||||
onCancel?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
||||
onOk?: () => void;
|
||||
}> = ({ visible, files: beforeFiles, onCancel, onOk }) => {
|
||||
const [files, setFiles] = useState<FileItem[]>(beforeFiles);
|
||||
useEffect(() => {
|
||||
setFiles(beforeFiles);
|
||||
}, [beforeFiles]);
|
||||
|
||||
const [previewResults, setPreviewResults] = useState<RenameResult[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// 预览回调o+
|
||||
const handlePreview = (results: RenameResult[]) => {
|
||||
setPreviewResults(results);
|
||||
};
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const results = previewResults.map((result) => ({
|
||||
id: result.id,
|
||||
sampleName: `${result.newName}`,
|
||||
}));
|
||||
await updateSamples(results);
|
||||
onOk?.();
|
||||
message.success('重命名成功');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// // 重命名回调
|
||||
// const handleRename = async (results: RenameResult[]) => {
|
||||
// setLoading(true);
|
||||
// try {
|
||||
// console.log("执行预览:", results);
|
||||
// // 模拟API调用
|
||||
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
// message.success(`成功重命名 ${results.length} 个文件`);
|
||||
// } catch (error) {
|
||||
// message.error("重命名失败");
|
||||
// } finally {
|
||||
// setLoading(false);
|
||||
// }
|
||||
// };
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width={800}
|
||||
onCancel={onCancel}
|
||||
onOk={handleOk}
|
||||
open={visible}
|
||||
title="重命名文件"
|
||||
>
|
||||
<div style={{ padding: '24px' }}>
|
||||
<Space direction="vertical" style={{ width: '100%' }} size="large">
|
||||
{/* 独立的重命名规则组件 */}
|
||||
<RenameRule
|
||||
files={files}
|
||||
onPreview={handlePreview}
|
||||
// onRename={handleRename}
|
||||
loading={loading}
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagManager;
|
||||
@@ -1,14 +1,21 @@
|
||||
import type {
|
||||
ProColumns,
|
||||
ProFormColumnsType,
|
||||
} from '@ant-design/pro-components';
|
||||
import dayjs from 'dayjs';
|
||||
import TagEditor from '@/components/TagEditor';
|
||||
import TinyMCEEditor from '@/components/Tinymce';
|
||||
export const baseTenantColumns: ProColumns<API.CategoryDO>[] = [
|
||||
import type { ProColumns } from '@ant-design/pro-components';
|
||||
import GroupTagSelect from '@/components/GroupTag/GroupTagSelect';
|
||||
import {
|
||||
type AiSampleRespVO,
|
||||
createSampleTag,
|
||||
createSampleTagGroup,
|
||||
deleteSampleTag,
|
||||
deleteSampleTagGroup,
|
||||
getSampleTagGroup,
|
||||
getSampleTagPage,
|
||||
updateSampleTag,
|
||||
updateSampleTagGroup,
|
||||
} from '@/services/ai/sample';
|
||||
export const baseTenantColumns: ProColumns<AiSampleRespVO>[] = [
|
||||
{
|
||||
title: '样本名称',
|
||||
dataIndex: 'sample_name',
|
||||
dataIndex: 'sampleName',
|
||||
// width: 500,
|
||||
},
|
||||
{
|
||||
title: '注释',
|
||||
@@ -19,6 +26,36 @@ export const baseTenantColumns: ProColumns<API.CategoryDO>[] = [
|
||||
title: '标签',
|
||||
hideInTable: true,
|
||||
dataIndex: 'tag_name',
|
||||
valueType: 'select',
|
||||
search: {
|
||||
transform: (value) => {
|
||||
console.log(value);
|
||||
return value.join(',');
|
||||
},
|
||||
},
|
||||
|
||||
renderFormItem: (_) => {
|
||||
return (
|
||||
<GroupTagSelect
|
||||
request={{
|
||||
groupsApi: {
|
||||
get: getSampleTagGroup,
|
||||
create: createSampleTagGroup,
|
||||
delete: deleteSampleTagGroup,
|
||||
update: updateSampleTagGroup,
|
||||
},
|
||||
tagsApi: {
|
||||
get: getSampleTagPage,
|
||||
create: createSampleTag,
|
||||
delete: deleteSampleTag,
|
||||
update: updateSampleTag,
|
||||
},
|
||||
}}
|
||||
editable
|
||||
placeholder="请选择技术栈"
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '样本格式',
|
||||
@@ -27,107 +64,107 @@ export const baseTenantColumns: ProColumns<API.CategoryDO>[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const formColumns = (data: {
|
||||
type: string;
|
||||
grade: number;
|
||||
}): ProFormColumnsType[] => [
|
||||
{
|
||||
title: '类目',
|
||||
dataIndex: 'grade',
|
||||
valueType: 'radio',
|
||||
fieldProps: {
|
||||
value: data.grade || 1,
|
||||
options: [
|
||||
{ label: '一级类目', value: 1 },
|
||||
{ label: '二级类目', value: 2 },
|
||||
{ label: '三级类目', value: 3 },
|
||||
],
|
||||
disabled: data.type === 'create',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '类目名称',
|
||||
dataIndex: 'username',
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '排序权重',
|
||||
dataIndex: 'sort',
|
||||
valueType: 'digit',
|
||||
},
|
||||
{
|
||||
title: '类目描述',
|
||||
dataIndex: 'description',
|
||||
valueType: 'textarea',
|
||||
renderFormItem: () => {
|
||||
return <TinyMCEEditor />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '关联父级',
|
||||
dataIndex: 'parentId',
|
||||
valueType: 'select',
|
||||
hideInForm: data.grade - 1 === 0,
|
||||
},
|
||||
{
|
||||
title: '类目icon',
|
||||
dataIndex: 'icon',
|
||||
},
|
||||
{
|
||||
title: '类目标签',
|
||||
dataIndex: 'tages',
|
||||
renderFormItem: () => {
|
||||
return (
|
||||
<TagEditor
|
||||
placeholder="输入标签名称"
|
||||
maxCount={10}
|
||||
tagProps={{
|
||||
color: 'blue',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '类目状态',
|
||||
dataIndex: 'status',
|
||||
hideInForm: data.type === 'create',
|
||||
},
|
||||
{
|
||||
title: '类目ID',
|
||||
dataIndex: 'categoryId',
|
||||
hideInForm: data.type === 'create',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
valueType: 'dateTime',
|
||||
hideInForm: data.type === 'create',
|
||||
},
|
||||
{
|
||||
title: '创建人',
|
||||
dataIndex: 'creator',
|
||||
hideInForm: data.type === 'create',
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updateTime',
|
||||
valueType: 'dateTime',
|
||||
hideInForm: data.type === 'create',
|
||||
},
|
||||
{
|
||||
title: '更新人',
|
||||
dataIndex: 'updator',
|
||||
hideInForm: data.type === 'create',
|
||||
},
|
||||
];
|
||||
// export const formColumns = (data: {
|
||||
// type: string;
|
||||
// grade: number;
|
||||
// }): ProFormColumnsType[] => [
|
||||
// {
|
||||
// title: "类目",
|
||||
// dataIndex: "grade",
|
||||
// valueType: "radio",
|
||||
// fieldProps: {
|
||||
// value: data.grade || 1,
|
||||
// options: [
|
||||
// { label: "一级类目", value: 1 },
|
||||
// { label: "二级类目", value: 2 },
|
||||
// { label: "三级类目", value: 3 },
|
||||
// ],
|
||||
// disabled: data.type === "create",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: "类目名称",
|
||||
// dataIndex: "username",
|
||||
// formItemProps: {
|
||||
// rules: [
|
||||
// {
|
||||
// required: true,
|
||||
// message: "请输入用户名",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: "排序权重",
|
||||
// dataIndex: "sort",
|
||||
// valueType: "digit",
|
||||
// },
|
||||
// {
|
||||
// title: "类目描述",
|
||||
// dataIndex: "description",
|
||||
// valueType: "textarea",
|
||||
// renderFormItem: () => {
|
||||
// return <TinyMCEEditor />;
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: "关联父级",
|
||||
// dataIndex: "parentId",
|
||||
// valueType: "select",
|
||||
// hideInForm: data.grade - 1 === 0,
|
||||
// },
|
||||
// {
|
||||
// title: "类目icon",
|
||||
// dataIndex: "icon",
|
||||
// },
|
||||
// {
|
||||
// title: "类目标签",
|
||||
// dataIndex: "tages",
|
||||
// renderFormItem: () => {
|
||||
// return (
|
||||
// <TagEditor
|
||||
// placeholder="输入标签名称"
|
||||
// maxCount={10}
|
||||
// tagProps={{
|
||||
// color: "blue",
|
||||
// }}
|
||||
// />
|
||||
// );
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: "类目状态",
|
||||
// dataIndex: "status",
|
||||
// hideInForm: data.type === "create",
|
||||
// },
|
||||
// {
|
||||
// title: "类目ID",
|
||||
// dataIndex: "categoryId",
|
||||
// hideInForm: data.type === "create",
|
||||
// },
|
||||
// {
|
||||
// title: "创建时间",
|
||||
// dataIndex: "createTime",
|
||||
// valueType: "dateTime",
|
||||
// hideInForm: data.type === "create",
|
||||
// },
|
||||
// {
|
||||
// title: "创建人",
|
||||
// dataIndex: "creator",
|
||||
// hideInForm: data.type === "create",
|
||||
// },
|
||||
// {
|
||||
// title: "更新时间",
|
||||
// dataIndex: "updateTime",
|
||||
// valueType: "dateTime",
|
||||
// hideInForm: data.type === "create",
|
||||
// },
|
||||
// {
|
||||
// title: "更新人",
|
||||
// dataIndex: "updator",
|
||||
// hideInForm: data.type === "create",
|
||||
// },
|
||||
// ];
|
||||
|
||||
// {
|
||||
// title: "模板内容",
|
||||
|
||||
@@ -1,81 +1,332 @@
|
||||
import {
|
||||
ProForm,
|
||||
ProFormCascader,
|
||||
ProFormCheckbox,
|
||||
ProFormColorPicker,
|
||||
ProFormDigit,
|
||||
ProFormDigitRange,
|
||||
ProFormGroup,
|
||||
ProFormRadio,
|
||||
ProFormSelect,
|
||||
ProFormSlider,
|
||||
ProFormSwitch,
|
||||
ProFormText,
|
||||
} from '@ant-design/pro-components';
|
||||
import { Switch } from 'antd';
|
||||
import { ProForm, ProFormGroup, ProFormText } from '@ant-design/pro-components';
|
||||
import { Button, message, Space, Tag } from 'antd';
|
||||
import type { RowSelectionType } from 'antd/es/table/interface';
|
||||
import type { FormInstance } from 'antd/lib';
|
||||
import Mock from 'mockjs';
|
||||
import { useRef, useState } from 'react';
|
||||
import TagEditor from '@/components/TagEditor';
|
||||
import dayjs from 'dayjs';
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import GroupTagModal from '@/components/GroupTag/GroupTagModal';
|
||||
import type { TagItem } from '@/components/GroupTag/types';
|
||||
import type { FileItem } from '@/components/RenameRule';
|
||||
import {
|
||||
createSampleTag,
|
||||
createSampleTagGroup,
|
||||
deleteSample,
|
||||
deleteSampleTag,
|
||||
deleteSampleTagGroup,
|
||||
deleteSampleTagRelate,
|
||||
getSampleTagGroup,
|
||||
getSampleTagPage,
|
||||
relateSample,
|
||||
updateSamples,
|
||||
updateSampleTag,
|
||||
updateSampleTagGroup,
|
||||
} from '@/services/ai/sample';
|
||||
import TagManager from './components/tag-manager';
|
||||
|
||||
export const waitTime = (time: number = 100) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(true);
|
||||
}, time);
|
||||
});
|
||||
};
|
||||
interface SampleTagDetailProps<T> {
|
||||
onRefresh?: (type?: string) => void;
|
||||
type: RowSelectionType;
|
||||
data?: T[];
|
||||
}
|
||||
|
||||
const SampleTagDetail = () => {
|
||||
const [readonly, setReadonly] = useState(false);
|
||||
const SampleTagDetail = <T extends Record<string, any>>(
|
||||
props: SampleTagDetailProps<T>,
|
||||
) => {
|
||||
const formRef = useRef<FormInstance>(null);
|
||||
const { type = 'radio', data } = props;
|
||||
const [modalVisible, setModalVisible] = useState<boolean>(false);
|
||||
const [tagManagerVisible, setTagManagerVisible] = useState<boolean>(false);
|
||||
const [value, setValue] = useState<{
|
||||
tagId?: number | number[];
|
||||
id?: number;
|
||||
remark?: string;
|
||||
sampleIds?: number[];
|
||||
tags?: TagItem[];
|
||||
updateTime?: number;
|
||||
createTime?: number;
|
||||
sampleSize?: number;
|
||||
sampleMineType?: string;
|
||||
sampleTime?: number;
|
||||
}>({});
|
||||
const handleAddTag = useCallback(() => {
|
||||
setModalVisible(true);
|
||||
}, [modalVisible]);
|
||||
|
||||
// const radioData = data && data[0];
|
||||
|
||||
// // 当 radioData 改变时更新表单值
|
||||
useEffect(() => {
|
||||
if (type === 'radio') {
|
||||
const item = data?.[0];
|
||||
setValue({ ...item, sampleIds: [item?.id] });
|
||||
} else {
|
||||
const sampleIds = data?.map((sample) => sample.id) || [];
|
||||
const tags = data?.map((sample) => {
|
||||
return sample.tags;
|
||||
});
|
||||
const map = new Map();
|
||||
const tags_total = tags
|
||||
?.flat()
|
||||
.filter((v) => !map.has(v.id) && map.set(v.id, v));
|
||||
setValue({ tags: tags_total as TagItem[], sampleIds });
|
||||
}
|
||||
}, [type, data]);
|
||||
useEffect(() => {
|
||||
formRef.current?.setFieldsValue(value);
|
||||
}, [value]);
|
||||
|
||||
const tagNames = useMemo<FileItem[]>(() => {
|
||||
return (
|
||||
data?.map((tag) => {
|
||||
return {
|
||||
id: tag.id,
|
||||
originalName: tag.sampleName,
|
||||
};
|
||||
}) || []
|
||||
);
|
||||
}, [data]);
|
||||
|
||||
const onListAddTag = async (tags: TagItem[]) => {
|
||||
const sampleIds = data?.map((sample) => sample.id);
|
||||
const ids = tags?.map((tag) => tag.id);
|
||||
await relateSample({ tagId: ids, sampleIds: sampleIds as number[] });
|
||||
setModalVisible(false);
|
||||
const map = new Map();
|
||||
const newTags = [...(value.tags || []), ...tags];
|
||||
const tags_total = newTags
|
||||
?.flat()
|
||||
.filter((v) => !map.has(v.id) && map.set(v.id, v));
|
||||
setValue({ ...value, tags: tags_total });
|
||||
// 执行刷新回调
|
||||
message.success('添加标签成功');
|
||||
if (props.onRefresh) {
|
||||
props.onRefresh();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteAll = async () => {
|
||||
const ids = data?.map((sample) => sample.id);
|
||||
if (ids) {
|
||||
await deleteSample(ids.join(','));
|
||||
message.success('删除成功');
|
||||
|
||||
if (props.onRefresh) {
|
||||
props.onRefresh('delete');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 下载
|
||||
const handleDownloadAll = () => {};
|
||||
|
||||
const handleTagManager = () => {
|
||||
setTagManagerVisible(true);
|
||||
};
|
||||
|
||||
const forMap = (tags: TagItem[]) => (
|
||||
<div style={{ display: 'inline-block', marginBottom: 10 }}>
|
||||
{tags.map((tag) => (
|
||||
<Tag
|
||||
closable
|
||||
key={tag.id}
|
||||
style={{ marginBottom: 10 }}
|
||||
onClose={async (e) => {
|
||||
e.preventDefault();
|
||||
await deleteSampleTagRelate({
|
||||
sampleIds: value.sampleIds || [],
|
||||
tagId: [tag.id],
|
||||
});
|
||||
message.success('删除成功');
|
||||
props?.onRefresh?.();
|
||||
setValue({ ...value, tags: tags.filter((t) => t.id !== tag.id) });
|
||||
}}
|
||||
>
|
||||
{tag.tagName}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
const onRename = () => {
|
||||
props.onRefresh?.();
|
||||
setTagManagerVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <Switch
|
||||
style={{
|
||||
marginBlockEnd: 16,
|
||||
}}
|
||||
checked={readonly}
|
||||
checkedChildren="编辑"
|
||||
unCheckedChildren="只读"
|
||||
onChange={setReadonly}
|
||||
/> */}
|
||||
<ProForm
|
||||
readonly={readonly}
|
||||
name="validate_other"
|
||||
formRef={formRef}
|
||||
initialValues={{
|
||||
sample_name: '1111',
|
||||
}}
|
||||
onValuesChange={(_, values) => {
|
||||
console.log(values);
|
||||
}}
|
||||
onFinish={async (value) => console.log(value)}
|
||||
>
|
||||
<ProFormGroup title="预览">{/* <audio></audio> */}</ProFormGroup>
|
||||
<ProForm name="validate_other" formRef={formRef} submitter={false}>
|
||||
{type === 'radio' && (
|
||||
<ProFormGroup title="预览">
|
||||
{data?.[0].sampleFilePath && (
|
||||
<audio
|
||||
controls
|
||||
preload="true"
|
||||
crossOrigin="anonymous"
|
||||
style={{ marginBottom: 24 }}
|
||||
>
|
||||
<source src={data[0].sampleFilePath} />
|
||||
<track kind="captions" />
|
||||
</audio>
|
||||
)}
|
||||
</ProFormGroup>
|
||||
)}
|
||||
<ProFormGroup title="基本信息">
|
||||
{type === 'radio' && (
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="sampleName"
|
||||
placeholder="请输入样本名称"
|
||||
fieldProps={{
|
||||
onBlur: async (e) => {
|
||||
if (e.target.value) {
|
||||
const newData =
|
||||
data?.map((sample) => {
|
||||
return {
|
||||
id: sample.id,
|
||||
sampleName: e.target.value,
|
||||
};
|
||||
}) || [];
|
||||
await updateSamples(newData);
|
||||
props?.onRefresh?.();
|
||||
message.success('更新成功');
|
||||
}
|
||||
},
|
||||
}}
|
||||
rules={[{ required: true, message: '样本名称不能为空' }]}
|
||||
/>
|
||||
)}
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="sample_name"
|
||||
placeholder="请输入样本名称"
|
||||
rules={[{ required: true, message: '样本名称不能为空' }]}
|
||||
fieldProps={{
|
||||
onBlur: async (e) => {
|
||||
if (e.target.value) {
|
||||
const newData =
|
||||
data?.map((sample) => {
|
||||
return {
|
||||
id: sample.id,
|
||||
remark: e.target.value,
|
||||
};
|
||||
}) || [];
|
||||
await updateSamples(newData);
|
||||
props?.onRefresh?.();
|
||||
}
|
||||
},
|
||||
}}
|
||||
name="remark"
|
||||
placeholder="请输入注释"
|
||||
/>
|
||||
<ProFormText width="md" name="remark" placeholder="请输入注释" />
|
||||
</ProFormGroup>
|
||||
<ProFormGroup
|
||||
title="标签"
|
||||
style={{
|
||||
gap: '0 32px',
|
||||
}}
|
||||
|
||||
<ProFormGroup title="标签">
|
||||
{/* <Form.Item name="tag"> */}
|
||||
{forMap(value.tags || [])}
|
||||
</ProFormGroup>
|
||||
<Button
|
||||
type="dashed"
|
||||
block
|
||||
style={{ marginBottom: 24 }}
|
||||
onClick={handleAddTag}
|
||||
>
|
||||
<ProForm.Item name="tags">
|
||||
<TagEditor placeholder="输入标签名称" maxCount={10} />
|
||||
</ProForm.Item>
|
||||
</ProFormGroup>
|
||||
添加标签
|
||||
</Button>
|
||||
<ProFormGroup title="文本信息" block></ProFormGroup>
|
||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||
<span>添加日期: </span>
|
||||
<span>{dayjs(value.createTime).format('YYYY-MM-DD HH:mm:ss')}</span>
|
||||
</Space>
|
||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||
<span>修改日期</span>
|
||||
<span>{dayjs(value.updateTime).format('YYYY-MM-DD HH:mm:ss')}</span>
|
||||
</Space>
|
||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||
<span>文件大小: </span>
|
||||
<span>{value.sampleSize}</span>
|
||||
</Space>
|
||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||
<span>格式: </span>
|
||||
<span>{value.sampleMineType}</span>
|
||||
</Space>
|
||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||
<span>时长: </span>
|
||||
<span>{value.sampleTime}</span>
|
||||
</Space>
|
||||
|
||||
{type === 'checkbox' && (
|
||||
<>
|
||||
<ProFormGroup title="其他"></ProFormGroup>
|
||||
<Button
|
||||
block
|
||||
style={{ marginBottom: 24 }}
|
||||
onClick={handleTagManager}
|
||||
>
|
||||
批量重命名
|
||||
</Button>
|
||||
<Button
|
||||
block
|
||||
style={{ marginBottom: 24 }}
|
||||
onClick={handleDownloadAll}
|
||||
>
|
||||
下载到本地
|
||||
</Button>
|
||||
<Button
|
||||
block
|
||||
color="danger"
|
||||
style={{ marginBottom: 24 }}
|
||||
onClick={handleDeleteAll}
|
||||
>
|
||||
删除样本
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</ProForm>
|
||||
<GroupTagModal
|
||||
visible={modalVisible}
|
||||
onCancel={() => setModalVisible(false)}
|
||||
onChange={onListAddTag}
|
||||
editable={false}
|
||||
value={value?.tags}
|
||||
request={{
|
||||
groupsApi: {
|
||||
get: getSampleTagGroup,
|
||||
create: createSampleTagGroup,
|
||||
delete: deleteSampleTagGroup,
|
||||
update: updateSampleTagGroup,
|
||||
},
|
||||
tagsApi: {
|
||||
get: getSampleTagPage,
|
||||
create: createSampleTag,
|
||||
delete: deleteSampleTag,
|
||||
update: updateSampleTag,
|
||||
},
|
||||
}}
|
||||
title="管理技术标签"
|
||||
width={800}
|
||||
height={500}
|
||||
/>
|
||||
<TagManager
|
||||
visible={tagManagerVisible}
|
||||
files={tagNames}
|
||||
onOk={onRename}
|
||||
onCancel={() => setTagManagerVisible(false)}
|
||||
></TagManager>
|
||||
<Space style={{ width: '100%', justifyContent: 'center', padding: 12 }}>
|
||||
<Button color="danger" onClick={() => {}}>
|
||||
下载
|
||||
</Button>
|
||||
<Button color="danger" variant="solid" onClick={handleDeleteAll}>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SampleTagDetail;
|
||||
export default React.memo(SampleTagDetail) as <T extends Record<string, any>>(
|
||||
props: SampleTagDetailProps<T>,
|
||||
) => React.ReactElement;
|
||||
|
||||
@@ -2,14 +2,20 @@
|
||||
display: flex;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
overflow: auto;
|
||||
:global {
|
||||
.ant-pro-table {
|
||||
flex: 1 auto;
|
||||
}
|
||||
.detail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-left: 1px solid #e8e8e8;
|
||||
width: 400px;
|
||||
padding: 16px;
|
||||
form {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,125 @@
|
||||
import type { ActionType } from '@ant-design/pro-components';
|
||||
import type { RowSelectionType } from 'antd/es/table/interface';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import EnhancedProTable from '@/components/EnhancedProTable';
|
||||
import type { ToolbarAction } from '@/components/EnhancedProTable/types';
|
||||
import GroupTagModal from '@/components/GroupTag/GroupTagModal';
|
||||
import UploadCard from '@/components/Upload/UploadCard';
|
||||
import {
|
||||
type AiSampleRespVO,
|
||||
createSampleTag,
|
||||
createSampleTagGroup,
|
||||
deleteSampleTag,
|
||||
deleteSampleTagGroup,
|
||||
getSamplePage,
|
||||
getSampleTagGroup,
|
||||
getSampleTagPage,
|
||||
type SampleReqVo,
|
||||
updateSampleTag,
|
||||
updateSampleTagGroup,
|
||||
} from '@/services/ai/sample';
|
||||
import { baseTenantColumns } from './config';
|
||||
import SampleTagDetail from './detail';
|
||||
import styles from './index.module.less';
|
||||
|
||||
const SampleTag: React.FC = () => {
|
||||
const tableRef = useRef<ActionType>(null);
|
||||
// const [detail, setDetail] = useState<any>(null);
|
||||
// const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
const handleAll = () => {
|
||||
// console.log(tableRef.current.getSelectedRowKeys());
|
||||
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
|
||||
const [selectedRows, setSelectedRows] = useState<AiSampleRespVO[]>([]);
|
||||
|
||||
const [selectTableType, setSelectTableType] =
|
||||
useState<RowSelectionType>('radio');
|
||||
|
||||
const handleAll = (selectTableType: RowSelectionType) => {
|
||||
setSelectedRows([]);
|
||||
setSelectTableType(selectTableType === 'radio' ? 'checkbox' : 'radio');
|
||||
};
|
||||
|
||||
const handleTags = () => {
|
||||
setModalVisible(true);
|
||||
};
|
||||
const toolbarActions: ToolbarAction[] = [
|
||||
{
|
||||
key: 'add',
|
||||
label: '批量编辑',
|
||||
label: selectTableType === 'checkbox' ? '取消编辑' : '批量编辑',
|
||||
onClick: () => handleAll(selectTableType),
|
||||
},
|
||||
{
|
||||
key: 'tags',
|
||||
label: '标签管理',
|
||||
type: 'primary',
|
||||
|
||||
onClick: handleAll,
|
||||
onClick: handleTags,
|
||||
},
|
||||
];
|
||||
const onFetch = async (_params: API.getProductCategoryCategoryListParams) => {
|
||||
// const data = await getCategoryList({
|
||||
// ...params,
|
||||
// });
|
||||
const data: any = [
|
||||
{ sample_name: 111, id: 1, remark: 222 },
|
||||
{ sample_name: 22, id: 2, remark: 33 },
|
||||
];
|
||||
const onFetch = async (params: SampleReqVo) => {
|
||||
const data = await getSamplePage({
|
||||
...params,
|
||||
});
|
||||
return {
|
||||
data: data,
|
||||
data: data.list,
|
||||
total: data.total,
|
||||
success: true,
|
||||
};
|
||||
};
|
||||
|
||||
const onRefresh = (type?: string) => {
|
||||
tableRef.current?.reload();
|
||||
tableRef.current?.onValuesChange({}, {});
|
||||
type && setSelectedRows([]);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<UploadCard />
|
||||
<div className={styles['tag-content']}>
|
||||
<EnhancedProTable<API.CategoryDO>
|
||||
<EnhancedProTable<AiSampleRespVO>
|
||||
ref={tableRef}
|
||||
columns={baseTenantColumns}
|
||||
request={onFetch}
|
||||
toolbarActions={toolbarActions}
|
||||
headerTitle="样本列表"
|
||||
showIndex={false}
|
||||
showSelection={true}
|
||||
enableRowClick={true}
|
||||
rowSelection={{
|
||||
type: selectTableType,
|
||||
selectedRowKeys: selectedRows.map((item) => item.id) as React.Key[],
|
||||
onChange: (_, selectedRows) => {
|
||||
setSelectedRows(selectedRows);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<div className="detail">
|
||||
<SampleTagDetail />
|
||||
</div>
|
||||
{selectedRows.length > 0 && (
|
||||
<div className="detail">
|
||||
<SampleTagDetail<AiSampleRespVO>
|
||||
type={selectTableType}
|
||||
data={selectedRows}
|
||||
onRefresh={onRefresh}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<GroupTagModal
|
||||
visible={modalVisible}
|
||||
onCancel={() => setModalVisible(false)}
|
||||
editable={true}
|
||||
request={{
|
||||
groupsApi: {
|
||||
get: getSampleTagGroup,
|
||||
create: createSampleTagGroup,
|
||||
delete: deleteSampleTagGroup,
|
||||
update: updateSampleTagGroup,
|
||||
},
|
||||
tagsApi: {
|
||||
get: getSampleTagPage,
|
||||
create: createSampleTag,
|
||||
delete: deleteSampleTag,
|
||||
update: updateSampleTag,
|
||||
},
|
||||
}}
|
||||
title="管理技术标签"
|
||||
width={800}
|
||||
height={500}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user