feat(component): 实现组件列表页面及新增组件弹窗
parent
9ce152a85c
commit
4a9390a211
@ -0,0 +1,9 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
// 公共路径
|
||||||
|
const urlPrefix = '/api/v1/bpms-workbench';
|
||||||
|
|
||||||
|
// 我的组件
|
||||||
|
export function getMyComponentList(params) {
|
||||||
|
return axios.get(`${urlPrefix}/componentBase/list`, { params });
|
||||||
|
}
|
||||||
@ -0,0 +1,146 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Modal, Form, Input, Grid, Space, Divider, Button, Table, TableColumnProps } from '@arco-design/web-react';
|
||||||
|
import styles from './style/addComponentModal.module.less';
|
||||||
|
import Cover from '@/pages/scene/cover';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
const columns: TableColumnProps[] = [
|
||||||
|
{
|
||||||
|
title: '接口名称',
|
||||||
|
dataIndex: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '输入参数',
|
||||||
|
dataIndex: 'salary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '输出参数',
|
||||||
|
dataIndex: 'address'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'email'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
name: 'Jane Doe',
|
||||||
|
salary: 23000,
|
||||||
|
address: '32 Park Road, London',
|
||||||
|
email: 'jane.doe@example.com'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
const AddComponentModal = ({ visible, setVisible }) => {
|
||||||
|
const [selectedImage, setSelectedImage] = useState('');
|
||||||
|
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 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>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
className={styles['add-component-modal']}
|
||||||
|
title="新增组件"
|
||||||
|
visible={visible}
|
||||||
|
onOk={() => setVisible(false)}
|
||||||
|
onCancel={() => setVisible(false)}
|
||||||
|
autoFocus={false}
|
||||||
|
focusLock={true}
|
||||||
|
style={{ width: '60%' }}
|
||||||
|
footer={modalFooter}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
<FormItem label="组件预览:">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: '80%',
|
||||||
|
height: 200,
|
||||||
|
border: '1px solid #dcdfe6',
|
||||||
|
borderRadius: 5
|
||||||
|
}}
|
||||||
|
|
||||||
|
>组件外壳
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
</div>
|
||||||
|
<div className={styles['component-info']}>
|
||||||
|
<Grid.Row gutter={8}>
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<FormItem label="名称:">
|
||||||
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
||||||
|
</FormItem>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<FormItem label="名称:">
|
||||||
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
||||||
|
</FormItem>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid.Row>
|
||||||
|
<Grid.Row gutter={8}>
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<FormItem label="名称:">
|
||||||
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
||||||
|
</FormItem>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<FormItem label="名称:">
|
||||||
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
||||||
|
</FormItem>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid.Row>
|
||||||
|
<Grid.Row gutter={8}>
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<FormItem label="名称:">
|
||||||
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
||||||
|
</FormItem>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={12}>
|
||||||
|
<FormItem label="名称:">
|
||||||
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
|
||||||
|
</FormItem>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid.Row>
|
||||||
|
<FormItem label="名称:">
|
||||||
|
富文本编辑器
|
||||||
|
</FormItem>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles['last-half']}>
|
||||||
|
<div className={styles['last-half-header']}>
|
||||||
|
<p> 组件接口</p>
|
||||||
|
<Button size="mini" type="primary" style={{ borderRadius: 5 }}>+ 新增接口</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Table columns={columns} data={data} pagination={false} />
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddComponentModal;
|
||||||
@ -1,98 +1,208 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import styles from './style/index.module.less';
|
import styles from './style/index.module.less';
|
||||||
import { Button, Divider, Input, Space, Table, Radio } from '@arco-design/web-react';
|
import { Button, Divider, Input, Space, Table, Radio, Pagination } from '@arco-design/web-react';
|
||||||
import { IconSearch } from '@arco-design/web-react/icon';
|
import { IconSearch } from '@arco-design/web-react/icon';
|
||||||
|
import { getMyComponentList } from '@/api/componentBase';
|
||||||
|
import { ComponentItem } from '@/api/interface';
|
||||||
|
import AddComponentModal from '@/pages/componentDevelopment/componentList/addComponentModal';
|
||||||
|
|
||||||
const Group = Radio.Group;
|
const Group = Radio.Group;
|
||||||
|
|
||||||
|
const menuItems = [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
label: '我的组件',
|
||||||
|
icon: '/ideContainer/icon/myComp.png',
|
||||||
|
activeIcon: '/ideContainer/icon/myComp_active.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
label: '协同组件',
|
||||||
|
icon: '/ideContainer/icon/teamComp.png',
|
||||||
|
activeIcon: '/ideContainer/icon/teamComp_active.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
label: '组件审核',
|
||||||
|
icon: '/ideContainer/icon/compAudit.png',
|
||||||
|
activeIcon: '/ideContainer/icon/compAudit_active.png'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '组件名称',
|
||||||
|
dataIndex: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '标识符',
|
||||||
|
dataIndex: 'identifier'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '分类',
|
||||||
|
dataIndex: 'componentClassify'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '语言',
|
||||||
|
dataIndex: 'codeLanguage'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
dataIndex: 'desc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'componentStatus'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新时间',
|
||||||
|
dataIndex: 'updateTime'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'operations',
|
||||||
|
render: () => (
|
||||||
|
<Button type="text">详情</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
const GlobalVarContainer = () => {
|
const GlobalVarContainer = () => {
|
||||||
const [selectedItem, setSelectedItem] = useState('数字类型');
|
const [selectedItem, setSelectedItem] = useState('我的组件');
|
||||||
|
const [componentData, setComponentData] = useState<ComponentItem[]>([]);
|
||||||
|
const [pagination, setPagination] = useState({
|
||||||
|
totalCount: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
totalPage: 0,
|
||||||
|
currPage: 1
|
||||||
|
});
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
const menuItems = [
|
useEffect(() => {
|
||||||
{
|
if (selectedItem === '我的组件') {
|
||||||
key: '1',
|
fetchComponentData();
|
||||||
label: '我的组件',
|
|
||||||
icon: '/ideContainer/icon/myComp.png',
|
|
||||||
activeIcon: '/ideContainer/icon/myComp_active.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '2',
|
|
||||||
label: '协同组件',
|
|
||||||
icon: '/ideContainer/icon/teamComp.png',
|
|
||||||
activeIcon: '/ideContainer/icon/teamComp_active.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '3',
|
|
||||||
label: '组件审核',
|
|
||||||
icon: '/ideContainer/icon/compAudit.png',
|
|
||||||
activeIcon: '/ideContainer/icon/compAudit_active.png'
|
|
||||||
}
|
}
|
||||||
];
|
}, [selectedItem, pagination.currPage, pagination.pageSize]);
|
||||||
|
|
||||||
|
const fetchComponentData = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res: any = await getMyComponentList({
|
||||||
|
currPage: pagination.currPage,
|
||||||
|
pageSize: pagination.pageSize
|
||||||
|
});
|
||||||
|
|
||||||
|
setComponentData(res.list);
|
||||||
|
setPagination({
|
||||||
|
totalCount: res.totalCount,
|
||||||
|
pageSize: res.pageSize,
|
||||||
|
totalPage: res.totalPage,
|
||||||
|
currPage: res.currPage
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取组件列表失败:', error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePageChange = (page: number, pageSize?: number) => {
|
||||||
|
setPagination({
|
||||||
|
...pagination,
|
||||||
|
currPage: page,
|
||||||
|
pageSize: pageSize || pagination.pageSize
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles['comp-list-container']}>
|
<>
|
||||||
{/*左侧菜单*/}
|
<div className={styles['comp-list-container']}>
|
||||||
<div className={styles['comp-list-menu']}>
|
{/*左侧菜单*/}
|
||||||
{menuItems.map((item, index) => (
|
<div className={styles['comp-list-menu']}>
|
||||||
<div
|
{menuItems.map((item, index) => (
|
||||||
key={index}
|
<div
|
||||||
className={selectedItem === item.label ? styles['selected'] : ''}
|
key={index}
|
||||||
onClick={() => setSelectedItem(item.label)}
|
className={selectedItem === item.label ? styles['selected'] : ''}
|
||||||
>
|
onClick={() => setSelectedItem(item.label)}
|
||||||
<img src={selectedItem === item.label ? item.activeIcon : item.icon} alt=""
|
>
|
||||||
style={{ width: 20, height: 20, marginRight: 12 }} />
|
<img src={selectedItem === item.label ? item.activeIcon : item.icon} alt=""
|
||||||
<span>{item.label}</span>
|
style={{ width: 20, height: 20, marginRight: 12 }} />
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className={styles['comp-list-content']}>
|
||||||
|
{/*头部*/}
|
||||||
|
<div className={styles['comp-list-header']}>
|
||||||
|
<div className={styles['comp-list-search']}>
|
||||||
|
<Space>
|
||||||
|
<Input
|
||||||
|
prefix={<IconSearch />}
|
||||||
|
placeholder={'搜索'}
|
||||||
|
style={{ width: 236 }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
style={{ marginLeft: 5, borderRadius: 4 }}
|
||||||
|
>
|
||||||
|
搜索
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
<div className={styles['comp-list-handle']}>
|
||||||
|
<Radio.Group defaultValue={'Beijing'} name="button-radio-group">
|
||||||
|
{['未设计', '编码中', '已部署'].map((item) => {
|
||||||
|
return (
|
||||||
|
<Radio key={item} value={item}>
|
||||||
|
{({ checked }) => {
|
||||||
|
return (
|
||||||
|
<Button tabIndex={-1} key={item} shape="round" type={checked ? 'primary' : 'default'}>
|
||||||
|
{item}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Radio>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Radio.Group>
|
||||||
|
<Space split={<Divider type="vertical" />}>
|
||||||
|
<Button type="secondary" style={{ borderRadius: 4 }}>生成组件</Button>
|
||||||
|
<Button type="outline" style={{ borderRadius: 4 }}>导入组件</Button>
|
||||||
|
<Button type="primary" style={{ borderRadius: 4 }} onClick={() => setVisible(true)}>+
|
||||||
|
新增组件</Button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
{/*数据列表*/}
|
||||||
</div>
|
<div className={styles['comp-list-list']}>
|
||||||
<div className={styles['comp-list-content']}>
|
<Table
|
||||||
{/*头部*/}
|
columns={columns}
|
||||||
<div className={styles['comp-list-header']}>
|
data={componentData}
|
||||||
<div className={styles['comp-list-search']}>
|
loading={loading}
|
||||||
<Space>
|
pagination={false}
|
||||||
<Input
|
/>
|
||||||
prefix={<IconSearch />}
|
<div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 16 }}>
|
||||||
placeholder={'搜索'}
|
<Pagination
|
||||||
style={{ width: 236 }}
|
current={pagination.currPage}
|
||||||
|
pageSize={pagination.pageSize}
|
||||||
|
total={pagination.totalCount}
|
||||||
|
// showTotal={(total, range) => `第 ${range[0]}-${range[1]} 条,共 ${total} 条`}
|
||||||
|
onChange={handlePageChange}
|
||||||
/>
|
/>
|
||||||
<Button
|
</div>
|
||||||
type="primary"
|
|
||||||
style={{ marginLeft: 5, borderRadius: 4 }}
|
|
||||||
>
|
|
||||||
搜索
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
<div className={styles['comp-list-handle']}>
|
|
||||||
<Radio.Group defaultValue={'Beijing'} name="button-radio-group">
|
|
||||||
{['未设计', '编码中', '已部署'].map((item) => {
|
|
||||||
return (
|
|
||||||
<Radio key={item} value={item}>
|
|
||||||
{({ checked }) => {
|
|
||||||
return (
|
|
||||||
<Button tabIndex={-1} key={item} shape="round" type={checked ? 'primary' : 'default'}>
|
|
||||||
{item}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Radio>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Radio.Group>
|
|
||||||
<Space split={<Divider type="vertical" />}>
|
|
||||||
<Button type="secondary" style={{ borderRadius: 4 }}>生成组件</Button>
|
|
||||||
<Button type="outline" style={{ borderRadius: 4 }}>导入组件</Button>
|
|
||||||
<Button type="primary" style={{ borderRadius: 4 }}>+ 新增组件</Button>
|
|
||||||
</Space>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
{/*数据列表*/}
|
|
||||||
<div className={styles['comp-list-list']}>
|
|
||||||
{/*<Table columns={columns} data={eventData} pagination={false} />*/}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
{/*新增弹窗*/}
|
||||||
|
<AddComponentModal
|
||||||
|
visible={visible}
|
||||||
|
setVisible={setVisible}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
.add-component-modal {
|
||||||
|
:global(.arco-modal-content) {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
background-color: #f7f8fa
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-component-container {
|
||||||
|
|
||||||
|
.first-half {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.component-preview {
|
||||||
|
overflow: hidden;
|
||||||
|
width: 30%;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 15px 5px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-info {
|
||||||
|
width: 67%;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 15px 5px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.last-half {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 15px 20px;
|
||||||
|
|
||||||
|
.last-half-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue