Merge branch 'wuxichen' of http://gitea.tashowz.com/tashow/tashow-manager into qianpw
Some checks failed
coverage CI / build (push) Has been cancelled
Some checks failed
coverage CI / build (push) Has been cancelled
This commit is contained in:
@@ -14,6 +14,8 @@ VITE_UPLOAD_TYPE=server
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
VITE_API_URL_PREFIX=/ai/sample/create
|
||||
|
||||
# 是否删除debugger
|
||||
VITE_DROP_DEBUGGER=false
|
||||
|
||||
|
||||
14
mock/ap.ts
Normal file
14
mock/ap.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { Request, Response } from "express";
|
||||
import mockjs from "mockjs";
|
||||
|
||||
const getTags = (_: Request, res: Response) => {
|
||||
return res.json({
|
||||
data: mockjs.mock({
|
||||
"list|100": [{ name: "@city", "value|1-100": 150, "type|0-2": 1 }],
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
"GET /api/tags": getTags,
|
||||
};
|
||||
113
mock/notices.ts
113
mock/notices.ts
@@ -1,117 +1,20 @@
|
||||
import type { Request, Response } from 'express';
|
||||
import type { Request, Response } from "express";
|
||||
|
||||
const getNotices = (_req: Request, res: Response) => {
|
||||
const getSampleTag = (_req: Request, res: Response) => {
|
||||
res.json({
|
||||
data: [
|
||||
{
|
||||
id: '000000001',
|
||||
id: "000000001",
|
||||
avatar:
|
||||
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/MSbDR4FR2MUAAAAAAAAAAAAAFl94AQBr',
|
||||
title: '你收到了 14 份新周报',
|
||||
datetime: '2017-08-09',
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000002',
|
||||
avatar:
|
||||
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/hX-PTavYIq4AAAAAAAAAAAAAFl94AQBr',
|
||||
title: '你推荐的 曲妮妮 已通过第三轮面试',
|
||||
datetime: '2017-08-08',
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000003',
|
||||
avatar:
|
||||
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/jHX5R5l3QjQAAAAAAAAAAAAAFl94AQBr',
|
||||
title: '这种模板可以区分多种通知类型',
|
||||
datetime: '2017-08-07',
|
||||
read: true,
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000004',
|
||||
avatar:
|
||||
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/Wr4mQqx6jfwAAAAAAAAAAAAAFl94AQBr',
|
||||
title: '左侧图标用于区分不同的类型',
|
||||
datetime: '2017-08-07',
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000005',
|
||||
avatar:
|
||||
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/Mzj_TbcWUj4AAAAAAAAAAAAAFl94AQBr',
|
||||
title: '内容不要超过两行字,超出时自动截断',
|
||||
datetime: '2017-08-07',
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000006',
|
||||
avatar:
|
||||
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/eXLzRbPqQE4AAAAAAAAAAAAAFl94AQBr',
|
||||
title: '曲丽丽 评论了你',
|
||||
description: '描述信息描述信息描述信息',
|
||||
datetime: '2017-08-07',
|
||||
type: 'message',
|
||||
clickClose: true,
|
||||
},
|
||||
{
|
||||
id: '000000007',
|
||||
avatar:
|
||||
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/w5mRQY2AmEEAAAAAAAAAAAAAFl94AQBr',
|
||||
title: '朱偏右 回复了你',
|
||||
description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像',
|
||||
datetime: '2017-08-07',
|
||||
type: 'message',
|
||||
clickClose: true,
|
||||
},
|
||||
{
|
||||
id: '000000008',
|
||||
avatar:
|
||||
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/wPadR5M9918AAAAAAAAAAAAAFl94AQBr',
|
||||
title: '标题',
|
||||
description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像',
|
||||
datetime: '2017-08-07',
|
||||
type: 'message',
|
||||
clickClose: true,
|
||||
},
|
||||
{
|
||||
id: '000000009',
|
||||
title: '任务名称',
|
||||
description: '任务需要在 2017-01-12 20:00 前启动',
|
||||
extra: '未开始',
|
||||
status: 'todo',
|
||||
type: 'event',
|
||||
},
|
||||
{
|
||||
id: '000000010',
|
||||
title: '第三方紧急代码变更',
|
||||
description:
|
||||
'冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
|
||||
extra: '马上到期',
|
||||
status: 'urgent',
|
||||
type: 'event',
|
||||
},
|
||||
{
|
||||
id: '000000011',
|
||||
title: '信息安全考试',
|
||||
description: '指派竹尔于 2017-01-09 前完成更新并发布',
|
||||
extra: '已耗时 8 天',
|
||||
status: 'doing',
|
||||
type: 'event',
|
||||
},
|
||||
{
|
||||
id: '000000012',
|
||||
title: 'ABCD 版本发布',
|
||||
description:
|
||||
'冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
|
||||
extra: '进行中',
|
||||
status: 'processing',
|
||||
type: 'event',
|
||||
"https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/MSbDR4FR2MUAAAAAAAAAAAAAFl94AQBr",
|
||||
title: "你收到了 14 份新周报",
|
||||
datetime: "2017-08-09",
|
||||
type: "notification",
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
'GET /api/notices': getNotices,
|
||||
"GET /api/notices": getSampleTag,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { ProFormColumnsType } from '@ant-design/pro-components';
|
||||
import { BetaSchemaForm } from '@ant-design/pro-components';
|
||||
import { Button, type ColProps, Drawer, Space, Typography } from 'antd';
|
||||
import type { FormInstance } from 'antd/lib';
|
||||
import React, { forwardRef, useImperativeHandle } from 'react';
|
||||
|
||||
interface ConfigurableDrawerFormProps {
|
||||
@@ -38,7 +39,7 @@ const ConfigurableDrawerForm = forwardRef<
|
||||
const [formData, setFormData] = React.useState(initialValues || {});
|
||||
const [loading, setLoading] = React.useState<boolean>(false);
|
||||
// 添加表单实例引用
|
||||
const formRef = React.useRef<any>(null);
|
||||
const formRef = React.useRef<FormInstance>(null);
|
||||
useImperativeHandle(ref, () => ({
|
||||
open: (data) => {
|
||||
if (data) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
type ParamsType,
|
||||
ProTable,
|
||||
} from '@ant-design/pro-components';
|
||||
import { Button, Space } from 'antd';
|
||||
import { Button, Space, Table } from 'antd';
|
||||
import React, { forwardRef, useCallback, useMemo, useState } from 'react';
|
||||
import { formatPaginationTotal } from '@/utils/antd/tableHelpers';
|
||||
import type { BaseRecord, EnhancedProTableProps } from './types';
|
||||
@@ -33,7 +33,7 @@ function EnhancedProTable<T extends BaseRecord, U extends ParamsType = any>(
|
||||
// onExport,
|
||||
// customToolbarRender,
|
||||
customActionRender,
|
||||
rowKey,
|
||||
rowKey = 'id',
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
@@ -42,45 +42,20 @@ function EnhancedProTable<T extends BaseRecord, U extends ParamsType = any>(
|
||||
// 行选择配置
|
||||
const rowSelection = useMemo(() => {
|
||||
if (!showSelection) return undefined;
|
||||
|
||||
return {
|
||||
selectedRowKeys,
|
||||
selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
|
||||
onChange: (keys: React.Key[], rows: T[]) => {
|
||||
setSelectedRowKeys(keys);
|
||||
setSelectedRows(rows);
|
||||
},
|
||||
getCheckboxProps: (record: T) => ({
|
||||
name: record.id?.toString(),
|
||||
name: record[rowKey]?.toString(),
|
||||
}),
|
||||
};
|
||||
}, [showSelection, selectedRowKeys]);
|
||||
|
||||
// 表格提醒渲染
|
||||
const tableAlertRender = useCallback(
|
||||
({ selectedRowKeys, onCleanSelected }: any) => {
|
||||
if (!showSelection || selectedRowKeys.length === 0) return false;
|
||||
|
||||
return (
|
||||
<Space size={24}>
|
||||
<span>
|
||||
已选 {selectedRowKeys.length} 项
|
||||
<a style={{ marginLeft: 8 }} onClick={onCleanSelected}>
|
||||
取消选择
|
||||
</a>
|
||||
</span>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
[showSelection],
|
||||
);
|
||||
|
||||
const toolBarRender = useCallback(() =>
|
||||
// action: ActionType | undefined,
|
||||
// rows: {
|
||||
// selectedRowKeys?: (string | number)[] | undefined;
|
||||
// selectedRows?: T[] | undefined;
|
||||
// }
|
||||
{
|
||||
const toolBarRender = useCallback(() => {
|
||||
const toolbarElements =
|
||||
toolbarActions?.map((action) => {
|
||||
return (
|
||||
@@ -96,16 +71,6 @@ function EnhancedProTable<T extends BaseRecord, U extends ParamsType = any>(
|
||||
</Button>
|
||||
);
|
||||
}) || [];
|
||||
// return [
|
||||
// <Button
|
||||
// key="button"
|
||||
// icon={<PlusOutlined />}
|
||||
// onClick={}
|
||||
// type="primary"
|
||||
// >
|
||||
// 新建
|
||||
// </Button>,
|
||||
// ];
|
||||
return toolbarElements;
|
||||
}, [toolbarActions]);
|
||||
return (
|
||||
@@ -114,12 +79,11 @@ function EnhancedProTable<T extends BaseRecord, U extends ParamsType = any>(
|
||||
columns={columns}
|
||||
actionRef={ref}
|
||||
request={request}
|
||||
rowKey={rowKey || 'id'}
|
||||
rowKey={rowKey}
|
||||
rowSelection={rowSelection}
|
||||
toolBarRender={toolBarRender}
|
||||
manualRequest={false}
|
||||
showSorterTooltip
|
||||
tableAlertRender={tableAlertRender}
|
||||
scroll={{ x: 'max-content' }}
|
||||
search={{
|
||||
labelWidth: 'auto',
|
||||
|
||||
8
src/components/Upload/UploadCard/index.module.less
Normal file
8
src/components/Upload/UploadCard/index.module.less
Normal file
@@ -0,0 +1,8 @@
|
||||
.uploader-card {
|
||||
background-color: #fff;
|
||||
:global {
|
||||
.ant-upload-drag {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
176
src/components/Upload/UploadCard/index.tsx
Normal file
176
src/components/Upload/UploadCard/index.tsx
Normal file
@@ -0,0 +1,176 @@
|
||||
import {
|
||||
DeleteOutlined,
|
||||
FileTextOutlined,
|
||||
PlayCircleOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { message, Upload } from 'antd';
|
||||
import type { RcFile, UploadFile, UploadProps } from 'antd/lib/upload';
|
||||
import React, { useState } from 'react';
|
||||
import { createSample, getSample } from '@/services/ai/sample';
|
||||
import styles from './index.module.less';
|
||||
|
||||
const { Dragger } = Upload;
|
||||
interface AudioUploaderProps {
|
||||
value?: UploadFile[] | UploadFile | null;
|
||||
onChange?: (file: UploadFile[] | UploadFile | null) => void;
|
||||
maxSize?: number;
|
||||
accept?: string;
|
||||
disabled?: boolean;
|
||||
maxCount?: number;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const AudioUploader: React.FC<AudioUploaderProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
maxSize = 10,
|
||||
accept = '.mp3,.wav,.flac,.aac,.ogg',
|
||||
disabled = false,
|
||||
maxCount = 10,
|
||||
placeholder = '点击或拖拽音频文件到此区域上传',
|
||||
}) => {
|
||||
const [fileList, setFileList] = useState<UploadFile[]>(() => {
|
||||
if (Array.isArray(value)) {
|
||||
return value;
|
||||
} else if (value) {
|
||||
return [value];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
const [uploading, setUploading] = useState<boolean>(false);
|
||||
|
||||
const beforeUpload = (file: RcFile): boolean => {
|
||||
const isAudio = file.type.startsWith('audio/');
|
||||
if (!isAudio) {
|
||||
message.error('只能上传音频文件!');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查文件大小
|
||||
const isLtMaxSize = file.size / 1024 / 1024 < maxSize;
|
||||
if (!isLtMaxSize) {
|
||||
message.error(`音频文件大小不能超过 ${maxSize}MB!`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查文件数量限制
|
||||
if (fileList.length >= maxCount) {
|
||||
message.error(`最多只能上传 ${maxCount} 个文件!`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// 实际的后端接口上传
|
||||
const uploadToServer = async (file: File) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
// formData.append("type", "audio"); // 可以添加额外参数
|
||||
|
||||
const response = await createSample(formData);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
};
|
||||
|
||||
const customRequest: UploadProps['customRequest'] = async (options) => {
|
||||
const { file, onSuccess, onError, onProgress } = options;
|
||||
|
||||
try {
|
||||
setUploading(true);
|
||||
|
||||
// 模拟进度更新
|
||||
onProgress?.({ percent: 10 });
|
||||
|
||||
// 调用后端接口
|
||||
const result = await uploadToServer(file as File);
|
||||
|
||||
onProgress?.({ percent: 100 });
|
||||
|
||||
if (result.success && result.data) {
|
||||
// 构造返回数据
|
||||
const responseData = {
|
||||
url: result.data.url,
|
||||
name: result.data.filename || (file as File).name,
|
||||
uid: (file as any).uid,
|
||||
status: 'done' as const,
|
||||
response: result.data,
|
||||
};
|
||||
|
||||
onSuccess?.(responseData);
|
||||
message.success('音频上传成功!');
|
||||
} else {
|
||||
throw new Error(result.message || '上传失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Upload error:', error);
|
||||
onError?.(error as Error);
|
||||
message.error(`上传失败: ${(error as Error).message}`);
|
||||
} finally {
|
||||
setUploading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleChange: UploadProps['onChange'] = ({
|
||||
fileList: newFileList,
|
||||
file,
|
||||
}) => {
|
||||
setFileList(newFileList);
|
||||
onChange?.(newFileList);
|
||||
};
|
||||
|
||||
const handleRemove = (file: UploadFile): boolean => {
|
||||
const newFileList = fileList.filter((item) => item.uid !== file.uid);
|
||||
setFileList(newFileList);
|
||||
onChange?.(newFileList);
|
||||
return true;
|
||||
};
|
||||
|
||||
const handlePreview = (file: UploadFile): void => {
|
||||
const audioUrl = file.url || (file.response as any)?.url;
|
||||
if (audioUrl) {
|
||||
const audio = new Audio(audioUrl);
|
||||
audio.play().catch(() => {
|
||||
message.error('音频播放失败');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const uploadProps: UploadProps = {
|
||||
name: 'file',
|
||||
multiple: true,
|
||||
fileList,
|
||||
accept,
|
||||
disabled: disabled || uploading,
|
||||
beforeUpload,
|
||||
customRequest,
|
||||
// onChange: handleChange,
|
||||
onRemove: handleRemove,
|
||||
onPreview: handlePreview,
|
||||
showUploadList: {
|
||||
showPreviewIcon: true,
|
||||
showRemoveIcon: true,
|
||||
previewIcon: <PlayCircleOutlined />,
|
||||
removeIcon: <DeleteOutlined />,
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles['uploader-card']}>
|
||||
<Dragger {...uploadProps}>
|
||||
<p className="">
|
||||
<FileTextOutlined style={{ fontSize: 36 }} />
|
||||
</p>
|
||||
<p className="ant-upload-text">{placeholder}</p>
|
||||
<p className="ant-upload-hint">
|
||||
支持格式:{accept},单次最多同时上传 {maxCount} 个文件
|
||||
</p>
|
||||
</Dragger>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AudioUploader;
|
||||
136
src/pages/ai/sample-tag/config.tsx
Normal file
136
src/pages/ai/sample-tag/config.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
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>[] = [
|
||||
{
|
||||
title: '样本名称',
|
||||
dataIndex: 'sample_name',
|
||||
},
|
||||
{
|
||||
title: '注释',
|
||||
dataIndex: 'remark',
|
||||
hideInSearch: true,
|
||||
},
|
||||
{
|
||||
title: '标签',
|
||||
hideInTable: true,
|
||||
dataIndex: 'tag_name',
|
||||
},
|
||||
{
|
||||
title: '样本格式',
|
||||
hideInTable: true,
|
||||
dataIndex: 'sample_mine_type',
|
||||
},
|
||||
];
|
||||
|
||||
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: "模板内容",
|
||||
// dataIndex: "content",
|
||||
// valueType: "textarea",
|
||||
// },
|
||||
81
src/pages/ai/sample-tag/detail.tsx
Normal file
81
src/pages/ai/sample-tag/detail.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import {
|
||||
ProForm,
|
||||
ProFormCascader,
|
||||
ProFormCheckbox,
|
||||
ProFormColorPicker,
|
||||
ProFormDigit,
|
||||
ProFormDigitRange,
|
||||
ProFormGroup,
|
||||
ProFormRadio,
|
||||
ProFormSelect,
|
||||
ProFormSlider,
|
||||
ProFormSwitch,
|
||||
ProFormText,
|
||||
} from '@ant-design/pro-components';
|
||||
import { Switch } from 'antd';
|
||||
import type { FormInstance } from 'antd/lib';
|
||||
import Mock from 'mockjs';
|
||||
import { useRef, useState } from 'react';
|
||||
import TagEditor from '@/components/TagEditor';
|
||||
|
||||
export const waitTime = (time: number = 100) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(true);
|
||||
}, time);
|
||||
});
|
||||
};
|
||||
|
||||
const SampleTagDetail = () => {
|
||||
const [readonly, setReadonly] = useState(false);
|
||||
const formRef = useRef<FormInstance>(null);
|
||||
|
||||
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>
|
||||
<ProFormGroup title="基本信息">
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="sample_name"
|
||||
placeholder="请输入样本名称"
|
||||
rules={[{ required: true, message: '样本名称不能为空' }]}
|
||||
/>
|
||||
<ProFormText width="md" name="remark" placeholder="请输入注释" />
|
||||
</ProFormGroup>
|
||||
<ProFormGroup
|
||||
title="标签"
|
||||
style={{
|
||||
gap: '0 32px',
|
||||
}}
|
||||
>
|
||||
<ProForm.Item name="tags">
|
||||
<TagEditor placeholder="输入标签名称" maxCount={10} />
|
||||
</ProForm.Item>
|
||||
</ProFormGroup>
|
||||
</ProForm>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SampleTagDetail;
|
||||
15
src/pages/ai/sample-tag/index.module.less
Normal file
15
src/pages/ai/sample-tag/index.module.less
Normal file
@@ -0,0 +1,15 @@
|
||||
.tag-content {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
:global {
|
||||
.ant-pro-table {
|
||||
flex: 1 auto;
|
||||
}
|
||||
.detail {
|
||||
border-left: 1px solid #e8e8e8;
|
||||
width: 400px;
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
61
src/pages/ai/sample-tag/index.tsx
Normal file
61
src/pages/ai/sample-tag/index.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import type { ActionType } from '@ant-design/pro-components';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import EnhancedProTable from '@/components/EnhancedProTable';
|
||||
import type { ToolbarAction } from '@/components/EnhancedProTable/types';
|
||||
import UploadCard from '@/components/Upload/UploadCard';
|
||||
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 toolbarActions: ToolbarAction[] = [
|
||||
{
|
||||
key: 'add',
|
||||
label: '批量编辑',
|
||||
type: 'primary',
|
||||
|
||||
onClick: handleAll,
|
||||
},
|
||||
];
|
||||
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 },
|
||||
];
|
||||
return {
|
||||
data: data,
|
||||
success: true,
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<UploadCard />
|
||||
<div className={styles['tag-content']}>
|
||||
<EnhancedProTable<API.CategoryDO>
|
||||
ref={tableRef}
|
||||
columns={baseTenantColumns}
|
||||
request={onFetch}
|
||||
toolbarActions={toolbarActions}
|
||||
headerTitle="样本列表"
|
||||
showIndex={false}
|
||||
showSelection={true}
|
||||
/>
|
||||
<div className="detail">
|
||||
<SampleTagDetail />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SampleTag;
|
||||
161
src/services/ai/sample/index.ts
Normal file
161
src/services/ai/sample/index.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
import { request } from "@umijs/max";
|
||||
|
||||
export interface SampleVo {
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
createTime?: string[];
|
||||
/**
|
||||
* 页码,从 1 开始", example = "1
|
||||
*/
|
||||
remark?: string;
|
||||
/**
|
||||
* 样本文件id
|
||||
*/
|
||||
sampleFileId?: number;
|
||||
/**
|
||||
* 样本格式
|
||||
*/
|
||||
sampleMineType?: string;
|
||||
/**
|
||||
* 样本名称
|
||||
*/
|
||||
sampleName?: string;
|
||||
/**
|
||||
* 样本大小
|
||||
*/
|
||||
sampleSize?: string;
|
||||
/**
|
||||
* 样本时长
|
||||
*/
|
||||
sampleTime?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回数据
|
||||
*
|
||||
* PageResultAiSampleRespVO
|
||||
*/
|
||||
export interface PageResultAiSampleRespVO {
|
||||
/**
|
||||
* 数据
|
||||
*/
|
||||
list?: AiSampleRespVO[];
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
total?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleRespVO
|
||||
*
|
||||
* AiSampleRespVO
|
||||
*/
|
||||
export interface AiSampleRespVO {
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
createTime?: string;
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
id?: number;
|
||||
/**
|
||||
* 样本注释
|
||||
*/
|
||||
remark?: string;
|
||||
/**
|
||||
* 样本文件id
|
||||
*/
|
||||
sampleFileId?: number;
|
||||
/**
|
||||
* 样本格式
|
||||
*/
|
||||
sampleMineType?: string;
|
||||
/**
|
||||
* 样本名称
|
||||
*/
|
||||
sampleName?: string;
|
||||
/**
|
||||
* 样本大小
|
||||
*/
|
||||
sampleSize?: string;
|
||||
/**
|
||||
* 样本时长
|
||||
*/
|
||||
sampleTime?: string;
|
||||
}
|
||||
|
||||
export interface SampleReqVo extends PageParam {
|
||||
name?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
// 获得样本库分页
|
||||
export const getSamplePage = async (params: SampleReqVo) => {
|
||||
return request("/ai/sample/get", {
|
||||
method: "GET",
|
||||
params,
|
||||
});
|
||||
};
|
||||
export const getSample = async (id: number) => {
|
||||
return request("/ai/sample/get", {
|
||||
method: "GET",
|
||||
params: { id },
|
||||
});
|
||||
};
|
||||
|
||||
// 查询部门列表
|
||||
// export const getDeptPage = async (params: DeptReq): Promise<Dept[]> => {
|
||||
// return await request.get({ url: "/system/dept/list", params });
|
||||
// };
|
||||
|
||||
export const getDeptPage = (params: SampleReqVo) => {
|
||||
return request("/system/dept/list", {
|
||||
method: "GET",
|
||||
params,
|
||||
});
|
||||
};
|
||||
|
||||
// 查询部门详情
|
||||
// export const getDept = async (id: number) => {
|
||||
// return await request.get({ url: "/system/dept/get?id=" + id });
|
||||
// };
|
||||
|
||||
export const getDept = (id: number) => {
|
||||
return request("/system/dept/get", {
|
||||
method: "GET",
|
||||
params: { id },
|
||||
});
|
||||
};
|
||||
|
||||
// 创建样本库
|
||||
export const createSample = (formData: FormData) => {
|
||||
return request("/ai/sample/create", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
data: formData,
|
||||
});
|
||||
};
|
||||
|
||||
export const updateSample = (params: SampleReqVo) => {
|
||||
return request("/ai/sample/update", {
|
||||
method: "PUT",
|
||||
data: params,
|
||||
});
|
||||
};
|
||||
|
||||
// 删除部门
|
||||
// export const deleteDept = async (id: number) => {
|
||||
// return await request.delete({ url: "/system/dept/delete?id=" + id });
|
||||
// };
|
||||
|
||||
export const deleteSample = (id: number) => {
|
||||
return request("/ai/sample/delete", {
|
||||
method: "DELETE",
|
||||
params: { id },
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user