Browse Source

Merge branch 'dev' of https://gitlink.org.cn/ci4s/ci4sManagement-cloud into dev

dev-active_learn
somunslotus 11 months ago
parent
commit
f501cee39e
12 changed files with 193 additions and 61 deletions
  1. +9
    -7
      react-ui/src/pages/AutoML/components/CreateForm/TrialConfig.tsx
  2. +12
    -9
      react-ui/src/pages/HyperParameter/components/CreateForm/ExecuteConfig.tsx
  3. +1
    -1
      react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.tsx
  4. +44
    -10
      react-ui/src/pages/Model/components/ModelEvolution/index.tsx
  5. +1
    -1
      react-ui/src/pages/Model/components/ModelEvolution/utils.tsx
  6. +6
    -3
      react-ui/src/pages/Model/components/ModelMetrics/index.tsx
  7. +52
    -2
      react-ui/src/pages/Model/components/NodeTooltips/index.less
  8. +8
    -2
      react-ui/src/pages/Model/components/NodeTooltips/index.tsx
  9. +12
    -11
      react-ui/src/pages/ModelDeployment/CreateVersion/index.tsx
  10. +2
    -1
      react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx
  11. +42
    -11
      react-ui/src/utils/ui.tsx
  12. +4
    -3
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ServiceServiceImpl.java

+ 9
- 7
react-ui/src/pages/AutoML/components/CreateForm/TrialConfig.tsx View File

@@ -1,6 +1,6 @@
import SubAreaTitle from '@/components/SubAreaTitle'; import SubAreaTitle from '@/components/SubAreaTitle';
import { AutoMLTaskType } from '@/enums'; import { AutoMLTaskType } from '@/enums';
import { modalConfirm } from '@/utils/ui';
import { removeFormListItem } from '@/utils/ui';
import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons';
import { Button, Col, Flex, Form, Input, InputNumber, Radio, Row, Select } from 'antd'; import { Button, Col, Flex, Form, Input, InputNumber, Radio, Row, Select } from 'antd';
import { classificationMetrics, regressionMetrics } from './ExecuteConfig'; import { classificationMetrics, regressionMetrics } from './ExecuteConfig';
@@ -72,12 +72,14 @@ function TrialConfig() {
type="text" type="text"
icon={<MinusCircleOutlined />} icon={<MinusCircleOutlined />}
onClick={() => { onClick={() => {
modalConfirm({
title: '确定要删除该指标权重吗?',
onOk: () => {
remove(name);
},
});
removeFormListItem(
form,
'metrics',
name,
remove,
['name', 'value'],
'删除后,该该指标权重将不可恢复',
);
}} }}
></Button> ></Button>
{index === fields.length - 1 && ( {index === fields.length - 1 && (


+ 12
- 9
react-ui/src/pages/HyperParameter/components/CreateForm/ExecuteConfig.tsx View File

@@ -8,7 +8,7 @@ import SubAreaTitle from '@/components/SubAreaTitle';
import { hyperParameterOptimizedModeOptions } from '@/enums'; import { hyperParameterOptimizedModeOptions } from '@/enums';
import { useComputingResource } from '@/hooks/resource'; import { useComputingResource } from '@/hooks/resource';
import { isEmpty } from '@/utils'; import { isEmpty } from '@/utils';
import { modalConfirm } 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';
import { import {
Button, Button,
@@ -396,12 +396,14 @@ function ExecuteConfig() {
size="middle" size="middle"
icon={<MinusCircleOutlined />} icon={<MinusCircleOutlined />}
onClick={() => { onClick={() => {
modalConfirm({
title: '确定要删除该参数吗?',
onOk: () => {
remove(name);
},
});
removeFormListItem(
form,
'parameters',
name,
remove,
['name', 'type'],
'删除后,该参数将不可恢复',
);
}} }}
></Button> ></Button>
{index === fields.length - 1 && ( {index === fields.length - 1 && (
@@ -460,7 +462,7 @@ function ExecuteConfig() {
); );
if (arr.length > 0 && arr.length < runParameters.length) { if (arr.length > 0 && arr.length < runParameters.length) {
return Promise.reject( return Promise.reject(
new Error(`手动运行超参数 ${name} 必须全部填写或者都不填写`),
new Error(`手动运行超参数 "${name}" 必须全部填写或者都不填写`),
); );
} }
} }
@@ -518,7 +520,8 @@ function ExecuteConfig() {
icon={<MinusCircleOutlined />} icon={<MinusCircleOutlined />}
onClick={() => { onClick={() => {
modalConfirm({ modalConfirm({
title: '确定要删除该运行参数吗?',
title: '删除后,该运行参数将不可恢复',
content: '是否确认删除?',
onOk: () => { onOk: () => {
remove(name); remove(name);
}, },


+ 1
- 1
react-ui/src/pages/HyperParameter/components/CreateForm/ParameterRange/index.tsx View File

@@ -68,7 +68,7 @@ function ParameterRange({ type, value, onConfirm }: ParameterRangeProps) {
<Flex <Flex
style={{ style={{
marginLeft: '10px', marginLeft: '10px',
marginBottom: '20px',
marginBottom: '24px',
flex: 'none', flex: 'none',
width: '66px', width: '66px',
}} }}


+ 44
- 10
react-ui/src/pages/Model/components/ModelEvolution/index.tsx View File

@@ -45,11 +45,14 @@ function ModelEvolution({
const [enterTooltip, setEnterTooltip] = useState(false); const [enterTooltip, setEnterTooltip] = useState(false);
const [nodeTooltipX, setNodeToolTipX] = useState(0); const [nodeTooltipX, setNodeToolTipX] = useState(0);
const [nodeTooltipY, setNodeToolTipY] = useState(0); const [nodeTooltipY, setNodeToolTipY] = useState(0);
const [isNodeTooltipLeft, setIsNodeTooltipLeft] = useState(true);
const [hoverNodeData, setHoverNodeData] = useState< const [hoverNodeData, setHoverNodeData] = useState<
ModelDepsData | ProjectDependency | TrainDataset | undefined ModelDepsData | ProjectDependency | TrainDataset | undefined
>(undefined); >(undefined);
const apiData = useRef<ModelDepsData | undefined>(undefined); // 接口返回的树形结构 const apiData = useRef<ModelDepsData | undefined>(undefined); // 接口返回的树形结构
const hierarchyNodes = useRef<ModelDepsData[]>([]); // 层级迭代树形结构,得到的节点列表 const hierarchyNodes = useRef<ModelDepsData[]>([]); // 层级迭代树形结构,得到的节点列表
const leaveNodeTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
const leaveTooltipTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);


useEffect(() => { useEffect(() => {
initGraph(); initGraph();
@@ -134,6 +137,12 @@ function ModelEvolution({
// 绑定事件 // 绑定事件
const bindEvents = () => { const bindEvents = () => {
graph.on('node:mouseenter', (e: G6GraphEvent) => { graph.on('node:mouseenter', (e: G6GraphEvent) => {
// 清除延时关闭tooltip的定时器
if (leaveNodeTimeout.current) {
clearTimeout(leaveNodeTimeout.current);
leaveNodeTimeout.current = null;
}

const nodeItem = e.item; const nodeItem = e.item;
graph.setItemState(nodeItem, 'hover', true); graph.setItemState(nodeItem, 'hover', true);


@@ -141,26 +150,37 @@ function ModelEvolution({
const { x, y } = model; const { x, y } = model;
const point = graph.getCanvasByPoint(x!, y!); const point = graph.getCanvasByPoint(x!, y!);
const zoom = graph.getZoom(); const zoom = graph.getZoom();
// 更加缩放,调整 tooltip 位置
const offsetX = (nodeWidth * zoom) / 4;
const offsetY = (nodeHeight * zoom) / 4;
point.x += offsetX;


// 根据缩放,调整 tooltip 位置
// const offsetX = (nodeWidth * zoom) / 4;
const offsetY = (nodeHeight * zoom) / 2;
// 25 是 `.model-evolution` 的 `padding-left` 值
const tooltipX = point.x + 25 - 20;
// 20 是 `.model-evolution` 的 `padding-bottom` 值
const tooltipY = graphRef.current!.clientHeight - point.y + offsetY + 20 + 10;
setNodeToolTipY(tooltipY);

// 如果右边显示不下
const canvasWidth = graphRef.current!.clientWidth; const canvasWidth = graphRef.current!.clientWidth;
if (point.x + 300 > canvasWidth + 30) {
point.x = canvasWidth + 30 - 300;
// 300 是 NodeTool 的宽度,canvasWidth + 50 是 `.model-evolution` 的宽度
if (tooltipX + 300 > canvasWidth + 50) {
setIsNodeTooltipLeft(false);
setNodeToolTipX(canvasWidth + 50 - (point.x + 25) - 20);
} else {
setNodeToolTipX(tooltipX);
setIsNodeTooltipLeft(true);
} }


setHoverNodeData(model); setHoverNodeData(model);
setNodeToolTipX(point.x);
setNodeToolTipY(graphRef.current!.clientHeight - point.y + offsetY);
setShowNodeTooltip(true); setShowNodeTooltip(true);
}); });


graph.on('node:mouseleave', (e: G6GraphEvent) => { graph.on('node:mouseleave', (e: G6GraphEvent) => {
const nodeItem = e.item; const nodeItem = e.item;
graph.setItemState(nodeItem, 'hover', false); graph.setItemState(nodeItem, 'hover', false);
setShowNodeTooltip(false);
leaveNodeTimeout.current = setTimeout(() => {
setShowNodeTooltip(false);
}, 100);
}); });


graph.on('node:click', (e: G6GraphEvent) => { graph.on('node:click', (e: G6GraphEvent) => {
@@ -191,6 +211,12 @@ function ModelEvolution({
setShowNodeTooltip(false); setShowNodeTooltip(false);
setEnterTooltip(false); setEnterTooltip(false);
}); });

// 开始拖拽画布时触发
graph.on('DRAG_START', () => {
setShowNodeTooltip(false);
setEnterTooltip(false);
});
}; };


// toggle 展开 // toggle 展开
@@ -205,11 +231,18 @@ function ModelEvolution({
}; };


const handleTooltipsMouseEnter = () => { const handleTooltipsMouseEnter = () => {
// 清除延时关闭tooltip的定时器
if (leaveTooltipTimeout.current) {
clearTimeout(leaveTooltipTimeout.current);
leaveTooltipTimeout.current = null;
}
setEnterTooltip(true); setEnterTooltip(true);
}; };


const handleTooltipsMouseLeave = () => { const handleTooltipsMouseLeave = () => {
setEnterTooltip(false);
leaveTooltipTimeout.current = setTimeout(() => {
setEnterTooltip(false);
}, 100);
}; };


// 获取模型依赖 // 获取模型依赖
@@ -254,6 +287,7 @@ function ModelEvolution({
resourceId={resourceId} resourceId={resourceId}
x={nodeTooltipX} x={nodeTooltipX}
y={nodeTooltipY} y={nodeTooltipY}
isLeft={isNodeTooltipLeft}
data={hoverNodeData!} data={hoverNodeData!}
onVersionChange={onVersionChange} onVersionChange={onVersionChange}
onMouseEnter={handleTooltipsMouseEnter} onMouseEnter={handleTooltipsMouseEnter}


+ 1
- 1
react-ui/src/pages/Model/components/ModelEvolution/utils.tsx View File

@@ -33,7 +33,7 @@ export type Rect = {
}; };


export interface TrainDataset extends NodeConfig { export interface TrainDataset extends NodeConfig {
repo_id: number;
repo_id: string;
name: string; name: string;
version: string; version: string;
identifier: string; identifier: string;


+ 6
- 3
react-ui/src/pages/Model/components/ModelMetrics/index.tsx View File

@@ -150,11 +150,14 @@ function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsPr


// 表头 // 表头
const columns: TableProps<TableData>['columns'] = useMemo(() => { const columns: TableProps<TableData>['columns'] = useMemo(() => {
const first: TableData | undefined = tableData.find(
const firstMetrics: TableData | undefined = tableData.find(
(item) => item.metrics_names && item.metrics_names.length > 0, (item) => item.metrics_names && item.metrics_names.length > 0,
); );
const metricsNames = first?.metrics_names ?? [];
const paramsNames = first?.params_names ?? [];
const firstParams: TableData | undefined = tableData.find(
(item) => item.params_names && item.params_names.length > 0,
);
const metricsNames = firstMetrics?.metrics_names ?? [];
const paramsNames = firstParams?.params_names ?? [];
return [ return [
{ {
title: '基本信息', title: '基本信息',


+ 52
- 2
react-ui/src/pages/Model/components/NodeTooltips/index.less View File

@@ -1,7 +1,5 @@
.node-tooltips { .node-tooltips {
position: absolute; position: absolute;
bottom: -100px;
left: -300px;
z-index: 10; z-index: 10;
width: 300px; width: 300px;
padding: 10px; padding: 10px;
@@ -10,6 +8,30 @@
border-radius: 4px; border-radius: 4px;
box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09); box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09);


&::after {
position: absolute;
bottom: -8px; /* 让三角形紧贴 div 底部 */
left: 12px; /* 控制三角形相对 div 的位置 */
width: 0;
height: 0;
border-top: 8px solid white; /* 主要颜色 */
border-right: 8px solid transparent;
border-left: 8px solid transparent;
content: '';
}

&::before {
position: absolute;
bottom: -10px; /* 边框略大,形成描边效果 */
left: 10px; /* 调整边框的偏移量,使其覆盖白色三角形 */
width: 0;
height: 0;
border-top: 10px solid #eaeaea; /* 这是边框颜色 */
border-right: 10px solid transparent;
border-left: 10px solid transparent;
content: '';
}

&__title { &__title {
margin: 10px 0; margin: 10px 0;
color: @text-color; color: @text-color;
@@ -59,3 +81,31 @@
} }
} }
} }

.node-tooltips.node-tooltips--right {
&::after {
position: absolute;
right: 12px; /* 控制三角形相对 div 的位置 */
bottom: -8px; /* 让三角形紧贴 div 底部 */
left: auto;
width: 0;
height: 0;
border-top: 8px solid white; /* 主要颜色 */
border-right: 8px solid transparent;
border-left: 8px solid transparent;
content: '';
}

&::before {
position: absolute;
right: 10px; /* 调整边框的偏移量,使其覆盖白色三角形 */
bottom: -10px; /* 边框略大,形成描边效果 */
left: auto;
width: 0;
height: 0;
border-top: 10px solid #eaeaea; /* 这是边框颜色 */
border-right: 10px solid transparent;
border-left: 10px solid transparent;
content: '';
}
}

+ 8
- 2
react-ui/src/pages/Model/components/NodeTooltips/index.tsx View File

@@ -2,6 +2,7 @@ import { ResourceInfoTabKeys } from '@/pages/Dataset/components/ResourceInfo';
import { getGitUrl } from '@/utils'; import { getGitUrl } from '@/utils';
import { formatDate } from '@/utils/date'; import { formatDate } from '@/utils/date';
import { useNavigate } from '@umijs/max'; import { useNavigate } from '@umijs/max';
import classNames from 'classnames';
import { ModelDepsData, NodeType, ProjectDependency, TrainDataset } from '../ModelEvolution/utils'; import { ModelDepsData, NodeType, ProjectDependency, TrainDataset } from '../ModelEvolution/utils';
import styles from './index.less'; import styles from './index.less';


@@ -180,6 +181,7 @@ type NodeTooltipsProps = {
data: ModelDepsData | ProjectDependency | TrainDataset; data: ModelDepsData | ProjectDependency | TrainDataset;
x: number; x: number;
y: number; y: number;
isLeft: boolean;
onMouseEnter?: () => void; onMouseEnter?: () => void;
onMouseLeave?: () => void; onMouseLeave?: () => void;
onVersionChange: (version: string) => void; onVersionChange: (version: string) => void;
@@ -190,6 +192,7 @@ function NodeTooltips({
data, data,
x, x,
y, y,
isLeft,
onMouseEnter, onMouseEnter,
onMouseLeave, onMouseLeave,
onVersionChange, onVersionChange,
@@ -208,10 +211,13 @@ function NodeTooltips({
) { ) {
Component = <ModelInfo resourceId={resourceId} data={data} onVersionChange={onVersionChange} />; Component = <ModelInfo resourceId={resourceId} data={data} onVersionChange={onVersionChange} />;
} }
const style = isLeft
? { left: `${x}px`, bottom: `${y}px` }
: { right: `${x}px`, bottom: `${y}px` };
return ( return (
<div <div
className={styles['node-tooltips']}
style={{ left: `${x}px`, bottom: `${y}px` }}
className={classNames(styles['node-tooltips'], { [styles['node-tooltips--right']]: !isLeft })}
style={style}
onMouseEnter={onMouseEnter} onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}
> >


+ 12
- 11
react-ui/src/pages/ModelDeployment/CreateVersion/index.tsx View File

@@ -20,7 +20,7 @@ import {
import { changePropertyName } from '@/utils'; import { changePropertyName } from '@/utils';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import SessionStorage from '@/utils/sessionStorage'; import SessionStorage from '@/utils/sessionStorage';
import { modalConfirm } 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, Select } from 'antd';
@@ -434,7 +434,6 @@ function CreateServiceVersion() {
{fields.map(({ key, name, ...restField }, index) => ( {fields.map(({ key, name, ...restField }, index) => (
<Flex <Flex
key={key} key={key}
align="center"
gap="0 8px" gap="0 8px"
style={{ style={{
position: 'relative', position: 'relative',
@@ -453,16 +452,16 @@ function CreateServiceVersion() {
}, },
]} ]}
> >
<Input placeholder="请输入变量名" disabled={disabled} />
<Input placeholder="请输入变量名" disabled={disabled} allowClear />
</Form.Item> </Form.Item>
<span style={{ marginBottom: '24px' }}>=</span>
<span style={{ lineHeight: '46px' }}>=</span>
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'value']} name={[name, 'value']}
style={{ flex: 1 }} style={{ flex: 1 }}
rules={[{ required: true, message: '请输入变量值' }]} rules={[{ required: true, message: '请输入变量值' }]}
> >
<Input placeholder="请输入变量值" disabled={disabled} />
<Input placeholder="请输入变量值" disabled={disabled} allowClear />
</Form.Item> </Form.Item>
<Flex <Flex
style={{ style={{
@@ -484,12 +483,14 @@ function CreateServiceVersion() {
icon={<MinusCircleOutlined />} icon={<MinusCircleOutlined />}
disabled={disabled} disabled={disabled}
onClick={() => { onClick={() => {
modalConfirm({
title: '确定要删除该环境变量吗?',
onOk: () => {
remove(name);
},
});
removeFormListItem(
form,
'env_variables',
name,
remove,
['key', 'value'],
'删除后,该环境变量将不可恢复',
);
}} }}
></Button> ></Button>
{index === fields.length - 1 && ( {index === fields.length - 1 && (


+ 2
- 1
react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx View File

@@ -40,7 +40,8 @@ const GlobalParamsDrawer = forwardRef(


const removeParameter = (name: number, remove: (param: number) => void) => { const removeParameter = (name: number, remove: (param: number) => void) => {
modalConfirm({ modalConfirm({
title: '确认删除该参数吗?',
title: '删除后,该全局参数将不可恢复',
content: '是否确认删除?',
onOk: () => { onOk: () => {
remove(name); remove(name);
}, },


+ 42
- 11
react-ui/src/utils/ui.tsx View File

@@ -8,7 +8,16 @@ import { removeAllPageCacheState } from '@/hooks/pageCacheState';
import themes from '@/styles/theme.less'; import themes from '@/styles/theme.less';
import { type ClientInfo } from '@/types'; import { type ClientInfo } from '@/types';
import { history } from '@umijs/max'; import { history } from '@umijs/max';
import { Modal, Upload, message, type ModalFuncProps, type UploadFile } from 'antd';
import {
Modal,
Upload,
message,
type FormInstance,
type ModalFuncProps,
type UploadFile,
} from 'antd';
import { NamePath } from 'antd/es/form/interface';
import { isEmpty } from './index';
import { closeAllModals } from './modal'; import { closeAllModals } from './modal';
import SessionStorage from './sessionStorage'; import SessionStorage from './sessionStorage';


@@ -143,16 +152,38 @@ export const limitUploadFileType = (type: string) => {
}; };


/** /**
* 滚动到底部
*
* @param {boolean} smooth - Determines if the scroll should be smooth
* 删除 FormList 表单项,如果表单项没有值,则直接删除,否则弹出确认框
* @param form From实例
* @param listName FormList 的 name
* @param name FormList 的其中一项
* @param remove FormList 的删除方法
* @param fieldNames FormList 的子项名称数组
* @param confirmTitle 弹出确认框的标题
*/ */
export const scrollToBottom = (element: HTMLElement | null, smooth: boolean = true) => {
if (element) {
const optons: ScrollToOptions = {
top: element.scrollHeight,
behavior: smooth ? 'smooth' : 'instant',
};
element.scrollTo(optons);
export const removeFormListItem = (
form: FormInstance,
listName: NamePath,
name: number,
remove: (name: number) => void,
fieldNames: NamePath[],
confirmTitle: string,
) => {
const fields = fieldNames.map((item) => [listName, name, item].flat());
const isEmptyField = fields.every((item) => {
const value = form.getFieldValue(item);
return isEmpty(value);
});

if (isEmptyField) {
remove(name);
return;
} }

modalConfirm({
title: confirmTitle,
content: '是否确认删除?',
onOk: () => {
remove(name);
},
});
}; };

+ 4
- 3
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ServiceServiceImpl.java View File

@@ -44,6 +44,7 @@ public class ServiceServiceImpl implements ServiceService {
private ServiceDao serviceDao; private ServiceDao serviceDao;
@Resource @Resource
private AssetWorkflowDao assetWorkflowDao; private AssetWorkflowDao assetWorkflowDao;

@Override @Override
public Page<com.ruoyi.platform.domain.Service> queryByPageService(com.ruoyi.platform.domain.Service service, PageRequest pageRequest) { public Page<com.ruoyi.platform.domain.Service> queryByPageService(com.ruoyi.platform.domain.Service service, PageRequest pageRequest) {
long total = serviceDao.countService(service); long total = serviceDao.countService(service);
@@ -225,9 +226,9 @@ public class ServiceServiceImpl implements ServiceService {
String req = HttpUtils.sendPost(argoUrl + modelService + "/delete", JSON.toJSONString(paramMap)); String req = HttpUtils.sendPost(argoUrl + modelService + "/delete", 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) {
return serviceDao.updateServiceVersion(serviceVersion) > 0 ? "删除成功" : "删除失败";
}
// if ((Integer) reqMap.get("code") == 200) {
return serviceDao.updateServiceVersion(serviceVersion) > 0 ? "删除成功" : "删除失败";
// }
} }
return "删除失败"; return "删除失败";
} }


Loading…
Cancel
Save