| @@ -63,3 +63,5 @@ mvnw | |||||
| /react-ui/docs | /react-ui/docs | ||||
| /react-ui/types/tsconfig.tsbuildinfo | /react-ui/types/tsconfig.tsbuildinfo | ||||
| /react-ui/storybook-static | |||||
| /react-ui/.storybook/deploy.sh | |||||
| @@ -4,7 +4,6 @@ export default function(babel) { | |||||
| visitor: { | visitor: { | ||||
| ImportDeclaration(path) { | ImportDeclaration(path) { | ||||
| const source = path.node.source.value; | const source = path.node.source.value; | ||||
| // console.log("zzzz", source); | |||||
| if (source.endsWith('.less')) { | if (source.endsWith('.less')) { | ||||
| if (path.node.specifiers.length > 0) { | if (path.node.specifiers.length > 0) { | ||||
| path.node.source.value += "?modules"; | path.node.source.value += "?modules"; | ||||
| @@ -16,7 +16,11 @@ const config: StorybookConfig = { | |||||
| name: '@storybook/react-webpack5', | name: '@storybook/react-webpack5', | ||||
| options: {}, | options: {}, | ||||
| }, | }, | ||||
| staticDirs: ['../public', { from: '../docs', to: '/docs' }], | |||||
| staticDirs: [ | |||||
| '../public', | |||||
| { from: '../docs', to: '/docs' }, | |||||
| { from: '../docs/index.html', to: '/docs/index.html' }, | |||||
| ], | |||||
| docs: { | docs: { | ||||
| defaultName: 'Documentation', | defaultName: 'Documentation', | ||||
| }, | }, | ||||
| @@ -40,6 +40,7 @@ | |||||
| "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev", | "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev", | ||||
| "storybook": "storybook dev -p 6006", | "storybook": "storybook dev -p 6006", | ||||
| "storybook-build": "storybook build", | "storybook-build": "storybook build", | ||||
| "storybook-deploy": "./.storybook/deploy.sh", | |||||
| "storybook-docs": "storybook dev --docs", | "storybook-docs": "storybook dev --docs", | ||||
| "storybook-docs-build": "storybook build --docs", | "storybook-docs-build": "storybook build --docs", | ||||
| "test": "jest", | "test": "jest", | ||||
| @@ -44,7 +44,7 @@ type IframePageProps = { | |||||
| /** 子系统 */ | /** 子系统 */ | ||||
| type: IframePageType; | type: IframePageType; | ||||
| /** 是否可以在页签上打开 */ | /** 是否可以在页签上打开 */ | ||||
| openInTab: boolean; | |||||
| openInTab?: boolean; | |||||
| /** 自定义样式类名 */ | /** 自定义样式类名 */ | ||||
| className?: string; | className?: string; | ||||
| /** 自定义样式 */ | /** 自定义样式 */ | ||||
| @@ -13,6 +13,7 @@ import { | |||||
| } from '@/pages/Dataset/config'; | } from '@/pages/Dataset/config'; | ||||
| import GraphLegend from '@/pages/Model/components/GraphLegend'; | import GraphLegend from '@/pages/Model/components/GraphLegend'; | ||||
| import ModelEvolution from '@/pages/Model/components/ModelEvolution'; | import ModelEvolution from '@/pages/Model/components/ModelEvolution'; | ||||
| import { VersionChangedMessage } from '@/utils/constant'; | |||||
| import { openAntdModal } from '@/utils/modal'; | import { openAntdModal } from '@/utils/modal'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| @@ -124,6 +125,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| onOk: () => { | onOk: () => { | ||||
| getVersionList(true); | getVersionList(true); | ||||
| close(); | close(); | ||||
| window.postMessage({ type: VersionChangedMessage }); | |||||
| }, | }, | ||||
| }); | }); | ||||
| }; | }; | ||||
| @@ -170,6 +172,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| if (res) { | if (res) { | ||||
| message.success('删除成功'); | message.success('删除成功'); | ||||
| getVersionList(true); | getVersionList(true); | ||||
| window.postMessage({ type: VersionChangedMessage }); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -11,7 +11,6 @@ | |||||
| text-align: center; | text-align: center; | ||||
| background: @background; | background: @background; | ||||
| border-radius: 4px 4px 0 0; | border-radius: 4px 4px 0 0; | ||||
| .singleLine(); | |||||
| } | } | ||||
| .text() { | .text() { | ||||
| @@ -20,7 +19,6 @@ | |||||
| font-size: 13px; | font-size: 13px; | ||||
| line-height: 22px; | line-height: 22px; | ||||
| word-break: break-all; | word-break: break-all; | ||||
| .singleLine(); | |||||
| } | } | ||||
| .version-container(@background) { | .version-container(@background) { | ||||
| @@ -88,7 +88,7 @@ function VersionCompareModal({ | |||||
| format: formatProject, | format: formatProject, | ||||
| }, | }, | ||||
| { | { | ||||
| key: 'description', | |||||
| key: 'version_desc', | |||||
| text: '版本描述', | text: '版本描述', | ||||
| }, | }, | ||||
| ] | ] | ||||
| @@ -123,7 +123,7 @@ function VersionCompareModal({ | |||||
| format: formatTrainTask, | format: formatTrainTask, | ||||
| }, | }, | ||||
| { | { | ||||
| key: 'description', | |||||
| key: 'version_desc', | |||||
| text: '版本描述', | text: '版本描述', | ||||
| }, | }, | ||||
| ], | ], | ||||
| @@ -193,7 +193,14 @@ function VersionCompareModal({ | |||||
| ))} | ))} | ||||
| </div> | </div> | ||||
| <div className={styles['version-compare__left']}> | <div className={styles['version-compare__left']}> | ||||
| <div className={styles['version-compare__left__title']}>{v1.version}</div> | |||||
| <div className={styles['version-compare__left__title']}> | |||||
| <Typography.Text | |||||
| ellipsis={{ tooltip: v1.version }} | |||||
| style={{ width: '100%', lineHeight: 'inherit' }} | |||||
| > | |||||
| {v1.version} | |||||
| </Typography.Text> | |||||
| </div> | |||||
| {fields.map(({ key, format }) => { | {fields.map(({ key, format }) => { | ||||
| const text = getValue(v1, key as keyof typeof v1, format); | const text = getValue(v1, key as keyof typeof v1, format); | ||||
| return ( | return ( | ||||
| @@ -203,7 +210,7 @@ function VersionCompareModal({ | |||||
| [styles['version-compare__left__text--different']]: isDifferent(key), | [styles['version-compare__left__text--different']]: isDifferent(key), | ||||
| })} | })} | ||||
| > | > | ||||
| <Typography.Text ellipsis={{ tooltip: text }}> | |||||
| <Typography.Text ellipsis={{ tooltip: text }} style={{ width: '100%' }}> | |||||
| {isEmpty(text) ? '--' : text} | {isEmpty(text) ? '--' : text} | ||||
| </Typography.Text> | </Typography.Text> | ||||
| </div> | </div> | ||||
| @@ -211,7 +218,14 @@ function VersionCompareModal({ | |||||
| })} | })} | ||||
| </div> | </div> | ||||
| <div className={styles['version-compare__right']}> | <div className={styles['version-compare__right']}> | ||||
| <div className={styles['version-compare__right__title']}>{v2.version}</div> | |||||
| <div className={styles['version-compare__right__title']}> | |||||
| <Typography.Text | |||||
| ellipsis={{ tooltip: v2.version }} | |||||
| style={{ width: '100%', lineHeight: 'inherit' }} | |||||
| > | |||||
| {v2.version} | |||||
| </Typography.Text> | |||||
| </div> | |||||
| {fields.map(({ key, format }) => { | {fields.map(({ key, format }) => { | ||||
| const text = getValue(v2, key as keyof typeof v2, format); | const text = getValue(v2, key as keyof typeof v2, format); | ||||
| return ( | return ( | ||||
| @@ -221,7 +235,7 @@ function VersionCompareModal({ | |||||
| [styles['version-compare__right__text--different']]: isDifferent(key), | [styles['version-compare__right__text--different']]: isDifferent(key), | ||||
| })} | })} | ||||
| > | > | ||||
| <Typography.Text ellipsis={{ tooltip: text }}> | |||||
| <Typography.Text ellipsis={{ tooltip: text }} style={{ width: '100%' }}> | |||||
| {isEmpty(text) ? '--' : text} | {isEmpty(text) ? '--' : text} | ||||
| </Typography.Text> | </Typography.Text> | ||||
| </div> | </div> | ||||
| @@ -90,6 +90,7 @@ function MirrorCreate() { | |||||
| ...omit(formData, ['fileList', 'upload_type']), | ...omit(formData, ['fileList', 'upload_type']), | ||||
| path: file.response.data.url, | path: file.response.data.url, | ||||
| file_size: file.response.data.fileSize, | file_size: file.response.data.fileSize, | ||||
| file_name: file.response.data.fileName, | |||||
| upload_type: 1, | upload_type: 1, | ||||
| image_type: 0, | image_type: 0, | ||||
| }; | }; | ||||
| @@ -289,7 +290,7 @@ function MirrorCreate() { | |||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请上传镜像地址', | |||||
| message: '请上传镜像文件', | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| @@ -3,6 +3,7 @@ import TableColTitle from '@/components/TableColTitle'; | |||||
| import { useCheck } from '@/hooks/useCheck'; | import { useCheck } from '@/hooks/useCheck'; | ||||
| import { getModelPageVersionsReq, getModelVersionsMetricsReq } from '@/services/dataset'; | import { getModelPageVersionsReq, getModelVersionsMetricsReq } from '@/services/dataset'; | ||||
| import { tableSorter } from '@/utils'; | import { tableSorter } from '@/utils'; | ||||
| import { VersionChangedMessage } from '@/utils/constant'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import tableCellRender from '@/utils/table'; | import tableCellRender from '@/utils/table'; | ||||
| import { Checkbox, Flex, Table, type TablePaginationConfig, type TableProps } from 'antd'; | import { Checkbox, Flex, Table, type TablePaginationConfig, type TableProps } from 'antd'; | ||||
| @@ -27,10 +28,10 @@ type ModelMetricsProps = { | |||||
| resourceId: number; | resourceId: number; | ||||
| identifier: string; | identifier: string; | ||||
| owner: string; | owner: string; | ||||
| version: string; | |||||
| version: string; // 当前版本 | |||||
| }; | }; | ||||
| function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsProps) { | |||||
| function ModelMetrics({ resourceId, identifier, owner, version, refreshTag }: ModelMetricsProps) { | |||||
| const [pagination, setPagination] = useState<TablePaginationConfig>({ | const [pagination, setPagination] = useState<TablePaginationConfig>({ | ||||
| current: 1, | current: 1, | ||||
| pageSize: 10, | pageSize: 10, | ||||
| @@ -59,6 +60,24 @@ function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsPr | |||||
| checkSingleMetrics, | checkSingleMetrics, | ||||
| ] = useCheck(allMetricsNames); | ] = useCheck(allMetricsNames); | ||||
| // 新增,删除版本时,重置分页,然后刷新版本列表 | |||||
| useEffect(() => { | |||||
| const handleMessage = (e: MessageEvent) => { | |||||
| const { type } = e.data; | |||||
| if (type === VersionChangedMessage) { | |||||
| setPagination({ | |||||
| current: 1, | |||||
| pageSize: 10, | |||||
| }); | |||||
| } | |||||
| }; | |||||
| window.addEventListener('message', handleMessage); | |||||
| return () => { | |||||
| window.removeEventListener('message', handleMessage); | |||||
| }; | |||||
| }, []); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| // 获取模型版本列表,带有参数和指标数据 | // 获取模型版本列表,带有参数和指标数据 | ||||
| const getModelPageVersions = async () => { | const getModelPageVersions = async () => { | ||||
| @@ -128,6 +147,7 @@ function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsPr | |||||
| } | } | ||||
| }; | }; | ||||
| // 行勾选 | |||||
| const rowSelection: TableProps<TableData>['rowSelection'] = { | const rowSelection: TableProps<TableData>['rowSelection'] = { | ||||
| type: 'checkbox', | type: 'checkbox', | ||||
| fixed: 'left', | fixed: 'left', | ||||
| @@ -140,6 +160,7 @@ function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsPr | |||||
| }), | }), | ||||
| }; | }; | ||||
| // 计算的表格数据 | |||||
| const showTableData = useMemo(() => { | const showTableData = useMemo(() => { | ||||
| const index = tableData.findIndex((item) => item.name === version); | const index = tableData.findIndex((item) => item.name === version); | ||||
| if (index !== -1) { | if (index !== -1) { | ||||
| @@ -8,11 +8,11 @@ import PageTitle from '@/components/PageTitle'; | |||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { CommonTabKeys, serviceTypeOptions } from '@/enums'; | import { CommonTabKeys, serviceTypeOptions } from '@/enums'; | ||||
| import { createServiceReq, getServiceInfoReq, updateServiceReq } from '@/services/modelDeployment'; | import { createServiceReq, getServiceInfoReq, updateServiceReq } from '@/services/modelDeployment'; | ||||
| import { ServiceCreatedMessage } from '@/utils/constant'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useNavigate, useParams } from '@umijs/max'; | import { useNavigate, useParams } from '@umijs/max'; | ||||
| import { App, Button, Col, Form, Input, Row, Select } from 'antd'; | import { App, Button, Col, Form, Input, Row, Select } from 'antd'; | ||||
| import { useEffect } from 'react'; | import { useEffect } from 'react'; | ||||
| import { createServiceVersionMessage } from '../types'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| // 表单数据 | // 表单数据 | ||||
| @@ -63,7 +63,7 @@ function CreateService() { | |||||
| navigate(-1); | navigate(-1); | ||||
| if (!serviceId) { | if (!serviceId) { | ||||
| setTimeout(() => { | setTimeout(() => { | ||||
| window.postMessage({ type: createServiceVersionMessage, payload: res.data.id }); | |||||
| window.postMessage({ type: ServiceCreatedMessage, payload: res.data.id }); | |||||
| }, 500); | }, 500); | ||||
| } | } | ||||
| } | } | ||||
| @@ -31,9 +31,9 @@ import { | |||||
| CreateServiceVersionFrom, | CreateServiceVersionFrom, | ||||
| ServiceData, | ServiceData, | ||||
| ServiceOperationType, | ServiceOperationType, | ||||
| createServiceVersionMessage, | |||||
| } from '../types'; | } from '../types'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import { ServiceCreatedMessage } from '@/utils/constant'; | |||||
| const allServiceTypeOptions = [{ label: '全部', value: '' }, ...serviceTypeOptions]; | const allServiceTypeOptions = [{ label: '全部', value: '' }, ...serviceTypeOptions]; | ||||
| @@ -95,7 +95,7 @@ function ModelDeployment() { | |||||
| useEffect(() => { | useEffect(() => { | ||||
| const handleMessage = (e: MessageEvent) => { | const handleMessage = (e: MessageEvent) => { | ||||
| const { type, payload } = e.data; | const { type, payload } = e.data; | ||||
| if (type === createServiceVersionMessage) { | |||||
| if (type === ServiceCreatedMessage) { | |||||
| modalConfirm({ | modalConfirm({ | ||||
| title: '创建服务成功', | title: '创建服务成功', | ||||
| content: '是否创建服务版本?', | content: '是否创建服务版本?', | ||||
| @@ -63,6 +63,3 @@ export enum CreateServiceVersionFrom { | |||||
| CreateService = 'CreateService', // 来自创建服务 | CreateService = 'CreateService', // 来自创建服务 | ||||
| ServiceInfo = 'ServiceInfo', // 来自服务详情 | ServiceInfo = 'ServiceInfo', // 来自服务详情 | ||||
| } | } | ||||
| // 去创建服务版本消息 | |||||
| export const createServiceVersionMessage = 'createServiceVersion'; | |||||
| @@ -4,7 +4,7 @@ import { fn } from '@storybook/test'; | |||||
| // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export | // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export | ||||
| const meta = { | const meta = { | ||||
| title: 'Components/FullScreenFrame 全屏iframe', | |||||
| title: 'Components/FullScreenFrame 全屏 iframe', | |||||
| component: FullScreenFrame, | component: FullScreenFrame, | ||||
| parameters: { | parameters: { | ||||
| // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout | // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout | ||||
| @@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react'; | |||||
| // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export | // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export | ||||
| const meta = { | const meta = { | ||||
| title: 'Components/IFramePage iframe页面', | |||||
| title: 'Components/IFramePage iframe 页面', | |||||
| component: IFramePage, | component: IFramePage, | ||||
| parameters: { | parameters: { | ||||
| // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout | // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout | ||||
| @@ -10,4 +10,10 @@ const xllCols = { span: 10 }; | |||||
| /** | /** | ||||
| * 输入控件宽度,xl: 12, xll: 10 | * 输入控件宽度,xl: 12, xll: 10 | ||||
| */ | */ | ||||
| export const formCols = { xl: xlCols, xxl: xllCols }; | |||||
| export const FormCols = { xl: xlCols, xxl: xllCols }; | |||||
| // 数据集、模型新增和删除版本消息 | |||||
| export const VersionChangedMessage = 'versionChanged'; | |||||
| // 创建服务成功消息,去创建服务版本 | |||||
| export const ServiceCreatedMessage = 'serviceCreated'; | |||||
| @@ -5,14 +5,10 @@ | |||||
| */ | */ | ||||
| /** | /** | ||||
| * Safely invokes a function with a given value, returning the result of the | |||||
| * function or the provided value if it is `undefined` or `null`. | |||||
| * 安全调用函数,如果参数是 `undefined` 或 `null`,直接返回 `undefined` 或 `null`,而不会导致异常 | |||||
| * | * | ||||
| * @template T - The type of the input value. | |||||
| * @template M - The type of the output value. | |||||
| * @param {function} fn - The function to be invoked with the input value. | |||||
| * @returns {function} A function that takes a value, invokes `fn` with it if | |||||
| * it's not `undefined` or `null`, and returns the result or the original value. | |||||
| * @param fn - 要调用的函数 | |||||
| * @returns 封装后的函数,该函数的参数如果是 `undefined` 或 `null`,结果直接返回 `undefined` 或 `null`,而不会导致异常 | |||||
| */ | */ | ||||
| export function safeInvoke<T, M>( | export function safeInvoke<T, M>( | ||||
| fn: (value: T) => M | undefined | null, | fn: (value: T) => M | undefined | null, | ||||