| @@ -1 +1 @@ | |||||
| v18.16.0 | |||||
| v18.20.7 | |||||
| @@ -30,35 +30,42 @@ function CodeSelect({ | |||||
| onChange, | onChange, | ||||
| ...rest | ...rest | ||||
| }: CodeSelectProps) { | }: CodeSelectProps) { | ||||
| // 选择代码配置 | |||||
| const selectResource = () => { | const selectResource = () => { | ||||
| const { close } = openAntdModal(CodeSelectorModal, { | const { close } = openAntdModal(CodeSelectorModal, { | ||||
| onOk: (res) => { | onOk: (res) => { | ||||
| if (res) { | if (res) { | ||||
| const { git_url, git_branch, code_repo_name } = res; | |||||
| const { id, code_repo_name, git_url, git_branch, git_user_name, git_password, ssh_key } = | |||||
| res; | |||||
| const jsonObj = { | const jsonObj = { | ||||
| id, | |||||
| name: code_repo_name, | |||||
| code_path: git_url, | code_path: git_url, | ||||
| branch: git_branch, | branch: git_branch, | ||||
| username: git_user_name, | |||||
| password: git_password, | |||||
| ssh_private_key: ssh_key, | |||||
| }; | }; | ||||
| const jsonObjStr = JSON.stringify(jsonObj); | const jsonObjStr = JSON.stringify(jsonObj); | ||||
| const showValue = code_repo_name; | |||||
| onChange?.({ | onChange?.({ | ||||
| value: jsonObjStr, | value: jsonObjStr, | ||||
| showValue, | |||||
| showValue: code_repo_name, | |||||
| fromSelect: true, | fromSelect: true, | ||||
| ...jsonObj, | ...jsonObj, | ||||
| }); | }); | ||||
| } else { | } else { | ||||
| onChange?.({ | |||||
| value: undefined, | |||||
| showValue: undefined, | |||||
| fromSelect: false, | |||||
| }); | |||||
| onChange?.(undefined); | |||||
| } | } | ||||
| close(); | close(); | ||||
| }, | }, | ||||
| }); | }); | ||||
| }; | }; | ||||
| // 删除 | |||||
| const handleRemove = () => { | |||||
| onChange?.(undefined); | |||||
| }; | |||||
| return ( | return ( | ||||
| <div className={classNames('kf-code-select', className)} style={style}> | <div className={classNames('kf-code-select', className)} style={style}> | ||||
| <ParameterInput | <ParameterInput | ||||
| @@ -68,6 +75,7 @@ function CodeSelect({ | |||||
| value={value} | value={value} | ||||
| onChange={onChange} | onChange={onChange} | ||||
| onClick={selectResource} | onClick={selectResource} | ||||
| onRemove={handleRemove} | |||||
| ></ParameterInput> | ></ParameterInput> | ||||
| <Button | <Button | ||||
| className="kf-code-select__button" | className="kf-code-select__button" | ||||
| @@ -6,7 +6,7 @@ | |||||
| import { CommonTabKeys } from '@/enums'; | import { CommonTabKeys } from '@/enums'; | ||||
| import { CloseOutlined } from '@ant-design/icons'; | import { CloseOutlined } from '@ant-design/icons'; | ||||
| import { Form, Input } from 'antd'; | |||||
| import { ConfigProvider, Form, Input } from 'antd'; | |||||
| import { RuleObject } from 'antd/es/form'; | import { RuleObject } from 'antd/es/form'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import './index.less'; | import './index.less'; | ||||
| @@ -67,7 +67,7 @@ function ParameterInput({ | |||||
| allowClear, | allowClear, | ||||
| className, | className, | ||||
| style, | style, | ||||
| size = 'middle', | |||||
| size, | |||||
| disabled = false, | disabled = false, | ||||
| id, | id, | ||||
| ...rest | ...rest | ||||
| @@ -81,10 +81,17 @@ function ParameterInput({ | |||||
| const placeholder = valueObj?.placeholder || rest?.placeholder; | const placeholder = valueObj?.placeholder || rest?.placeholder; | ||||
| const InputComponent = textArea ? Input.TextArea : Input; | const InputComponent = textArea ? Input.TextArea : Input; | ||||
| const { status } = Form.Item.useStatus(); | const { status } = Form.Item.useStatus(); | ||||
| const { componentSize } = ConfigProvider.useConfig(); | |||||
| const mySize = size || componentSize; | |||||
| // 删除 | // 删除 | ||||
| const handleRemove = (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => { | const handleRemove = (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => { | ||||
| e.stopPropagation(); | e.stopPropagation(); | ||||
| if (onRemove) { | |||||
| onRemove(); | |||||
| return; | |||||
| } | |||||
| onChange?.({ | onChange?.({ | ||||
| ...valueObj, | ...valueObj, | ||||
| value: undefined, | value: undefined, | ||||
| @@ -94,7 +101,6 @@ function ParameterInput({ | |||||
| expandedKeys: [], | expandedKeys: [], | ||||
| checkedKeys: [], | checkedKeys: [], | ||||
| }); | }); | ||||
| onRemove?.(); | |||||
| }; | }; | ||||
| return ( | return ( | ||||
| @@ -104,8 +110,8 @@ function ParameterInput({ | |||||
| id={id} | id={id} | ||||
| className={classNames( | className={classNames( | ||||
| 'parameter-input', | 'parameter-input', | ||||
| { 'parameter-input--large': size === 'large' }, | |||||
| { 'parameter-input--small': size === 'small' }, | |||||
| { 'parameter-input--large': mySize === 'large' }, | |||||
| { 'parameter-input--small': mySize === 'small' }, | |||||
| { [`parameter-input--${status}`]: status }, | { [`parameter-input--${status}`]: status }, | ||||
| className, | className, | ||||
| )} | )} | ||||
| @@ -128,7 +134,7 @@ function ParameterInput({ | |||||
| <InputComponent | <InputComponent | ||||
| {...rest} | {...rest} | ||||
| id={id} | id={id} | ||||
| size={size} | |||||
| size={mySize} | |||||
| className={className} | className={className} | ||||
| style={style} | style={style} | ||||
| placeholder={placeholder} | placeholder={placeholder} | ||||
| @@ -1,21 +1,10 @@ | |||||
| import { filterResourceStandard, resourceFieldNames } from '@/hooks/resource'; | |||||
| import { ServiceData } from '@/pages/ModelDeployment/types'; | import { ServiceData } from '@/pages/ModelDeployment/types'; | ||||
| import { getDatasetList, getModelList } from '@/services/dataset/index.js'; | import { getDatasetList, getModelList } from '@/services/dataset/index.js'; | ||||
| import { getServiceListReq } from '@/services/modelDeployment'; | import { getServiceListReq } from '@/services/modelDeployment'; | ||||
| import { getComputingResourceReq } from '@/services/pipeline'; | |||||
| import { ComputingResource } from '@/types'; | |||||
| import { type SelectProps } from 'antd'; | import { type SelectProps } from 'antd'; | ||||
| import { pick } from 'lodash'; | import { pick } from 'lodash'; | ||||
| // 过滤资源规格 | |||||
| const filterResourceStandard: SelectProps<string, ComputingResource>['filterOption'] = ( | |||||
| input: string, | |||||
| option?: ComputingResource, | |||||
| ) => { | |||||
| return ( | |||||
| option?.computing_resource?.toLocaleLowerCase()?.includes(input.toLocaleLowerCase()) ?? false | |||||
| ); | |||||
| }; | |||||
| // id 从 number 转换为 string | // id 从 number 转换为 string | ||||
| const convertId = (item: any) => ({ | const convertId = (item: any) => ({ | ||||
| ...item, | ...item, | ||||
| @@ -86,17 +75,10 @@ export const paramSelectConfig: Record<string, SelectPropsConfig> = { | |||||
| }, | }, | ||||
| resource: { | resource: { | ||||
| getOptions: async () => { | getOptions: async () => { | ||||
| const res = await getComputingResourceReq({ | |||||
| page: 0, | |||||
| size: 1000, | |||||
| resource_type: '', | |||||
| }); | |||||
| return res?.data?.content ?? []; | |||||
| }, | |||||
| fieldNames: { | |||||
| label: 'description', | |||||
| value: 'standard', | |||||
| // 不需要这个函数 | |||||
| return []; | |||||
| }, | }, | ||||
| fieldNames: resourceFieldNames, | |||||
| filterOption: filterResourceStandard as SelectProps['filterOption'], | filterOption: filterResourceStandard as SelectProps['filterOption'], | ||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -4,6 +4,7 @@ | |||||
| * @Description: 参数下拉选择组件,支持资源规格、数据集、模型、服务 | * @Description: 参数下拉选择组件,支持资源规格、数据集、模型、服务 | ||||
| */ | */ | ||||
| import { useComputingResource } from '@/hooks/resource'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { Select, type SelectProps } from 'antd'; | import { Select, type SelectProps } from 'antd'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| @@ -20,7 +21,7 @@ export interface ParameterSelectProps extends SelectProps { | |||||
| dataType: 'dataset' | 'model' | 'service' | 'resource'; | dataType: 'dataset' | 'model' | 'service' | 'resource'; | ||||
| /** 是否只是展示信息 */ | /** 是否只是展示信息 */ | ||||
| display?: boolean; | display?: boolean; | ||||
| /** 值 */ | |||||
| /** 值,支持对象,对象必须包含 value */ | |||||
| value?: string | ParameterSelectObject; | value?: string | ParameterSelectObject; | ||||
| /** 修改后回调 */ | /** 修改后回调 */ | ||||
| onChange?: (value: string | ParameterSelectObject) => void; | onChange?: (value: string | ParameterSelectObject) => void; | ||||
| @@ -34,9 +35,10 @@ function ParameterSelect({ | |||||
| onChange, | onChange, | ||||
| ...rest | ...rest | ||||
| }: ParameterSelectProps) { | }: ParameterSelectProps) { | ||||
| const [options, setOptions] = useState([]); | |||||
| const [options, setOptions] = useState<SelectProps['options']>([]); | |||||
| const propsConfig = paramSelectConfig[dataType]; | const propsConfig = paramSelectConfig[dataType]; | ||||
| const valueText = typeof value === 'object' && value !== null ? value.value : value; | const valueText = typeof value === 'object' && value !== null ? value.value : value; | ||||
| const [resourceStandardList] = useComputingResource(); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| // 获取下拉数据 | // 获取下拉数据 | ||||
| @@ -54,6 +56,8 @@ function ParameterSelect({ | |||||
| getSelectOptions(); | getSelectOptions(); | ||||
| }, [propsConfig]); | }, [propsConfig]); | ||||
| const selectOptions = dataType === 'resource' ? resourceStandardList : options; | |||||
| const handleChange = (text: string) => { | const handleChange = (text: string) => { | ||||
| if (typeof value === 'object' && value !== null) { | if (typeof value === 'object' && value !== null) { | ||||
| onChange?.({ | onChange?.({ | ||||
| @@ -71,7 +75,7 @@ function ParameterSelect({ | |||||
| <FormInfo | <FormInfo | ||||
| select | select | ||||
| value={valueText} | value={valueText} | ||||
| options={options} | |||||
| options={selectOptions} | |||||
| fieldNames={propsConfig?.fieldNames} | fieldNames={propsConfig?.fieldNames} | ||||
| ></FormInfo> | ></FormInfo> | ||||
| ); | ); | ||||
| @@ -81,7 +85,7 @@ function ParameterSelect({ | |||||
| <Select | <Select | ||||
| {...rest} | {...rest} | ||||
| filterOption={propsConfig?.filterOption} | filterOption={propsConfig?.filterOption} | ||||
| options={options} | |||||
| options={selectOptions} | |||||
| fieldNames={propsConfig?.fieldNames} | fieldNames={propsConfig?.fieldNames} | ||||
| optionFilterProp={propsConfig?.optionFilterProp} | optionFilterProp={propsConfig?.optionFilterProp} | ||||
| value={valueText} | value={valueText} | ||||
| @@ -11,10 +11,9 @@ import ResourceSelectorModal, { | |||||
| selectorTypeConfig, | selectorTypeConfig, | ||||
| } from '@/components/ResourceSelectorModal'; | } from '@/components/ResourceSelectorModal'; | ||||
| import { openAntdModal } from '@/utils/modal'; | import { openAntdModal } from '@/utils/modal'; | ||||
| import { Button } from 'antd'; | |||||
| import { Button, ConfigProvider } from 'antd'; | |||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { pick } from 'lodash'; | import { pick } from 'lodash'; | ||||
| import { useEffect, useState } from 'react'; | |||||
| import ParameterInput, { type ParameterInputProps } from '../ParameterInput'; | import ParameterInput, { type ParameterInputProps } from '../ParameterInput'; | ||||
| import './index.less'; | import './index.less'; | ||||
| @@ -46,43 +45,40 @@ function ResourceSelect({ | |||||
| onChange, | onChange, | ||||
| ...rest | ...rest | ||||
| }: ResourceSelectProps) { | }: ResourceSelectProps) { | ||||
| const [selectedResource, setSelectedResource] = useState<ResourceSelectorResponse | undefined>( | |||||
| undefined, | |||||
| ); | |||||
| useEffect(() => { | |||||
| if ( | |||||
| value && | |||||
| typeof value === 'object' && | |||||
| value.activeTab && | |||||
| value.id && | |||||
| value.name && | |||||
| value.version && | |||||
| value.path && | |||||
| (type === ResourceSelectorType.Mirror || (value.identifier && value.owner)) | |||||
| ) { | |||||
| const originResource = pick(value, [ | |||||
| 'activeTab', | |||||
| 'id', | |||||
| 'identifier', | |||||
| 'name', | |||||
| 'owner', | |||||
| 'version', | |||||
| 'path', | |||||
| ]) as ResourceSelectorResponse; | |||||
| setSelectedResource(originResource); | |||||
| } | |||||
| }, [value, type]); | |||||
| const { componentSize } = ConfigProvider.useConfig(); | |||||
| const mySize = size || componentSize; | |||||
| let selectedResource: ResourceSelectorResponse | undefined = undefined; | |||||
| if ( | |||||
| value && | |||||
| typeof value === 'object' && | |||||
| value.activeTab && | |||||
| value.id && | |||||
| value.name && | |||||
| value.version && | |||||
| value.path && | |||||
| (type === ResourceSelectorType.Mirror || (value.identifier && value.owner)) | |||||
| ) { | |||||
| selectedResource = pick(value, [ | |||||
| 'activeTab', | |||||
| 'id', | |||||
| 'identifier', | |||||
| 'name', | |||||
| 'owner', | |||||
| 'version', | |||||
| 'path', | |||||
| ]) as ResourceSelectorResponse; | |||||
| } | |||||
| // 选择数据集、模型、镜像 | |||||
| const selectResource = () => { | const selectResource = () => { | ||||
| const resource = selectedResource; | |||||
| const { close } = openAntdModal(ResourceSelectorModal, { | const { close } = openAntdModal(ResourceSelectorModal, { | ||||
| type, | type, | ||||
| defaultExpandedKeys: resource ? [resource.id] : [], | |||||
| defaultCheckedKeys: resource ? [`${resource.id}-${resource.version}`] : [], | |||||
| defaultActiveTab: resource?.activeTab, | |||||
| defaultExpandedKeys: selectedResource ? [selectedResource.id] : [], | |||||
| defaultCheckedKeys: selectedResource | |||||
| ? [`${selectedResource.id}-${selectedResource.version}`] | |||||
| : [], | |||||
| defaultActiveTab: selectedResource?.activeTab, | |||||
| onOk: (res) => { | onOk: (res) => { | ||||
| setSelectedResource(res); | |||||
| if (res) { | if (res) { | ||||
| const { activeTab, id, name, version, path, identifier, owner } = res; | const { activeTab, id, name, version, path, identifier, owner } = res; | ||||
| if (type === ResourceSelectorType.Mirror) { | if (type === ResourceSelectorType.Mirror) { | ||||
| @@ -116,32 +112,32 @@ function ResourceSelect({ | |||||
| }); | }); | ||||
| } | } | ||||
| } else { | } else { | ||||
| onChange?.({ | |||||
| value: undefined, | |||||
| showValue: undefined, | |||||
| fromSelect: false, | |||||
| activeTab: undefined, | |||||
| }); | |||||
| onChange?.(undefined); | |||||
| } | } | ||||
| close(); | close(); | ||||
| }, | }, | ||||
| }); | }); | ||||
| }; | }; | ||||
| // 删除 | |||||
| const handleRemove = () => { | |||||
| onChange?.(undefined); | |||||
| }; | |||||
| return ( | return ( | ||||
| <div className={classNames('kf-resource-select', className)} style={style}> | <div className={classNames('kf-resource-select', className)} style={style}> | ||||
| <ParameterInput | <ParameterInput | ||||
| {...rest} | {...rest} | ||||
| disabled={disabled} | disabled={disabled} | ||||
| value={value} | value={value} | ||||
| size={size} | |||||
| size={mySize} | |||||
| onChange={onChange} | onChange={onChange} | ||||
| onRemove={() => setSelectedResource(undefined)} | |||||
| onRemove={handleRemove} | |||||
| onClick={selectResource} | onClick={selectResource} | ||||
| ></ParameterInput> | ></ParameterInput> | ||||
| <Button | <Button | ||||
| className="kf-resource-select__button" | className="kf-resource-select__button" | ||||
| size={size} | |||||
| size={mySize} | |||||
| type="link" | type="link" | ||||
| icon={getSelectBtnIcon(type)} | icon={getSelectBtnIcon(type)} | ||||
| disabled={disabled} | disabled={disabled} | ||||
| @@ -12,6 +12,22 @@ import { useCallback, useEffect, useState } from 'react'; | |||||
| const computingResource: ComputingResource[] = []; | const computingResource: ComputingResource[] = []; | ||||
| // 过滤资源规格 | |||||
| export const filterResourceStandard: SelectProps<string, ComputingResource>['filterOption'] = ( | |||||
| input: string, | |||||
| option?: ComputingResource, | |||||
| ) => { | |||||
| return ( | |||||
| option?.computing_resource?.toLocaleLowerCase()?.includes(input.toLocaleLowerCase()) ?? false | |||||
| ); | |||||
| }; | |||||
| // 资源规格字段 | |||||
| export const resourceFieldNames = { | |||||
| label: 'description', | |||||
| value: 'id', | |||||
| }; | |||||
| // 获取资源规格 | // 获取资源规格 | ||||
| export function useComputingResource() { | export function useComputingResource() { | ||||
| const [resourceStandardList, setResourceStandardList] = useState<ComputingResource[]>([]); | const [resourceStandardList, setResourceStandardList] = useState<ComputingResource[]>([]); | ||||
| @@ -25,7 +41,7 @@ export function useComputingResource() { | |||||
| resource_type: '', | resource_type: '', | ||||
| }; | }; | ||||
| const [res] = await to(getComputingResourceReq(params)); | const [res] = await to(getComputingResourceReq(params)); | ||||
| if (res && res.data && res.data.content) { | |||||
| if (res && res.data && Array.isArray(res.data.content)) { | |||||
| setResourceStandardList(res.data.content); | setResourceStandardList(res.data.content); | ||||
| computingResource.splice(0, computingResource.length, ...res.data.content); | computingResource.splice(0, computingResource.length, ...res.data.content); | ||||
| } | } | ||||
| @@ -38,25 +54,16 @@ export function useComputingResource() { | |||||
| } | } | ||||
| }, []); | }, []); | ||||
| // 过滤资源规格 | |||||
| const filterResourceStandard: SelectProps<string, ComputingResource>['filterOption'] = | |||||
| useCallback((input: string, option?: ComputingResource) => { | |||||
| return ( | |||||
| option?.computing_resource?.toLocaleLowerCase()?.includes(input.toLocaleLowerCase()) ?? | |||||
| false | |||||
| ); | |||||
| }, []); | |||||
| // 根据 standard 获取 description | // 根据 standard 获取 description | ||||
| const getDescription = useCallback( | const getDescription = useCallback( | ||||
| (standard?: string) => { | |||||
| if (!standard) { | |||||
| (id?: string | number) => { | |||||
| if (!id) { | |||||
| return undefined; | return undefined; | ||||
| } | } | ||||
| return resourceStandardList.find((item) => item.standard === standard)?.description; | |||||
| return resourceStandardList.find((item) => Number(item.id) === Number(id))?.description; | |||||
| }, | }, | ||||
| [resourceStandardList], | [resourceStandardList], | ||||
| ); | ); | ||||
| return [resourceStandardList, filterResourceStandard, getDescription] as const; | |||||
| return [resourceStandardList, getDescription] as const; | |||||
| } | } | ||||
| @@ -40,7 +40,7 @@ function AutoMLInstance() { | |||||
| closeSSE(); | closeSSE(); | ||||
| }; | }; | ||||
| // eslint-disable-next-line react-hooks/exhaustive-deps | // eslint-disable-next-line react-hooks/exhaustive-deps | ||||
| }, []); | |||||
| }, [instanceId]); | |||||
| // 获取实验实例详情 | // 获取实验实例详情 | ||||
| const getExperimentInsInfo = async (isStatusDetermined: boolean) => { | const getExperimentInsInfo = async (isStatusDetermined: boolean) => { | ||||
| @@ -30,7 +30,6 @@ function DatasetConfig() { | |||||
| type={ResourceSelectorType.Dataset} | type={ResourceSelectorType.Dataset} | ||||
| placeholder="请选择数据集" | placeholder="请选择数据集" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -431,7 +431,12 @@ function ExecuteConfig() { | |||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item label="是否打乱" name="shuffle" tooltip="拆分数据前是否打乱顺序"> | |||||
| <Form.Item | |||||
| label="是否打乱" | |||||
| name="shuffle" | |||||
| tooltip="拆分数据前是否打乱顺序" | |||||
| valuePropName="checked" | |||||
| > | |||||
| <Switch /> | <Switch /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -6,17 +6,17 @@ | |||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import KFRadio, { type KFRadioItem } from '@/components/KFRadio'; | import KFRadio, { type KFRadioItem } from '@/components/KFRadio'; | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import ParameterSelect from '@/components/ParameterSelect'; | |||||
| import ResourceSelect, { | import ResourceSelect, { | ||||
| requiredValidator, | requiredValidator, | ||||
| ResourceSelectorType, | ResourceSelectorType, | ||||
| type ParameterInputObject, | type ParameterInputObject, | ||||
| } from '@/components/ResourceSelect'; | } from '@/components/ResourceSelect'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { useComputingResource } from '@/hooks/resource'; | |||||
| import { createEditorReq } from '@/services/developmentEnvironment'; | import { createEditorReq } from '@/services/developmentEnvironment'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useNavigate } from '@umijs/max'; | import { useNavigate } from '@umijs/max'; | ||||
| import { App, Button, Col, Form, Input, Row, Select } from 'antd'; | |||||
| import { App, Button, Col, Form, Input, Row } from 'antd'; | |||||
| import { omit, pick } from 'lodash'; | import { omit, pick } from 'lodash'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -51,7 +51,6 @@ function EditorCreate() { | |||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| const [resourceStandardList, filterResourceStandard] = useComputingResource(); | |||||
| // 创建编辑器 | // 创建编辑器 | ||||
| const createEditor = async (formData: FormData) => { | const createEditor = async (formData: FormData) => { | ||||
| @@ -62,8 +61,8 @@ function EditorCreate() { | |||||
| const params = { | const params = { | ||||
| ...omit(formData, ['image', 'model', 'dataset']), | ...omit(formData, ['image', 'model', 'dataset']), | ||||
| image: image.value, | image: image.value, | ||||
| model: pick(model, ['id', 'version', 'path', 'showValue']), | |||||
| dataset: pick(dataset, ['id', 'version', 'path', 'showValue']), | |||||
| model: model && pick(model, ['id', 'version', 'path', 'showValue']), | |||||
| dataset: dataset && pick(dataset, ['id', 'version', 'path', 'showValue']), | |||||
| }; | }; | ||||
| const [res] = await to(createEditorReq(params)); | const [res] = await to(createEditorReq(params)); | ||||
| if (res) { | if (res) { | ||||
| @@ -146,16 +145,7 @@ function EditorCreate() { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Select | |||||
| showSearch | |||||
| placeholder="请选择资源规格" | |||||
| filterOption={filterResourceStandard} | |||||
| options={resourceStandardList} | |||||
| fieldNames={{ | |||||
| label: 'description', | |||||
| value: 'standard', | |||||
| }} | |||||
| /> | |||||
| <ParameterSelect dataType="resource" placeholder="请选择资源规格" /> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -181,7 +171,6 @@ function EditorCreate() { | |||||
| type={ResourceSelectorType.Mirror} | type={ResourceSelectorType.Mirror} | ||||
| placeholder="请选择镜像" | placeholder="请选择镜像" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -193,7 +182,6 @@ function EditorCreate() { | |||||
| type={ResourceSelectorType.Model} | type={ResourceSelectorType.Model} | ||||
| placeholder="请选择模型" | placeholder="请选择模型" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -205,7 +193,6 @@ function EditorCreate() { | |||||
| type={ResourceSelectorType.Dataset} | type={ResourceSelectorType.Dataset} | ||||
| placeholder="请选择数据集" | placeholder="请选择数据集" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -1,7 +1,6 @@ | |||||
| import FormInfo from '@/components/FormInfo'; | import FormInfo from '@/components/FormInfo'; | ||||
| import ParameterSelect from '@/components/ParameterSelect'; | import ParameterSelect from '@/components/ParameterSelect'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { useComputingResource } from '@/hooks/resource'; | |||||
| import { PipelineNodeModelSerialize } from '@/types'; | import { PipelineNodeModelSerialize } from '@/types'; | ||||
| import { Form } from 'antd'; | import { Form } from 'antd'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -11,8 +10,6 @@ type ExperimentParameterProps = { | |||||
| }; | }; | ||||
| function ExperimentParameter({ nodeData }: ExperimentParameterProps) { | function ExperimentParameter({ nodeData }: ExperimentParameterProps) { | ||||
| const [resourceStandardList] = useComputingResource(); // 资源规模 | |||||
| // 控制策略 | // 控制策略 | ||||
| const controlStrategyList = Object.entries(nodeData.control_strategy ?? {}).map( | const controlStrategyList = Object.entries(nodeData.control_strategy ?? {}).map( | ||||
| ([key, value]) => ({ key, value }), | ([key, value]) => ({ key, value }), | ||||
| @@ -112,14 +109,7 @@ function ExperimentParameter({ nodeData }: ExperimentParameterProps) { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <FormInfo | |||||
| select | |||||
| options={resourceStandardList} | |||||
| fieldNames={{ | |||||
| label: 'description', | |||||
| value: 'standard', | |||||
| }} | |||||
| /> | |||||
| <ParameterSelect dataType="resource" placeholder="请选择资源规格" display /> | |||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item label="挂载路径" name="mount_path"> | <Form.Item label="挂载路径" name="mount_path"> | ||||
| <FormInfo /> | <FormInfo /> | ||||
| @@ -33,7 +33,7 @@ function LogGroup({ | |||||
| status, | status, | ||||
| }: LogGroupProps) { | }: LogGroupProps) { | ||||
| const [collapse, setCollapse] = useState(true); | const [collapse, setCollapse] = useState(true); | ||||
| const [logList, setLogList, logListRef] = useStateRef<Log[]>([]); | |||||
| const [logList, setLogList] = useState<Log[]>([]); | |||||
| const [completed, setCompleted] = useState(false); | const [completed, setCompleted] = useState(false); | ||||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
| const [_isMouseDown, setIsMouseDown, isMouseDownRef] = useStateRef(false); | const [_isMouseDown, setIsMouseDown, isMouseDownRef] = useStateRef(false); | ||||
| @@ -126,6 +126,14 @@ function LogGroup({ | |||||
| socketRef.current = socket; | socketRef.current = socket; | ||||
| }; | }; | ||||
| // 关闭 socket | |||||
| const closeSocket = () => { | |||||
| if (socketRef.current) { | |||||
| socketRef.current.close(1000, 'completed'); | |||||
| socketRef.current = undefined; | |||||
| } | |||||
| }; | |||||
| if (status === ExperimentStatus.Running) { | if (status === ExperimentStatus.Running) { | ||||
| setupSockect(); | setupSockect(); | ||||
| } | } | ||||
| @@ -133,7 +141,7 @@ function LogGroup({ | |||||
| return () => { | return () => { | ||||
| closeSocket(); | closeSocket(); | ||||
| }; | }; | ||||
| }, [status, start_time, pod_name, isMouseDownRef, setLogList]); | |||||
| }, [status, start_time, pod_name, isMouseDownRef]); | |||||
| // 鼠标拖到中不滚动到底部 | // 鼠标拖到中不滚动到底部 | ||||
| useEffect(() => { | useEffect(() => { | ||||
| @@ -153,8 +161,8 @@ function LogGroup({ | |||||
| // 请求日志 | // 请求日志 | ||||
| const requestExperimentPodsLog = async () => { | const requestExperimentPodsLog = async () => { | ||||
| const list = logListRef.current; | |||||
| const startTime = list.length > 0 ? list[list.length - 1].start_time : start_time; | |||||
| const last = logList[logList.length - 1]; | |||||
| const startTime = last ? last.start_time : start_time; | |||||
| const params = { | const params = { | ||||
| pod_name, | pod_name, | ||||
| start_time: startTime, | start_time: startTime, | ||||
| @@ -201,14 +209,6 @@ function LogGroup({ | |||||
| requestExperimentPodsLog(); | requestExperimentPodsLog(); | ||||
| }; | }; | ||||
| // 关闭 socket | |||||
| const closeSocket = () => { | |||||
| if (socketRef.current) { | |||||
| socketRef.current.close(1000, 'completed'); | |||||
| socketRef.current = undefined; | |||||
| } | |||||
| }; | |||||
| // 滚动到底部 | // 滚动到底部 | ||||
| const scrollToBottom = (smooth: boolean = true) => { | const scrollToBottom = (smooth: boolean = true) => { | ||||
| // const element = document.getElementById(listId); | // const element = document.getElementById(listId); | ||||
| @@ -277,7 +277,6 @@ function Experiment() { | |||||
| current, | current, | ||||
| pageSize, | pageSize, | ||||
| }); | }); | ||||
| getExperimentList(); | |||||
| }; | }; | ||||
| // 运行实验 | // 运行实验 | ||||
| const runExperiment = async (id) => { | const runExperiment = async (id) => { | ||||
| @@ -44,7 +44,7 @@ function HyperParameterInstance() { | |||||
| closeSSE(); | closeSSE(); | ||||
| }; | }; | ||||
| // eslint-disable-next-line react-hooks/exhaustive-deps | // eslint-disable-next-line react-hooks/exhaustive-deps | ||||
| }, []); | |||||
| }, [instanceId]); | |||||
| // 获取实验实例详情 | // 获取实验实例详情 | ||||
| const getExperimentInsInfo = async (isStatusDetermined: boolean) => { | const getExperimentInsInfo = async (isStatusDetermined: boolean) => { | ||||
| @@ -1,12 +1,12 @@ | |||||
| import CodeSelect from '@/components/CodeSelect'; | import CodeSelect from '@/components/CodeSelect'; | ||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import ParameterSelect from '@/components/ParameterSelect'; | |||||
| import ResourceSelect, { | import ResourceSelect, { | ||||
| ResourceSelectorType, | ResourceSelectorType, | ||||
| requiredValidator, | requiredValidator, | ||||
| } from '@/components/ResourceSelect'; | } from '@/components/ResourceSelect'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { hyperParameterOptimizedModeOptions } from '@/enums'; | import { hyperParameterOptimizedModeOptions } from '@/enums'; | ||||
| import { useComputingResource } from '@/hooks/resource'; | |||||
| import { isEmpty } from '@/utils'; | import { isEmpty } from '@/utils'; | ||||
| import { modalConfirm, removeFormListItem } from '@/utils/ui'; | import { modalConfirm, removeFormListItem } from '@/utils/ui'; | ||||
| import { MinusCircleOutlined, PlusCircleOutlined, QuestionCircleOutlined } from '@ant-design/icons'; | import { MinusCircleOutlined, PlusCircleOutlined, QuestionCircleOutlined } from '@ant-design/icons'; | ||||
| @@ -86,7 +86,6 @@ function ExecuteConfig() { | |||||
| const searchAlgorithm = Form.useWatch('search_alg', form); | const searchAlgorithm = Form.useWatch('search_alg', form); | ||||
| const paramsTypeOptions = searchAlgorithm === 'Ax' ? axParameterOptions : parameterOptions; | const paramsTypeOptions = searchAlgorithm === 'Ax' ? axParameterOptions : parameterOptions; | ||||
| const paramsTypeTooltip = searchAlgorithm === 'Ax' ? axParameterTooltip : parameterTooltip; | const paramsTypeTooltip = searchAlgorithm === 'Ax' ? axParameterTooltip : parameterTooltip; | ||||
| const [resourceStandardList, filterResourceStandard] = useComputingResource(); | |||||
| const handleSearchAlgorithmChange = (value: string) => { | const handleSearchAlgorithmChange = (value: string) => { | ||||
| if ( | if ( | ||||
| @@ -157,7 +156,6 @@ function ExecuteConfig() { | |||||
| type={ResourceSelectorType.Mirror} | type={ResourceSelectorType.Mirror} | ||||
| placeholder="请选择镜像" | placeholder="请选择镜像" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -180,7 +178,6 @@ function ExecuteConfig() { | |||||
| type={ResourceSelectorType.Dataset} | type={ResourceSelectorType.Dataset} | ||||
| placeholder="请选择数据集" | placeholder="请选择数据集" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -193,7 +190,6 @@ function ExecuteConfig() { | |||||
| type={ResourceSelectorType.Model} | type={ResourceSelectorType.Model} | ||||
| placeholder="请选择模型" | placeholder="请选择模型" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -596,7 +592,7 @@ function ExecuteConfig() { | |||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="资源规格" | label="资源规格" | ||||
| name="resource" | |||||
| name="computing_resource_id" | |||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| @@ -604,16 +600,7 @@ function ExecuteConfig() { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Select | |||||
| showSearch | |||||
| placeholder="请选择资源规格" | |||||
| filterOption={filterResourceStandard} | |||||
| options={resourceStandardList} | |||||
| fieldNames={{ | |||||
| label: 'description', | |||||
| value: 'standard', | |||||
| }} | |||||
| /> | |||||
| <ParameterSelect dataType="resource" placeholder="请选择资源规格" /> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -41,7 +41,7 @@ function HyperParameterBasic({ | |||||
| runStatus, | runStatus, | ||||
| isInstance = false, | isInstance = false, | ||||
| }: HyperParameterBasicProps) { | }: HyperParameterBasicProps) { | ||||
| const getResourceDescription = useComputingResource()[2]; | |||||
| const getResourceDescription = useComputingResource()[1]; | |||||
| const basicDatas: BasicInfoData[] = useMemo(() => { | const basicDatas: BasicInfoData[] = useMemo(() => { | ||||
| if (!info) { | if (!info) { | ||||
| @@ -136,7 +136,7 @@ function HyperParameterBasic({ | |||||
| }, | }, | ||||
| { | { | ||||
| label: '资源规格', | label: '资源规格', | ||||
| value: info.resource, | |||||
| value: info.computing_resource_id, | |||||
| format: getResourceDescription, | format: getResourceDescription, | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| @@ -24,7 +24,7 @@ export type FormData = { | |||||
| num_samples: number; // 总试验次数 | num_samples: number; // 总试验次数 | ||||
| max_t: number; // 单次试验最大时间 | max_t: number; // 单次试验最大时间 | ||||
| min_samples_required: number; // 计算中位数的最小试验数 | min_samples_required: number; // 计算中位数的最小试验数 | ||||
| resource: string; // 资源规格 | |||||
| computing_resource_id: number; // 资源规格 | |||||
| parameters: FormParameter[]; | parameters: FormParameter[]; | ||||
| points_to_evaluate: { [key: string]: any }[]; | points_to_evaluate: { [key: string]: any }[]; | ||||
| }; | }; | ||||
| @@ -5,13 +5,13 @@ | |||||
| */ | */ | ||||
| import CodeSelect from '@/components/CodeSelect'; | import CodeSelect from '@/components/CodeSelect'; | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import ParameterSelect from '@/components/ParameterSelect'; | |||||
| import ResourceSelect, { | import ResourceSelect, { | ||||
| ResourceSelectorType, | ResourceSelectorType, | ||||
| requiredValidator, | requiredValidator, | ||||
| type ParameterInputObject, | type ParameterInputObject, | ||||
| } from '@/components/ResourceSelect'; | } from '@/components/ResourceSelect'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { useComputingResource } from '@/hooks/resource'; | |||||
| import { | import { | ||||
| createServiceVersionReq, | createServiceVersionReq, | ||||
| getServiceInfoReq, | getServiceInfoReq, | ||||
| @@ -23,7 +23,7 @@ import SessionStorage from '@/utils/sessionStorage'; | |||||
| import { removeFormListItem } from '@/utils/ui'; | import { removeFormListItem } from '@/utils/ui'; | ||||
| import { MinusCircleOutlined, PlusCircleOutlined, PlusOutlined } from '@ant-design/icons'; | import { MinusCircleOutlined, PlusCircleOutlined, PlusOutlined } from '@ant-design/icons'; | ||||
| import { useNavigate, useParams } from '@umijs/max'; | import { useNavigate, useParams } from '@umijs/max'; | ||||
| import { App, Button, Col, Flex, Form, Input, InputNumber, Row, Select } from 'antd'; | |||||
| import { App, Button, Col, Flex, Form, Input, InputNumber, Row } from 'antd'; | |||||
| import { omit, pick } from 'lodash'; | import { omit, pick } from 'lodash'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import { CreateServiceVersionFrom, ServiceOperationType, ServiceVersionData } from '../types'; | import { CreateServiceVersionFrom, ServiceOperationType, ServiceVersionData } from '../types'; | ||||
| @@ -51,7 +51,7 @@ type ServiceVersionCache = ServiceVersionData & { | |||||
| function CreateServiceVersion() { | function CreateServiceVersion() { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| const [resourceStandardList, filterResourceStandard] = useComputingResource(); | |||||
| const [operationType, setOperationType] = useState(ServiceOperationType.Create); | const [operationType, setOperationType] = useState(ServiceOperationType.Create); | ||||
| const [lastPage, setLastPage] = useState(CreateServiceVersionFrom.ServiceInfo); | const [lastPage, setLastPage] = useState(CreateServiceVersionFrom.ServiceInfo); | ||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| @@ -305,7 +305,6 @@ function CreateServiceVersion() { | |||||
| placeholder="请选择模型" | placeholder="请选择模型" | ||||
| disabled={disabled} | disabled={disabled} | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -327,7 +326,6 @@ function CreateServiceVersion() { | |||||
| type={ResourceSelectorType.Mirror} | type={ResourceSelectorType.Mirror} | ||||
| placeholder="请选择镜像" | placeholder="请选择镜像" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| disabled={disabled} | disabled={disabled} | ||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| @@ -357,16 +355,7 @@ function CreateServiceVersion() { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Select | |||||
| showSearch | |||||
| placeholder="请选择资源规格" | |||||
| filterOption={filterResourceStandard} | |||||
| options={resourceStandardList} | |||||
| fieldNames={{ | |||||
| label: 'description', | |||||
| value: 'standard', | |||||
| }} | |||||
| /> | |||||
| <ParameterSelect dataType="resource" placeholder="请选择资源规格" /> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -87,7 +87,7 @@ function ServiceInfo() { | |||||
| format: formatDate, | format: formatDate, | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| const getResourceDescription = useComputingResource()[2]; | |||||
| const getResourceDescription = useComputingResource()[1]; | |||||
| // 获取服务详情 | // 获取服务详情 | ||||
| const getServiceInfo = useCallback(async () => { | const getServiceInfo = useCallback(async () => { | ||||
| @@ -36,7 +36,7 @@ const formatEnvText = (env?: Record<string, string>) => { | |||||
| }; | }; | ||||
| function VersionBasicInfo({ info }: BasicInfoProps) { | function VersionBasicInfo({ info }: BasicInfoProps) { | ||||
| const getResourceDescription = useComputingResource()[2]; | |||||
| const getResourceDescription = useComputingResource()[1]; | |||||
| const datas: BasicInfoData[] = [ | const datas: BasicInfoData[] = [ | ||||
| { | { | ||||
| @@ -42,7 +42,7 @@ const formatEnvText = (env: Record<string, string>) => { | |||||
| function VersionCompareModal({ version1, version2, ...rest }: VersionCompareModalProps) { | function VersionCompareModal({ version1, version2, ...rest }: VersionCompareModalProps) { | ||||
| const [compareData, setCompareData] = useState<CompareData | undefined>(undefined); | const [compareData, setCompareData] = useState<CompareData | undefined>(undefined); | ||||
| const getResourceDescription = useComputingResource()[2]; | |||||
| const getResourceDescription = useComputingResource()[1]; | |||||
| const fields: FiledType[] = useMemo( | const fields: FiledType[] = useMemo( | ||||
| () => [ | () => [ | ||||
| @@ -7,7 +7,7 @@ import { to } from '@/utils/promise'; | |||||
| import G6 from '@antv/g6'; | import G6 from '@antv/g6'; | ||||
| import { useNavigate, useParams } from '@umijs/max'; | import { useNavigate, useParams } from '@umijs/max'; | ||||
| import { App, Button } from 'antd'; | import { App, Button } from 'antd'; | ||||
| import { useEffect, useRef } from 'react'; | |||||
| import { useEffect, useRef, useState } from 'react'; | |||||
| import GlobalParamsDrawer from '../components/GlobalParamsDrawer'; | import GlobalParamsDrawer from '../components/GlobalParamsDrawer'; | ||||
| import ModelMenu from '../components/ModelMenu'; | import ModelMenu from '../components/ModelMenu'; | ||||
| import Props from '../components/PipelineNodeDrawer'; | import Props from '../components/PipelineNodeDrawer'; | ||||
| @@ -24,7 +24,7 @@ const EditPipeline = () => { | |||||
| const propsRef = useRef(); | const propsRef = useRef(); | ||||
| const [paramsDrawerOpen, openParamsDrawer, closeParamsDrawer] = useVisible(false); | const [paramsDrawerOpen, openParamsDrawer, closeParamsDrawer] = useVisible(false); | ||||
| const [globalParam, setGlobalParam, globalParamRef] = useStateRef([]); | const [globalParam, setGlobalParam, globalParamRef] = useStateRef([]); | ||||
| const [workflowInfo, setWorkflowInfo] = useStateRef(undefined); | |||||
| const [workflowInfo, setWorkflowInfo] = useState(undefined); | |||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| let sourceAnchorIdx, targetAnchorIdx, dropAnchorIdx; | let sourceAnchorIdx, targetAnchorIdx, dropAnchorIdx; | ||||
| let dragSourceNode; | let dragSourceNode; | ||||
| @@ -8,7 +8,6 @@ import ResourceSelectorModal, { | |||||
| } from '@/components/ResourceSelectorModal'; | } from '@/components/ResourceSelectorModal'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { CommonTabKeys } from '@/enums'; | import { CommonTabKeys } from '@/enums'; | ||||
| import { useComputingResource } from '@/hooks/resource'; | |||||
| import { canInput, createMenuItems } from '@/pages/Pipeline/Info/utils'; | import { canInput, createMenuItems } from '@/pages/Pipeline/Info/utils'; | ||||
| import { | import { | ||||
| PipelineGlobalParam, | PipelineGlobalParam, | ||||
| @@ -19,7 +18,7 @@ import { | |||||
| import { openAntdModal } from '@/utils/modal'; | import { openAntdModal } from '@/utils/modal'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { INode } from '@antv/g6'; | import { INode } from '@antv/g6'; | ||||
| import { Button, Drawer, Form, Input, MenuProps, Select } from 'antd'; | |||||
| import { Button, Drawer, Form, Input, MenuProps } from 'antd'; | |||||
| import { NamePath } from 'antd/es/form/interface'; | import { NamePath } from 'antd/es/form/interface'; | ||||
| import { forwardRef, useImperativeHandle, useState } from 'react'; | import { forwardRef, useImperativeHandle, useState } from 'react'; | ||||
| import PropsLabel from '../PropsLabel'; | import PropsLabel from '../PropsLabel'; | ||||
| @@ -36,7 +35,6 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| {} as PipelineNodeModelSerialize, | {} as PipelineNodeModelSerialize, | ||||
| ); | ); | ||||
| const [open, setOpen] = useState(false); | const [open, setOpen] = useState(false); | ||||
| const [resourceStandardList, filterResourceStandard] = useComputingResource(); // 资源规模 | |||||
| const [menuItems, setMenuItems] = useState<MenuProps['items']>([]); | const [menuItems, setMenuItems] = useState<MenuProps['items']>([]); | ||||
| const afterOpenChange = async () => { | const afterOpenChange = async () => { | ||||
| @@ -152,19 +150,21 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| const { close } = openAntdModal(CodeSelectorModal, { | const { close } = openAntdModal(CodeSelectorModal, { | ||||
| onOk: (res) => { | onOk: (res) => { | ||||
| if (res) { | if (res) { | ||||
| const { id, code_repo_name, git_url, git_branch, git_user_name, git_password, ssh_key } = | |||||
| res; | |||||
| const value = JSON.stringify({ | const value = JSON.stringify({ | ||||
| id: res.id, | |||||
| name: res.code_repo_name, | |||||
| code_path: res.git_url, | |||||
| branch: res.git_branch, | |||||
| username: res.git_user_name, | |||||
| password: res.git_password, | |||||
| ssh_private_key: res.ssh_key, | |||||
| id, | |||||
| name: code_repo_name, | |||||
| code_path: git_url, | |||||
| branch: git_branch, | |||||
| username: git_user_name, | |||||
| password: git_password, | |||||
| ssh_private_key: ssh_key, | |||||
| }); | }); | ||||
| form.setFieldValue(formItemName, { | form.setFieldValue(formItemName, { | ||||
| ...item, | ...item, | ||||
| value, | value, | ||||
| showValue: res.code_repo_name, | |||||
| showValue: code_repo_name, | |||||
| fromSelect: true, | fromSelect: true, | ||||
| }); | }); | ||||
| form.validateFields([formItemName]); | form.validateFields([formItemName]); | ||||
| @@ -458,16 +458,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Select | |||||
| placeholder="请选择资源规格" | |||||
| filterOption={filterResourceStandard} | |||||
| options={resourceStandardList} | |||||
| fieldNames={{ | |||||
| label: 'description', | |||||
| value: 'standard', | |||||
| }} | |||||
| showSearch | |||||
| /> | |||||
| <ParameterSelect dataType="resource" placeholder="请选择资源规格" /> | |||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item | <Form.Item | ||||
| name="mount_path" | name="mount_path" | ||||
| @@ -41,6 +41,7 @@ export const Primary: Story = { | |||||
| canInput: false, | canInput: false, | ||||
| textArea: false, | textArea: false, | ||||
| size: 'large', | size: 'large', | ||||
| placeholder: '请选择代码配置', | |||||
| style: { width: 400 }, | style: { width: 400 }, | ||||
| }, | }, | ||||
| render: function Render(args) { | render: function Render(args) { | ||||
| @@ -1,5 +1,7 @@ | |||||
| import ParameterInput, { ParameterInputValue } from '@/components/ParameterInput'; | import ParameterInput, { ParameterInputValue } from '@/components/ParameterInput'; | ||||
| import { action } from '@storybook/addon-actions'; | |||||
| import type { Meta, StoryObj } from '@storybook/react'; | import type { Meta, StoryObj } from '@storybook/react'; | ||||
| import { fn } from '@storybook/test'; | |||||
| import { Button } from 'antd'; | import { Button } from 'antd'; | ||||
| import { useState } from 'react'; | import { useState } from 'react'; | ||||
| @@ -18,7 +20,7 @@ const meta = { | |||||
| // backgroundColor: { control: 'color' }, | // backgroundColor: { control: 'color' }, | ||||
| }, | }, | ||||
| // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args | // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args | ||||
| // args: { onClick: fn() }, | |||||
| args: { onChange: fn() }, | |||||
| } satisfies Meta<typeof ParameterInput>; | } satisfies Meta<typeof ParameterInput>; | ||||
| export default meta; | export default meta; | ||||
| @@ -37,45 +39,6 @@ export const Input: Story = { | |||||
| }; | }; | ||||
| export const Select: Story = { | export const Select: Story = { | ||||
| args: { | |||||
| placeholder: '请输入工作目录', | |||||
| style: { width: 300 }, | |||||
| value: 'storybook', | |||||
| canInput: false, | |||||
| size: 'large', | |||||
| }, | |||||
| }; | |||||
| export const SelectWithObjctValue: Story = { | |||||
| args: { | |||||
| placeholder: '请输入工作目录', | |||||
| style: { width: 300 }, | |||||
| value: { | |||||
| value: 'storybook', | |||||
| showValue: 'storybook', | |||||
| fromSelect: true, | |||||
| }, | |||||
| canInput: true, | |||||
| size: 'large', | |||||
| }, | |||||
| }; | |||||
| export const Disabled: Story = { | |||||
| args: { | |||||
| placeholder: '请输入工作目录', | |||||
| style: { width: 300 }, | |||||
| value: { | |||||
| value: 'storybook', | |||||
| showValue: 'storybook', | |||||
| fromSelect: true, | |||||
| }, | |||||
| canInput: true, | |||||
| size: 'large', | |||||
| disabled: true, | |||||
| }, | |||||
| }; | |||||
| export const Application: Story = { | |||||
| args: { | args: { | ||||
| placeholder: '请输入工作目录', | placeholder: '请输入工作目录', | ||||
| style: { width: 300 }, | style: { width: 300 }, | ||||
| @@ -86,18 +49,24 @@ export const Application: Story = { | |||||
| const [value, setValue] = useState<ParameterInputValue | undefined>(''); | const [value, setValue] = useState<ParameterInputValue | undefined>(''); | ||||
| const onClick = () => { | const onClick = () => { | ||||
| setValue({ | |||||
| const value = { | |||||
| value: 'storybook', | value: 'storybook', | ||||
| showValue: 'storybook', | showValue: 'storybook', | ||||
| fromSelect: true, | fromSelect: true, | ||||
| }); | |||||
| otherValue: 'others', | |||||
| }; | |||||
| setValue(value); | |||||
| action('onChange')(value); | |||||
| }; | }; | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <ParameterInput | <ParameterInput | ||||
| {...args} | {...args} | ||||
| value={value} | value={value} | ||||
| onChange={(value) => setValue(value)} | |||||
| onChange={(value) => { | |||||
| setValue(value); | |||||
| action('onChange')(value); | |||||
| }} | |||||
| ></ParameterInput> | ></ParameterInput> | ||||
| <Button type="primary" style={{ display: 'block', marginTop: 10 }} onClick={onClick}> | <Button type="primary" style={{ display: 'block', marginTop: 10 }} onClick={onClick}> | ||||
| 模拟从全局参数选择 | 模拟从全局参数选择 | ||||
| @@ -106,3 +75,18 @@ export const Application: Story = { | |||||
| ); | ); | ||||
| }, | }, | ||||
| }; | }; | ||||
| export const Disabled: Story = { | |||||
| args: { | |||||
| placeholder: '请输入工作目录', | |||||
| style: { width: 300 }, | |||||
| value: { | |||||
| value: 'storybook', | |||||
| showValue: 'storybook', | |||||
| fromSelect: true, | |||||
| }, | |||||
| canInput: true, | |||||
| size: 'large', | |||||
| disabled: true, | |||||
| }, | |||||
| }; | |||||
| @@ -76,6 +76,7 @@ export const Primary: Story = { | |||||
| canInput: false, | canInput: false, | ||||
| textArea: false, | textArea: false, | ||||
| size: 'large', | size: 'large', | ||||
| placeholder: '请选择数据集', | |||||
| style: { width: 400 }, | style: { width: 400 }, | ||||
| }, | }, | ||||
| render: function Render(args) { | render: function Render(args) { | ||||
| @@ -120,7 +121,6 @@ export const InForm: Story = { | |||||
| type={ResourceSelectorType.Dataset} | type={ResourceSelectorType.Dataset} | ||||
| placeholder="请选择" | placeholder="请选择" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| onChange={onChange} | onChange={onChange} | ||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| @@ -133,7 +133,6 @@ export const InForm: Story = { | |||||
| type={ResourceSelectorType.Model} | type={ResourceSelectorType.Model} | ||||
| placeholder="请选择" | placeholder="请选择" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| onChange={onChange} | onChange={onChange} | ||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| @@ -146,7 +145,6 @@ export const InForm: Story = { | |||||
| type={ResourceSelectorType.Mirror} | type={ResourceSelectorType.Mirror} | ||||
| placeholder="请选择" | placeholder="请选择" | ||||
| canInput={false} | canInput={false} | ||||
| size="large" | |||||
| onChange={onChange} | onChange={onChange} | ||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| @@ -349,6 +349,7 @@ public class SysUser extends BaseEntity { | |||||
| .append("dept", getDept()) | .append("dept", getDept()) | ||||
| .append("gitLinkUsername", getGitLinkUsername()) | .append("gitLinkUsername", getGitLinkUsername()) | ||||
| .append("gitLinkPassword", getGitLinkPassword()) | .append("gitLinkPassword", getGitLinkPassword()) | ||||
| .append("credit", getCredit()) | |||||
| .toString(); | .toString(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -53,7 +53,6 @@ public class Constant { | |||||
| // 任务类型 | // 任务类型 | ||||
| public final static String TaskType_Dev = "dev_environment"; | public final static String TaskType_Dev = "dev_environment"; | ||||
| public final static String TaskType_Workflow = "workflow"; | public final static String TaskType_Workflow = "workflow"; | ||||
| public final static String TaskType_AutoMl = "auto_ml"; | |||||
| public final static String TaskType_Ray = "ray"; | public final static String TaskType_Ray = "ray"; | ||||
| public final static String TaskType_ActiveLearn = "active_learn"; | public final static String TaskType_ActiveLearn = "active_learn"; | ||||
| public final static String TaskType_Service = "service"; | public final static String TaskType_Service = "service"; | ||||
| @@ -13,6 +13,7 @@ import org.springframework.data.domain.PageRequest; | |||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.util.Map; | |||||
| /** | /** | ||||
| * (ComputingResource)表控制层 | * (ComputingResource)表控制层 | ||||
| @@ -104,5 +105,11 @@ public class ComputingResourceController extends BaseController { | |||||
| PageRequest pageRequest = PageRequest.of(page, size); | PageRequest pageRequest = PageRequest.of(page, size); | ||||
| return genericsSuccess(resourceOccupyService.queryByPage(pageRequest)); | return genericsSuccess(resourceOccupyService.queryByPage(pageRequest)); | ||||
| } | } | ||||
| @GetMapping("/credit") | |||||
| @ApiOperation("查询用户积分使用情况") | |||||
| public GenericsAjaxResult<Map<String, Double>> queryCredit() { | |||||
| return genericsSuccess(resourceOccupyService.queryCredit()); | |||||
| } | |||||
| } | } | ||||
| @@ -49,7 +49,7 @@ public class ComputingResource implements Serializable { | |||||
| private Integer gpuNums; | private Integer gpuNums; | ||||
| @ApiModelProperty("积分/小时") | @ApiModelProperty("积分/小时") | ||||
| private Float creditPerHour; | |||||
| private Double creditPerHour; | |||||
| @ApiModelProperty("标签") | @ApiModelProperty("标签") | ||||
| private String labels; | private String labels; | ||||
| @@ -19,8 +19,14 @@ public class ResourceOccupy { | |||||
| @ApiModelProperty("计算资源") | @ApiModelProperty("计算资源") | ||||
| private Integer computingResourceId; | private Integer computingResourceId; | ||||
| @ApiModelProperty("描述") | |||||
| private String description; | |||||
| @ApiModelProperty("积分/小时") | @ApiModelProperty("积分/小时") | ||||
| private Float creditPerHour; | |||||
| private Double creditPerHour; | |||||
| @ApiModelProperty("扣除的积分") | |||||
| private Double deduceCredit; | |||||
| @ApiModelProperty("上一次扣分时间") | @ApiModelProperty("上一次扣分时间") | ||||
| private Date deduceLastTime; | private Date deduceLastTime; | ||||
| @@ -36,4 +42,7 @@ public class ResourceOccupy { | |||||
| @ApiModelProperty("类型id") | @ApiModelProperty("类型id") | ||||
| private Long taskId; | private Long taskId; | ||||
| @ApiModelProperty("流水线节点id") | |||||
| private String nodeId; | |||||
| } | } | ||||
| @@ -14,15 +14,19 @@ public interface ResourceOccupyDao { | |||||
| int edit(@Param("resourceOccupy") ResourceOccupy resourceOccupy); | int edit(@Param("resourceOccupy") ResourceOccupy resourceOccupy); | ||||
| ResourceOccupy getResourceOccupyByTask(@Param("taskType") String taskType, @Param("taskId") Long taskId); | |||||
| List<ResourceOccupy> getResourceOccupyByTask(@Param("taskType") String taskType, @Param("taskId") Long taskId, @Param("nodeId") String nodeId); | |||||
| int deduceCredit(@Param("credit") Float credit, @Param("userId") Long userId); | |||||
| int deduceCredit(@Param("credit") Double credit, @Param("userId") Long userId); | |||||
| int updateUsed(@Param("id") Integer id, @Param("used") Integer used); | int updateUsed(@Param("id") Integer id, @Param("used") Integer used); | ||||
| int updateUnUsed(@Param("id") Integer id, @Param("used") Integer used); | int updateUnUsed(@Param("id") Integer id, @Param("used") Integer used); | ||||
| long count(); | |||||
| long count(@Param("userId") Long userId); | |||||
| List<ResourceOccupy> queryByPage(@Param("pageable") Pageable pageable); | |||||
| List<ResourceOccupy> queryByPage(@Param("userId") Long userId, @Param("pageable") Pageable pageable); | |||||
| Double getUserCredit(@Param("userId") Long userId); | |||||
| Double getDeduceCredit(@Param("userId") Long userId); | |||||
| } | } | ||||
| @@ -1,11 +1,13 @@ | |||||
| package com.ruoyi.platform.scheduling; | package com.ruoyi.platform.scheduling; | ||||
| import com.ruoyi.platform.constant.Constant; | |||||
| import com.ruoyi.platform.domain.Experiment; | import com.ruoyi.platform.domain.Experiment; | ||||
| import com.ruoyi.platform.domain.ExperimentIns; | import com.ruoyi.platform.domain.ExperimentIns; | ||||
| import com.ruoyi.platform.mapper.ExperimentDao; | import com.ruoyi.platform.mapper.ExperimentDao; | ||||
| import com.ruoyi.platform.mapper.ExperimentInsDao; | import com.ruoyi.platform.mapper.ExperimentInsDao; | ||||
| import com.ruoyi.platform.service.AimService; | import com.ruoyi.platform.service.AimService; | ||||
| import com.ruoyi.platform.service.ExperimentInsService; | import com.ruoyi.platform.service.ExperimentInsService; | ||||
| import com.ruoyi.platform.service.ResourceOccupyService; | |||||
| import com.ruoyi.platform.utils.JacksonUtil; | import com.ruoyi.platform.utils.JacksonUtil; | ||||
| import com.ruoyi.platform.utils.JsonUtils; | import com.ruoyi.platform.utils.JsonUtils; | ||||
| import com.ruoyi.platform.vo.InsMetricInfoVo; | import com.ruoyi.platform.vo.InsMetricInfoVo; | ||||
| @@ -16,6 +18,8 @@ import org.springframework.stereotype.Component; | |||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.text.SimpleDateFormat; | |||||
| import java.time.Instant; | |||||
| import java.util.*; | import java.util.*; | ||||
| @Component() | @Component() | ||||
| @@ -28,6 +32,8 @@ public class ExperimentInstanceStatusTask { | |||||
| private ExperimentInsDao experimentInsDao; | private ExperimentInsDao experimentInsDao; | ||||
| @Resource | @Resource | ||||
| private AimService aimService; | private AimService aimService; | ||||
| @Resource | |||||
| private ResourceOccupyService resourceOccupyService; | |||||
| private List<Integer> experimentIds = new ArrayList<>(); | private List<Integer> experimentIds = new ArrayList<>(); | ||||
| @@ -43,7 +49,27 @@ public class ExperimentInstanceStatusTask { | |||||
| try { | try { | ||||
| experimentIns = experimentInsService.queryStatusFromArgo(experimentIns); | experimentIns = experimentInsService.queryStatusFromArgo(experimentIns); | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| experimentIns.setStatus("Failed"); | |||||
| experimentIns.setStatus(Constant.Failed); | |||||
| // 结束扣除积分 | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Workflow, Long.valueOf(experimentIns.getId()), null, null); | |||||
| } | |||||
| // 扣除积分 | |||||
| if (StringUtils.isNotEmpty(experimentIns.getNodesStatus())) { | |||||
| Map<String, Object> nodesStatusMap = JsonUtils.jsonToMap(experimentIns.getNodesStatus()); | |||||
| for (String key : nodesStatusMap.keySet()) { | |||||
| Map<String, Object> value = (Map<String, Object>) nodesStatusMap.get(key); | |||||
| String startedAt = (String) value.get("startedAt"); | |||||
| Instant instant = Instant.parse(startedAt); | |||||
| Date startTime = Date.from(instant); | |||||
| String finishedAt = (String) value.get("finishedAt"); | |||||
| if (StringUtils.isEmpty(finishedAt)) { | |||||
| resourceOccupyService.deducing(Constant.TaskType_Workflow, Long.valueOf(experimentIns.getId()), key, startTime); | |||||
| } else { | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Workflow, Long.valueOf(experimentIns.getId()), key, startTime); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| //运行成功的实验实例记录指标数值 | //运行成功的实验实例记录指标数值 | ||||
| Map<String, Object> metricRecord = JacksonUtil.parseJSONStr2Map(experimentIns.getMetricRecord()); | Map<String, Object> metricRecord = JacksonUtil.parseJSONStr2Map(experimentIns.getMetricRecord()); | ||||
| @@ -42,13 +42,18 @@ public class RayInsStatusTask { | |||||
| //当原本状态为null或非终止态时才调用argo接口 | //当原本状态为null或非终止态时才调用argo接口 | ||||
| try { | try { | ||||
| rayIns = rayInsService.queryStatusFromArgo(rayIns); | rayIns = rayInsService.queryStatusFromArgo(rayIns); | ||||
| // 扣除积分 | |||||
| if (Constant.Running.equals(rayIns.getStatus())) { | if (Constant.Running.equals(rayIns.getStatus())) { | ||||
| resourceOccupyService.deducing(Constant.TaskType_Ray, rayIns.getId()); | |||||
| } else { | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Ray, rayIns.getId()); | |||||
| resourceOccupyService.deducing(Constant.TaskType_Ray, rayIns.getId(), null,null); | |||||
| } else if (Constant.Failed.equals(rayIns.getStatus()) || Constant.Terminated.equals(rayIns.getStatus()) | |||||
| || Constant.Succeeded.equals(rayIns.getStatus())) { | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Ray, rayIns.getId(), null,null); | |||||
| } | } | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| rayIns.setStatus(Constant.Failed); | rayIns.setStatus(Constant.Failed); | ||||
| // 结束扣除积分 | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Ray, rayIns.getId(), null, null); | |||||
| } | } | ||||
| // 线程安全的添加操作 | // 线程安全的添加操作 | ||||
| synchronized (rayIds) { | synchronized (rayIds) { | ||||
| @@ -25,11 +25,11 @@ public class ResourceOccupyTask { | |||||
| private ServiceDao serviceDao; | private ServiceDao serviceDao; | ||||
| // 开发环境功能扣除积分 | // 开发环境功能扣除积分 | ||||
| @Scheduled(cron = "0 0/10 * * * ?") // 每10分钟执行一次 | |||||
| @Scheduled(cron = "0 0/1 * * * ?") // 每10分钟执行一次 | |||||
| public void devDeduceCredit() { | public void devDeduceCredit() { | ||||
| List<DevEnvironment> devEnvironments = devEnvironmentDao.getRunning(); | List<DevEnvironment> devEnvironments = devEnvironmentDao.getRunning(); | ||||
| for (DevEnvironment devEnvironment : devEnvironments) { | for (DevEnvironment devEnvironment : devEnvironments) { | ||||
| resourceOccupyService.deducing(Constant.TaskType_Dev, Long.valueOf(devEnvironment.getId())); | |||||
| resourceOccupyService.deducing(Constant.TaskType_Dev, Long.valueOf(devEnvironment.getId()), null, null); | |||||
| } | } | ||||
| } | } | ||||
| @@ -38,7 +38,7 @@ public class ResourceOccupyTask { | |||||
| public void serviceDeduceCredit() { | public void serviceDeduceCredit() { | ||||
| List<ServiceVersion> serviceVersions = serviceDao.getRunning(); | List<ServiceVersion> serviceVersions = serviceDao.getRunning(); | ||||
| for (ServiceVersion serviceVersion : serviceVersions) { | for (ServiceVersion serviceVersion : serviceVersions) { | ||||
| resourceOccupyService.deducing(Constant.TaskType_Service, serviceVersion.getId()); | |||||
| resourceOccupyService.deducing(Constant.TaskType_Service, serviceVersion.getId(), null, null); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -4,15 +4,20 @@ import com.ruoyi.platform.domain.ResourceOccupy; | |||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| import java.util.Date; | |||||
| import java.util.Map; | |||||
| public interface ResourceOccupyService { | public interface ResourceOccupyService { | ||||
| Boolean haveResource(Integer computingResourceId) throws Exception; | Boolean haveResource(Integer computingResourceId) throws Exception; | ||||
| void startDeduce(Integer computingResourceId, String taskType, Long taskId); | |||||
| void startDeduce(Integer computingResourceId, String taskType, Long taskId, String nodeId); | |||||
| void endDeduce(String taskType, Long taskId); | |||||
| void endDeduce(String taskType, Long taskId, String nodeId, Date nodeStartTime); | |||||
| void deducing(String taskType, Long taskId); | |||||
| void deducing(String taskType, Long taskId, String nodeId, Date nodeStartTime); | |||||
| Page<ResourceOccupy> queryByPage(PageRequest pageRequest); | Page<ResourceOccupy> queryByPage(PageRequest pageRequest); | ||||
| Map<String, Double> queryCredit(); | |||||
| } | } | ||||
| @@ -64,11 +64,11 @@ public class DevEnvironmentServiceImpl implements DevEnvironmentService { | |||||
| if (!devEnv.getStatus().equals(PodStatus.Terminated.getName()) && | if (!devEnv.getStatus().equals(PodStatus.Terminated.getName()) && | ||||
| !devEnv.getStatus().equals(PodStatus.Failed.getName())) { | !devEnv.getStatus().equals(PodStatus.Failed.getName())) { | ||||
| PodStatusVo podStatusVo = this.jupyterService.getJupyterStatus(devEnv); | PodStatusVo podStatusVo = this.jupyterService.getJupyterStatus(devEnv); | ||||
| devEnv.setStatus(podStatusVo.getStatus()); | |||||
| devEnv.setUrl(podStatusVo.getUrl()); | |||||
| if(!devEnv.getStatus().equals(podStatusVo.getStatus())){ | if(!devEnv.getStatus().equals(podStatusVo.getStatus())){ | ||||
| this.devEnvironmentDao.update(devEnv); | this.devEnvironmentDao.update(devEnv); | ||||
| } | } | ||||
| devEnv.setStatus(podStatusVo.getStatus()); | |||||
| devEnv.setUrl(podStatusVo.getUrl()); | |||||
| } | } | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| devEnv.setStatus(PodStatus.Unknown.getName()); | devEnv.setStatus(PodStatus.Unknown.getName()); | ||||
| @@ -3,6 +3,7 @@ package com.ruoyi.platform.service.impl; | |||||
| import cn.hutool.json.JSONUtil; | import cn.hutool.json.JSONUtil; | ||||
| import com.alibaba.fastjson2.JSON; | import com.alibaba.fastjson2.JSON; | ||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.constant.Constant; | |||||
| import com.ruoyi.platform.domain.DatasetTempStorage; | import com.ruoyi.platform.domain.DatasetTempStorage; | ||||
| import com.ruoyi.platform.domain.Experiment; | import com.ruoyi.platform.domain.Experiment; | ||||
| import com.ruoyi.platform.domain.ExperimentIns; | import com.ruoyi.platform.domain.ExperimentIns; | ||||
| @@ -12,6 +13,7 @@ import com.ruoyi.platform.mapper.ExperimentDao; | |||||
| import com.ruoyi.platform.mapper.ExperimentInsDao; | import com.ruoyi.platform.mapper.ExperimentInsDao; | ||||
| import com.ruoyi.platform.mapper.ModelDependency1Dao; | import com.ruoyi.platform.mapper.ModelDependency1Dao; | ||||
| import com.ruoyi.platform.service.ExperimentInsService; | import com.ruoyi.platform.service.ExperimentInsService; | ||||
| import com.ruoyi.platform.service.ResourceOccupyService; | |||||
| import com.ruoyi.platform.utils.*; | import com.ruoyi.platform.utils.*; | ||||
| import com.ruoyi.platform.vo.LogRequestVo; | import com.ruoyi.platform.vo.LogRequestVo; | ||||
| import com.ruoyi.platform.vo.PodLogVo; | import com.ruoyi.platform.vo.PodLogVo; | ||||
| @@ -66,6 +68,9 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||||
| @Resource | @Resource | ||||
| private DatasetTempStorageDao datasetTempStorageDao; | private DatasetTempStorageDao datasetTempStorageDao; | ||||
| @Resource | |||||
| private ResourceOccupyService resourceOccupyService; | |||||
| private final MinioUtil minioUtil; | private final MinioUtil minioUtil; | ||||
| public ExperimentInsServiceImpl(MinioUtil minioUtil) { | public ExperimentInsServiceImpl(MinioUtil minioUtil) { | ||||
| @@ -410,6 +415,8 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||||
| //修改实验状态 | //修改实验状态 | ||||
| updateExperimentStatus(experimentIns.getExperimentId()); | updateExperimentStatus(experimentIns.getExperimentId()); | ||||
| // 结束扣除积分 | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Workflow, Long.valueOf(experimentIns.getId()), null, null); | |||||
| return true; | return true; | ||||
| } else { | } else { | ||||
| throw new Exception("终止错误"); | throw new Exception("终止错误"); | ||||
| @@ -10,7 +10,6 @@ import com.ruoyi.platform.domain.*; | |||||
| import com.ruoyi.platform.domain.dependencydomain.ProjectDepency; | import com.ruoyi.platform.domain.dependencydomain.ProjectDepency; | ||||
| import com.ruoyi.platform.domain.dependencydomain.TrainTaskDepency; | import com.ruoyi.platform.domain.dependencydomain.TrainTaskDepency; | ||||
| import com.ruoyi.platform.mapper.ExperimentDao; | import com.ruoyi.platform.mapper.ExperimentDao; | ||||
| import com.ruoyi.platform.mapper.ExperimentInsDao; | |||||
| import com.ruoyi.platform.mapper.ModelDependency1Dao; | import com.ruoyi.platform.mapper.ModelDependency1Dao; | ||||
| import com.ruoyi.platform.service.*; | import com.ruoyi.platform.service.*; | ||||
| import com.ruoyi.platform.utils.HttpUtils; | import com.ruoyi.platform.utils.HttpUtils; | ||||
| @@ -62,6 +61,9 @@ public class ExperimentServiceImpl implements ExperimentService { | |||||
| @Lazy | @Lazy | ||||
| private ExperimentInsService experimentInsService; | private ExperimentInsService experimentInsService; | ||||
| @Resource | |||||
| private ResourceOccupyService resourceOccupyService; | |||||
| @Resource | @Resource | ||||
| private ModelDependency1Dao modelDependency1Dao; | private ModelDependency1Dao modelDependency1Dao; | ||||
| @@ -233,6 +235,14 @@ public class ExperimentServiceImpl implements ExperimentService { | |||||
| } | } | ||||
| Map<String, Object> converMap = JsonUtils.jsonToMap(convertRes); | Map<String, Object> converMap = JsonUtils.jsonToMap(convertRes); | ||||
| // 判断积分和资源是否足够 | |||||
| Map<String, Map<String, Object>> resourceInfo = (Map<String, Map<String, Object>>) converMap.get("resource_info"); | |||||
| for (Map.Entry<String, Map<String, Object>> entry : resourceInfo.entrySet()) { | |||||
| Map<String, Object> node = entry.getValue(); | |||||
| resourceOccupyService.haveResource((Integer) node.get("computing_resource_id")); | |||||
| } | |||||
| // 组装运行接口json | // 组装运行接口json | ||||
| Map<String, Object> runReqMap = new HashMap<>(); | Map<String, Object> runReqMap = new HashMap<>(); | ||||
| runReqMap.put("data", converMap.get("data")); | runReqMap.put("data", converMap.get("data")); | ||||
| @@ -300,6 +310,11 @@ public class ExperimentServiceImpl implements ExperimentService { | |||||
| insertDatasetTempStorage(datasetDependendcy, trainInfo, experiment.getId(), insert.getId(), experiment.getName(), experiment.getWorkflowId()); | insertDatasetTempStorage(datasetDependendcy, trainInfo, experiment.getId(), insert.getId(), experiment.getName(), experiment.getWorkflowId()); | ||||
| } | } | ||||
| // 记录开始扣积分 | |||||
| for (Map.Entry<String, Map<String, Object>> entry : resourceInfo.entrySet()) { | |||||
| Map<String, Object> node = entry.getValue(); | |||||
| resourceOccupyService.startDeduce((Integer) node.get("computing_resource_id"), Constant.TaskType_Workflow, Long.valueOf(insert.getId()), entry.getKey()); | |||||
| } | |||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
| @@ -133,9 +133,6 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| return "pod不存在!"; | return "pod不存在!"; | ||||
| } | } | ||||
| // 结束扣积分 | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Dev, Long.valueOf(id)); | |||||
| // 使用 Kubernetes API 删除 Pod | // 使用 Kubernetes API 删除 Pod | ||||
| String deleteResult = k8sClientUtil.deletePod(podName, namespace); | String deleteResult = k8sClientUtil.deletePod(podName, namespace); | ||||
| // 删除service | // 删除service | ||||
| @@ -143,6 +140,9 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| devEnvironment.setStatus(Constant.Terminated); | devEnvironment.setStatus(Constant.Terminated); | ||||
| this.devEnvironmentService.update(devEnvironment); | this.devEnvironmentService.update(devEnvironment); | ||||
| // 结束扣积分 | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Dev, Long.valueOf(id), null, null); | |||||
| return deleteResult + ",编辑器已停止"; | return deleteResult + ",编辑器已停止"; | ||||
| } | } | ||||
| @@ -168,7 +168,7 @@ public class RayInsServiceImpl implements RayInsService { | |||||
| rayInsDao.update(ins); | rayInsDao.update(ins); | ||||
| updateRayStatus(rayIns.getRayId()); | updateRayStatus(rayIns.getRayId()); | ||||
| // 结束扣积分 | // 结束扣积分 | ||||
| resourceOccupyService.endDeduce(Constant.TaskType_Ray, id); | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Ray, id, null, null); | |||||
| return true; | return true; | ||||
| } else { | } else { | ||||
| return false; | return false; | ||||
| @@ -205,7 +205,8 @@ public class RayServiceImpl implements RayService { | |||||
| rayIns.setResultPath(outputPath); | rayIns.setResultPath(outputPath); | ||||
| rayInsDao.insert(rayIns); | rayInsDao.insert(rayIns); | ||||
| rayInsService.updateRayStatus(id); | rayInsService.updateRayStatus(id); | ||||
| resourceOccupyService.startDeduce(ray.getComputingResourceId(), Constant.TaskType_Ray, rayIns.getId()); | |||||
| // 记录开始扣除积分 | |||||
| resourceOccupyService.startDeduce(ray.getComputingResourceId(), Constant.TaskType_Ray, rayIns.getId(), null); | |||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
| } | } | ||||
| @@ -12,9 +12,13 @@ import org.springframework.data.domain.Page; | |||||
| import org.springframework.data.domain.PageImpl; | import org.springframework.data.domain.PageImpl; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | |||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| @Service("resourceOccupyService") | @Service("resourceOccupyService") | ||||
| public class ResourceOccupyServiceImpl implements ResourceOccupyService { | public class ResourceOccupyServiceImpl implements ResourceOccupyService { | ||||
| @@ -48,15 +52,18 @@ public class ResourceOccupyServiceImpl implements ResourceOccupyService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public void startDeduce(Integer computingResourceId, String taskType, Long taskId) { | |||||
| @Transactional | |||||
| public void startDeduce(Integer computingResourceId, String taskType, Long taskId, String nodeId) { | |||||
| ResourceOccupy resourceOccupy = new ResourceOccupy(); | ResourceOccupy resourceOccupy = new ResourceOccupy(); | ||||
| ComputingResource computingResource = computingResourceDao.queryById(computingResourceId); | ComputingResource computingResource = computingResourceDao.queryById(computingResourceId); | ||||
| resourceOccupy.setComputingResourceId(computingResourceId); | resourceOccupy.setComputingResourceId(computingResourceId); | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| resourceOccupy.setUserId(loginUser.getUserid()); | resourceOccupy.setUserId(loginUser.getUserid()); | ||||
| resourceOccupy.setCreditPerHour(computingResource.getCreditPerHour()); | resourceOccupy.setCreditPerHour(computingResource.getCreditPerHour()); | ||||
| resourceOccupy.setDescription(computingResource.getDescription()); | |||||
| resourceOccupy.setTaskType(taskType); | resourceOccupy.setTaskType(taskType); | ||||
| resourceOccupy.setTaskId(taskId); | resourceOccupy.setTaskId(taskId); | ||||
| resourceOccupy.setNodeId(nodeId); | |||||
| resourceOccupyDao.save(resourceOccupy); | resourceOccupyDao.save(resourceOccupy); | ||||
| if (Constant.Computing_Resource_GPU.equals(computingResource.getComputingResource())) { | if (Constant.Computing_Resource_GPU.equals(computingResource.getComputingResource())) { | ||||
| @@ -67,36 +74,58 @@ public class ResourceOccupyServiceImpl implements ResourceOccupyService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public void endDeduce(String taskType, Long taskId) { | |||||
| ResourceOccupy resourceOccupy = resourceOccupyDao.getResourceOccupyByTask(taskType, taskId); | |||||
| deducing(taskType, taskId); | |||||
| resourceOccupy.setState(Constant.State_invalid); | |||||
| resourceOccupyDao.edit(resourceOccupy); | |||||
| @Transactional | |||||
| public void endDeduce(String taskType, Long taskId, String nodeId, Date nodeStartTime) { | |||||
| List<ResourceOccupy> resourceOccupys = resourceOccupyDao.getResourceOccupyByTask(taskType, taskId, nodeId); | |||||
| for (ResourceOccupy resourceOccupy : resourceOccupys) { | |||||
| deducing(taskType, taskId, nodeId, nodeStartTime); | |||||
| resourceOccupy.setState(Constant.State_invalid); | |||||
| resourceOccupyDao.edit(resourceOccupy); | |||||
| ComputingResource computingResource = computingResourceDao.queryById(resourceOccupy.getComputingResourceId()); | |||||
| if (Constant.Computing_Resource_GPU.equals(computingResource.getComputingResource())) { | |||||
| resourceOccupyDao.updateUnUsed(computingResource.getResourceId(), computingResource.getGpuNums()); | |||||
| } else { | |||||
| resourceOccupyDao.updateUnUsed(computingResource.getResourceId(), computingResource.getCpuCores()); | |||||
| ComputingResource computingResource = computingResourceDao.queryById(resourceOccupy.getComputingResourceId()); | |||||
| if (Constant.Computing_Resource_GPU.equals(computingResource.getComputingResource())) { | |||||
| resourceOccupyDao.updateUnUsed(computingResource.getResourceId(), computingResource.getGpuNums()); | |||||
| } else { | |||||
| resourceOccupyDao.updateUnUsed(computingResource.getResourceId(), computingResource.getCpuCores()); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @Override | @Override | ||||
| public void deducing(String taskType, Long taskId) { | |||||
| ResourceOccupy resourceOccupy = resourceOccupyDao.getResourceOccupyByTask(taskType, taskId); | |||||
| long timeDifferenceMillis = new Date().getTime() - resourceOccupy.getDeduceLastTime().getTime(); | |||||
| Float hours = (float) (timeDifferenceMillis / (1000 * 60 * 60)); | |||||
| float deduceCredit = resourceOccupy.getCreditPerHour() * hours; | |||||
| resourceOccupyDao.deduceCredit(deduceCredit, resourceOccupy.getUserId()); | |||||
| @Transactional | |||||
| public void deducing(String taskType, Long taskId, String nodeId, Date nodeStartTime) { | |||||
| List<ResourceOccupy> resourceOccupys = resourceOccupyDao.getResourceOccupyByTask(taskType, taskId, nodeId); | |||||
| for (ResourceOccupy resourceOccupy : resourceOccupys) { | |||||
| Date now = new Date(); | |||||
| long timeDifferenceMillis; | |||||
| if (nodeStartTime != null && resourceOccupy.getDeduceLastTime().before(nodeStartTime)) { | |||||
| timeDifferenceMillis = now.getTime() - nodeStartTime.getTime(); | |||||
| } else { | |||||
| timeDifferenceMillis = now.getTime() - resourceOccupy.getDeduceLastTime().getTime(); | |||||
| } | |||||
| Double hours = (double) timeDifferenceMillis / (1000 * 60 * 60); | |||||
| Double deduceCredit = resourceOccupy.getCreditPerHour() * hours; | |||||
| resourceOccupyDao.deduceCredit(deduceCredit, resourceOccupy.getUserId()); | |||||
| resourceOccupy.setDeduceLastTime(new Date()); | |||||
| resourceOccupyDao.edit(resourceOccupy); | |||||
| resourceOccupy.setDeduceCredit(resourceOccupy.getDeduceCredit() + deduceCredit); | |||||
| resourceOccupy.setDeduceLastTime(now); | |||||
| resourceOccupyDao.edit(resourceOccupy); | |||||
| } | |||||
| } | } | ||||
| @Override | @Override | ||||
| public Page<ResourceOccupy> queryByPage(PageRequest pageRequest) { | public Page<ResourceOccupy> queryByPage(PageRequest pageRequest) { | ||||
| long total = resourceOccupyDao.count(); | |||||
| return new PageImpl<>(resourceOccupyDao.queryByPage(pageRequest), pageRequest, total); | |||||
| long total = resourceOccupyDao.count(SecurityUtils.getLoginUser().getUserid()); | |||||
| return new PageImpl<>(resourceOccupyDao.queryByPage(SecurityUtils.getLoginUser().getUserid(), pageRequest), pageRequest, total); | |||||
| } | |||||
| @Override | |||||
| public Map<String, Double> queryCredit() { | |||||
| Double userCredit = resourceOccupyDao.getUserCredit(SecurityUtils.getLoginUser().getUserid()); | |||||
| Double deduceCredit = resourceOccupyDao.getDeduceCredit(SecurityUtils.getLoginUser().getUserid()); | |||||
| HashMap<String, Double> result = new HashMap<>(); | |||||
| result.put("userCredit", userCredit); | |||||
| result.put("deduceCredit", deduceCredit); | |||||
| return result; | |||||
| } | } | ||||
| } | } | ||||
| @@ -252,19 +252,21 @@ public class ServiceServiceImpl implements ServiceService { | |||||
| paramMap.put("service_type", service.getServiceType()); | paramMap.put("service_type", service.getServiceType()); | ||||
| paramMap.put("deploy_type", serviceVersion.getDeployType()); | paramMap.put("deploy_type", serviceVersion.getDeployType()); | ||||
| // 记录开始扣积分 | |||||
| // 判断是否有资源 | |||||
| if (resourceOccupyService.haveResource(serviceVersion.getComputingResourceId())) { | if (resourceOccupyService.haveResource(serviceVersion.getComputingResourceId())) { | ||||
| String req = HttpUtils.sendPost(argoUrl + modelService + "/create", JSON.toJSONString(paramMap)); | String req = HttpUtils.sendPost(argoUrl + modelService + "/create", JSON.toJSONString(paramMap)); | ||||
| if (StringUtils.isNotEmpty(req)) { | if (StringUtils.isNotEmpty(req)) { | ||||
| Map<String, Object> reqMap = JacksonUtil.parseJSONStr2Map(req); | Map<String, Object> reqMap = JacksonUtil.parseJSONStr2Map(req); | ||||
| if ((Integer) reqMap.get("code") == 200) { | if ((Integer) reqMap.get("code") == 200) { | ||||
| resourceOccupyService.startDeduce(serviceVersion.getComputingResourceId(), Constant.TaskType_Service, serviceVersion.getId()); | |||||
| Map<String, String> data = (Map<String, String>) reqMap.get("data"); | Map<String, String> data = (Map<String, String>) reqMap.get("data"); | ||||
| serviceVersion.setUrl(data.get("url")); | serviceVersion.setUrl(data.get("url")); | ||||
| serviceVersion.setDeploymentName(data.get("deployment_name")); | serviceVersion.setDeploymentName(data.get("deployment_name")); | ||||
| serviceVersion.setSvcName(data.get("svc_name")); | serviceVersion.setSvcName(data.get("svc_name")); | ||||
| serviceVersion.setRunState(Constant.Pending); | serviceVersion.setRunState(Constant.Pending); | ||||
| serviceDao.updateServiceVersion(serviceVersion); | serviceDao.updateServiceVersion(serviceVersion); | ||||
| // 记录开始扣积分 | |||||
| resourceOccupyService.startDeduce(serviceVersion.getComputingResourceId(), Constant.TaskType_Service, serviceVersion.getId(), null); | |||||
| return "启动成功"; | return "启动成功"; | ||||
| } else { | } else { | ||||
| throw new RuntimeException("启动失败"); | throw new RuntimeException("启动失败"); | ||||
| @@ -286,7 +288,7 @@ public class ServiceServiceImpl implements ServiceService { | |||||
| serviceVersion.setRunState(Constant.Stopped); | serviceVersion.setRunState(Constant.Stopped); | ||||
| serviceDao.updateServiceVersion(serviceVersion); | serviceDao.updateServiceVersion(serviceVersion); | ||||
| // 结束扣积分 | // 结束扣积分 | ||||
| resourceOccupyService.endDeduce(Constant.TaskType_Service, id); | |||||
| resourceOccupyService.endDeduce(Constant.TaskType_Service, id, null, null); | |||||
| return "停止成功"; | return "停止成功"; | ||||
| } else { | } else { | ||||
| throw new RuntimeException("停止失败"); | throw new RuntimeException("停止失败"); | ||||
| @@ -1,6 +1,5 @@ | |||||
| package com.ruoyi.platform.utils; | package com.ruoyi.platform.utils; | ||||
| import com.alibaba.fastjson2.JSON; | |||||
| import com.ruoyi.platform.constant.Constant; | import com.ruoyi.platform.constant.Constant; | ||||
| import com.ruoyi.platform.domain.ComputingResource; | import com.ruoyi.platform.domain.ComputingResource; | ||||
| import com.ruoyi.platform.domain.DevEnvironment; | import com.ruoyi.platform.domain.DevEnvironment; | ||||
| @@ -11,7 +10,6 @@ import io.kubernetes.client.custom.IntOrString; | |||||
| import io.kubernetes.client.custom.Quantity; | import io.kubernetes.client.custom.Quantity; | ||||
| import io.kubernetes.client.openapi.ApiClient; | import io.kubernetes.client.openapi.ApiClient; | ||||
| import io.kubernetes.client.openapi.ApiException; | import io.kubernetes.client.openapi.ApiException; | ||||
| import io.kubernetes.client.openapi.apis.AppsV1Api; | |||||
| import io.kubernetes.client.openapi.apis.CoreV1Api; | import io.kubernetes.client.openapi.apis.CoreV1Api; | ||||
| import io.kubernetes.client.openapi.models.*; | import io.kubernetes.client.openapi.models.*; | ||||
| import io.kubernetes.client.util.ClientBuilder; | import io.kubernetes.client.util.ClientBuilder; | ||||
| @@ -19,7 +17,6 @@ import io.kubernetes.client.util.Config; | |||||
| import io.kubernetes.client.util.credentials.AccessTokenAuthentication; | import io.kubernetes.client.util.credentials.AccessTokenAuthentication; | ||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| import org.apache.commons.lang.StringUtils; | import org.apache.commons.lang.StringUtils; | ||||
| import org.json.JSONObject; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
| @@ -519,7 +516,8 @@ public class K8sClientUtil { | |||||
| pod = api.createNamespacedPod(namespace, pod, null, null, null); | pod = api.createNamespacedPod(namespace, pod, null, null, null); | ||||
| String nodeName = getNodeName(podName, namespace); | String nodeName = getNodeName(podName, namespace); | ||||
| resourceOccupyService.startDeduce(devEnvironment.getComputingResourceId(), Constant.TaskType_Dev, Long.valueOf(devEnvironment.getId())); | |||||
| // 记录开始扣除积分 | |||||
| resourceOccupyService.startDeduce(devEnvironment.getComputingResourceId(), Constant.TaskType_Dev, Long.valueOf(devEnvironment.getId()), null); | |||||
| } | } | ||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| throw new RuntimeException("创建pod异常:" + e.getResponseBody()); | throw new RuntimeException("创建pod异常:" + e.getResponseBody()); | ||||
| @@ -699,8 +697,7 @@ public class K8sClientUtil { | |||||
| ComputingResource computingResource = computingResourceDao.queryById(computingResourceId); | ComputingResource computingResource = computingResourceDao.queryById(computingResourceId); | ||||
| //配置pod资源 | //配置pod资源 | ||||
| String memory = computingResource.getMemoryGb().toString(); | |||||
| memory = memory.substring(0, memory.length() - 1).concat("i"); | |||||
| String memory = computingResource.getMemoryGb().toString().concat("Gi"); | |||||
| HashMap<String, Quantity> limitMap = new HashMap<>(); | HashMap<String, Quantity> limitMap = new HashMap<>(); | ||||
| if (computingResource.getGpuNums() != null && computingResource.getGpuNums() != 0) { | if (computingResource.getGpuNums() != null && computingResource.getGpuNums() != 0) { | ||||
| limitMap.put("nvidia.com/gpu", new Quantity(String.valueOf(computingResource.getGpuNums()))); | limitMap.put("nvidia.com/gpu", new Quantity(String.valueOf(computingResource.getGpuNums()))); | ||||
| @@ -2,8 +2,11 @@ | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||||
| <mapper namespace="com.ruoyi.platform.mapper.ResourceOccupyDao"> | <mapper namespace="com.ruoyi.platform.mapper.ResourceOccupyDao"> | ||||
| <insert id="save"> | <insert id="save"> | ||||
| insert into resource_occupy (user_id, computing_resource_id, credit_per_hour) | |||||
| values (#{resourceOccupy.userId}, #{resourceOccupy.computingResourceId}, #{resourceOccupy.creditPerHour}) | |||||
| insert into resource_occupy (user_id, computing_resource_id, credit_per_hour, description, task_type, task_id, | |||||
| node_id) | |||||
| values (#{resourceOccupy.userId}, #{resourceOccupy.computingResourceId}, #{resourceOccupy.creditPerHour}, | |||||
| #{resourceOccupy.description}, #{resourceOccupy.taskType}, #{resourceOccupy.taskId}, | |||||
| #{resourceOccupy.nodeId}) | |||||
| </insert> | </insert> | ||||
| <update id="edit"> | <update id="edit"> | ||||
| @@ -15,6 +18,9 @@ | |||||
| <if test="resourceOccupy.deduceLastTime != null"> | <if test="resourceOccupy.deduceLastTime != null"> | ||||
| deduce_last_time = #{resourceOccupy.deduceLastTime}, | deduce_last_time = #{resourceOccupy.deduceLastTime}, | ||||
| </if> | </if> | ||||
| <if test="resourceOccupy.deduceCredit != null"> | |||||
| deduce_credit = #{resourceOccupy.deduceCredit}, | |||||
| </if> | |||||
| </set> | </set> | ||||
| where id = #{resourceOccupy.id} | where id = #{resourceOccupy.id} | ||||
| </update> | </update> | ||||
| @@ -46,17 +52,42 @@ | |||||
| <select id="getResourceOccupyByTask" resultType="com.ruoyi.platform.domain.ResourceOccupy"> | <select id="getResourceOccupyByTask" resultType="com.ruoyi.platform.domain.ResourceOccupy"> | ||||
| select * | select * | ||||
| from resource_occupy | from resource_occupy | ||||
| where task_type = #{task_type} | |||||
| and task_id = #{task_id} | |||||
| where task_type = #{taskType} | |||||
| and task_id = #{taskId} | |||||
| <if test="nodeId != null and nodeId !=''"> | |||||
| and node_id = #{nodeId} | |||||
| </if> | |||||
| and state = 1 | |||||
| </select> | </select> | ||||
| <select id="count" resultType="java.lang.Long"> | <select id="count" resultType="java.lang.Long"> | ||||
| select count(1) resource_occupy | |||||
| select count(1) | |||||
| from resource_occupy | |||||
| where user_id = #{userId} | |||||
| </select> | </select> | ||||
| <select id="queryByPage" resultType="com.ruoyi.platform.domain.ResourceOccupy"> | <select id="queryByPage" resultType="com.ruoyi.platform.domain.ResourceOccupy"> | ||||
| select * | |||||
| select id, | |||||
| user_id, | |||||
| description, | |||||
| credit_per_hour, | |||||
| TRUNCATE(deduce_credit, 1) as deduce_credit, | |||||
| start_time, | |||||
| state | |||||
| from resource_occupy | from resource_occupy | ||||
| where user_id = #{userId} | |||||
| order by start_time desc limit #{pageable.offset}, #{pageable.pageSize} | order by start_time desc limit #{pageable.offset}, #{pageable.pageSize} | ||||
| </select> | </select> | ||||
| <select id="getUserCredit" resultType="java.lang.Double"> | |||||
| select TRUNCATE(credit, 1) as credit | |||||
| from sys_user | |||||
| where user_id = #{userId} | |||||
| </select> | |||||
| <select id="getDeduceCredit" resultType="java.lang.Double"> | |||||
| select TRUNCATE(sum(deduce_credit), 1) as deduce_credit | |||||
| from resource_occupy | |||||
| where user_id = #{userId} | |||||
| </select> | |||||
| </mapper> | </mapper> | ||||
| @@ -60,7 +60,7 @@ | |||||
| u.password, | u.password, | ||||
| u.git_link_username, | u.git_link_username, | ||||
| u.git_link_password, | u.git_link_password, | ||||
| u.credit, | |||||
| TRUNCATE(u.credit, 1) as credit, | |||||
| u.sex, | u.sex, | ||||
| u.status, | u.status, | ||||
| u.del_flag, | u.del_flag, | ||||
| @@ -90,7 +90,7 @@ | |||||
| <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult"> | <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult"> | ||||
| select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, | select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, | ||||
| u.git_link_username, u.credit, | |||||
| u.git_link_username, TRUNCATE(u.credit, 1) as credit, | |||||
| u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader | u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader | ||||
| from sys_user u | from sys_user u | ||||
| left join sys_dept d on u.dept_id = d.dept_id | left join sys_dept d on u.dept_id = d.dept_id | ||||
| @@ -125,7 +125,7 @@ | |||||
| </select> | </select> | ||||
| <select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult"> | <select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult"> | ||||
| select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time, u.credit, u.git_link_username | |||||
| select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time, TRUNCATE(u.credit, 1) as credit, u.git_link_username | |||||
| from sys_user u | from sys_user u | ||||
| left join sys_dept d on u.dept_id = d.dept_id | left join sys_dept d on u.dept_id = d.dept_id | ||||
| left join sys_user_role ur on u.user_id = ur.user_id | left join sys_user_role ur on u.user_id = ur.user_id | ||||
| @@ -142,7 +142,7 @@ | |||||
| </select> | </select> | ||||
| <select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult"> | <select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult"> | ||||
| select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time , u.credit, u.git_link_username | |||||
| select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time , TRUNCATE(u.credit, 1) as credit, u.git_link_username | |||||
| from sys_user u | from sys_user u | ||||
| left join sys_dept d on u.dept_id = d.dept_id | left join sys_dept d on u.dept_id = d.dept_id | ||||
| left join sys_user_role ur on u.user_id = ur.user_id | left join sys_user_role ur on u.user_id = ur.user_id | ||||