样式修改

main
zjlnb666 3 weeks ago
parent 8b9c5ffbba
commit e4eeefc275

@ -52,6 +52,18 @@ export default [
name: 'assetlist',
component: './assetmangement_assetgrouping/AssetGrouping',
},
// 资产属性定义
{
path: '/topnavbar00/business/assetmanagement/assetdefined',
name: 'assetdefined',
component: './assetmangement_assetdefined/AssetDefined',
},
// 资产维保管理
{
path: '/topnavbar00/business/assetmanagement/maintenance',
name: 'maintenance',
component: './assetmangement_maintenance/Maintenance',
},
]
}
],

@ -14,7 +14,7 @@
"dependencies": {
"@ant-design/icons": "^4.8.0",
"@umijs/max": "^4.0.70",
"antd": "5.6.0",
"antd": "5.10.0",
"braft-editor": "^2.3.9",
"braft-finder": "^0.0.21",
"braft-utils": "^3.0.2",

@ -0,0 +1,58 @@
<svg width="76" height="76" viewBox="0 0 76 76" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2942_31317)">
<g filter="url(#filter0_dif_2942_31317)">
<path d="M35.4467 10.0789H35.3354C18.458 10.0789 4.76465 23.7722 4.76465 40.6496C4.76465 57.5269 18.458 71.2203 35.3354 71.2203C52.1756 71.2203 65.8689 57.6011 65.9061 40.7609H35.4467V10.0789Z" fill="url(#paint0_linear_2942_31317)"/>
</g>
<foreignObject x="29.3865" y="-6.53511" width="53.2821" height="55.7966"><div xmlns="http://www.w3.org/1999/xhtml" style="backdrop-filter:blur(5.65px);clip-path:url(#bgblur_1_2942_31317_clip_path);height:100%;width:100%"></div></foreignObject><g filter="url(#filter1_di_2942_31317)" data-figma-bg-blur-radius="11.3">
<path d="M40.7979 4.76489H40.6865V35.2614H71.3686C71.3314 18.384 57.6381 4.76489 40.7979 4.76489Z" fill="white" fill-opacity="0.6" shape-rendering="crispEdges"/>
<path d="M40.9365 5.01587C57.4921 5.09001 70.9435 18.4342 71.1143 35.011H40.9365V5.01587Z" stroke="url(#paint1_linear_2942_31317)" stroke-width="0.5" shape-rendering="crispEdges"/>
</g>
</g>
<defs>
<filter id="filter0_dif_2942_31317" x="-5.23535" y="4.07886" width="81.1416" height="81.1414" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.545673 0 0 0 0 1 0 0 0 0 0.85613 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2942_31317"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2942_31317" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.1"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="shape" result="effect2_innerShadow_2942_31317"/>
<feGaussianBlur stdDeviation="1" result="effect3_foregroundBlur_2942_31317"/>
</filter>
<filter id="filter1_di_2942_31317" x="29.3865" y="-6.53511" width="53.2821" height="55.7966" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.545673 0 0 0 0 1 0 0 0 0 0.795553 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2942_31317"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2942_31317" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.1"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="shape" result="effect2_innerShadow_2942_31317"/>
</filter>
<clipPath id="bgblur_1_2942_31317_clip_path" transform="translate(-29.3865 6.53511)"><path d="M40.7979 4.76489H40.6865V35.2614H71.3686C71.3314 18.384 57.6381 4.76489 40.7979 4.76489Z"/>
</clipPath><linearGradient id="paint0_linear_2942_31317" x1="-25.9151" y1="70.1833" x2="69.7658" y2="45.9344" gradientUnits="userSpaceOnUse">
<stop stop-color="#15A669"/>
<stop offset="1" stop-color="#7FE2B4"/>
</linearGradient>
<linearGradient id="paint1_linear_2942_31317" x1="62.7821" y1="-5.87747" x2="35.7299" y2="30.9278" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<clipPath id="clip0_2942_31317">
<rect width="76" height="76" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

@ -0,0 +1,122 @@
import {Pagination, Table} from "antd";
import {useEffect, useState} from "react";
const TableWithPagination = ({
columns, // 表格列配置(必需)
dataSource: externalDataSource, // 外部传入的静态数据(可选,与 fetchData 二选一)
fetchData, // 外部传入的动态请求函数(可选)
paginationProps = {
total: 0,
defaultPageSize: 5,
pageSizeOptions: ["5", "10", "20", "50"],
}, // 分页参数(可选,带默认值)
rowSelection = false, // 是否显示复选框(默认 false
tableStyle = {}, // 表格样式(可选)
paginationStyle = {}, // 分页组件样式(可选)
rowKey = "key", // 行唯一标识(默认 'key'
}) => {
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(paginationProps.defaultPageSize || 5);
const [total, setTotal] = useState(paginationProps.total || 0);
const [tableData, setTableData] = useState(externalDataSource || []);
const [isLoading, setIsLoading] = useState(false);
const {pageSizeOptions}= paginationProps
// 动态请求数据(如果外部传入 fetchData则内部触发请求
const loadData = async () => {
if (!fetchData) return; // 无请求函数,使用静态数据
try {
setIsLoading(true);
// 调用外部传入的请求函数,传入当前页码和页大小
const data = await fetchData(currentPage, pageSize);
setTableData(data);
// 注意:总条数如果由接口返回,需要外部在 fetchData 中处理(或通过 props 传递更新)
// 这里简化为:如果外部传入 total直接使用否则由数据长度推导仅静态场景
if (paginationProps.total === undefined && externalDataSource) {
setTotal(externalDataSource.length);
}
} catch (error) {
console.error("表格数据请求失败:", error);
setTableData([]);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
// 缓冲一下,避免中间态请求(优化体验)
const timer = setTimeout(() => {
loadData();
}, 0);
return () => clearTimeout(timer);
}, [currentPage, pageSize, fetchData]);
// 监听外部传入的静态数据变化(如果外部数据更新,表格同步更新)
useEffect(() => {
if (externalDataSource) {
setTableData(externalDataSource);
setTotal(paginationProps.total || externalDataSource.length);
}
}, [externalDataSource, paginationProps.total]);
// 页码变更处理
const handlePageChange = (page) => {
setCurrentPage(page);
};
// 页大小变更处理(重置页码为 1
const handleShowSizeChange = (_, size) => {
setPageSize(size);
setCurrentPage(1);
};
// 处理复选框选择(如果外部需要,可通过 props 传递 onChange
const handleRowSelection =
typeof rowSelection === "object" && rowSelection.onChange
? rowSelection.onChange
: () => {};
// 组装复选框配置
const rowSelectionConfig = rowSelection
? {
type: "checkbox",
onChange: handleRowSelection,
...(typeof rowSelection === "object" ? rowSelection : {}),
}
: null;
return (
<div style={{width: "100%", ...tableStyle}}>
<Table
columns={columns}
dataSource={tableData}
rowKey={rowKey}
pagination={false} // 关闭 AntD 自带分页,使用自定义分页
rowSelection={rowSelectionConfig}
loading={isLoading}
bordered={false}
scroll={{x: "max-content"}} // 适配多列,避免横向溢出
className="zjl-table-header"
/>
<style jsx={true} >{`
:global(.zjl-table-header .ant-table-thead > tr > th) {
background-color: #F0F7F7 !important;
}
`}</style>
{/* 分页组件 */}
<div style={{textAlign: "right", marginTop: 16, ...paginationStyle}}>
<Pagination
current={currentPage}
pageSize={pageSize}
total={total}
onChange={handlePageChange}
onShowSizeChange={handleShowSizeChange}
showSizeChanger
pageSizeOptions={pageSizeOptions}
showTotal={(total) => `${total} 条记录`}
/>
</div>
</div>
)
}
export default TableWithPagination;

@ -0,0 +1,432 @@
import {Button, Col, Form, Input, Radio, Row, Select, Space, Tag, Tree} from "antd";
import TableWithPagination from "../../components/assetmangement/table";
import Title from '../homepage/compontent/title'
import styles from './AssetDefined.less'
import {PlusOutlined, PushpinOutlined} from "@ant-design/icons";
const AssetDefined = () => {
// 数据源
const dataSource = [
{
key: '1',
id: 1,
propertyName: '通信协议',
type: 'enum',
required: true,
defaultValue: 'MQTT',
enumValues: ['MQTT', 'COAP', 'HTTP'],
description: '设备与平台的通信协议',
validationRule: '',
displayOrder: 1,
},
{
key: '2',
id: 2,
propertyName: '供电电压',
type: 'number',
required: true,
defaultValue: '12',
enumValues: [],
description: '设备供电电压单位V',
validationRule: '5-24',
displayOrder: 2,
},
{
key: '3',
id: 3,
propertyName: '设备型号',
type: 'text',
required: true,
defaultValue: 'DS18B20',
enumValues: [],
description: '传感器的具体型号标识',
validationRule: '',
displayOrder: 3,
},
{
key: '4',
id: 4,
propertyName: '支持无线',
type: 'boolean',
required: false,
defaultValue: 'false',
enumValues: [],
description: '设备是否具备无线通信能力',
validationRule: '',
displayOrder: 4,
},
{
key: '5',
id: 5,
propertyName: '软件版本号',
type: 'text',
required: true,
defaultValue: 'V1.0',
enumValues: [],
description: '嵌入式固件的版本标识',
validationRule: '^\\d+\\.\\d+$',
displayOrder: 5,
},
{
key: '6',
id: 6,
propertyName: '采样周期',
type: 'number',
required: true,
defaultValue: '10',
enumValues: [],
description: '传感器数据采样间隔,单位秒',
validationRule: '1-300',
displayOrder: 6,
},
{
key: '7',
id: 7,
propertyName: '安装位置',
type: 'text',
required: false,
defaultValue: '',
enumValues: [],
description: '设备的物理安装位置(如车间A-01)',
validationRule: '',
displayOrder: 7,
},
];
// 列配置
const columns = [
{
title: '序号',
dataIndex: 'id',
key: 'id',
width: 60,
align: 'center',
},
{
title: '属性名称',
dataIndex: 'propertyName',
key: 'propertyName',
width: 100,
},
{
title: '类型',
dataIndex: 'type',
key: 'type',
width: 80,
render: (type) => {
const typeMap = {
'enum': { text: '枚举', color: 'blue' },
'number': { text: '数值', color: 'green' },
'text': { text: '文本', color: 'orange' },
'boolean': { text: '布尔', color: 'purple' },
};
const typeInfo = typeMap[type] || { text: type, color: 'default' };
return <Tag color={typeInfo.color}>{typeInfo.text}</Tag>;
},
},
{
title: '是否必填',
dataIndex: 'required',
key: 'required',
width: 85,
render: (required) => (
<Tag color={required ? 'red' : 'green'}>
{required ? '是' : '否'}
</Tag>
),
},
{
title: '默认值',
dataIndex: 'defaultValue',
key: 'defaultValue',
width: 100,
},
{
title: '枚举值',
dataIndex: 'enumValues',
key: 'enumValues',
width: 160,
render: (values) => values.length > 0 ? values.join('、') : '-',
},
{
title: '描述',
dataIndex: 'description',
key: 'description',
width: 220,
},
{
title: '验证规则',
dataIndex: 'validationRule',
key: 'validationRule',
width: 100,
render: (rule) => rule || '-',
},
{
title: '显示顺序',
dataIndex: 'displayOrder',
key: 'displayOrder',
width: 85,
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align:'center',
render: (_, record) => (
<Space size="small">
<Button type="link" size="small" style={{ color: '#1890ff' }}>
编辑
</Button>
<Button type="link" size="small" style={{ color: '#52c41a' }}>
下载
</Button>
<Button type="link" size="small" danger>
删除
</Button>
</Space>
),
},
];
const treeData=[
{
title:'硬件',
key:'硬件',
children:[
{
title: '传感器',
key:'传感器',
children:[
{
title:'温度传感器',
key:'温度传感器',
children:[
{
title: 'DS18B20',
key:'DS18B20'
},
{
title: 'SHT30',
key:'SHT30'
},
]
},
{
title:'压力传感器',
key:'压力传感器',
children: [
{
title:'MPX570',
key:'MPX570'
}
]
}
]
},
{
title:'网关',
key:'网关',
children:[
{
title:'工业网关',
key:'工业网关',
children: [
{
title:'OW-200',
key:'OW-200',
}
]
}
]
},
{
title:'执行器',
key:'执行器',
children:[
{
title:'电磁阀',
key:'电磁阀',
children: [
{
title:'Ev-100',
key:'Ev-100'
}
]
}
]
}
]
},
{
title:'软件',
key:'软件',
children:[
{
title:'嵌入式程序',
key:'嵌入式程序',
children:[
{
title:'传感器固件',
key:'传感器固件',
children:[
{
title:'FW-TempV1.0',
key:'FW-TempV1.0',
}
]
}
]
},
{
title:'平台管理软件',
key:'平台管理软件',
children:[
{
title:'设备管理软件',
key:'设备管理软件',
children: [
{
title:'V3.2',
key:'V3.2',
}
]
}
]
}
]
}
]
return (
<div style={{padding:'20px'}}>
<Row gutter={20}>
<Col span={5}>
<div style={{padding:'20px',backgroundColor:'#e7f2ee',height:'100%'}}>
<Title title={'资产模型'}></Title>
<Tree
treeData={treeData}
showLine={true}
defaultExpandAll
style={{backgroundColor:'#e7f2ee',paddingTop:'20px'}}
checkable={true}
/>
</div>
</Col>
<Col span={19} style={{paddingBottom:'30px'}}>
<Title title={'单属性配置'}></Title>
<Form
layout="inline"
style={{
marginTop:'20px',
paddingBottom:'20px',
borderBottom:'1px solid #eeeeee'
}}
>
<Row gutter={[20,20]} >
<Col span={6}>
<Form.Item label="属性名称" name="name">
<Input placeholder={'请输入'} style={{width:'200px'}}/>
</Form.Item>
</Col>
<Col span={6}>
<Form.Item label='属性类型' name='type'>
<Select
style={{width:'132px'}}
defaultValue={'全部'}
options={[
{
label: '全部',
value: '全部',
}
]}
/>
</Form.Item>
</Col>
<Col span={6}>
<Form.Item label='枚举值配置'>
<Input placeholder={'请输入'} style={{width:'200px'}}></Input>
</Form.Item>
</Col>
<Col span={6}>
<Form.Item label={'是否必填'}>
<Radio.Group
>
<Radio value="1"></Radio>
<Radio value="2"></Radio>
</Radio.Group>
</Form.Item>
</Col>
<Col span={6}>
<Form.Item label={'默认值'}>
<Input placeholder={'请输入'} style={{width:'200px'}}/>
</Form.Item>
</Col>
<Col span={12} >
<Form.Item label={'描述'}>
<Input placeholder={'请输入'} style={{width:'522px'}}/>
</Form.Item>
</Col>
<Col span={6}>
<Form.Item label={'显示顺序'}>
<Input placeholder={'请输入'} style={{width:'200px'}}/>
</Form.Item>
</Col>
</Row>
<Row style={{marginTop:'20px',width:'100%'}} >
<Col span={12}>
<Form.Item label={'验证规则'}>
<Input placeholder={'请输入'} style={{width:'200px'}}/>
</Form.Item>
</Col>
<Col span={12} style={{textAlign:'right'}}>
<Button icon={<svg width="13" height="13" viewBox="0 0 13 13" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M5.90734 6.99734C6.05952 7.30875 5.83278 7.67188 5.48619 7.67188H1.40625C1.14736 7.67188 0.9375 7.88173 0.9375 8.14062V10.1719H12V8.14062C12 7.88173 11.7901 7.67188 11.5312 7.67188H7.48209C7.13717 7.67188 6.91038 7.31192 7.05927 7.00078L8.37405 4.25333C8.38031 4.23889 8.38739 4.22456 8.3953 4.21036C8.57581 3.88608 8.67188 3.52086 8.67188 3.14062C8.67188 1.92387 7.6855 0.9375 6.46875 0.9375C5.252 0.9375 4.26562 1.92387 4.26562 3.14062C4.26562 3.53387 4.36837 3.91103 4.56089 4.24325C4.57048 4.25979 4.57909 4.27687 4.58667 4.29442L5.90736 6.99734H5.90734ZM4.73545 6.73438L3.73755 4.69203C3.47066 4.22309 3.32812 3.69172 3.32812 3.14062C3.32812 1.40609 4.73422 0 6.46875 0C8.20328 0 9.60938 1.40609 9.60938 3.14062C9.60938 3.67473 9.4755 4.19047 9.224 4.64903L8.22606 6.73438H11.5312C12.3079 6.73438 12.9375 7.36397 12.9375 8.14062V10.6406C12.9375 10.8995 12.7276 11.1094 12.4688 11.1094H0.46875C0.209859 11.1094 0 10.8995 0 10.6406V8.14062C0 7.36397 0.629594 6.73438 1.40625 6.73438H4.73544H4.73545ZM0.46875 12.9297C0.209859 12.9297 0 12.7198 0 12.4609C0 12.202 0.209859 11.9922 0.46875 11.9922H12.4688C12.7276 11.9922 12.9375 12.202 12.9375 12.4609C12.9375 12.7198 12.7276 12.9297 12.4688 12.9297H0.46875Z" fill="white"/>
</svg>
} className={styles['search-button']} style={{marginRight: '30px'}}>提交审核</Button>
<Button icon={<svg width="13" height="13" viewBox="0 0 13 13" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M6.56446 0C4.9396 0 3.37972 0.65 2.20982 1.69L2.07983 0.65C2.07983 0.26 1.75486 5.08502e-08 1.36489 0.0650001C0.97492 0.0650001 0.714942 0.39 0.779936 0.78L0.909926 2.535C0.97492 3.38 1.68986 4.03 2.53479 4.03H2.66478L4.41964 3.9C4.80961 3.9 5.06959 3.575 5.00459 3.185C5.00459 2.795 4.67962 2.535 4.28965 2.6L2.98976 2.665C3.96468 1.82 5.19957 1.3 6.49947 1.3C9.35923 1.3 11.699 3.64 11.699 6.5C11.699 9.36 9.35923 11.7 6.49947 11.7C3.6397 11.7 1.29989 9.36 1.29989 6.5C1.29989 6.11 1.03992 5.85 0.649947 5.85C0.259979 5.85 -1.52331e-08 6.11 0 6.5C0 10.075 2.92476 13 6.49947 13C10.0742 13 12.9989 10.075 12.9989 6.5C13.0639 2.925 10.1392 -1.52344e-08 6.56446 0Z"
fill="#006665"/>
</svg>
} className={styles['reset-button']}>重置</Button>
</Col>
</Row>
</Form>
<Row style={{marginTop: '20px'}}>
<Title title={'属性列表'}></Title>
<Row style={{width:'100%',marginTop:'20px'}}>
<Col span={18}>
<Button style={{marginRight:'30px'}} className={styles['search-button']}>批量导入属性</Button>
<Button style={{marginRight:'30px'}} className={styles['reset-button']}>导出模型属性</Button>
<Button style={{marginRight:'30px'}} className={styles['del-button']}>删除</Button>
</Col>
<Col span={6} style={{textAlign:'right'}}>
<Button icon={<PlusOutlined></PlusOutlined>} className={styles['search-button']}></Button>
</Col>
</Row>
</Row>
<Row style={{width:'100%',marginTop:'20px'}}>
<TableWithPagination
columns={columns}
dataSource={dataSource}
tableStyle={{width: "100%"}}
paginationStyle={{textAlign: "right", marginTop: 16}}
rowKey="key"
rowSelection={{
onChange: (e) => {
console.log(e)
}
}}
/>
</Row>
</Col>
</Row>
</div>
)
}
export default AssetDefined;

@ -0,0 +1,34 @@
.search-button{
background-image: url('../../assets/img/assetmangement1.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: #fff;
border-radius: 4px;
height: 36px;
border-color:#d9d9d9 ;
background-color: #045F5E80;
}
.reset-button{
background-image: url('../../assets/img/assetmangement2.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: rgba(0, 102, 101, 1);
border-radius: 4px;
height: 36px;
border-color:#d9d9d9 ;
background-color: #B7E5D533;
}
.del-button{
background-image: url('../../assets/img/assetmangement3.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: #000;
border-radius: 4px;
height: 36px;
width:88px;
border-color:#d9d9d9 ;
background-color: #E5B7B733;
}

@ -197,6 +197,7 @@ const AssetGroupTable=()=>{
rowKey="groupId"
pagination={false} // 关闭表格自带分页使用外部Pagination组件
style={{width:'100%'}}
// className={styles.table}
/>
<div style={{textAlign: 'right', marginTop: 16}}>
<Pagination
@ -253,6 +254,60 @@ const AssetGrouping = () => {
],
},
];
const columns = [
{
title: '分组ID',
dataIndex: 'groupId',
key: 'groupId',
},
{
title: '分组名称',
dataIndex: 'groupName',
key: 'groupName',
},
{
title: '分组层级',
dataIndex: 'groupLevel',
key: 'groupLevel',
},
{
title: '父分组',
dataIndex: 'parentGroup',
key: 'parentGroup',
},
{
title: '资产数量',
dataIndex: 'assetCount',
key: 'assetCount',
},
{
title: '权限策略',
dataIndex: 'permissionStrategy',
key: 'permissionStrategy',
},
{
title: '管理策略',
dataIndex: 'managementStrategy',
key: 'managementStrategy',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
},
{
title: '操作',
key: 'action',
render: (_, record) => (
<Space size="middle">
<Button style={{color:'#2C9E9D'}} type="text" onClick={() => handleEdit(record)}>编辑</Button>
<Button style={{color:'#2C9E9D'}} type="text" onClick={() => handlePermissionConfig(record)}>权限配置</Button>
<Button style={{color:'#006665'}} type="text" onClick={() => handleViewAsset(record)}>查看资产</Button>
</Space>
),
align:'center'
},
];
return (
<div style={{padding:'20px'}}>
<Row gutter={16}>
@ -296,7 +351,16 @@ const AssetGrouping = () => {
</div>
</Row>
<Row style={{margin:'30px 0'}}>
<AssetGroupTable ></AssetGroupTable>
{/*<AssetGroupTable ></AssetGroupTable>*/}
<Table
// rowSelection={rowSelection}
columns={columns}
dataSource={mockData} // 实际场景中替换为接口返回的dataSource
rowKey="groupId"
pagination={false} // 关闭表格自带分页使用外部Pagination组件
style={{width:'100%'}}
// className={styles.table}
/>
</Row>
</Col>
</Row>

@ -32,3 +32,9 @@
border-color:#d9d9d9 ;
background-color: #E5B7B733;
}
//.table{
// :global(.ant-table-thead > tr > th) {
// background-color: #F0F7F7 !important;
// }
//}

@ -30,3 +30,8 @@
border-color:#d9d9d9 ;
background-color: #E5B7B733;
}
.table{
:global(.ant-table-thead > tr > th) {
background-color: #F0F7F7 !important;
}
}

@ -1,5 +1,6 @@
import {useEffect, useState} from "react";
import {Pagination, Table, Button, Tag} from "antd";
import styles from '../AssetList.less'
const mockData = [
{
'key': '1',
@ -279,6 +280,7 @@ const AssetTable = () => {
// },
}}
style={{width:'100%'}}
className={styles.table}
/>
<div style={{ textAlign: 'right', marginTop: 16 }}>
<CustomPagination

@ -0,0 +1,174 @@
import {Button, Col, Pagination, Progress, Row, Table, Tabs, Tag} from "antd";
import Title from '../homepage/compontent/title'
import styles from './Maintenance.less'
import svg1 from '../../assets/img/asset-main1.svg'
import {DownloadOutlined, PlusOutlined, UploadOutlined} from "@ant-design/icons";
import TabPane from "antd/es/tabs/TabPane";
import TableWithPagination from "@/components/assetmangement/table";
const Maintenance = ()=>{
const progressStyle = [
{title:'即将到期',num:'12',percent:24,color:'#6E5612',strokeColor:'#FFE666'},
{title:'已逾期',num:'5',percent:10,color:'#6E1212',strokeColor:'#FF8966'},
{title:'正常',num:'33',percent:66,color:'#12386E',strokeColor:'#66C9FF'},
]
// 维保计划数据
const maintenancePlanData = [
{key: '1', assetName: '核心服务器A', assetType: '硬件-服务器', maintenanceType: '年度硬件维保', nextMaintenanceDate: '2025-10-28', lastMaintenanceDate: '2024-10-28', status: '即将到期', notificationMethod: '短信+平台通知', importance: '核心'},
{key: '2', assetName: '工业传感器B', assetType: '硬件-传感器', maintenanceType: '故障维保', nextMaintenanceDate: '--', lastMaintenanceDate: '2025-10-20', status: '已逾期', notificationMethod: '邮件+平台通知', importance: '重要'},
{key: '3', assetName: '网关C', assetType: '硬件-网关', maintenanceType: '季度软件维保', nextMaintenanceDate: '2025-11-15', lastMaintenanceDate: '2025-08-15', status: '正常', notificationMethod: '平台通知', importance: '普通'},
{key: '4', assetName: '数据库集群D', assetType: '硬件-服务器', maintenanceType: '月度巡检维保', nextMaintenanceDate: '2025-10-30', lastMaintenanceDate: '2025-09-30', status: '即将到期', notificationMethod: '短信+邮件', importance: '核心'},
{key: '5', assetName: '边缘计算节点E', assetType: '硬件-网关', maintenanceType: '固件升级维保', nextMaintenanceDate: '2025-12-01', lastMaintenanceDate: '2025-09-01', status: '正常', notificationMethod: '平台通知', importance: '重要'},
{key: '6', assetName: '温湿度传感器F', assetType: '硬件-传感器', maintenanceType: '年度校准维保', nextMaintenanceDate: '2025-11-05', lastMaintenanceDate: '2024-11-05', status: '正常', notificationMethod: '邮件通知', importance: '普通'},
];
// 状态标签颜色
const getStatusColor = (status) => {
switch(status) {
case '正常': return '#52c41a';
case '即将到期': return '#faad14';
case '已逾期': return '#ff4d4f';
default: return '#1890ff';
}
};
// 维保计划列表列定义
const planColumns = [
{title: '序号', dataIndex: 'key', key: 'key', width: 60},
{title: '资产名称', dataIndex: 'assetName', key: 'assetName'},
{title: '资产类型', dataIndex: 'assetType', key: 'assetType'},
{title: '维保类型', dataIndex: 'maintenanceType', key: 'maintenanceType'},
{title: '下次维保时间', dataIndex: 'nextMaintenanceDate', key: 'nextMaintenanceDate'},
{title: '上次维保时间', dataIndex: 'lastMaintenanceDate', key: 'lastMaintenanceDate'},
{title: '维保状态', dataIndex: 'status', key: 'status',
render: (status) => <span style={{color: getStatusColor(status)}}>{status}</span>
},
{title: '提醒方式', dataIndex: 'notificationMethod', key: 'notificationMethod'},
{title: '资产重要程度', dataIndex: 'importance', key: 'importance',
render: (importance) => <span>{importance}</span>
},
{title: '操作', key: 'action',align:'center',
render: () => (
<span>
<a style={{color:'#2C9E9D',marginRight:'10px'}} href="#">编辑</a>
<a style={{color:'#2C9E9D',marginRight:'10px'}} href="#">执行</a>
<a style={{color:'#006665'}} href="#">记录</a>
</span>
)
},
];
const items = [
{key: '1', label: <Title title={'维保计划列表'}/>,children:<TableWithPagination columns={planColumns} dataSource={maintenancePlanData} rowSelection={false}/>},
{key: '2', label: <span style={{fontSize:'20px'}}>维保记录列表</span>,children:<TableWithPagination columns={planColumns} dataSource={maintenancePlanData} rowSelection={false}/>},
];
const operations = <div style={{marginLeft: 20, display: 'flex'}}>
<Button className={styles['reset-button']} type="default" style={{marginRight: 30}}>导入维保计划</Button>
<Button className={styles['reset-button']} type="default" style={{marginRight: 30}}>导出维保数据</Button>
<Button className={styles['search-button']} type="primary" icon={<PlusOutlined/>}>新增维保计划</Button>
</div>;
// 自定义提醒规则数据
const reminderRuleData = [
{key: '1', ruleId: '1', maintenanceType: '年度硬件维保', importance: '核心', advanceNoticeDays: '7', notificationMethod: '短信+邮件+平台通知', repeatInterval: '24', status: '启用'},
{key: '2', ruleId: '2', maintenanceType: '故障维保', importance: '重要', advanceNoticeDays: '0(立即提醒)', notificationMethod: '短信+平台通知', repeatInterval: '12', status: '启用'},
{key: '3', ruleId: '3', maintenanceType: '软件版本迭代', importance: '普通', advanceNoticeDays: '3', notificationMethod: '平台通知', repeatInterval: '--(仅一次)', status: '启用'},
];
// 自定义提醒规则列定义
const ruleColumns = [
{
title: '',
dataIndex: 'select',
key: 'select',
width: 40,
render: () => <input type="checkbox" />
},
{title: '序号', dataIndex: 'ruleId', key: 'ruleId', width: 60},
{title: '维保类型', dataIndex: 'maintenanceType', key: 'maintenanceType'},
{title: '资产重要程度', dataIndex: 'importance', key: 'importance'},
{title: '提前提醒时间(天)', dataIndex: 'advanceNoticeDays', key: 'advanceNoticeDays'},
{title: '提醒方式(可多选)', dataIndex: 'notificationMethod', key: 'notificationMethod'},
{title: '重复提醒间隔(小时)', dataIndex: 'repeatInterval', key: 'repeatInterval'},
{title: '启用状态', dataIndex: 'status', key: 'status',
render: (status) => <Tag color="green">{status}</Tag>
},
{title: '操作', key: 'action', align: 'center',
render: () => (
<span>
<a style={{color:'#2C9E9D',marginRight:'10px'}} href="#">编辑</a>
<a style={{color:'#ff4d4f'}} href="#">删除</a>
</span>
)
},
];
return (
<div>
<div style={{backgroundColor: '#f0f7f7', height: '100%', overflow: 'hidden'}}>
<Row gutter={20} style={{height: '100%'}}>
<Col span={4}>
<div style={{padding: '20px', backgroundColor: '#fff', height: '100%'}}>
<Title title={'维保任务总览'}></Title>
<div style={{
display: 'flex',
flexDirection: 'column',
marginTop: '20px',
}}>
<div className={styles['item']}>
<Row wrap={false}>
<Col span={12}>
<div className={styles['item-num']}>50</div>
<div className={styles['item-title']}>总计划数</div>
</Col>
<Col span={12} style={{textAlign:'right'}}>
<img src={svg1} alt=""/>
</Col>
</Row>
</div>
{
progressStyle.map((item)=>{
return (
<div className={styles['item']}>
<Row wrap={false}>
<Col span={12}>
<div className={styles['item-num']} style={{color: item.color}}>{item.num}
</div>
<div className={styles['item-title']}>{item.title}</div>
</Col>
<Col span={12} style={{textAlign: 'right'}}>
<Progress type={'circle'} percent={item.percent} size={[76, 76]}
strokeColor={item.strokeColor}/>
</Col>
</Row>
</div>
)
})
}
</div>
</div>
</Col>
<Col span={20}>
<Row style={{backgroundColor: '#fff',padding:'20px'}}>
<Tabs tabBarExtraContent={operations} items={items} style={{flex:'1'}}/>
</Row>
<Row style={{marginTop:'20px',backgroundColor:'#fff',padding:'20px'}}>
<Title title={'自定义提醒规则配置'}></Title>
<Row style={{width:'100%',marginTop:'20px'}}>
<Col span={12}>
<Button className={styles['search-button']} type="default" style={{marginRight: 30}}>导入规则模板</Button>
<Button className={styles['reset-button']} type="default" style={{marginRight: 30}}>导出规则模板</Button>
<Button className={styles['search-button']} type="primary" style={{marginRight: 30}}>启用</Button>
<Button className={styles['del-button']} type="primary" >禁用</Button>
</Col>
<Col span={12} style={{textAlign:'right'}}>
<Button className={styles['search-button']} type="default" icon={<PlusOutlined></PlusOutlined>} ></Button>
</Col>
</Row>
<Row style={{width:'100%',marginTop:'20px',marginBottom:'50px'}}>
<TableWithPagination columns={ruleColumns} dataSource={reminderRuleData} rowSelection={true}></TableWithPagination>
</Row>
</Row>
</Col>
</Row>
</div>
</div>
)
}
export default Maintenance;

@ -0,0 +1,82 @@
.item{
padding: 20px;
background: #FFFFFF4D;
backdrop-filter: blur(15px);
border-radius: 8px;
position: relative;
margin-top: 20px;
// 使用伪元素创建边框
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 1px solid transparent;
border-image-slice: 1;
border-image-source: conic-gradient(from 102.21deg at 52.75% 38.75%, rgba(249, 249, 249, 0.5) -32.95deg, rgba(64, 64, 64, 0.5) 10.52deg, rgba(64, 64, 64, 0.35) 32.12deg, #FFFFFF 60.28deg, rgba(255, 255, 255, 0.5) 107.79deg, rgba(64, 64, 64, 0.35) 187.59deg, #F9F9F9 207.58deg, #FFFFFF 287.31deg, rgba(249, 249, 249, 0.5) 327.05deg, rgba(64, 64, 64, 0.5) 370.52deg);
border-radius: 8px;
pointer-events: none;
}
// 合并多个阴影效果,用逗号分隔
box-shadow:
-2px 4px 10px 0px #9191910D,
-7px 17px 18px 0px #9191910A,
-15px 37px 24px 0px #91919108,
-27px 66px 29px 0px #91919103,
-42px 103px 31px 0px #91919100;
}
.item-num{
font-size: 26px;
font-weight: 600;
line-height: 32px;
letter-spacing: 0em;
text-align: left;
}
.item-title{
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0em;
text-align: left;
margin-top: 20px;
color:#666666;
}
.search-button{
background-image: url('../../assets/img/assetmangement1.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: #fff;
border-radius: 4px;
height: 36px;
border-color:#d9d9d9 ;
background-color: #045F5E80;
}
.reset-button{
background-image: url('../../assets/img/assetmangement2.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: rgba(0, 102, 101, 1);
border-radius: 4px;
height: 36px;
border-color:#d9d9d9 ;
background-color: #B7E5D533;
}
.del-button{
background-image: url('../../assets/img/assetmangement3.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: #000;
border-radius: 4px;
height: 36px;
width:88px;
border-color:#d9d9d9 ;
background-color: #E5B7B733;
}

@ -0,0 +1,17 @@
.item{
padding: 20px;
border: 1px solid;
border-image-slice: 1;
border-image-source: conic-gradient(from 102.21deg at 52.75% 38.75%, rgba(249, 249, 249, 0.5) -32.95deg, rgba(64, 64, 64, 0.5) 10.52deg, rgba(64, 64, 64, 0.35) 32.12deg, #FFFFFF 60.28deg, rgba(255, 255, 255, 0.5) 107.79deg, rgba(64, 64, 64, 0.35) 187.59deg, #F9F9F9 207.58deg, #FFFFFF 287.31deg, rgba(249, 249, 249, 0.5) 327.05deg, rgba(64, 64, 64, 0.5) 370.52deg);
background: #FFFFFF4D;
backdrop-filter: blur(15px);
border-radius: 8px;
// 合并多个阴影效果,用逗号分隔
box-shadow:
-2px 4px 10px 0px #9191910D,
-7px 17px 18px 0px #9191910A,
-15px 37px 24px 0px #91919108,
-27px 66px 29px 0px #91919103,
-42px 103px 31px 0px #91919100;
}

@ -141,7 +141,18 @@ const SystemContentList = (props) => {
path: '/topnavbar00/business/assetmanagement/assetgrouping',
key: "/topnavbar00/business/assetmanagement/assetgrouping",
"label": "资产分组"
}
},
// 资产属性定义
{
path: '/topnavbar00/business/assetmanagement/assetdefined',
key: "/topnavbar00/business/assetmanagement/assetdefined",
"label": "资产属性定义"
},
{
path: '/topnavbar00/business/assetmanagement/maintenance',
key: "/topnavbar00/business/assetmanagement/maintenance",
"label": "维保管理"
},
]
}
]

@ -24,6 +24,16 @@ const menuItem = [
label: '资产分组',
key: '/topnavbar00/business/assetmanagement/assetgrouping',
},
// 资产属性定义
{
label: '资产属性定义',
key: '/topnavbar00/business/assetmanagement/assetdefined',
},
// 资产维保管理
{
label: '维保管理',
key: '/topnavbar00/business/assetmanagement/maintenance',
},
]
const TopNavBar = (props) => {
@ -126,8 +136,11 @@ const TopNavBar = (props) => {
checkboxBorderColor:'#006665'
},
Table:{
headerBg:'#F0F7F7',
// bodyBg:'#F0F7F7',
headerBg: '#F0F7F7', // 正确的表头背景 Token5.x 组件专属)
// cellFontSize: 24,
// headerCellStyle: { // 额外添加,强制覆盖表头单元格样式(解决优先级问题)
// backgroundColor: '#F0F7F7 !important',
// },
},
Menu:{
activeBarHeight:0
@ -137,13 +150,31 @@ const TopNavBar = (props) => {
colorBorder:'#2C9E9D'
},
Input:{
colorBorder:'#2C9E9D'
colorBorder:'#2C9E9D',
activeBorderColor:'#2C9E9D'
},
DatePicker:{
colorBorder:'#2C9E9D'
},
Button:{
colorBorder:'#2C9E9D',
},
Radio:{
colorPrimary: '#2C9E9D', // 选中时的圆圈边框色 + 内部圆点色(核心颜色)
colorBorder: '#2C9E9D', // 未选中时的圆圈边框色(你的需求,和选中色一致)
colorBgChecked: '#2C9E9D', // 选中时内部圆点的颜色(可和 colorPrimary 一致)
sizeDefault: 16, // 圆形单选框的尺寸(默认 16px可改 14/18/20 等)
colorText: '#333', // 单选框旁边的文字颜色(可选)
colorTextChecked: '#2C9E9D', // 选中时的文字颜色(可选,默认继承 colorPrimary
// hover/聚焦状态(可选,增强交互)
colorBorderHover: '#1A7D7C', // 未选中时 hover 边框色(比选中色深一点)
colorPrimaryHover: '#1A7D7C', // 选中时 hover 颜色
},
Tabs:{
inkBarColor:'#2C9E9D',
itemActiveColor:'#333333',
itemHoverColor:'#333333',
itemSelectedColor:'#333333',
}
},
}

Loading…
Cancel
Save