feat(scene): 新增工程场景页面功能
- 添加创建和编辑工程场景的弹窗 - 实现工程场景列表的展示和分页 - 增加工程场景的搜索功能 - 添加工程场景的封面图选择功能 - 实现工程场景的大屏配置功能master
parent
599d37c46d
commit
1bf8b3e9cf
@ -0,0 +1,101 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Button, Input, Table, TableColumnProps } from '@arco-design/web-react';
|
||||||
|
import { IconDelete, IconPlusCircle } from '@arco-design/web-react/icon';
|
||||||
|
|
||||||
|
interface TableDataItem {
|
||||||
|
key: number | string;
|
||||||
|
label: string;
|
||||||
|
url: string;
|
||||||
|
|
||||||
|
[key: string]: any; // 允许其他自定义字段
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConfigTable = () => {
|
||||||
|
const [tableData, setTableData] = useState([]);
|
||||||
|
|
||||||
|
const columns: TableColumnProps[] = [
|
||||||
|
{
|
||||||
|
title: '标签',
|
||||||
|
dataIndex: 'label',
|
||||||
|
render: (_: any, record: TableDataItem) => (
|
||||||
|
<Input
|
||||||
|
value={record.label}
|
||||||
|
onChange={(value) => handleSave({ ...record, label: value })}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'url',
|
||||||
|
dataIndex: 'url',
|
||||||
|
render: (_: any, record: TableDataItem) => (
|
||||||
|
<Input
|
||||||
|
value={record.url}
|
||||||
|
onChange={(value) => handleSave({ ...record, url: value })}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'address',
|
||||||
|
render: (_: any, record: TableDataItem) => (
|
||||||
|
<Button onClick={() => removeRow(record.key)} type="text" status="danger">
|
||||||
|
<IconDelete />
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const newKey = Date.now();
|
||||||
|
const addRow = () => {
|
||||||
|
const newRow = {
|
||||||
|
key: newKey,
|
||||||
|
label: '',
|
||||||
|
url: ''
|
||||||
|
};
|
||||||
|
const newData = [...tableData, newRow];
|
||||||
|
setTableData(newData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeRow = (key: number | string) => {
|
||||||
|
const newData = tableData.filter((item) => item.key !== key);
|
||||||
|
setTableData(newData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = (row: TableDataItem) => {
|
||||||
|
const newData = [...tableData];
|
||||||
|
const index = newData.findIndex((item) => row.key === item.key);
|
||||||
|
if (index >= 0) {
|
||||||
|
newData.splice(index, 1, { ...newData[index], ...row });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newData.push(row);
|
||||||
|
}
|
||||||
|
setTableData(newData);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{!!tableData.length && (
|
||||||
|
<>
|
||||||
|
<Table columns={columns} data={tableData} />
|
||||||
|
<Button
|
||||||
|
style={{ height: 45, marginTop: 5 }}
|
||||||
|
long
|
||||||
|
type="outline"
|
||||||
|
onClick={addRow}
|
||||||
|
>
|
||||||
|
+ 添加
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!tableData.length && (
|
||||||
|
<div className={'add-icon'}>
|
||||||
|
<IconPlusCircle style={{ fontSize: 24, color: 'rgb(0, 117, 255)', cursor: 'pointer' }} onClick={addRow} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ConfigTable;
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import styles from '@/pages/scene/style/cover.module.less';
|
||||||
|
import { Image, Modal, List } from '@arco-design/web-react';
|
||||||
|
import scene01 from '@/assets/images/scene01.jpg';
|
||||||
|
import scene02 from '@/assets/images/scene02.jpg';
|
||||||
|
import scene03 from '@/assets/images/scene03.jpeg';
|
||||||
|
import scene04 from '@/assets/images/scene04.png';
|
||||||
|
import scene07 from '@/assets/images/scene07.png';
|
||||||
|
import scene08 from '@/assets/images/scene08.jpg';
|
||||||
|
import { getImageUrl } from '@/utils/pubUse';
|
||||||
|
|
||||||
|
const imageList = [scene01, scene02, scene03, scene04, scene07, scene08];
|
||||||
|
|
||||||
|
interface CoverProps {
|
||||||
|
defaultImage?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Cover: React.FC<CoverProps> = ({ defaultImage }) => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const [currentImage, setCurrentImage] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (defaultImage) {
|
||||||
|
setCurrentImage(getImageUrl(defaultImage));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const imageRandom = Math.floor(Math.random() * imageList.length);
|
||||||
|
setCurrentImage(imageList[imageRandom].src);
|
||||||
|
}
|
||||||
|
}, [defaultImage]);
|
||||||
|
return (
|
||||||
|
<div className={styles['cover-container']}>
|
||||||
|
<div className={styles['cover-image']}>
|
||||||
|
<Image width={200} src={currentImage} preview={false} onClick={() => setVisible(true)}></Image>
|
||||||
|
</div>
|
||||||
|
<Modal
|
||||||
|
style={{ width: '60%' }}
|
||||||
|
title="选择封面图"
|
||||||
|
visible={visible}
|
||||||
|
onOk={() => setVisible(false)}
|
||||||
|
onCancel={() => setVisible(false)}
|
||||||
|
autoFocus={false}
|
||||||
|
focusLock={true}
|
||||||
|
>
|
||||||
|
<List
|
||||||
|
grid={{ gutter: 0, span: 6 }}
|
||||||
|
size="small"
|
||||||
|
dataSource={imageList}
|
||||||
|
render={(item, index) => {
|
||||||
|
return (
|
||||||
|
<List.Item key={index}>
|
||||||
|
<Image width={200} src={item.src} preview={false} onClick={() => {
|
||||||
|
setCurrentImage(item.src);
|
||||||
|
setVisible(false);
|
||||||
|
}}></Image>
|
||||||
|
</List.Item>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Cover;
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { Modal, Form, Input, Checkbox } from '@arco-design/web-react';
|
||||||
|
import Cover from '@/pages/scene/cover';
|
||||||
|
import ConfigTable from '@/pages/scene/configTable';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
interface OperationModalProps {
|
||||||
|
show: boolean;
|
||||||
|
type: string;
|
||||||
|
item: any;
|
||||||
|
onCancel: (status: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OperationModal: React.FC<OperationModalProps> = ({ show, type, item, onCancel }) => {
|
||||||
|
const [visible, setVisible] = React.useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setVisible(show);
|
||||||
|
}, [show]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
style={{ width: '50%' }}
|
||||||
|
title={type === 'ADD' ? '创建工程' : '编辑工程'}
|
||||||
|
visible={visible}
|
||||||
|
onOk={() => setVisible(false)}
|
||||||
|
onCancel={() => onCancel(false)}
|
||||||
|
autoFocus={false}
|
||||||
|
focusLock={true}
|
||||||
|
>
|
||||||
|
<Form autoComplete="off">
|
||||||
|
<FormItem label="封面图">
|
||||||
|
<Cover defaultImage={item?.logo} />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="名称" required>
|
||||||
|
<Input placeholder="请输入工程名称" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="描述" required>
|
||||||
|
<Input placeholder="请输入工程描述" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="大屏">
|
||||||
|
<ConfigTable />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label=" ">
|
||||||
|
<Checkbox>是否公开</Checkbox>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OperationModal;
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
.cover-container {
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue