Commit 74d0c2b4 authored by chenshouchao's avatar chenshouchao

Merge branch 'feat-20221012-environment' into 'staging'

cn-Feat 20221012 environment

See merge request !155
parents e4258ebe ff63dd42
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 09:56:57 * @Date: 2022-06-13 09:56:57
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 13:41:26 * @LastEditTime: 2022-10-25 18:23:37
* @FilePath: /bkunyun/src/api/api_manager.ts * @FilePath: /bkunyun/src/api/api_manager.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -60,6 +60,7 @@ const RESTAPI = { ...@@ -60,6 +60,7 @@ const RESTAPI = {
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`, // 删除模板 API_WORKFLOWSPEC_DETAIL:`${BACKEND_API_URI_PREFIX}/cpp/workbench/workflowspec`, // 删除模板
API_OPERATOR_DETAILS:`${BACKEND_API_URI_PREFIX}/cpp/workflow/actorspec/detail`, // 获取算子详情
}; };
export default RESTAPI; export default RESTAPI;
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-19 17:09:23 * @Date: 2022-10-19 17:09:23
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 13:41:53 * @LastEditTime: 2022-10-25 20:26:42
* @FilePath: /bkunyun/src/api/resourceCenter.ts * @FilePath: /bkunyun/src/api/resourceCenter.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -15,7 +15,8 @@ type addActorenvBuildenvParams = { ...@@ -15,7 +15,8 @@ type addActorenvBuildenvParams = {
baseEnvId: string, baseEnvId: string,
type: "BATCH" | "FLOW", type: "BATCH" | "FLOW",
filePaths: Array<string>, filePaths: Array<string>,
bashScript: string, bashScript?: string,
script?: string,
computeType: string, computeType: string,
publicProjectId: string, publicProjectId: string,
} }
...@@ -59,6 +60,7 @@ const getActorenvList = (params: { ...@@ -59,6 +60,7 @@ const getActorenvList = (params: {
page: number, page: number,
size: number, size: number,
title?: string, title?: string,
order?: string,
}) => { }) => {
return request({ return request({
url: Api.API_ACTORENV_LIST, url: Api.API_ACTORENV_LIST,
...@@ -114,9 +116,9 @@ const getWorkflowspecList = (params: {productId?: string, title?: string}) => { ...@@ -114,9 +116,9 @@ const getWorkflowspecList = (params: {productId?: string, title?: string}) => {
// API_WORKFLOWSPEC_LIST // API_WORKFLOWSPEC_LIST
// 新增应用环境 // 新增应用环境
const saveOperator = (params: any) => { const saveOperator = (params: any, isEdit: boolean) => {
return request({ return request({
url: Api.API_SAVE_OPERATOR, url: `${Api.API_SAVE_OPERATOR}?isEdit=${isEdit}`,
method: "post", method: "post",
data: params, data: params,
}); });
...@@ -133,6 +135,16 @@ const deleteWorkflowspec = (params: { ...@@ -133,6 +135,16 @@ const deleteWorkflowspec = (params: {
}); });
}; };
// 查询算子的详情信息
const getOperatorDetail = (id: string) => {
return request({
url:`${Api.API_OPERATOR_DETAILS}/${id}`,
method: "get",
});
};
// 获取工作流模板详情 // 获取工作流模板详情
const getWorkflowspecDetail = (id: string) => { const getWorkflowspecDetail = (id: string) => {
return request({ return request({
...@@ -154,5 +166,6 @@ export { ...@@ -154,5 +166,6 @@ export {
getWorkflowspecList, getWorkflowspecList,
saveOperator, saveOperator,
deleteWorkflowspec, deleteWorkflowspec,
getWorkflowspecDetail getWorkflowspecDetail,
getOperatorDetail
}; };
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 89备份</title>
<g id="新" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="个人资源-工作流算子" transform="translate(-982.000000, -323.000000)">
<g id="编组-6备份" transform="translate(641.000000, 298.000000)">
<g id="编组-89备份" transform="translate(349.000000, 33.000000) rotate(-270.000000) translate(-349.000000, -33.000000) translate(341.000000, 25.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-88" transform="translate(2.250000, 6.750000)" fill="#8A9099">
<circle id="椭圆形" cx="1.25" cy="1.25" r="1.25"></circle>
<circle id="椭圆形备份-15" cx="5.75" cy="1.25" r="1.25"></circle>
<circle id="椭圆形备份-16" cx="10.25" cy="1.25" r="1.25"></circle>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
...@@ -2,15 +2,17 @@ ...@@ -2,15 +2,17 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-20 19:45:32 * @Date: 2022-10-20 19:45:32
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-21 10:19:46 * @LastEditTime: 2022-10-25 21:16:13
* @FilePath: /bkunyun/src/components/CommonComponents/Code/index.tsx * @FilePath: /bkunyun/src/components/CommonComponents/Code/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import CodeMirror, { ReactCodeMirrorProps } from "@uiw/react-codemirror"; import CodeMirror, { ReactCodeMirrorProps } from "@uiw/react-codemirror";
import { memo } from "react";
import { isEqual } from "lodash";
// import { javascript } from "@codemirror/lang-javascript"; // import { javascript } from "@codemirror/lang-javascript";
interface ICodeType extends ReactCodeMirrorProps { interface ICodeType extends ReactCodeMirrorProps {
value: string; value?: string;
onChange: any; onChange: any;
height?: string; height?: string;
width?: string; width?: string;
...@@ -19,6 +21,7 @@ interface ICodeType extends ReactCodeMirrorProps { ...@@ -19,6 +21,7 @@ interface ICodeType extends ReactCodeMirrorProps {
} }
const Code = (props: ICodeType) => { const Code = (props: ICodeType) => {
console.log("----");
const { value, onChange, height, theme = "dark", width, maxWidth } = props; const { value, onChange, height, theme = "dark", width, maxWidth } = props;
return ( return (
<CodeMirror <CodeMirror
...@@ -32,4 +35,12 @@ const Code = (props: ICodeType) => { ...@@ -32,4 +35,12 @@ const Code = (props: ICodeType) => {
/> />
); );
}; };
// const handleEqual = (prvProps: ICodeType, nextProps: ICodeType) => {
// if (isEqual(prvProps, nextProps)) {
// return true;
// }
// return true;
// };
export default Code; export default Code;
...@@ -76,14 +76,14 @@ export default function MyBorderlessSelect(props: IProps) { ...@@ -76,14 +76,14 @@ export default function MyBorderlessSelect(props: IProps) {
background: "rgba(247, 248, 250, 1)", background: "rgba(247, 248, 250, 1)",
cursor: "not-allowed", cursor: "not-allowed",
"& .MuiOutlinedInput-notchedOutline": { "& .MuiOutlinedInput-notchedOutline": {
borderWidth: '0px' borderWidth: "0px",
}, },
}, },
}, },
input: { input: {
fontSize: "14px", fontSize: "14px",
"&.Mui-focused":{ "&.Mui-focused": {
color:"#1370FF", color: "#1370FF",
}, },
"&.Mui-disabled": { "&.Mui-disabled": {
background: "rgba(247, 248, 250, 1)", background: "rgba(247, 248, 250, 1)",
...@@ -127,7 +127,7 @@ export default function MyBorderlessSelect(props: IProps) { ...@@ -127,7 +127,7 @@ export default function MyBorderlessSelect(props: IProps) {
root: { root: {
"&.Mui-focused .MuiOutlinedInput-notchedOutline": { "&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderWidth: "0px", borderWidth: "0px",
color: '#1370FF' color: "#1370FF",
}, },
"& .MuiOutlinedInput-notchedOutline": { "& .MuiOutlinedInput-notchedOutline": {
borderColor: "#DDE1E6", borderColor: "#DDE1E6",
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13 * @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 20:23:02 * @LastEditTime: 2022-10-25 21:27:26
* @FilePath: /bkunyun/src/router/index.ts * @FilePath: /bkunyun/src/router/index.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
import { AnyMap } from "immer/dist/internal"; import { AnyMap } from "immer/dist/internal";
...@@ -56,7 +56,7 @@ export const elements: { ...@@ -56,7 +56,7 @@ export const elements: {
Demo: Demo, Demo: Demo,
UserResources: UserResources, UserResources: UserResources,
SeeEnv: SeeEnv, SeeEnv: SeeEnv,
OperatorDetails: OperatorDetails, SeeFloe: OperatorDetails,
ProjectSetting: ProjectSetting, ProjectSetting: ProjectSetting,
ProjectData: ProjectData, ProjectData: ProjectData,
ProjectWorkbench: ProjectWorkbench, ProjectWorkbench: ProjectWorkbench,
......
...@@ -30,11 +30,11 @@ const OperatorList = (props: IProps) => { ...@@ -30,11 +30,11 @@ const OperatorList = (props: IProps) => {
return 1; return 1;
} else { } else {
const countArr = operatorList.map((operatorLi) => { const countArr = operatorList.map((operatorLi) => {
const _index = operatorLi.id.indexOf("_"); const _index = operatorLi.id?.indexOf("_");
if (_index === -1) { if (_index === -1) {
return 1; return 1;
} else { } else {
return Number(operatorLi.id.slice(_index + 1)); return Number(operatorLi.id?.slice(_index + 1));
} }
}); });
const maxCount = Math.max(...countArr); const maxCount = Math.max(...countArr);
......
...@@ -203,7 +203,7 @@ const SaveOperator = (props: IProps) => { ...@@ -203,7 +203,7 @@ const SaveOperator = (props: IProps) => {
style={{ style={{
position: "absolute", position: "absolute",
fontSize: "14px", fontSize: "14px",
bottom: "7px", top: "96px",
right: "12px", right: "12px",
color: description.length >= 300 ? "#d32f2f" : "#C2C6CC", color: description.length >= 300 ? "#d32f2f" : "#C2C6CC",
}} }}
......
...@@ -8,7 +8,7 @@ import { ITask } from "../Project/ProjectSubmitWork/interface"; ...@@ -8,7 +8,7 @@ import { ITask } from "../Project/ProjectSubmitWork/interface";
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-24 18:08:47 * @Date: 2022-10-24 18:08:47
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 18:31:12 * @LastEditTime: 2022-10-25 18:16:34
* @FilePath: /bkunyun/src/views/CustomOperator/useCheckOperator.tsx * @FilePath: /bkunyun/src/views/CustomOperator/useCheckOperator.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -18,7 +18,7 @@ const useCheckOperator = ( ...@@ -18,7 +18,7 @@ const useCheckOperator = (
nullText?: string nullText?: string
) => { ) => {
const Message = useMessage(); const Message = useMessage();
const [checkStatus, setCheckStatus] = useState<boolean>(false); let checkStatus = false;
// 判断 每个起始算子(可以有多个起始点)的输入必须为文件的路径输入或数据集的路径输入。 // 判断 每个起始算子(可以有多个起始点)的输入必须为文件的路径输入或数据集的路径输入。
const checkIn = (targetArr: string[]) => { const checkIn = (targetArr: string[]) => {
...@@ -105,6 +105,7 @@ const useCheckOperator = ( ...@@ -105,6 +105,7 @@ const useCheckOperator = (
const handleCheck = () => { const handleCheck = () => {
if (operatorList.length === 0) { if (operatorList.length === 0) {
Message.error(nullText || "内容不能为空!"); Message.error(nullText || "内容不能为空!");
checkStatus = false;
return; return;
} }
let sourceArr: string[] = []; let sourceArr: string[] = [];
...@@ -116,20 +117,23 @@ const useCheckOperator = ( ...@@ -116,20 +117,23 @@ const useCheckOperator = (
}); });
}); });
if (!checkHasOneLine([...sourceArr], [...targetArr])) { if (!checkHasOneLine([...sourceArr], [...targetArr])) {
checkStatus = false;
Message.error("部分算子没有流程线,请检查流程!"); Message.error("部分算子没有流程线,请检查流程!");
return; return;
} }
if (!checkIn([...targetArr])) { if (!checkIn([...targetArr])) {
checkStatus = false;
Message.error("每个流程第一步需读取文件/数据集,请检查流程!"); Message.error("每个流程第一步需读取文件/数据集,请检查流程!");
return; return;
} }
if (!checkOut([...sourceArr])) { if (!checkOut([...sourceArr])) {
checkStatus = false;
Message.error( Message.error(
"每个流程最后一步必须将数据写入为文件/数据集,请检查流程!" "每个流程最后一步必须将数据写入为文件/数据集,请检查流程!"
); );
return; return;
} }
setCheckStatus(true); checkStatus = true;
successCallBack(); successCallBack();
}; };
......
...@@ -358,7 +358,7 @@ const BaseInfo = observer(() => { ...@@ -358,7 +358,7 @@ const BaseInfo = observer(() => {
style={{ style={{
fontSize: "14px", fontSize: "14px",
position: "absolute", position: "absolute",
bottom: "7px", top: "96px",
right: "12px", right: "12px",
color: projectInfo.desc.length >= 100 ? "#d32f2f" : "#C2C6CC", color: projectInfo.desc.length >= 100 ? "#d32f2f" : "#C2C6CC",
}} }}
......
...@@ -224,7 +224,7 @@ const AddProject = observer((props: IAddProjectProps) => { ...@@ -224,7 +224,7 @@ const AddProject = observer((props: IAddProjectProps) => {
style={{ style={{
position: "absolute", position: "absolute",
fontSize: "14px", fontSize: "14px",
bottom: "7px", top: "96px",
right: "12px", right: "12px",
color: desc.length >= 300 ? "#d32f2f" : "#C2C6CC", color: desc.length >= 300 ? "#d32f2f" : "#C2C6CC",
}} }}
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
.content { .content {
display: flex; display: flex;
border-radius: 4px; border-radius: 4px;
margin-bottom: 24px;
height: 580px; height: 580px;
} }
.form { .form {
...@@ -51,6 +50,22 @@ ...@@ -51,6 +50,22 @@
border-top-right-radius: 4px; border-top-right-radius: 4px;
border-bottom-right-radius: 4px; border-bottom-right-radius: 4px;
} }
.codeBox2 {
flex: 1;
display: flex;
flex-direction: column;
border-radius: 4px;
margin-top: 20px;
}
.codeBox2 .codeTitle {
border-top-right-radius: 4px;
border-top-left-radius: 4px;
}
.codeBox2 .code {
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
overflow: hidden;
}
.codeTitle { .codeTitle {
background-color: rgba(230, 233, 237, 1); background-color: rgba(230, 233, 237, 1);
padding: 11px 20px; padding: 11px 20px;
...@@ -143,3 +158,6 @@ ...@@ -143,3 +158,6 @@
line-height: 20px; line-height: 20px;
margin-top: 12px; margin-top: 12px;
} }
.button {
margin-top: 24px;
}
...@@ -48,6 +48,7 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -48,6 +48,7 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
const [envList, setEnvList] = useState<Array<any>>([]); // 基础环境列表 和taskType环境类型有关 const [envList, setEnvList] = useState<Array<any>>([]); // 基础环境列表 和taskType环境类型有关
const [progress, setProgress] = useState("0%"); // 上传压缩包进度 const [progress, setProgress] = useState("0%"); // 上传压缩包进度
const [code, setCode] = useState(""); // 脚本内容 const [code, setCode] = useState(""); // 脚本内容
const [flowCode, setFlowCode] = useState(""); // 脚本内容
const [codeWidth, setCodeWidth] = useState(0); const [codeWidth, setCodeWidth] = useState(0);
const [upload, setUpload] = useState<any>(() => {}); // 上传压缩包实例 用于暂停(取消上传)upload.abort(true); const [upload, setUpload] = useState<any>(() => {}); // 上传压缩包实例 用于暂停(取消上传)upload.abort(true);
const [nameHelper, setNameHelper] = useState({ const [nameHelper, setNameHelper] = useState({
...@@ -270,6 +271,7 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -270,6 +271,7 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
}; };
const handleSubmit = () => { const handleSubmit = () => {
if (taskType === "BATCH") {
if ( if (
!checkName(name) && !checkName(name) &&
!checkDesc(desc) && !checkDesc(desc) &&
...@@ -290,6 +292,29 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -290,6 +292,29 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
} else { } else {
Message.error("请完善环境信息"); Message.error("请完善环境信息");
} }
} else {
if (
!checkName(name) &&
!checkDesc(desc) &&
!checkFile(filePaths) &&
baseEnvId &&
flowCode
) {
addActorenvBuildenvFn({
title: name,
desc,
baseEnvId,
type: taskType,
filePaths,
bashScript: Base64.encode(code),
script: Base64.encode(flowCode),
publicProjectId,
computeType,
});
} else {
Message.error("请完善环境信息");
}
}
}; };
const handleAbort = () => { const handleAbort = () => {
...@@ -358,7 +383,7 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -358,7 +383,7 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
style={{ style={{
position: "absolute", position: "absolute",
fontSize: "14px", fontSize: "14px",
bottom: "7px", top: "96px",
right: "12px", right: "12px",
color: desc.length >= 300 ? "#d32f2f" : "#C2C6CC", color: desc.length >= 300 ? "#d32f2f" : "#C2C6CC",
}} }}
...@@ -462,7 +487,10 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -462,7 +487,10 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
</div> </div>
<div className={style.codeBox}> <div className={style.codeBox}>
<div className={style.codeTitle}> <div className={style.codeTitle}>
{taskType === "BATCH" ? "Shell脚本" : "Python脚本"} Shell脚本
{taskType === "BATCH" && (
<span className={style.required}>*</span>
)}
</div> </div>
<div className={style.code} id="addEnvironmentCode"> <div className={style.code} id="addEnvironmentCode">
<Code <Code
...@@ -474,6 +502,22 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -474,6 +502,22 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
</div> </div>
</div> </div>
</div> </div>
{taskType === "FLOW" && (
<div className={style.codeBox2}>
<div className={style.codeTitle}>
Python脚本
<span className={style.required}>*</span>
</div>
<div className={style.code} id="addEnvironmentCode">
<Code
value={flowCode}
onChange={(e: string) => setFlowCode(e)}
height="535px"
width={`${codeWidth + 368}px`}
/>
</div>
</div>
)}
<div className={style.button}> <div className={style.button}>
<MyButton <MyButton
text="开始构建" text="开始构建"
......
...@@ -144,7 +144,11 @@ const SeeEnv = () => { ...@@ -144,7 +144,11 @@ const SeeEnv = () => {
className={style.goBackIcon} className={style.goBackIcon}
src={goback} src={goback}
alt="" alt=""
onClick={() => navigate("/utility/resourceCenter/userResources")} onClick={() =>
navigate("/utility/resourceCenter/userResources", {
state: { defaultTab: "USERRESOURCES_ENVIRONMENT" },
})
}
/> />
<div className={style.title}>{info.title}</div> <div className={style.title}>{info.title}</div>
<div className={style.type}> <div className={style.type}>
......
...@@ -5,7 +5,7 @@ import style from "./index.module.css"; ...@@ -5,7 +5,7 @@ import style from "./index.module.css";
import SearchInput from "@/components/BusinessComponents/SearchInput"; import SearchInput from "@/components/BusinessComponents/SearchInput";
import MySelect from "@/components/mui/MySelect"; import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton"; import MyButton from "@/components/mui/MyButton";
import MyTable from "@/components/mui/MyTableNew"; import MyTable, { sortState } from "@/components/mui/MyTableNew";
import useMyRequest from "@/hooks/useMyRequest"; import useMyRequest from "@/hooks/useMyRequest";
import { getActorenvList } from "@/api/resourceCenter"; import { getActorenvList } from "@/api/resourceCenter";
import Add from "@mui/icons-material/Add"; import Add from "@mui/icons-material/Add";
...@@ -28,6 +28,10 @@ const UserResourcesEnvironment = () => { ...@@ -28,6 +28,10 @@ const UserResourcesEnvironment = () => {
const [id, setId] = useState(""); const [id, setId] = useState("");
const [deleteOpen, setDeleteOpen] = useState(false); const [deleteOpen, setDeleteOpen] = useState(false);
const [totalElements, setTotalElements] = useState(0); const [totalElements, setTotalElements] = useState(0);
const [sortState, setSortState] = useState<sortState>({
field: "createdTime",
order: "DESC",
});
const headCells: Array<any> = [ const headCells: Array<any> = [
{ {
id: "title", id: "title",
...@@ -42,6 +46,7 @@ const UserResourcesEnvironment = () => { ...@@ -42,6 +46,7 @@ const UserResourcesEnvironment = () => {
id: "createdTime", id: "createdTime",
label: "创建时间", label: "创建时间",
width: 180, width: 180,
sort: true,
}, },
{ {
id: "status", id: "status",
...@@ -73,9 +78,10 @@ const UserResourcesEnvironment = () => { ...@@ -73,9 +78,10 @@ const UserResourcesEnvironment = () => {
size, size,
title, title,
type: type === "ALL" ? "" : type, type: type === "ALL" ? "" : type,
order: sortState.order || "DESC",
}); });
} }
}, [getList, page, size, title, type, addOpen, deleteOpen]); }, [getList, page, size, title, type, addOpen, deleteOpen, sortState]);
const renderType = (item: any) => { const renderType = (item: any) => {
if (item.type === "BATCH") { if (item.type === "BATCH") {
...@@ -256,6 +262,8 @@ const UserResourcesEnvironment = () => { ...@@ -256,6 +262,8 @@ const UserResourcesEnvironment = () => {
paginationType="complex" paginationType="complex"
totalElements={totalElements} totalElements={totalElements}
loading={loading} loading={loading}
sortState={sortState}
setSortState={setSortState}
></MyTable> ></MyTable>
</div> </div>
{addOpen && <AddEnvironment setAddopen={setAddopen}></AddEnvironment>} {addOpen && <AddEnvironment setAddopen={setAddopen}></AddEnvironment>}
......
...@@ -16,6 +16,7 @@ import WorkFlowEdit from "@/views/WorkFlowEdit"; ...@@ -16,6 +16,7 @@ import WorkFlowEdit from "@/views/WorkFlowEdit";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import TemplateDetail from "./TemplateDetail"; import TemplateDetail from "./TemplateDetail";
import style from "./index.module.css"; import style from "./index.module.css";
import NoData from "@/components/BusinessComponents/NoData";
const UserResourcesTemplate = observer(() => { const UserResourcesTemplate = observer(() => {
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
...@@ -162,6 +163,7 @@ const UserResourcesTemplate = observer(() => { ...@@ -162,6 +163,7 @@ const UserResourcesTemplate = observer(() => {
</div> </div>
</div> </div>
<div className={style.tableBox}> <div className={style.tableBox}>
{list.length === 0 && <NoData text="暂无相关模板"></NoData>}
<CardTable <CardTable
data={list} data={list}
renderItem={renderItem} renderItem={renderItem}
......
...@@ -94,3 +94,12 @@ ...@@ -94,3 +94,12 @@
.descBox { .descBox {
padding-left: 32px; padding-left: 32px;
} }
.codeErrorBox {
padding-left: 20px;
height: 32px;
line-height: 32px;
width: calc(100% - 20px);
color: #ff4e4e;
background-color: #ffe8e8;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-18 16:12:55 * @Date: 2022-10-18 16:12:55
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 20:39:26 * @LastEditTime: 2022-10-26 13:57:17
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/index.tsx * @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -25,9 +25,19 @@ import OperatorList from "@/views/CustomOperator/components/OperatorList"; ...@@ -25,9 +25,19 @@ import OperatorList from "@/views/CustomOperator/components/OperatorList";
import FormItemBox from "@/components/mui/FormItemBox"; import FormItemBox from "@/components/mui/FormItemBox";
import { useStores } from "@/store"; import { useStores } from "@/store";
import useMyRequest from "@/hooks/useMyRequest"; import useMyRequest from "@/hooks/useMyRequest";
import { getActorEnvOptions, saveOperator } from "@/api/resourceCenter"; import {
getActorEnvOptions,
getOperatorDetail,
saveOperator,
} from "@/api/resourceCenter";
import { IOperatorAddFormData } from "../../interface"; import { IOperatorAddFormData } from "../../interface";
import { checkFormData, checkParamsConfig, initCode, text } from "./utils"; import {
checkFormData,
checkParamsConfig,
editDefaultVersion,
initCode,
text,
} from "./utils";
import batchOperator from "@/assets/resourceCenter/batchOperator.svg"; import batchOperator from "@/assets/resourceCenter/batchOperator.svg";
import flowOperator from "@/assets/resourceCenter/flowOperator.svg"; import flowOperator from "@/assets/resourceCenter/flowOperator.svg";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
...@@ -39,12 +49,13 @@ interface IAddOperator { ...@@ -39,12 +49,13 @@ interface IAddOperator {
pageType: string; pageType: string;
setPageType: (val: string) => void; setPageType: (val: string) => void;
detailsId: string; detailsId: string;
getList: () => void;
} }
type IBuildType = "ENVIRONMENT" | "OPERATOR"; type IBuildType = "ENVIRONMENT" | "OPERATOR";
const AddOperator = observer((props: IAddOperator) => { const AddOperator = observer((props: IAddOperator) => {
const { pageType, setPageType, detailsId } = props; const { pageType, setPageType, detailsId, getList } = props;
const Message = useMessage(); const Message = useMessage();
/** 创建类型 BATCH - 批算子; FLOW - 流算子*/ /** 创建类型 BATCH - 批算子; FLOW - 流算子*/
...@@ -66,15 +77,23 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -66,15 +77,23 @@ const AddOperator = observer((props: IAddOperator) => {
const [actorEnvOptions, setActorEnvOptions] = useState([]); const [actorEnvOptions, setActorEnvOptions] = useState([]);
/** 参数配置 */ /** 参数配置 */
const [code, setCode] = useState(JSON.stringify(initCode, null, "\t")); const [code, setCode] = useState(JSON.stringify(initCode, null, "\t"));
/** 参数配置 错误提示 */
const [parametersError, setParametersError] = useState<string>("");
/** 运行脚本 */ /** 运行脚本 */
const [command, setCommand] = useState<string>(""); const [command, setCommand] = useState<string>("");
/** 表单数据 */ /** 表单数据 */
const [formData, setFormData] = useState<IOperatorAddFormData>({}); const [formData, setFormData] = useState<IOperatorAddFormData>({
version: "1.0.0",
productId: defaultProduct,
});
/** 表单数据修改 */ /** 表单数据修改 */
const [formErrors, setFormErrors] = useState<IOperatorAddFormData>({}); const [formErrors, setFormErrors] = useState<IOperatorAddFormData>({});
/** 是否打开帮助手册 */ /** 是否打开帮助手册 */
const [tipsOpen, setTipsOpen] = useState<boolean>(false); const [tipsOpen, setTipsOpen] = useState<boolean>(false);
/** 详情数据 */
const [detailInfo, setDetailInfo] = useState<any>();
const { handleCheck, checkStatus } = useCheckOperator( const { handleCheck, checkStatus } = useCheckOperator(
operatorList, operatorList,
...@@ -97,22 +116,81 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -97,22 +116,81 @@ const AddOperator = observer((props: IAddOperator) => {
[formData] [formData]
); );
/** 获取算子详情 */
const { run: fetchOperatorDetail } = useMyRequest(getOperatorDetail, {
onSuccess: (res: any) => {
if (res.message === "success") {
const {
title = "",
type = "BATCH",
version = "",
productId = "",
description = "",
envId = "",
command: newCommand,
} = res.data;
const newVersion = editDefaultVersion(version);
/** 设置表单数据 */
setFormData({
title,
type,
version: newVersion,
productId,
description,
envId,
});
setCommand(Base64.decode(newCommand || ""));
/** 有envId 就是基于应用环境创建的 */
if (type === "BATCH") {
setBatchBuildType(envId ? "ENVIRONMENT" : "OPERATOR");
}
/** 有envId 就是基于应用环境创建的 */
setTaskType(type || "BATCH");
/** 设置参数配置 */
if (type === "BATCH" && !envId) {
setOperatorList(res?.data?.parameters || []);
} else {
setCode(JSON.stringify(res?.data?.parameters, null, "\t"));
}
/** 设置详情信息 */
setDetailInfo(res.data);
}
},
});
/** 保存修改算子 */
const { run: runSaveOperator } = useMyRequest(saveOperator, {
onSuccess: (res: any) => {
if (res?.message === "success") {
Message.success("构建成功");
setPageType("");
getList();
}
},
});
useEffect(() => {
if (!detailsId) return;
fetchOperatorDetail(detailsId);
}, [detailsId, fetchOperatorDetail]);
const paramsConfigBlur = useCallback(() => { const paramsConfigBlur = useCallback(() => {
console.log(2); let result, resultError;
if (code === "") return; console.log(batchBuildType, "batchBuildType");
let result; if (batchBuildType === "OPERATOR") return;
if (code === "") {
resultError = "请输入参数配置!";
}
try { try {
result = JSON.stringify(JSON.parse(code), null, "\t"); result = JSON.stringify(JSON.parse(code), null, "\t");
if (typeof result === "string") { if (typeof result === "string") {
setCode(result); setCode(result);
const checkErrorArr = checkParamsConfig(result); const checkErrorArr = checkParamsConfig(result);
console.log(checkErrorArr, "checkErrorArr");
if (checkErrorArr.length) { if (checkErrorArr.length) {
// Message.error("参数配置不正确!"); resultError = "参数配置不正确!";
// setFormErrors({
// ...formErrors,
// ...{ parameters: "参数配置不正确!" },
// });
const codeDom = document.getElementById("paramsConfig"); const codeDom = document.getElementById("paramsConfig");
const all = codeDom?.getElementsByClassName("cm-line"); const all = codeDom?.getElementsByClassName("cm-line");
const allArr = Array.prototype.slice.call(all); const allArr = Array.prototype.slice.call(all);
...@@ -128,17 +206,15 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -128,17 +206,15 @@ const AddOperator = observer((props: IAddOperator) => {
}, 200); }, 200);
} }
} }
} else {
const newFormErrors = _.cloneDeep(formErrors);
delete newFormErrors.parameters;
setFormErrors(newFormErrors);
} }
} }
} catch (error) { } catch (error) {
Message.error("JSON格式不正确!"); resultError = "JSON格式不正确!";
console.log("JSON格式不正确!"); console.log("JSON格式不正确!");
} }
}, [Message, code, formErrors]); setParametersError(resultError || "");
return resultError;
}, [batchBuildType, code]);
/** 获取应用环境下拉 */ /** 获取应用环境下拉 */
const { run: fetchActorEnvOptions } = useMyRequest(getActorEnvOptions, { const { run: fetchActorEnvOptions } = useMyRequest(getActorEnvOptions, {
...@@ -163,17 +239,24 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -163,17 +239,24 @@ const AddOperator = observer((props: IAddOperator) => {
}; };
const handleSubmit = useCallback(() => { const handleSubmit = useCallback(() => {
const resultErrors = checkFormData(formData, batchBuildType); const resultErrors = checkFormData(
// paramsConfigBlur(); formData,
formErrors?.parameters batchBuildType,
? setFormErrors({ ...resultErrors, parameters: formErrors.parameters }) detailInfo?.version || "0.99.99"
: setFormErrors({ ...resultErrors }); );
const paramsResultError = paramsConfigBlur();
setFormErrors(resultErrors);
if (taskType === "BATCH" && batchBuildType === "OPERATOR") { if (taskType === "BATCH" && batchBuildType === "OPERATOR") {
handleCheck(); handleCheck();
} }
if (Object.getOwnPropertyNames(resultErrors)?.length || !checkStatus) if (
Object.getOwnPropertyNames(resultErrors)?.length ||
checkStatus ||
paramsResultError
)
return; return;
console.log(code, "111");
let newParameters = []; let newParameters = [];
try { try {
newParameters = JSON.parse(code); newParameters = JSON.parse(code);
...@@ -181,9 +264,8 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -181,9 +264,8 @@ const AddOperator = observer((props: IAddOperator) => {
console.log(err); console.log(err);
} }
console.log(operatorList, "operatorList");
const params = { const params = {
...(detailsId ? detailInfo : {}),
...formData, ...formData,
...(batchBuildType === "ENVIRONMENT" && taskType === "BATCH" ...(batchBuildType === "ENVIRONMENT" && taskType === "BATCH"
? { command: Base64.encode(command) } ? { command: Base64.encode(command) }
...@@ -200,23 +282,20 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -200,23 +282,20 @@ const AddOperator = observer((props: IAddOperator) => {
delete params.envId; delete params.envId;
} }
saveOperator(params).then((res: any) => { console.log(params, "params");
if (res?.message === "success") { runSaveOperator(params, detailsId ? true : false);
Message.success("构建成功");
} else {
Message.success(res?.message || "构建失败");
}
});
}, [ }, [
Message,
batchBuildType, batchBuildType,
checkStatus, checkStatus,
code, code,
command, command,
detailInfo,
detailsId,
formData, formData,
formErrors.parameters,
handleCheck, handleCheck,
operatorList, operatorList,
paramsConfigBlur,
runSaveOperator,
taskType, taskType,
]); ]);
...@@ -224,6 +303,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -224,6 +303,7 @@ const AddOperator = observer((props: IAddOperator) => {
<div className={style.addOperatorBox}> <div className={style.addOperatorBox}>
<div className={style.left}> <div className={style.left}>
<SwitchBatchFolw <SwitchBatchFolw
type={pageType !== "add" ? "edit" : undefined}
bottomImg={flowOperator} bottomImg={flowOperator}
topImg={batchOperator} topImg={batchOperator}
active={taskType} active={taskType}
...@@ -238,7 +318,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -238,7 +318,7 @@ const AddOperator = observer((props: IAddOperator) => {
<div className={style.title}> <div className={style.title}>
{taskType === "BATCH" ? "批式算子信息" : "流式算子信息"} {taskType === "BATCH" ? "批式算子信息" : "流式算子信息"}
</div> </div>
{taskType === "BATCH" ? ( {taskType === "BATCH" && pageType !== "edit" ? (
<div <div
style={{ style={{
paddingBottom: batchBuildType === "ENVIRONMENT" ? "20px" : "2px", paddingBottom: batchBuildType === "ENVIRONMENT" ? "20px" : "2px",
...@@ -274,6 +354,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -274,6 +354,7 @@ const AddOperator = observer((props: IAddOperator) => {
helperText={ helperText={
formErrors?.title ? "" : "15字符以内,仅限字母、数字、中文" formErrors?.title ? "" : "15字符以内,仅限字母、数字、中文"
} }
disabled={!!detailsId}
placeholder="请输入算子名称" placeholder="请输入算子名称"
value={formData?.title} value={formData?.title}
onChange={(e) => { onChange={(e) => {
...@@ -310,8 +391,8 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -310,8 +391,8 @@ const AddOperator = observer((props: IAddOperator) => {
> >
<MySelect <MySelect
fullWidth fullWidth
disabled={!!detailsId}
options={productListStore?.productList || []} options={productListStore?.productList || []}
defaultValue={defaultProduct}
value={formData?.productId} value={formData?.productId}
onChange={(e) => { onChange={(e) => {
changeFormData({ productId: e }); changeFormData({ productId: e });
...@@ -353,6 +434,20 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -353,6 +434,20 @@ const AddOperator = observer((props: IAddOperator) => {
changeFormData({ description: e.target.value }); changeFormData({ description: e.target.value });
}} }}
/> />
<span
style={{
position: "absolute",
fontSize: "14px",
bottom: "7px",
right: "12px",
color:
Number(formData?.description?.length) >= 300
? "#d32f2f"
: "#C2C6CC",
}}
>
{formData?.description?.length || 0}/300
</span>
</FormItemBox> </FormItemBox>
) : null} ) : null}
</div> </div>
...@@ -370,22 +465,26 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -370,22 +465,26 @@ const AddOperator = observer((props: IAddOperator) => {
horizontal: "right", horizontal: "right",
}} }}
> >
<span style={{ color: "#1370FF" }}>帮助手册</span> <span style={{ color: "#1370FF", cursor: "pointer" }}>
帮助手册
</span>
</MyPopover> </MyPopover>
</div> </div>
<div className={style.code}> <div className={style.code}>
<Code <Code
id="paramsConfig" id="paramsConfig"
value={code} value={code}
// placeholder="dd" onChange={(e: string) => {
onChange={(e: string, viewUpdate: any) => {
setCode(e); setCode(e);
}} }}
onBlur={paramsConfigBlur} onBlur={paramsConfigBlur}
height="535px" height={parametersError ? "480px" : "512px"}
width="600" width="600"
style={{ flex: 1 }} style={{ flex: 1 }}
/> />
{parametersError ? (
<p className={style.codeErrorBox}>{parametersError}</p>
) : null}
</div> </div>
</div> </div>
) : ( ) : (
...@@ -407,6 +506,20 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -407,6 +506,20 @@ const AddOperator = observer((props: IAddOperator) => {
changeFormData({ description: e.target.value }); changeFormData({ description: e.target.value });
}} }}
/> />
<span
style={{
position: "absolute",
fontSize: "14px",
bottom: "7px",
right: "12px",
color:
Number(formData?.description?.length) >= 300
? "#d32f2f"
: "#C2C6CC",
}}
>
{formData?.description?.length || 0}/300
</span>
</FormItemBox> </FormItemBox>
</div> </div>
)} )}
...@@ -433,7 +546,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -433,7 +546,7 @@ const AddOperator = observer((props: IAddOperator) => {
operatorList={operatorList} operatorList={operatorList}
setOperatorList={setOperatorList} setOperatorList={setOperatorList}
setInputActive={setInputActive} setInputActive={setInputActive}
productId={formData.productId || defaultProduct || ""} productId={formData.productId || ""}
/> />
<BatchOperatorFlow <BatchOperatorFlow
tasks={operatorList} tasks={operatorList}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-20 17:36:14 * @Date: 2022-10-20 17:36:14
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 15:52:56 * @LastEditTime: 2022-10-26 13:56:10
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/utils.ts * @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/utils.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -12,11 +12,36 @@ import { IOperatorAddFormData } from "../../interface"; ...@@ -12,11 +12,36 @@ import { IOperatorAddFormData } from "../../interface";
type IBuildType = "ENVIRONMENT" | "OPERATOR"; type IBuildType = "ENVIRONMENT" | "OPERATOR";
export const checkFormData = (formData: IOperatorAddFormData, taskType: IBuildType)=>{
// 校验新版本号是否大于旧版本号
const checkNewOldVersion = (version: string, oldVersion: string): string => {
let versionArr: any[] = version.split(".");
let oldVersionArr: any[] = oldVersion.split(".");
versionArr = versionArr.map((item) => Number(item));
oldVersionArr = oldVersionArr.map((item) => Number(item));
if (versionArr[0] < oldVersionArr[0]) {
return "新版本号必须大于老版本号且大于等于1.0.0"
} else if (versionArr[0] === oldVersionArr[0]) {
if (versionArr[1] < oldVersionArr[1]) {
return "新版本号必须大于老版本号且大于等于1.0.0"
} else if (versionArr[1] === oldVersionArr[1]) {
if (versionArr[2] <= oldVersionArr[2]) {
return "新版本号必须大于老版本号且大于等于1.0.0"
}
}
}
return '';
}
export const checkFormData = (formData: IOperatorAddFormData, taskType: IBuildType, oldVersion: string)=>{
const reg = new RegExp("^[A-Za-z0-9\u4e00-\u9fa5]{1,15}$"); const reg = new RegExp("^[A-Za-z0-9\u4e00-\u9fa5]{1,15}$");
const result:IOperatorAddFormData = {} const result:IOperatorAddFormData = {}
const versionErr = checkNewOldVersion(formData?.version || '', oldVersion )
if(!formData?.title){ if(!formData?.title){
result.title = '请输入算子名称' result.title = '请输入算子名称'
} }
...@@ -26,6 +51,10 @@ export const checkFormData = (formData: IOperatorAddFormData, taskType: IBuildTy ...@@ -26,6 +51,10 @@ export const checkFormData = (formData: IOperatorAddFormData, taskType: IBuildTy
if(!/^[1-9]\d?(\.(0|[1-9]\d?)){2}$/.test(formData?.version || '')){ if(!/^[1-9]\d?(\.(0|[1-9]\d?)){2}$/.test(formData?.version || '')){
result.version = '格式不正确,必须为X.Y.Z格式,且XYZ必须为0~99的正整数' result.version = '格式不正确,必须为X.Y.Z格式,且XYZ必须为0~99的正整数'
} }
if(versionErr) {
result.version = versionErr
}
if(!formData?.version){ if(!formData?.version){
result.version = '请输入算子版本' result.version = '请输入算子版本'
} }
...@@ -39,6 +68,26 @@ export const checkFormData = (formData: IOperatorAddFormData, taskType: IBuildTy ...@@ -39,6 +68,26 @@ export const checkFormData = (formData: IOperatorAddFormData, taskType: IBuildTy
return result return result
} }
/** 编辑算子版本默认加0.0.1 */
export const editDefaultVersion = (version: string)=>{
let arr = version.split(".");
if (arr.length === 3) {
if (Number(arr[2]) < 99) {
arr[2] = String(Number(arr[2]) + 1);
} else {
arr[2] = "0";
if (Number(arr[1]) < 99) {
arr[1] = String(Number(arr[1]) + 1);
} else {
arr[1] = "0";
arr[0] = String(Number(arr[0]) + 1);
}
}
}
return arr.join(".")
}
/** 参数配置校验 */ /** 参数配置校验 */
export const checkParamsConfig = (val: string) => { export const checkParamsConfig = (val: string) => {
let result: any = [] let result: any = []
...@@ -56,7 +105,7 @@ export const checkParamsConfig = (val: string) => { ...@@ -56,7 +105,7 @@ export const checkParamsConfig = (val: string) => {
if( item?.description > 300 ){ if( item?.description > 300 ){
result.push(`description: ${item?.description}`) result.push(`description: ${item?.description}`)
} }
if( !['STRING','FILE','DATASET','INT','FLOAT','DOUBLE','BOOLEAN','ARRAY_STRING','ARRAY_FILE','ARRAY_DATASET','ARRAY_INT','ARRAY_FLOAT','ARRAY_DOUBLE','ARRAY_BOOLEAN'].includes(item?.classType )){ if( !['STRING','FILE','DATASET','INT','FLOAT','DOUBLE','BOOLEAN','ARRAY_STRING','ARRAY_FILE','ARRAY_DATASET','ARRAY_INT','ARRAY_FLOAT','ARRAY_DOUBLE','ARRAY_BOOLEAN','TEXT','JSON'].includes(item?.classType )){
result.push(`classType: ${item?.classType}`) result.push(`classType: ${item?.classType}`)
} }
if(!['true','false'].includes(String(item?.required)) ) { if(!['true','false'].includes(String(item?.required)) ) {
......
...@@ -51,8 +51,9 @@ ...@@ -51,8 +51,9 @@
display: inline-block; display: inline-block;
width: 24px; width: 24px;
height: 24px; height: 24px;
text-align: center; display: flex;
line-height: 24px; align-items: center;
justify-content: center;
cursor: pointer; cursor: pointer;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11 * @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 20:38:16 * @LastEditTime: 2022-10-25 21:32:49
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx * @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -14,6 +14,7 @@ import { useStores } from "@/store"; ...@@ -14,6 +14,7 @@ import { useStores } from "@/store";
import { useMemo } from "react"; import { useMemo } from "react";
import MyMenu from "@/components/mui/MyMenu"; import MyMenu from "@/components/mui/MyMenu";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import expandOperationSvg from "@/assets/project/expandOperationSvg.svg";
interface IProps { interface IProps {
operatorInfo: IOperatorInfo; operatorInfo: IOperatorInfo;
...@@ -45,9 +46,9 @@ const OperatorCard = observer((props: IProps) => { ...@@ -45,9 +46,9 @@ const OperatorCard = observer((props: IProps) => {
} }
}; };
const handleToSeeOperator = (item: any) => { const handleToSeeOperator = () => {
navigate("/utility/resourceCenter/userResources/seeFloe", { navigate("/utility/resourceCenter/userResources/seeFloe", {
state: { id: item.id }, state: { id },
}); });
}; };
...@@ -70,7 +71,13 @@ const OperatorCard = observer((props: IProps) => { ...@@ -70,7 +71,13 @@ const OperatorCard = observer((props: IProps) => {
zIndex: 1601, zIndex: 1601,
}} }}
> >
<span className={styles.operationBox}>大大</span> <span className={styles.operationBox}>
<img
style={{ width: 16, height: 16 }}
src={expandOperationSvg}
alt=""
/>
</span>
</MyMenu> </MyMenu>
</div> </div>
<div className={styles.itemContentBox}> <div className={styles.itemContentBox}>
......
...@@ -2,9 +2,38 @@ ...@@ -2,9 +2,38 @@
padding: 0 24px; padding: 0 24px;
} }
.titleBox { .baseInfoBox {
font-size: 16px; font-size: 16px;
color: #1e2633; color: #1e2633;
line-height: 24px; line-height: 24px;
padding: 20px 0; padding: 20px 0;
} }
.titleBox {
padding: 14px 24px;
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid rgba(235, 237, 240, 1);
}
.goBackIcon {
width: 22px;
height: 22px;
cursor: pointer;
}
.title {
margin-left: 2px;
font-size: 18px;
line-height: 26px;
color: rgba(30, 38, 51, 1);
font-weight: 550;
margin-right: 16px;
}
.type {
background-color: rgba(235, 237, 240, 1);
font-size: 12px;
line-height: 20px;
padding: 1px 9px;
color: #565c66;
border-radius: 2px;
}
...@@ -2,17 +2,25 @@ ...@@ -2,17 +2,25 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11 * @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 10:30:55 * @LastEditTime: 2022-10-26 09:27:56
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx * @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import styles from "./index.module.css"; import { observer } from "mobx-react-lite";
import { useEffect, useMemo, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import BasicInfo from "../../../../components/BasinInfo"; import BasicInfo from "../../../../components/BasinInfo";
import { useMemo, useState } from "react";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle"; import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import useMyRequest from "@/hooks/useMyRequest";
import { getOperatorDetail } from "@/api/resourceCenter";
import { useStores } from "@/store";
import goback from "@/assets/project/goback.svg";
import styles from "./index.module.css";
const OperatorDetails = () => { const OperatorDetails = observer(() => {
const contentTypeList = useMemo(() => { const contentTypeList = useMemo(() => {
return [ return [
{ value: "flowChart", label: "流程图" }, { value: "flowChart", label: "流程图" },
...@@ -21,31 +29,85 @@ const OperatorDetails = () => { ...@@ -21,31 +29,85 @@ const OperatorDetails = () => {
]; ];
}, []); }, []);
/** 产品store */
const { productListStore } = useStores();
const navigate = useNavigate();
/** 详情类型 */ /** 详情类型 */
const [contentType, setContentType] = useState<string>("flowChart"); const [contentType, setContentType] = useState<string>("flowChart");
/** 详情数据 */
const [detailInfo, setDetailInfo] = useState<any>({});
/** 获取算子详情 */
const { run: fetchOperatorDetail } = useMyRequest(getOperatorDetail, {
onSuccess: (res: any) => {
if (res.message === "success") {
/** 设置详情信息 */
setDetailInfo(res.data);
}
},
});
const location = useLocation();
const locationInfo: any = location?.state;
const {
title = "",
version = "",
productId = "",
createdTime = "",
creator = "",
description = "",
type,
} = detailInfo;
/** 切换类型 */ /** 切换类型 */
const handleRadio = (val: string) => { const handleRadio = (val: string) => {
setContentType(val); setContentType(val);
}; };
const productText = useMemo(() => {
const result = productListStore.productList?.filter((item) => {
return item.value === productId;
});
return result?.length ? result[0].label : "";
}, [productListStore.productList, productId]);
useEffect(() => {
fetchOperatorDetail(locationInfo.id);
}, [fetchOperatorDetail, locationInfo.id]);
return ( return (
<div className={styles.detailsBox}> <div className={styles.detailsBox}>
<h2 className={styles.titleBox}>基础信息</h2> <div className={styles.titleBox}>
<img
className={styles.goBackIcon}
src={goback}
alt=""
onClick={() =>
navigate("/utility/resourceCenter/userResources", {
state: { defaultTab: "USERRESOURCES_FLOE" },
})
}
/>
<div className={styles.title}>{title}</div>
<div className={styles.type}>
{type === "BATCH" ? "批算子" : "流算子"}
</div>
</div>
<h2 className={styles.baseInfoBox}>基础信息</h2>
<div style={{ border: "1px solid #EBEDF0" }}> <div style={{ border: "1px solid #EBEDF0" }}>
<BasicInfo <BasicInfo
infoList={[ infoList={[
{ label: "33333331", value: "1" }, { label: "所属产品", value: productText },
{ {
label: "1", label: "创建时间",
value: "42543253245325325432452345235432452323542352354235235321", value: createdTime,
}, },
{ label: "1", value: "1" }, { label: "创建人", value: creator },
{ label: "1", value: "1" }, { label: "算子版本", value: version },
{ label: "1", value: "1" }, { label: "应用环境", value: "1" },
]} ]}
/> />
<BasicInfo infoList={[{ label: "2", value: "2" }]} /> <BasicInfo infoList={[{ label: "描述", value: description }]} />
</div> </div>
<div style={{ padding: "26px 0 16px 0" }}> <div style={{ padding: "26px 0 16px 0" }}>
<RadioGroupOfButtonStyle <RadioGroupOfButtonStyle
...@@ -58,6 +120,6 @@ const OperatorDetails = () => { ...@@ -58,6 +120,6 @@ const OperatorDetails = () => {
<div>11</div> <div>11</div>
</div> </div>
); );
}; });
export default OperatorDetails; export default OperatorDetails;
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11 * @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 20:40:16 * @LastEditTime: 2022-10-26 14:05:04
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx * @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -12,6 +12,7 @@ import { observer } from "mobx-react"; ...@@ -12,6 +12,7 @@ import { observer } from "mobx-react";
import _ from "lodash"; import _ from "lodash";
import Add from "@mui/icons-material/Add"; import Add from "@mui/icons-material/Add";
import noFile from "@/assets/project/noFile.svg";
import SearchInput from "@/components/BusinessComponents/SearchInput"; import SearchInput from "@/components/BusinessComponents/SearchInput";
import MySelect from "@/components/mui/MySelect"; import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton"; import MyButton from "@/components/mui/MyButton";
...@@ -23,6 +24,7 @@ import useMyRequest from "@/hooks/useMyRequest"; ...@@ -23,6 +24,7 @@ import useMyRequest from "@/hooks/useMyRequest";
import { IOperatorInfo } from "./interface"; import { IOperatorInfo } from "./interface";
import styles from "./index.module.css"; import styles from "./index.module.css";
import MyCircularProgress from "@/components/mui/MyCircularProgress";
const WorkflowOperator = observer(() => { const WorkflowOperator = observer(() => {
const [pageType, setPageType] = useState<string>(""); const [pageType, setPageType] = useState<string>("");
...@@ -39,7 +41,7 @@ const WorkflowOperator = observer(() => { ...@@ -39,7 +41,7 @@ const WorkflowOperator = observer(() => {
const [list, setList] = useState<IOperatorInfo[]>(); const [list, setList] = useState<IOperatorInfo[]>();
const { run: getList } = useMyRequest(getOperatorList, { const { run: getList, loading } = useMyRequest(getOperatorList, {
// refreshDeps: [], // refreshDeps: [],
onSuccess: (res) => { onSuccess: (res) => {
console.log(res); console.log(res);
...@@ -71,6 +73,7 @@ const WorkflowOperator = observer(() => { ...@@ -71,6 +73,7 @@ const WorkflowOperator = observer(() => {
return ( return (
<> <>
<MyCircularProgress loading={loading}>
<div className={styles.indexBox}> <div className={styles.indexBox}>
<div className={styles.headerBox}> <div className={styles.headerBox}>
<div> <div>
...@@ -129,6 +132,7 @@ const WorkflowOperator = observer(() => { ...@@ -129,6 +132,7 @@ const WorkflowOperator = observer(() => {
}} }}
></MyButton> ></MyButton>
</div> </div>
{list?.length ? (
<div className={styles.contentBox}> <div className={styles.contentBox}>
{list?.map((item) => { {list?.map((item) => {
return ( return (
...@@ -140,9 +144,38 @@ const WorkflowOperator = observer(() => { ...@@ -140,9 +144,38 @@ const WorkflowOperator = observer(() => {
); );
})} })}
</div> </div>
) : (
<div style={{ position: "relative" }}>
<img
src={noFile}
alt=""
style={{
position: "absolute",
top: "100px",
left: "50%",
transform: "translate(-50%, 0)",
}}
/>
<span
style={{
position: "absolute",
top: "165px",
left: "50%",
transform: "translate(-50%, 0)",
fontSize: "14px",
lineHeight: "22px",
color: "#8a9099",
}}
>
暂无工作流算子
</span>
</div>
)}
</div> </div>
</MyCircularProgress>
{pageType && ( {pageType && (
<AddOperator <AddOperator
getList={newGetList}
detailsId={detailsId} detailsId={detailsId}
setPageType={setPageType} setPageType={setPageType}
pageType={pageType} pageType={pageType}
......
...@@ -2,12 +2,14 @@ import style from "./index.module.css"; ...@@ -2,12 +2,14 @@ import style from "./index.module.css";
import usePass from "@/hooks/usePass"; import usePass from "@/hooks/usePass";
import UserResourcesTemplate from "./UserResourcesTemplate"; import UserResourcesTemplate from "./UserResourcesTemplate";
import UserResourcesEnvironment from "./UserResourcesEnvironment"; import UserResourcesEnvironment from "./UserResourcesEnvironment";
import { useLocation } from "react-router-dom";
import { useMemo } from "react"; import { useMemo } from "react";
import Tabs from "@/components/mui/MyTabs"; import Tabs from "@/components/mui/MyTabs";
import WorkflowOperator from "./WorkflowOperator"; import WorkflowOperator from "./WorkflowOperator";
import OperatorDetails from "./WorkflowOperator/components/OperatorDetails"; import OperatorDetails from "./WorkflowOperator/components/OperatorDetails";
const UserResources = () => { const UserResources = () => {
const isPass = usePass(); const isPass = usePass();
const location: any = useLocation();
const tabList = useMemo(() => { const tabList = useMemo(() => {
return [ return [
{ {
...@@ -36,7 +38,7 @@ const UserResources = () => { ...@@ -36,7 +38,7 @@ const UserResources = () => {
<Tabs <Tabs
title="个人资源" title="个人资源"
tabList={tabList} tabList={tabList}
defaultValue={"USERRESOURCES_TEMPLATE"} defaultValue={location?.state?.defaultTab || "USERRESOURCES_TEMPLATE"}
tabPanelSx={{ padding: "0" }} tabPanelSx={{ padding: "0" }}
/> />
{/* <OperatorDetails /> */} {/* <OperatorDetails /> */}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-18 09:32:40 * @Date: 2022-10-18 09:32:40
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-24 14:57:06 * @LastEditTime: 2022-10-25 14:48:51
* @FilePath: /bkunyun/src/views/ResourceCenter/components/SwitchBatchFolw/index.tsx * @FilePath: /bkunyun/src/views/ResourceCenter/components/SwitchBatchFolw/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -17,12 +17,13 @@ type ISwitchBatchFolwProps = { ...@@ -17,12 +17,13 @@ type ISwitchBatchFolwProps = {
topImg?: string; topImg?: string;
bottomImg?: string; bottomImg?: string;
active: "BATCH" | "FLOW"; active: "BATCH" | "FLOW";
type?: "edit";
setActive: any; setActive: any;
goBack: any; goBack: any;
}; };
const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => { const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => {
const { active, setActive, goBack, topImg, bottomImg } = props; const { active, setActive, goBack, topImg, bottomImg, type } = props;
return ( return (
<div className={style.switchBatchFolw}> <div className={style.switchBatchFolw}>
<div className={style.goBackBox}> <div className={style.goBackBox}>
...@@ -35,6 +36,8 @@ const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => { ...@@ -35,6 +36,8 @@ const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => {
<span className={style.goBackText}>返回</span> <span className={style.goBackText}>返回</span>
</div> </div>
<div className={style.switchBox}> <div className={style.switchBox}>
{/* type为edit 只显示一个 */}
{type === "edit" && active !== "BATCH" ? null : (
<div <div
className={classNames({ className={classNames({
[style.switchItem]: true, [style.switchItem]: true,
...@@ -52,6 +55,8 @@ const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => { ...@@ -52,6 +55,8 @@ const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => {
/> />
{active === "BATCH" && <div className={style.arrow}></div>} {active === "BATCH" && <div className={style.arrow}></div>}
</div> </div>
)}
{type === "edit" && active !== "FLOW" ? null : (
<div <div
className={classNames({ className={classNames({
[style.switchItem]: true, [style.switchItem]: true,
...@@ -69,6 +74,7 @@ const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => { ...@@ -69,6 +74,7 @@ const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => {
/> />
{active === "FLOW" && <div className={style.arrow}></div>} {active === "FLOW" && <div className={style.arrow}></div>}
</div> </div>
)}
</div> </div>
</div> </div>
); );
......
...@@ -253,7 +253,7 @@ const SaveCustomTemplate = (props: IProps) => { ...@@ -253,7 +253,7 @@ const SaveCustomTemplate = (props: IProps) => {
style={{ style={{
position: "absolute", position: "absolute",
fontSize: "14px", fontSize: "14px",
bottom: "7px", top: "96px",
right: "12px", right: "12px",
color: description.length >= 300 ? "#d32f2f" : "#C2C6CC", color: description.length >= 300 ? "#d32f2f" : "#C2C6CC",
}} }}
......
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