You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 6.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import editExperimentIcon from '@/assets/img/edit-experiment.png';
  2. import KFModal from '@/components/KFModal';
  3. import {
  4. DataSource,
  5. ResourceType,
  6. ResourceVersionData,
  7. resourceConfig,
  8. type ResourceData,
  9. } from '@/pages/Dataset/config';
  10. import { to } from '@/utils/promise';
  11. import { InfoCircleOutlined } from '@ant-design/icons';
  12. import { Form, Input, ModalProps, Select } from 'antd';
  13. import { pick } from 'lodash';
  14. import { useEffect, useState } from 'react';
  15. import styles from './index.less';
  16. type FormData = {
  17. id: number;
  18. version: string;
  19. version_desc: string;
  20. };
  21. interface ExportModelModalProps extends Omit<ModalProps, 'onOk'> {
  22. resourceType: ResourceType;
  23. pipelineId: number; // 流水线 id
  24. experimentId: number; // 实验 id
  25. experimentName: string; // 实验 name
  26. experimentInsId: number; // 实验实例 id
  27. pipelineNodeId: string; // 流水线节点 id
  28. path: string; // 文件路径
  29. onOk: () => void;
  30. }
  31. function ExportModelModal({
  32. resourceType,
  33. pipelineId,
  34. experimentId,
  35. experimentName,
  36. experimentInsId,
  37. pipelineNodeId,
  38. path,
  39. onOk,
  40. ...rest
  41. }: ExportModelModalProps) {
  42. const [form] = Form.useForm();
  43. const [resources, setResources] = useState<ResourceData[]>([]);
  44. const [versions, setVersions] = useState<ResourceVersionData[]>([]);
  45. const config = resourceConfig[resourceType];
  46. const layout = {
  47. labelCol: { span: 24 },
  48. wrapperCol: { span: 24 },
  49. };
  50. useEffect(() => {
  51. // 获取数据集、模型列表
  52. const requestResourceList = async () => {
  53. const params = {
  54. page: 0,
  55. size: 1000,
  56. is_public: false, // 个人
  57. };
  58. const [res] = await to(config.getList(params));
  59. if (res && res.data) {
  60. setResources(res.data.content || []);
  61. }
  62. };
  63. requestResourceList();
  64. }, [config]);
  65. // 获取选中的数据集、模型
  66. const getSelectedResource = (id: number | undefined) => {
  67. if (id) {
  68. return resources.find((item) => item.id === id);
  69. }
  70. return undefined;
  71. };
  72. // 版本 tooltip
  73. const getTooltip = () => {
  74. const id = form.getFieldValue('id');
  75. const resource = getSelectedResource(id);
  76. const name = resource?.name ?? '';
  77. const versionNames = versions.map((item: ResourceVersionData) => item.name).join('、');
  78. const tooltip =
  79. versions.length > 0 ? `${name}有以下版本:\n${versionNames}\n注意不能重复` : undefined;
  80. return tooltip;
  81. };
  82. // 处理数据集、模型选择变化
  83. const handleResourceChange = (id: number | undefined) => {
  84. if (id) {
  85. getRecourceVersions(id);
  86. } else {
  87. setVersions([]);
  88. }
  89. };
  90. // 获取数据集、模型版本列表
  91. const getRecourceVersions = async (id: number) => {
  92. const resource = getSelectedResource(id);
  93. if (!resource) {
  94. return;
  95. }
  96. const [res] = await to(config.getVersions(pick(resource, ['identifier', 'owner'])));
  97. if (res && res.data) {
  98. setVersions(res.data);
  99. }
  100. };
  101. // 提交
  102. const hanldeFinish = (formData: FormData) => {
  103. exportToResource(formData);
  104. };
  105. // 导出到数据集、模型
  106. const exportToResource = async (formData: FormData) => {
  107. const id = form.getFieldValue('id');
  108. const resource = getSelectedResource(id);
  109. const params = {
  110. ...formData,
  111. identifier: resource?.identifier,
  112. owner: resource?.owner,
  113. is_public: resource?.is_public,
  114. name: resource?.name,
  115. [config.sourceParamKey]: DataSource.HandExport,
  116. train_task: {
  117. workflow_id: pipelineId,
  118. experiment_id: experimentId,
  119. name: experimentName,
  120. ins_id: experimentInsId,
  121. task_id: pipelineNodeId,
  122. },
  123. [config.filePropKey]: [
  124. {
  125. url: path,
  126. },
  127. ],
  128. };
  129. const [res] = await to(config.addVersion(params));
  130. if (res) {
  131. onOk();
  132. }
  133. };
  134. return (
  135. <KFModal
  136. {...rest}
  137. title={`导出到${config.name}`}
  138. image={editExperimentIcon}
  139. okButtonProps={{
  140. htmlType: 'submit',
  141. form: 'form',
  142. }}
  143. width={825}
  144. className={styles['export-model-modal']}
  145. >
  146. <Form
  147. name="form"
  148. layout="horizontal"
  149. onFinish={hanldeFinish}
  150. autoComplete="off"
  151. form={form}
  152. {...layout}
  153. labelAlign="left"
  154. labelWrap
  155. >
  156. <Form.Item
  157. label={`${config.name}名称`}
  158. name="id"
  159. rules={[{ required: true, message: `请选择${config.name}` }]}
  160. >
  161. <Select
  162. placeholder={`请选择${config.name}`}
  163. onChange={handleResourceChange}
  164. options={resources}
  165. fieldNames={{ label: 'name', value: 'id' }}
  166. optionFilterProp="name"
  167. showSearch
  168. allowClear
  169. ></Select>
  170. </Form.Item>
  171. <Form.Item
  172. label={`${config.name}版本`}
  173. name="version"
  174. tooltip={
  175. getTooltip()
  176. ? {
  177. overlayClassName: styles['export-model-modal__tooltip'],
  178. title: getTooltip(),
  179. icon: <InfoCircleOutlined />,
  180. }
  181. : undefined
  182. }
  183. rules={[
  184. { required: true, message: `请输入${config.name}版本` },
  185. {
  186. validator: (_, value) => {
  187. if (value && versions.map((item) => item.name).includes(value)) {
  188. return Promise.reject(`${config.name}版本已存在`);
  189. } else {
  190. return Promise.resolve();
  191. }
  192. },
  193. },
  194. ]}
  195. >
  196. <Input placeholder={`请输入${config.name}版本`} maxLength={64} showCount allowClear />
  197. </Form.Item>
  198. <Form.Item
  199. label="版本描述"
  200. name="version_desc"
  201. rules={[{ required: true, message: '请输入版本描述' }]}
  202. >
  203. <Input.TextArea
  204. placeholder="请输入版本描述"
  205. maxLength={128}
  206. autoSize={{ minRows: 2, maxRows: 5 }}
  207. showCount
  208. allowClear
  209. />
  210. </Form.Item>
  211. </Form>
  212. </KFModal>
  213. );
  214. }
  215. export default ExportModelModal;