feat(component): 实现组件列表页面及新增组件弹窗

master
钟良源 3 months ago
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 });
}

@ -230,4 +230,29 @@ export interface GlobalParams {
arrayType: any, arrayType: any,
defaultValue: any, defaultValue: any,
sceneId: string, sceneId: string,
} }
// component
export interface ComponentItem {
id: number;
name: string;
identifier: string;
projectId: string;
componentClassify: string;
codeLanguage: string;
desc: string;
componentStatus: string;
tags: string[];
version: string;
logoUrl: string;
localProjectPath: string;
publishStatus: number;
publicStatus: number;
publishTime: string;
updateTime: string;
onlineInstanceCount: number;
createUser: string;
permission: string;
repoCloneUrl: string;
createUserName: string;
}

@ -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…
Cancel
Save