Commit ad209280 authored by chenshouchao's avatar chenshouchao

feat: 工作流模板完成

parent b6651d99
...@@ -59,6 +59,7 @@ const RESTAPI = { ...@@ -59,6 +59,7 @@ const RESTAPI = {
API_SAVE_OPERATOR:`${BACKEND_API_URI_PREFIX}/cpp/workflow/custom/actor`, // 保存自定义批流算子 API_SAVE_OPERATOR:`${BACKEND_API_URI_PREFIX}/cpp/workflow/custom/actor`, // 保存自定义批流算子
API_WORKFLOWSPEC_LIST:`${BACKEND_API_URI_PREFIX}/cpp/workbench/product/workflowspec/list`, // 模板列表 所有的 API_WORKFLOWSPEC_LIST:`${BACKEND_API_URI_PREFIX}/cpp/workbench/product/workflowspec/list`, // 模板列表 所有的
API_WORKFLOWSPEC_DELETE:`${BACKEND_API_URI_PREFIX}/cpp/workbench/workflowspec/delete`, // 删除模板 API_WORKFLOWSPEC_DELETE:`${BACKEND_API_URI_PREFIX}/cpp/workbench/workflowspec/delete`, // 删除模板
API_WORKFLOWSPEC_DETAIL:`${BACKEND_API_URI_PREFIX}/cpp/workbench/workflowspec`, // 删除模板
}; };
export default RESTAPI; export default RESTAPI;
...@@ -133,6 +133,14 @@ const deleteWorkflowspec = (params: { ...@@ -133,6 +133,14 @@ const deleteWorkflowspec = (params: {
}); });
}; };
// 获取工作流模板详情
const getWorkflowspecDetail = (id: string) => {
return request({
url: Api.API_WORKFLOWSPEC_DETAIL + '/' + id,
method: "get",
});
};
export { export {
getPublicEnv, getPublicEnv,
...@@ -145,5 +153,6 @@ export { ...@@ -145,5 +153,6 @@ export {
getActorEnvOptions, getActorEnvOptions,
getWorkflowspecList, getWorkflowspecList,
saveOperator, saveOperator,
deleteWorkflowspec deleteWorkflowspec,
getWorkflowspecDetail
}; };
.swBox {
position: fixed;
z-index: 1000;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: RGBA(247, 248, 250, 1);
overflow-y: overlay;
}
.swHeader {
z-index: 1001;
position: sticky;
top: 0;
height: 56px;
background-color: #fff;
box-shadow: 0px 3px 10px 0px rgba(0, 24, 57, 0.06);
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
.swHeaderLeft {
display: flex;
justify-content: flex-start;
align-items: center;
}
.goBackIcon {
cursor: pointer;
}
.goBackIconBox {
width: 32px;
height: 32px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
}
.goBackIconBox:hover {
background-color: rgb(240, 242, 245);
}
.swTemplateTitle {
margin: 0 19px 0 3px;
line-height: 20px;
font-size: 14px;
color: rgba(30, 38, 51, 1);
font-weight: 700;
}
.swContent {
display: flex;
height: calc(100vh - 56px);
}
.swFormBox {
background-color: #fff;
border-right: 1px solid #ebedf0;
width: 360px;
overflow-y: overlay;
box-sizing: border-box;
padding: 24px;
}
.swFlowBox {
flex: 1;
height: calc(100vh - 56px);
}
.title {
color: rgba(30, 38, 51, 1);
font-size: 16px;
line-height: 24px;
font-weight: 600;
margin-bottom: 16px;
}
.taskInfoLi {
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.taskInfoParams {
color: rgba(138, 144, 153, 1);
font-size: 14px;
line-height: 22px;
width: 80px;
margin-right: 44px;
word-wrap: break-word;
}
.taskInfoValue {
color: rgba(30, 38, 51, 1);
font-size: 14px;
line-height: 22px;
display: flex;
position: relative;
align-items: center;
text-align: left;
word-break: break-all;
flex: 1;
justify-content: flex-end;
word-wrap: break-word;
}
.taskInfoValueShowAll {
white-space: normal;
}
.taskInfoValueIcon {
margin-right: 9px;
}
.tabs {
display: flex;
justify-content: flex-start;
border-bottom: 1px solid rgba(240, 242, 245, 1);
}
.tabLi {
cursor: pointer;
font-size: 14px;
line-height: 22px;
padding-bottom: 8px;
color: rgba(138, 144, 153, 1);
margin-right: 32px;
position: relative;
}
.tabLiAcitve {
color: rgba(19, 112, 255, 1);
border-bottom: 2px solid rgba(19, 112, 255, 1);
}
.overview {
padding-top: 19px;
}
.params {
padding-top: 19px;
}
.options {
position: absolute;
top: 33px;
max-height: 230px;
overflow-y: overlay;
padding: 8px 0px;
background: #ffffff;
box-shadow: 0px 3px 10px 0px rgba(0, 24, 57, 0.14);
border-radius: 4px;
z-index: 1002;
}
import { useEffect, useState, useMemo } from "react";
import { observer } from "mobx-react-lite";
import classNames from "classnames";
import useMyRequest from "@/hooks/useMyRequest";
import { getWorkflowspecDetail } from "@/api/resourceCenter";
import { IResponse } from "@/api/http";
import goback from "@/assets/project/goback.svg";
import { ITaskInfo } from "@/views/Project/ProjectSubmitWork/interface";
import Flow from "@/views/Project/components/Flow";
import moment from "moment";
import MyTooltip from "@/components/mui/MyTooltip";
import { toJS } from "mobx";
import { useStores } from "@/store";
import styles from "./index.module.css";
interface ITemplateDetailProps {
id: string;
setShowDetail: any;
}
const TemplateDetail = observer((props: ITemplateDetailProps) => {
const { id, setShowDetail } = props;
const [templateInfo, setTemplateInfo] = useState<any>({});
const [overviewActive, setOverviewActive] = useState(true);
/** 选中的node Id */
const [activeFlowIndex, setActiveFlowIndex] = useState<string>("");
const { productListStore } = useStores();
const getProductName = (productId: string) => {
let res = "-";
toJS(productListStore.productList).forEach((item) => {
if (item.value === productId) {
res = item.label;
}
});
return res;
};
const taskInfo = useMemo(() => {
if (activeFlowIndex) {
return templateInfo.tasks.filter(
(task: any) => task.id === activeFlowIndex
)[0];
} else {
return {};
}
}, [templateInfo, activeFlowIndex]);
const randerParameters = useMemo(() => {
return taskInfo.parameters;
}, [taskInfo]);
/** 获取模版数据 */
const { run } = useMyRequest(getWorkflowspecDetail, {
onSuccess: (res: IResponse<ITaskInfo>) => {
console.log(res);
setTemplateInfo(res.data);
},
});
useEffect(() => {
run(id);
}, [id, run]);
/** 返回事件 */
const onBack = () => {
setShowDetail(false);
};
const setExternalSelectedNodeId = (id: string) => {
setActiveFlowIndex(id);
};
const handleParams = () => {
setOverviewActive(false);
};
return (
<div className={styles.swBox}>
<div className={styles.swHeader}>
<div className={styles.swHeaderLeft}>
<div className={styles.goBackIconBox}>
<img
onClick={onBack}
className={styles.goBackIcon}
src={goback}
alt=""
/>
</div>
<div className={styles.swTemplateTitle}>{templateInfo.title}</div>
</div>
</div>
<div className={styles.swContent}>
<div className={styles.swFormBox}>
{!activeFlowIndex && (
<div>
<div className={styles.title}>基础信息</div>
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>模板名称</div>
<div className={styles.taskInfoValue}>{templateInfo.title}</div>
</div>
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>描述</div>
<div className={styles.taskInfoValue}>
{templateInfo.description}
</div>
</div>
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>创建时间</div>
<div className={styles.taskInfoValue}>
{moment(new Date(templateInfo.createdAt)).format(
"yyyy-MM-DD hh:mm"
)}
</div>
</div>
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>创建人</div>
<div className={styles.taskInfoValue}>
{templateInfo.creator}
</div>
</div>
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>版本</div>
<div className={styles.taskInfoValue}>
{templateInfo.version}
</div>
</div>
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>所属产品</div>
<div className={styles.taskInfoValue}>
{getProductName(templateInfo.productId)}
</div>
</div>
</div>
)}
{activeFlowIndex && (
<div className={styles.suanziInfo}>
<MyTooltip>
<div className={styles.title}>{taskInfo?.title}</div>
</MyTooltip>
<div className={styles.tabs}>
<div
className={classNames({
[styles.tabLi]: true,
[styles.tabLiAcitve]: overviewActive,
})}
onClick={() => setOverviewActive(true)}
>
概览
</div>
<div
className={classNames({
[styles.tabLi]: true,
[styles.tabLiAcitve]: !overviewActive,
})}
onClick={() => handleParams()}
>
参数
</div>
</div>
{overviewActive && (
<div className={styles.overview}>
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>描述</div>
<div
className={classNames({
[styles.taskInfoValue]: true,
[styles.taskInfoValueShowAll]: true,
})}
>
{taskInfo?.description}
</div>
</div>
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>算子版本</div>
<div className={styles.taskInfoValue}>
{taskInfo?.version || "-"}
</div>
</div>
</div>
)}
{!overviewActive && (
<div className={styles.params}>
{randerParameters?.map((parameter: any) => {
return (
<div className={styles.taskInfoLi} key={parameter.name}>
<div className={styles.taskInfoParams}>
{parameter.name}
</div>
<div className={styles.taskInfoValue}>
{parameter.defaultValue || "-"}
</div>
</div>
);
})}
</div>
)}
</div>
)}
</div>
<div className={styles.swFlowBox}>
<Flow
externalSelectedNodeId={activeFlowIndex}
tasks={templateInfo?.tasks}
setExternalSelectedNodeId={setExternalSelectedNodeId}
/>
</div>
</div>
</div>
);
});
export default TemplateDetail;
...@@ -14,14 +14,16 @@ import { toJS } from "mobx"; ...@@ -14,14 +14,16 @@ import { toJS } from "mobx";
import ProductSelect from "@/components/BusinessComponents/ProductSelect"; import ProductSelect from "@/components/BusinessComponents/ProductSelect";
import WorkFlowEdit from "@/views/WorkFlowEdit"; import WorkFlowEdit from "@/views/WorkFlowEdit";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import TemplateDetail from "./TemplateDetail";
import style from "./index.module.css"; import style from "./index.module.css";
const UserResourcesTemplate = observer(() => { const UserResourcesTemplate = observer(() => {
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
const Message = useMessage(); const Message = useMessage();
const [showAddTemplate, setShowAddTemplate] = useState(false); const [showAddTemplate, setShowAddTemplate] = useState(false); // 新增、编辑模板弹窗
const [showProductSelect, setShowProductSelect] = useState(false); const [showProductSelect, setShowProductSelect] = useState(false);
const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [showDeleteDialog, setShowDeleteDialog] = useState(false);
const [showDetail, setShowDetail] = useState(false); // 详情
const [templateId, setTemplateId] = useState(""); const [templateId, setTemplateId] = useState("");
const [product, setProduct] = useState(""); // 搜索列表用 const [product, setProduct] = useState(""); // 搜索列表用
const [productId, setProductId] = useState(""); // 新增模板用 const [productId, setProductId] = useState(""); // 新增模板用
...@@ -52,13 +54,19 @@ const UserResourcesTemplate = observer(() => { ...@@ -52,13 +54,19 @@ const UserResourcesTemplate = observer(() => {
<img src={templateIcon} alt="" /> <img src={templateIcon} alt="" />
<div className={style.templateTitle}>{item.title}</div> <div className={style.templateTitle}>{item.title}</div>
</div> </div>
<div className={style.templateDesc}> <div className={style.templateDesc}>{item.description}</div>
{item.description}
啊手动阀卡拉实际付款啦世界的分厘卡就是啊手动阀卡拉实际付款啦世界的分厘卡就是啊手动阀卡拉实际付款啦世界的分厘卡就是啊手动阀卡拉实际付款啦世界的分厘卡就是啊手动阀卡拉实际付款啦世界的分厘卡就是啊手动阀卡拉实际付款啦世界的分厘卡就是啊手动阀卡拉实际付款啦世界的分厘卡就是啊手动阀卡拉实际付款啦世界的分厘卡就是啊手动阀卡拉实际付款啦世界的分厘卡就是
</div>
<div className={style.templateButtons}> <div className={style.templateButtons}>
<div className={style.templateBL}> <div className={style.templateBL}>
<span className={style.button}>升级</span> <span
className={style.button}
onClick={() => {
setTemplateId(item.id);
setProductId(item.productId);
setShowAddTemplate(true);
}}
>
升级
</span>
</div> </div>
<div className={style.templateBR}> <div className={style.templateBR}>
<MyButton <MyButton
...@@ -74,7 +82,14 @@ const UserResourcesTemplate = observer(() => { ...@@ -74,7 +82,14 @@ const UserResourcesTemplate = observer(() => {
setTemplateId(item.id); setTemplateId(item.id);
}} }}
></MyButton> ></MyButton>
<MyButton text="查看" variant="outlined"></MyButton> <MyButton
text="查看"
variant="outlined"
onClick={() => {
setTemplateId(item.id);
setShowDetail(true);
}}
></MyButton>
</div> </div>
</div> </div>
</div> </div>
...@@ -89,11 +104,13 @@ const UserResourcesTemplate = observer(() => { ...@@ -89,11 +104,13 @@ const UserResourcesTemplate = observer(() => {
}); });
useEffect(() => { useEffect(() => {
run({ if (!showAddTemplate) {
productId: product === "all" ? "" : product, run({
title, productId: product === "all" ? "" : product,
}); title,
}, [run, title, product]); });
}
}, [run, title, product, showAddTemplate]);
const { run: deleteWorkflowspecFn } = useMyRequest(deleteWorkflowspec, { const { run: deleteWorkflowspecFn } = useMyRequest(deleteWorkflowspec, {
onSuccess: () => { onSuccess: () => {
...@@ -163,8 +180,8 @@ const UserResourcesTemplate = observer(() => { ...@@ -163,8 +180,8 @@ const UserResourcesTemplate = observer(() => {
productId={productId} productId={productId}
setProductId={setProductId} setProductId={setProductId}
onConfirm={() => { onConfirm={() => {
setShowAddTemplate(true);
setTemplateId(""); setTemplateId("");
setShowAddTemplate(true);
}} }}
></ProductSelect> ></ProductSelect>
)} )}
...@@ -179,6 +196,12 @@ const UserResourcesTemplate = observer(() => { ...@@ -179,6 +196,12 @@ const UserResourcesTemplate = observer(() => {
确定要删除这个模板吗? 确定要删除这个模板吗?
</MyDialog> </MyDialog>
)} )}
{showDetail && (
<TemplateDetail
id={templateId}
setShowDetail={setShowDetail}
></TemplateDetail>
)}
</div> </div>
); );
}); });
......
...@@ -190,25 +190,25 @@ const SaveCustomTemplate = (props: IProps) => { ...@@ -190,25 +190,25 @@ const SaveCustomTemplate = (props: IProps) => {
// 表单弹窗确定,新建/编辑自定义模板保存 // 表单弹窗确定,新建/编辑自定义模板保存
const handleOncofirm = () => { const handleOncofirm = () => {
if (checkTitle(title) && checkVersion(version)) { if (checkTitle(title) && checkVersion(version)) {
if (id) { // if (id) {
saveUserSpecRun({ // saveUserSpecRun({
title, // title,
version, // version,
description, // description,
tasks: templateConfigInfo, // tasks: templateConfigInfo,
productId, // productId,
id, // id,
creator, // creator,
}); // });
} else { // } else {
saveUserSpecRun({ saveUserSpecRun({
title, title,
version, version,
description, description,
tasks: templateConfigInfo, tasks: templateConfigInfo,
productId, productId,
}); });
} // }
} }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment