Commit 37c40624 authored by chenshouchao's avatar chenshouchao

feat: 完成提交任务静态表单、input组件、文件夹选择组件

parent f5818d25
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 6备份 5</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-25">
<rect id="矩形" x="0" y="0" width="20" height="20"></rect>
<g id="编组-32" transform="translate(0.533333, 3.452381)">
<path d="M8.36688938,0.416666667 L9.55313606,1.36249983 C9.81887602,1.6286558 10.1795465,1.77821568 10.5556538,1.77821568 L10.5556538,1.77821568 L14.8884238,1.77821568 L15.4717571,5.1407542 L8.77799689,5.3817735 L2.18238271,5.25717634 L2.18238271,1 L8.36688938,0.416666667 Z" id="路径-7" stroke="#8A9099" stroke-width="0.833333333" fill="#EBEDF0"></path>
<path d="M1.19361766,4.3897647 L17.7662846,4.3897647 C18.3185693,4.3897647 18.7662846,4.83747995 18.7662846,5.3897647 C18.7662846,5.43928252 18.7626065,5.48873196 18.7552809,5.53770491 L17.7437151,12.3001318 C17.6704625,12.7898332 17.2498687,13.1521916 16.7547187,13.1521916 L2.39674962,13.1521916 C1.91203684,13.1521916 1.49711429,12.804574 1.41221027,12.3273551 L0.209078316,5.56492826 C0.112338155,5.02118219 0.474708039,4.50196551 1.01845411,4.40522535 C1.07627469,4.39493825 1.1348891,4.3897647 1.19361766,4.3897647 Z" id="矩形" fill="#8A9099"></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
.rootTitle {
border-radius: 4px 4px 0 0;
background-color: rgba(25, 118, 210, 0.08);
/* background-color: rgba(25, 118, 210, 0.5); */
line-height: 44px;
color: rgba(30, 38, 51, 1);
font-size: 14px;
font-weight: 600;
display: flex;
justify-content: flex-start;
align-items: center;
}
.rootTitleActive {
background-color: rgba(25, 118, 210, 0.2);
}
.bigFolderIcon {
margin: 0 9px;
}
.treeLabel {
display: flex;
justify-content: flex-start;
align-items: center;
}
.treeLabelText {
line-height: 44px;
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
white-space: nowrap;
width: 320px;
}
.labelFolderIcon {
margin-right: 9px;
}
import MyDialog from "../mui/Dialog";
import { useStores } from "@/store";
import { observer } from "mobx-react-lite";
import { toJS } from "mobx";
import { useEffect, useState } from "react";
import CloudEController from "@/api/fileserver/CloudEController";
import MyTreeView from "@/components/mui/MyTreeView";
import classNames from "classnames";
import bigFolderIcon from "@/assets/project/bigFolderIcon.svg";
import folderIcon from "@/assets/project/folderIcon.svg";
import style from "./index.module.css";
type FileSelectProps = {
open: boolean;
onConfirm: any;
onClose: any;
};
const FileSelect = observer((props: FileSelectProps) => {
const { onConfirm } = props;
const { currentProjectStore } = useStores();
const projectId = toJS(currentProjectStore.currentProjectInfo.id);
const fileToken = toJS(currentProjectStore.currentProjectInfo.filetoken);
const [treeData, setTreeData] = useState<Array<any>>([]);
const [rootActive, setRootActive] = useState(true);
const [newPath, setNewPath] = useState("/");
useEffect(() => {
if (fileToken && projectId) {
CloudEController.JobOutFileDirtree(
"/",
fileToken,
projectId,
false
)?.then((res: any) => {
if (Array.isArray(res.data)) {
setTreeData(res.data);
} else {
setTreeData([]);
}
});
}
}, [projectId, fileToken]);
const renderLabel = (labelNmae: string) => {
return (
<span className={style.treeLabel}>
<img className={style.labelFolderIcon} src={folderIcon} alt="" />
<span className={style.treeLabelText}>{labelNmae}</span>
</span>
);
};
const handleRoot = () => {
setNewPath("/");
setRootActive(true);
};
const onNodeSelect = (a: any, b: any) => {
setNewPath(b);
setRootActive(false);
};
// 给路径去掉第一个'/'然后结尾加上文件名 方便后面直接使用
const idFunc = (item: any) => {
return `${item.dir.substr(1)}${item.name}`;
};
const fileSelectOnConfirm = () => {
onConfirm(newPath);
};
return (
<MyDialog
open={props.open}
onClose={props.onClose}
onConfirm={fileSelectOnConfirm}
>
<div
className={classNames({
[style.rootTitle]: true,
[style.rootTitleActive]: rootActive,
})}
onClick={handleRoot}
>
<img className={style.bigFolderIcon} src={bigFolderIcon} alt="" />
ProjectData
</div>
<MyTreeView
treeData={treeData}
renderLabel={renderLabel}
onNodeSelect={onNodeSelect}
idFunc={idFunc}
treeViewSx={{
width: 400,
overflow: "hidden",
}}
></MyTreeView>
</MyDialog>
);
});
export default FileSelect;
import TextField from "@mui/material/TextField";
type MyInputProps = {
value: any;
inputSx?: any;
onChange?: any;
onFocus?: any;
label?: string;
variant?: "standard" | "filled" | "outlined";
id?: string;
size?: "small" | "medium";
placeholder?: string;
fullWidth?: boolean; // 宽度是否和容器一致
InputProps?: any; // input加前后icon可以用这个
};
const MyInput = (props: MyInputProps) => {
const {
inputSx = {},
value,
onChange,
onFocus,
label,
id,
variant,
size = "small",
placeholder = "请输入",
fullWidth = true,
InputProps,
} = props;
return (
<TextField
value={value}
sx={{ ...inputSx }}
id={id}
label={label}
variant={variant}
onChange={onChange}
onFocus={onFocus}
size={size}
placeholder={placeholder}
fullWidth={fullWidth}
InputProps={{
...InputProps,
}}
/>
);
};
export default MyInput;
.formBox {
position: relative;
}
.templateDescBox {
margin-bottom: 40px;
}
.templateDescTitle {
font-size: 16px;
line-height: 24px;
color: rgba(30, 38, 51, 1);
font-weight: 600;
margin-bottom: 12px;
}
.templateDesc {
font-size: 12px;
line-height: 20px;
color: #565c66;
}
.backgroundTitle {
background-color: rgba(245, 246, 247, 1);
height: 48px;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 12px 16px;
box-sizing: border-box;
position: relative;
}
.backgroundTitleText {
font-size: 16px;
font-weight: 600;
line-height: 24px;
color: rgba(30, 38, 51, 1);
margin-left: 28px;
}
.formItems {
padding: 20px 44px 40px 44px;
}
.formItem {
margin-bottom: 20px;
}
.fileSelectImg {
cursor: pointer;
}
.formItemLable {
margin-bottom: 12px;
font-size: 14px;
color: rgba(30, 38, 51, 1);
line-height: 22px;
font-weight: 600;
}
.required::after {
content: "*";
color: red;
margin-left: 3px;
}
const ConfigForm = () => {
return <div>form</div>;
import { ITemplateConfig } from "../interface";
import styles from "./index.module.css";
import MyInput from "@/components/mui/MyInput";
import classnames from "classnames";
import { useState } from "react";
import FileSelect from "@/components/FileSelect";
import moment from "moment";
import fileSelectIcon from "@/assets/project/fileSelect.svg";
type ConfigFormProps = {
templateConfigInfo: ITemplateConfig;
};
const ConfigForm = (props: ConfigFormProps) => {
const { templateConfigInfo } = props;
const [name, setName] = useState<string>(
`${templateConfigInfo.title}_${moment(new Date()).format(
"YYYY_MM_DD_HH_mm"
)}`
); // 任务名称
const [outputPath, setOutputPath] = useState<string>("ProjectData"); // 输出路径
const [fileSelectOpen, setFileSelectOpen] = useState(false); // 选择输出路径的弹窗显示控制
const onFileSelectConfirm = (path: string) => {
setFileSelectOpen(false);
setOutputPath(`ProjectData${path === "/" ? "" : path}`);
};
const handleFileSelectOnClose = () => {
setFileSelectOpen(false);
};
const handleOpenFileSelect = () => {
setFileSelectOpen(true);
};
const handleNameChange = (e: any) => {
setName(e.target.value);
};
return (
<div className={styles.formBox}>
<div className={styles.templateDescBox}>
<div className={styles.templateDescTitle}>模板描述</div>
<div className={styles.templateDesc}>
{templateConfigInfo.description}
</div>
</div>
<div
className={classnames({
[styles.backgroundTitle]: true,
[styles.backgroundTitlePass]: true,
})}
>
<img src="" alt="" />
<span className={styles.backgroundTitleText}>基础信息</span>
</div>
<div className={styles.formItems}>
<div className={styles.formItem}>
<div
className={classnames({
[styles.formItemLable]: true,
[styles.required]: true,
})}
>
任务名称
</div>
<div className={styles.formItem}>
<MyInput
value={name}
onChange={handleNameChange}
placeholder="请输入任务名称"
></MyInput>
</div>
</div>
<div className={styles.formItem}>
<div
className={classnames({
[styles.formItemLable]: true,
[styles.required]: true,
})}
>
输出路径
</div>
<div className={styles.formItem}>
<MyInput
value={outputPath}
InputProps={{
endAdornment: (
<img
onClick={handleOpenFileSelect}
src={fileSelectIcon}
alt="选择输出路径"
className={styles.fileSelectImg}
/>
),
}}
></MyInput>
</div>
</div>
</div>
<FileSelect
onClose={handleFileSelectOnClose}
open={fileSelectOpen}
onConfirm={onFileSelectConfirm}
/>
</div>
);
};
export default ConfigForm;
......@@ -9,6 +9,7 @@
overflow-y: scroll;
}
.swHeader {
z-index: 1001;
position: sticky;
top: 0;
height: 56px;
......
......@@ -9,8 +9,9 @@ import IconButton from "@mui/material/IconButton";
import { ITemplateConfig } from "./interface";
const ProjectSubmitWork = () => {
const [templateConfigInfo, setTemplateConfigInfo] =
useState<ITemplateConfig>(templateConfigJson);
const [templateConfigInfo, setTemplateConfigInfo] = useState<ITemplateConfig>(
templateConfigJson as ITemplateConfig
);
return (
<div className={styles.swBox}>
......@@ -54,7 +55,7 @@ const ProjectSubmitWork = () => {
</div>
<div className={styles.swContent}>
<div className={styles.swFormBox}>
<ConfigForm />
<ConfigForm templateConfigInfo={templateConfigInfo} />
</div>
<div className={styles.swFlowBox}>
<WorkFlow />
......
......@@ -19,7 +19,7 @@ export interface ITaskFlow {
x: number;
y: number;
};
type: "flow" | string;
type: "flow";
parentNode: string;
parameters: Array<IParameter>;
edges: Array<IEdge>;
......@@ -33,7 +33,7 @@ export interface ITaskBatch {
x: number;
y: number;
};
type: "batch" | string;
type: "batch";
parameters: Array<IParameter>;
edges: Array<IEdge>;
}
......@@ -43,29 +43,30 @@ export interface IParameter {
id?: string;
name: string;
required: boolean;
domType: IDomType | string;
domType: IDomType;
dataType: string;
value: string;
description: string;
validators: IValidator;
validators: Array<IValidator>;
choices: Array<IChoice>;
}
export enum IDomType {
PathSelect = "pathSelect",
DatasetSelect = "datasetSelect",
FileSelect = "fileSelect",
Input = "input",
Select = "select",
MultipleSelect = "multipleSelect",
Radio = "radio",
Checkbox = "checkbox",
}
export type IDomType =
| "pathSelect"
| "datasetSelect"
| "fileSelect"
| "input"
| "File"
| "select"
| "multipleSelect"
| "radio"
| "checkbox";
type IValidator = any;
// export interface IValidator {
// // 待定
// }
// 待定
export type IValidator = {
regex: string;
message: string;
};
export interface IChoice {
key: string;
......
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