|
|
|
|
@ -1,9 +1,29 @@
|
|
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
import { Modal, Form, Input, Grid, Space, Divider, Button, Table, TableColumnProps } from '@arco-design/web-react';
|
|
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
|
import {
|
|
|
|
|
Modal,
|
|
|
|
|
Form,
|
|
|
|
|
Input,
|
|
|
|
|
Grid,
|
|
|
|
|
Space,
|
|
|
|
|
Divider,
|
|
|
|
|
Button,
|
|
|
|
|
Table,
|
|
|
|
|
TableColumnProps,
|
|
|
|
|
Select,
|
|
|
|
|
Message,
|
|
|
|
|
Upload,
|
|
|
|
|
Progress
|
|
|
|
|
} from '@arco-design/web-react';
|
|
|
|
|
import { IconPlus, IconEdit } from '@arco-design/web-react/icon';
|
|
|
|
|
import styles from './style/addComponentModal.module.less';
|
|
|
|
|
import Cover from '@/pages/scene/cover';
|
|
|
|
|
import EditorSection from '@/components/EditorSection';
|
|
|
|
|
import { getComponentClassify } from '@/api/componentClassify';
|
|
|
|
|
import { compProjectValidate, compSubmit, getTagList } from '@/api/componentBase';
|
|
|
|
|
|
|
|
|
|
const FormItem = Form.Item;
|
|
|
|
|
const Option = Select.Option;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const columns: TableColumnProps[] = [
|
|
|
|
|
{
|
|
|
|
|
@ -34,32 +54,177 @@ const data = [
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const AddComponentModal = ({ visible, setVisible }) => {
|
|
|
|
|
const AddComponentModal = ({ visible, setVisible, onReFresh }) => {
|
|
|
|
|
const [selectedImage, setSelectedImage] = useState('');
|
|
|
|
|
const [description, setDescription] = useState('');
|
|
|
|
|
const [classifyList, setClassifyList] = useState([]);
|
|
|
|
|
const [showSaveBtn, setShowSaveBtn] = useState(false);
|
|
|
|
|
const [tagsList, setTagsList] = useState([]);
|
|
|
|
|
const [componentData, setComponentData] = useState({});
|
|
|
|
|
const [file, setFile] = useState(null);
|
|
|
|
|
const [form] = Form.useForm();
|
|
|
|
|
|
|
|
|
|
const transformImageUrl = (image: string) => {
|
|
|
|
|
if (!image) return;
|
|
|
|
|
if (image.includes('/')) setSelectedImage(image.split('/')[image.split('/').length - 1]);
|
|
|
|
|
else setSelectedImage(image);
|
|
|
|
|
const cs = `arco-upload-list-item${file && file.status === 'error' ? ' is-error' : ''}`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getComponentClassifyList = async () => {
|
|
|
|
|
const res: any = await getComponentClassify('component');
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
const data = [];
|
|
|
|
|
res.data.forEach((item) => {
|
|
|
|
|
data.push({
|
|
|
|
|
label: item.classifyName,
|
|
|
|
|
value: item.id
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
setClassifyList(data);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getTageList = async () => {
|
|
|
|
|
const res: any = await getTagList();
|
|
|
|
|
if (res.code === 200) setTagsList(res.data);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const validateProjectId = async (projectId: string) => {
|
|
|
|
|
if (!projectId) return;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const res = await compProjectValidate(projectId);
|
|
|
|
|
if (res.data === false) {
|
|
|
|
|
// 项目标识已存在,设置表单字段错误
|
|
|
|
|
form.setFields({
|
|
|
|
|
projectId: {
|
|
|
|
|
value: projectId,
|
|
|
|
|
error: {
|
|
|
|
|
message: '项目标识已存在'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// 项目标识可用,清除错误
|
|
|
|
|
form.setFields({
|
|
|
|
|
projectId: {
|
|
|
|
|
value: projectId,
|
|
|
|
|
error: null
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// API调用出错
|
|
|
|
|
form.setFields({
|
|
|
|
|
projectId: {
|
|
|
|
|
value: projectId,
|
|
|
|
|
error: {
|
|
|
|
|
message: '验证项目标识时发生错误'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onSubmit = async () => {
|
|
|
|
|
try {
|
|
|
|
|
await form.validate();
|
|
|
|
|
const formData = form.getFields();
|
|
|
|
|
const params = {
|
|
|
|
|
name: formData.name,
|
|
|
|
|
projectId: formData.projectId,
|
|
|
|
|
logoUrl: selectedImage,
|
|
|
|
|
desc: description,
|
|
|
|
|
componentClassify: formData.componentClassify,
|
|
|
|
|
codeLanguage: formData.codeLanguage === 'Java:8' ? 'Java' : 'Python',
|
|
|
|
|
type: formData.type === '普通组件' ? 'normal' : 'loop',
|
|
|
|
|
tags: formData.tags
|
|
|
|
|
};
|
|
|
|
|
const res: any = await compSubmit(params);
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
setComponentData(res.data);
|
|
|
|
|
setShowSaveBtn(true);
|
|
|
|
|
Message.success('组件信息提交完成,可继续组件接口设计');
|
|
|
|
|
onReFresh();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Message.error('组件信息提交失败');
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
getComponentClassifyList();
|
|
|
|
|
getTageList();
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const modalFooter = () => {
|
|
|
|
|
return (
|
|
|
|
|
<Space size={30}>
|
|
|
|
|
<Button size="small" type="secondary" style={{ borderRadius: 5 }}>代码初始化</Button>
|
|
|
|
|
<Button size="small" type="outline" style={{ borderRadius: 5 }}>取消</Button>
|
|
|
|
|
<Button size="small" type="primary" style={{ borderRadius: 5 }}>保存</Button>
|
|
|
|
|
<Button size="small" type="outline" style={{ borderRadius: 5 }} onClick={() => setVisible(false)}>取消</Button>
|
|
|
|
|
{showSaveBtn &&
|
|
|
|
|
<Button size="small" type="primary" style={{ borderRadius: 5 }} onClick={() => onSubmit()}>保存</Button>}
|
|
|
|
|
{!showSaveBtn && <Button size="small" type="primary" style={{ borderRadius: 5 }}
|
|
|
|
|
onClick={() => onSubmit()}>提交组件信息</Button>}
|
|
|
|
|
</Space>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const UploadImage = () => {
|
|
|
|
|
return (
|
|
|
|
|
<Upload
|
|
|
|
|
action="/api/v1/bpms-workbench/fileSystem/fileUpload"
|
|
|
|
|
fileList={file ? [file] : []}
|
|
|
|
|
showUploadList={false}
|
|
|
|
|
onChange={(_, currentFile: any) => {
|
|
|
|
|
setFile({
|
|
|
|
|
...currentFile,
|
|
|
|
|
url: URL.createObjectURL(currentFile.originFile)
|
|
|
|
|
});
|
|
|
|
|
if (currentFile.status === 'done') setSelectedImage(currentFile.response.data.link);
|
|
|
|
|
}}
|
|
|
|
|
onProgress={(currentFile) => {
|
|
|
|
|
setFile(currentFile);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<div className={cs}>
|
|
|
|
|
{file && file.url ? (
|
|
|
|
|
<div className="arco-upload-list-item-picture custom-upload-avatar">
|
|
|
|
|
<img src={file.url} />
|
|
|
|
|
<div className="arco-upload-list-item-picture-mask">
|
|
|
|
|
<IconEdit />
|
|
|
|
|
</div>
|
|
|
|
|
{file.status === 'uploading' && file.percent < 100 && (
|
|
|
|
|
<Progress
|
|
|
|
|
percent={file.percent}
|
|
|
|
|
type="circle"
|
|
|
|
|
size="mini"
|
|
|
|
|
style={{
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
left: '50%',
|
|
|
|
|
top: '50%',
|
|
|
|
|
transform: 'translateX(-50%) translateY(-50%)'
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<div className="arco-upload-trigger-picture">
|
|
|
|
|
<div className="arco-upload-trigger-picture-text">
|
|
|
|
|
<IconPlus />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</Upload>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Modal
|
|
|
|
|
className={styles['add-component-modal']}
|
|
|
|
|
title="新增组件"
|
|
|
|
|
visible={visible}
|
|
|
|
|
onOk={() => setVisible(false)}
|
|
|
|
|
onCancel={() => setVisible(false)}
|
|
|
|
|
autoFocus={false}
|
|
|
|
|
focusLock={true}
|
|
|
|
|
style={{ width: '60%' }}
|
|
|
|
|
@ -68,12 +233,8 @@ const AddComponentModal = ({ visible, setVisible }) => {
|
|
|
|
|
<Form form={form} className={styles['add-component-container']}>
|
|
|
|
|
<div className={styles['first-half']}>
|
|
|
|
|
<div className={styles['component-preview']}>
|
|
|
|
|
<FormItem label="图标:">
|
|
|
|
|
<Cover
|
|
|
|
|
defaultImage={selectedImage}
|
|
|
|
|
imgWidth={100}
|
|
|
|
|
onImageChange={(selectedImage) => transformImageUrl(selectedImage)}
|
|
|
|
|
/>
|
|
|
|
|
<FormItem label="图标:" field="logoUrl">
|
|
|
|
|
<UploadImage />
|
|
|
|
|
</FormItem>
|
|
|
|
|
<FormItem label="组件预览:">
|
|
|
|
|
<div
|
|
|
|
|
@ -83,7 +244,6 @@ const AddComponentModal = ({ visible, setVisible }) => {
|
|
|
|
|
border: '1px solid #dcdfe6',
|
|
|
|
|
borderRadius: 5
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
>组件外壳
|
|
|
|
|
</div>
|
|
|
|
|
</FormItem>
|
|
|
|
|
@ -91,53 +251,152 @@ const AddComponentModal = ({ visible, setVisible }) => {
|
|
|
|
|
<div className={styles['component-info']}>
|
|
|
|
|
<Grid.Row gutter={8}>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem label="名称:">
|
|
|
|
|
<FormItem label="名称:" field="name" required rules={[
|
|
|
|
|
{
|
|
|
|
|
validator(value, cb) {
|
|
|
|
|
if (!value) {
|
|
|
|
|
return cb('请输入名称');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cb();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]}>
|
|
|
|
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem label="名称:">
|
|
|
|
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
|
|
|
|
<FormItem label="代码标识:" field="projectId" required rules={[
|
|
|
|
|
{
|
|
|
|
|
validator(value, cb) {
|
|
|
|
|
if (!value) {
|
|
|
|
|
return cb('请输入代码标识');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cb();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]}>
|
|
|
|
|
<Input
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
allowClear
|
|
|
|
|
placeholder="请输入代码标识"
|
|
|
|
|
onChange={(e) => validateProjectId(e)}
|
|
|
|
|
/>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
</Grid.Row>
|
|
|
|
|
<Grid.Row gutter={8}>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem label="名称:">
|
|
|
|
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
|
|
|
|
<FormItem label="分类:" field="componentClassify" required rules={[
|
|
|
|
|
{
|
|
|
|
|
validator(value, cb) {
|
|
|
|
|
if (!value) {
|
|
|
|
|
return cb('请选择分类');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cb();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]}>
|
|
|
|
|
<Select
|
|
|
|
|
placeholder="请选择分类"
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
>
|
|
|
|
|
{classifyList.map((option, index) => (
|
|
|
|
|
<Option key={option.id} value={option.label}>
|
|
|
|
|
{option.label}
|
|
|
|
|
</Option>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem label="名称:">
|
|
|
|
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
|
|
|
|
<FormItem label="组件语言:" field="codeLanguage" required rules={[
|
|
|
|
|
{
|
|
|
|
|
validator(value, cb) {
|
|
|
|
|
if (!value) {
|
|
|
|
|
return cb('请选择组件语言');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cb();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]}>
|
|
|
|
|
<Select
|
|
|
|
|
placeholder="请选择组件语言"
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
>
|
|
|
|
|
{['Java:8', 'Python:3.10.12'].map((option, index) => (
|
|
|
|
|
<Option key={option} disabled={index === 3} value={option}>
|
|
|
|
|
{option}
|
|
|
|
|
</Option>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
</Grid.Row>
|
|
|
|
|
<Grid.Row gutter={8}>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem label="名称:">
|
|
|
|
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
|
|
|
|
<FormItem label="标签:" field="tags">
|
|
|
|
|
<Select
|
|
|
|
|
placeholder="请选择标签"
|
|
|
|
|
allowCreate
|
|
|
|
|
mode="multiple"
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
>
|
|
|
|
|
{tagsList.map((option, index) => (
|
|
|
|
|
<Option key={option.value} value={option.value}>
|
|
|
|
|
{option.label}
|
|
|
|
|
</Option>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem label="名称:">
|
|
|
|
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
|
|
|
|
<FormItem label="组件类型:" field="type" required rules={[
|
|
|
|
|
{
|
|
|
|
|
validator(value, cb) {
|
|
|
|
|
if (!value) {
|
|
|
|
|
return cb('请选择组件类型');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cb();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]}>
|
|
|
|
|
<Select
|
|
|
|
|
placeholder="请选择组件类型"
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
>
|
|
|
|
|
{['普通组件', '监听组件'].map((option, index) => (
|
|
|
|
|
<Option key={option} disabled={index === 3} value={option}>
|
|
|
|
|
{option}
|
|
|
|
|
</Option>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
</Grid.Row>
|
|
|
|
|
<FormItem label="名称:">
|
|
|
|
|
富文本编辑器
|
|
|
|
|
</FormItem>
|
|
|
|
|
|
|
|
|
|
<div className={styles['markdown-editor']}>
|
|
|
|
|
<div className={styles['markdown-label']}>描述:</div>
|
|
|
|
|
<EditorSection initialContent={description} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['last-half']}>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{showSaveBtn && <div className={styles['last-half']}>
|
|
|
|
|
<div className={styles['last-half-header']}>
|
|
|
|
|
<p> 组件接口</p>
|
|
|
|
|
<Space split={<Divider type="vertical" />}>
|
|
|
|
|
<Button size="small" type="secondary" style={{ borderRadius: 5 }}>代码初始化</Button>
|
|
|
|
|
<Button size="mini" type="primary" style={{ borderRadius: 5 }}>+ 新增接口</Button>
|
|
|
|
|
</Space>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Table columns={columns} data={data} pagination={false} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>}
|
|
|
|
|
</Form>
|
|
|
|
|
</Modal>
|
|
|
|
|
);
|
|
|
|
|
|