静态页提交

main
wangyunfei 2 weeks ago
parent cd4bbf95c0
commit 79352c660d

@ -1,122 +1,557 @@
import React from 'react';
import { Card, Table, Input, Button, Space } from 'antd';
import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
import React, { useState, useEffect, useRef } from 'react';
import * as echarts from 'echarts';
import styles from './CustomerInfoManagement.less';
const CustomerInfoManagement = () => {
const onSearch = (value) => {
console.log('搜索内容:', value);
const [searchKeyword, setSearchKeyword] = useState('');
const [customerType, setCustomerType] = useState('全部');
const [customerLevel, setCustomerLevel] = useState('全部');
const [cooperationStatus, setCooperationStatus] = useState('全部');
const [selectedRows, setSelectedRows] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
// 图表引用
const customerTypeChartRef = useRef(null);
const customerValueChartRef = useRef(null);
const customerTypeChartInstance = useRef(null);
const customerValueChartInstance = useRef(null);
// KPI数据
const kpiData = {
totalCustomers: 389,
highValueCustomers: 180,
inCooperation: 360,
newThisMonth: 8,
};
const columns = [
{
title: '编号3333',
dataIndex: 'id',
key: 'id',
width: 80,
// 客户类型分布图表配置
const customerTypeChartOption = {
title: {
text: '客户类型分布',
left: 'left',
textStyle: {
fontSize: 16,
fontWeight: 600,
},
},
{
title: '客户名称',
dataIndex: 'customerName',
key: 'customerName',
width: 150,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
{
title: '联系人',
dataIndex: 'contact',
key: 'contact',
width: 120,
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
{
title: '联系电话',
dataIndex: 'phone',
key: 'phone',
width: 150,
xAxis: {
type: 'category',
data: ['客户', '供应商', '第3周', '第4周'],
axisLabel: {
rotate: 0,
},
},
yAxis: {
type: 'value',
max: 100,
},
series: [
{
name: '数量',
type: 'bar',
data: [56, 32, 85, 15],
itemStyle: {
color: '#1890ff',
},
label: {
show: true,
position: 'top',
},
},
],
};
// 客户价值分布环形图配置
const customerValueChartOption = {
title: {
text: '客户价值分布',
left: 'left',
textStyle: {
fontSize: 16,
fontWeight: 600,
},
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)',
},
legend: {
orient: 'vertical',
left: 'right',
top: 'middle',
},
series: [
{
name: '客户价值',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2,
},
label: {
show: false,
},
emphasis: {
label: {
show: true,
fontSize: 16,
fontWeight: 'bold',
},
},
data: [
{ value: 180, name: '高价值客户', itemStyle: { color: '#5B9BD5' } },
{ value: 120, name: '中等客户', itemStyle: { color: '#FFC000' } },
{ value: 89, name: '小客户', itemStyle: { color: '#9E7CC1' } },
],
},
],
};
// 初始化图表
useEffect(() => {
// 初始化客户类型分布图表
if (customerTypeChartRef.current) {
customerTypeChartInstance.current = echarts.init(customerTypeChartRef.current);
customerTypeChartInstance.current.setOption(customerTypeChartOption);
}
// 初始化客户价值分布图表
if (customerValueChartRef.current) {
customerValueChartInstance.current = echarts.init(customerValueChartRef.current);
customerValueChartInstance.current.setOption(customerValueChartOption);
}
// 响应式调整
const handleResize = () => {
customerTypeChartInstance.current?.resize();
customerValueChartInstance.current?.resize();
};
window.addEventListener('resize', handleResize);
// 清理函数
return () => {
window.removeEventListener('resize', handleResize);
customerTypeChartInstance.current?.dispose();
customerValueChartInstance.current?.dispose();
};
}, []);
// 最近活动数据
const recentActivities = [
{
title: '公司地址',
dataIndex: 'address',
key: 'address',
width: 200,
id: 1,
title: '新合同签署',
description: '与中石化华东分公司签署年度供应合同',
time: '2小时前',
},
{
title: '客户类型',
dataIndex: 'customerType',
key: 'customerType',
width: 120,
id: 2,
title: '订单完成',
description: '完成海南石油贸易有限公司的油品配送',
time: '昨天',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 180,
id: 3,
title: '客户反馈',
description: '收到华南能源集团的满意度调查回复',
time: '昨天',
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
width: 150,
render: (text, record) => (
<Space>
<Button type="link" size="small">编辑</Button>
<Button type="link" size="small" danger>删除</Button>
</Space>
),
id: 4,
title: '新客户注册',
description: '新客户"浙江能源有限公司"完成注册',
time: '3天前',
},
];
// 表格数据
const tableData = [
{
key: '1',
id: '001',
customerName: '某某石油公司',
contact: '张经理',
phone: '138****8888',
address: '北京市朝阳区xxx路xxx号',
customerType: '企业客户',
createTime: '2024-12-20 10:00:00',
id: '1',
customerName: '中国石化销售股份有限公司',
contact: '钱亚男',
phone: '18901563341',
classification: '高价值',
monthlyAmount: 1250000,
cooperationStatus: '合作中',
satisfaction: 4.5,
},
{
id: '2',
customerName: '中石化华东分公司',
contact: '郑宇雅',
phone: '15341731282',
classification: '常规客户',
monthlyAmount: 1250000,
cooperationStatus: '合作中',
satisfaction: 4.0,
},
{
id: '3',
customerName: '海南石油贸易有限公司',
contact: '孙向明',
phone: '13252257033',
classification: '高价值',
monthlyAmount: 850000,
cooperationStatus: '合作中',
satisfaction: 4.5,
},
{
key: '2',
id: '002',
customerName: '某某加油站',
contact: '李经理',
phone: '139****9999',
address: '上海市浦东新区xxx路xxx号',
customerType: '零售客户',
createTime: '2024-12-20 10:00:00',
id: '4',
customerName: '东莞石化有限公司',
contact: '何思颖',
phone: '18931788771',
classification: '高价值',
monthlyAmount: 980000,
cooperationStatus: '合作中',
satisfaction: 4.5,
},
{
id: '5',
customerName: '中国石油化工集团有限公司',
contact: '钱佳仪',
phone: '13743378254',
classification: '常规客户',
monthlyAmount: 980000,
cooperationStatus: '暂停合作',
satisfaction: 4.0,
},
];
// 处理选择
const handleSelectRow = (id) => {
if (selectedRows.includes(id)) {
setSelectedRows(selectedRows.filter(rowId => rowId !== id));
} else {
setSelectedRows([...selectedRows, id]);
}
};
// 处理全选
const handleSelectAll = () => {
if (selectedRows.length === tableData.length) {
setSelectedRows([]);
} else {
setSelectedRows(tableData.map(item => item.id));
}
};
// 渲染星级评分
const renderStars = (rating) => {
const stars = [];
const fullStars = Math.floor(rating);
const hasHalfStar = rating % 1 !== 0;
for (let i = 0; i < fullStars; i++) {
stars.push(<span key={i} className={styles.starFull}></span>);
}
if (hasHalfStar) {
stars.push(<span key="half" className={styles.starHalf}></span>);
}
const emptyStars = 5 - Math.ceil(rating);
for (let i = 0; i < emptyStars; i++) {
stars.push(<span key={`empty-${i}`} className={styles.starEmpty}></span>);
}
return stars;
};
// 计算总页数
const totalPages = Math.ceil(85 / pageSize);
return (
<div className={styles.container}>
<Card>
<div className={styles.header}>
<div className={styles.title}>客户信息管理</div>
<Space>
<Input.Search
placeholder="搜索客户名称..."
onSearch={onSearch}
style={{ width: 200 }}
prefix={<SearchOutlined />}
{/* KPI卡片区域 */}
<div className={styles.kpiRow}>
<div className={styles.kpiCard}>
<div className={styles.kpiIcon}>👥</div>
<div className={styles.kpiValue}>{kpiData.totalCustomers}</div>
<div className={styles.kpiTitle}>总客户数</div>
</div>
<div className={styles.kpiCard}>
<div className={styles.kpiIcon}>👑</div>
<div className={styles.kpiValue}>{kpiData.highValueCustomers}</div>
<div className={styles.kpiTitle}>高价值客户</div>
</div>
<div className={styles.kpiCard}>
<div className={styles.kpiIcon}>🤝</div>
<div className={styles.kpiValue}>{kpiData.inCooperation}</div>
<div className={styles.kpiTitle}>合作中</div>
</div>
<div className={styles.kpiCard}>
<div className={styles.kpiIcon}></div>
<div className={styles.kpiValue}>{kpiData.newThisMonth}</div>
<div className={styles.kpiTitle}>本月新增</div>
</div>
</div>
{/* 图表和活动区域 */}
<div className={styles.chartRow}>
{/* 客户类型分布图表 */}
<div className={styles.chartCard}>
<div className={styles.chartHeader}>
<div className={styles.chartTitle}>客户类型分布</div>
<select className={styles.timeSelect} defaultValue="全部时间">
<option value="全部时间">全部时间</option>
<option value="本月">本月</option>
<option value="本季度">本季度</option>
<option value="本年">本年</option>
</select>
</div>
<div
ref={customerTypeChartRef}
className={styles.chartContainer}
/>
</div>
{/* 客户价值分布图表 */}
<div className={styles.chartCard}>
<div className={styles.chartHeader}>
<div className={styles.chartTitle}>客户价值分布</div>
</div>
<div
ref={customerValueChartRef}
className={styles.chartContainer}
/>
</div>
{/* 最近活动列表 */}
<div className={styles.activityCard}>
<div className={styles.chartHeader}>
<div className={styles.chartTitle}>最近活动</div>
</div>
<div className={styles.activityList}>
{recentActivities.map((activity) => (
<div key={activity.id} className={styles.activityItem}>
<div className={styles.activityIcon}>
{activity.id === 1 && '📄'}
{activity.id === 2 && '✅'}
{activity.id === 3 && '💬'}
{activity.id === 4 && '👤'}
</div>
<div className={styles.activityContent}>
<div className={styles.activityTitle}>{activity.title}</div>
<div className={styles.activityDesc}>{activity.description}</div>
<div className={styles.activityTime}>🕐 {activity.time}</div>
</div>
</div>
))}
</div>
</div>
</div>
{/* 客户列表区域 */}
<div className={styles.tableCard}>
<div className={styles.tableHeader}>
<div className={styles.tableTitle}>客户列表</div>
</div>
{/* 筛选栏 */}
<div className={styles.filterBar}>
<div className={styles.filterGroup}>
<input
type="text"
className={styles.searchInput}
placeholder="搜索关键词"
value={searchKeyword}
onChange={(e) => setSearchKeyword(e.target.value)}
/>
<Button type="primary" icon={<PlusOutlined />}>
新增客户
</Button>
</Space>
<select
className={styles.filterSelect}
value={customerType}
onChange={(e) => setCustomerType(e.target.value)}
>
<option value="全部">客户类型: 全部</option>
<option value="客户">客户</option>
<option value="供应商">供应商</option>
</select>
<select
className={styles.filterSelect}
value={customerLevel}
onChange={(e) => setCustomerLevel(e.target.value)}
>
<option value="全部">客户等级: 全部</option>
<option value="高价值">高价值</option>
<option value="常规客户">常规客户</option>
</select>
<select
className={styles.filterSelect}
value={cooperationStatus}
onChange={(e) => setCooperationStatus(e.target.value)}
>
<option value="全部">合作状态: 全部</option>
<option value="合作中">合作中</option>
<option value="暂停合作">暂停合作</option>
</select>
<button className={styles.queryBtn} onClick={() => console.log('查询')}>
🔍 查询
</button>
<button className={styles.resetBtn} onClick={() => {
setSearchKeyword('');
setCustomerType('全部');
setCustomerLevel('全部');
setCooperationStatus('全部');
}}>
🔄 重置
</button>
<button className={styles.addBtn}>
新增客户
</button>
<button className={styles.exportBtn}>
📥 批量导出
</button>
</div>
</div>
{/* 表格 */}
<div className={styles.tableWrapper}>
<table className={styles.dataTable}>
<thead>
<tr>
<th>
<input
type="checkbox"
checked={selectedRows.length === tableData.length}
onChange={handleSelectAll}
/>
</th>
<th>客户名称</th>
<th>联系人</th>
<th>联系电话</th>
<th>分类</th>
<th>交易额度()</th>
<th>合作状态</th>
<th>满意度</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{tableData.map((row) => (
<tr key={row.id}>
<td>
<input
type="checkbox"
checked={selectedRows.includes(row.id)}
onChange={() => handleSelectRow(row.id)}
/>
</td>
<td>{row.customerName}</td>
<td>{row.contact}</td>
<td>{row.phone}</td>
<td>
<span className={`${styles.tag} ${row.classification === '高价值' ? styles.tagGold : styles.tagBlue}`}>
{row.classification}
</span>
</td>
<td>¥{row.monthlyAmount.toLocaleString()}</td>
<td>
<span className={`${styles.tag} ${row.cooperationStatus === '合作中' ? styles.tagGreen : styles.tagOrange}`}>
{row.cooperationStatus}
</span>
</td>
<td>
<div className={styles.stars}>
{renderStars(row.satisfaction)}
</div>
</td>
<td>
<div className={styles.actionBtns}>
<button className={styles.actionBtn}>查看详情</button>
<button className={styles.actionBtn}>修改</button>
<button className={`${styles.actionBtn} ${styles.deleteBtn}`}>删除</button>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
<Table
columns={columns}
dataSource={tableData}
pagination={{
pageSize: 10,
showTotal: (total) => `${total}`,
}}
/>
</Card>
{/* 分页 */}
<div className={styles.pagination}>
<div className={styles.paginationInfo}>
共85条
<select
className={styles.pageSizeSelect}
value={pageSize}
onChange={(e) => {
setPageSize(Number(e.target.value));
setCurrentPage(1);
}}
>
<option value="10">10 / page</option>
<option value="20">20 / page</option>
<option value="50">50 / page</option>
<option value="100">100 / page</option>
</select>
</div>
<div className={styles.paginationControls}>
<button
className={styles.pageBtn}
disabled={currentPage === 1}
onClick={() => setCurrentPage(currentPage - 1)}
>
</button>
{currentPage > 3 && (
<>
<button className={styles.pageBtn} onClick={() => setCurrentPage(1)}>1</button>
<span className={styles.pageEllipsis}>...</span>
</>
)}
{Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
let pageNum;
if (currentPage <= 3) {
pageNum = i + 1;
} else if (currentPage >= totalPages - 2) {
pageNum = totalPages - 4 + i;
} else {
pageNum = currentPage - 2 + i;
}
if (pageNum > totalPages) return null;
return (
<button
key={pageNum}
className={`${styles.pageBtn} ${currentPage === pageNum ? styles.pageBtnActive : ''}`}
onClick={() => setCurrentPage(pageNum)}
>
{pageNum}
</button>
);
})}
{currentPage < totalPages - 2 && (
<>
<span className={styles.pageEllipsis}>...</span>
<button className={styles.pageBtn} onClick={() => setCurrentPage(totalPages)}>{totalPages}</button>
</>
)}
<button
className={styles.pageBtn}
disabled={currentPage === totalPages}
onClick={() => setCurrentPage(currentPage + 1)}
>
</button>
</div>
</div>
</div>
</div>
);
};
export default CustomerInfoManagement;

@ -1,19 +1,414 @@
.container {
padding: 20px;
// background: #f5f5f5;
min-height: 100%;
background: #f5f5f5;
min-height: 100vh;
.header {
// KPI卡片区域
.kpiRow {
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
margin-bottom: 20px;
.title {
font-size: 18px;
font-weight: 600;
color: #333;
.kpiCard {
flex: 1;
background: #fff;
border-radius: 8px;
padding: 24px;
text-align: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s;
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
.kpiIcon {
font-size: 32px;
margin-bottom: 12px;
}
.kpiValue {
font-size: 32px;
font-weight: 600;
color: #1890ff;
margin-bottom: 8px;
}
.kpiTitle {
font-size: 14px;
color: #666;
}
}
}
}
// 图表和活动区域
.chartRow {
display: flex;
gap: 16px;
margin-bottom: 20px;
.chartCard,
.activityCard {
flex: 1;
background: #fff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.chartHeader {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #f0f0f0;
.chartTitle {
font-size: 16px;
font-weight: 600;
color: #333;
}
.timeSelect {
padding: 4px 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
&:hover {
border-color: #40a9ff;
}
}
}
.chartContainer {
height: 300px;
width: 100%;
}
}
.activityCard {
.activityList {
.activityItem {
display: flex;
gap: 12px;
padding: 12px 0;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.activityIcon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
border-radius: 8px;
font-size: 20px;
flex-shrink: 0;
}
.activityContent {
flex: 1;
.activityTitle {
font-size: 14px;
font-weight: 500;
color: #333;
margin-bottom: 4px;
}
.activityDesc {
font-size: 13px;
color: #666;
margin-bottom: 4px;
}
.activityTime {
font-size: 12px;
color: #999;
}
}
}
}
}
}
// 表格区域
.tableCard {
background: #fff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.tableHeader {
margin-bottom: 16px;
.tableTitle {
font-size: 18px;
font-weight: 600;
color: #333;
}
}
.filterBar {
margin-bottom: 16px;
padding: 16px;
background: #fafafa;
border-radius: 4px;
.filterGroup {
display: flex;
gap: 12px;
flex-wrap: wrap;
align-items: center;
.searchInput {
padding: 8px 12px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 14px;
width: 200px;
&:focus {
outline: none;
border-color: #40a9ff;
}
}
.filterSelect {
padding: 8px 12px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 14px;
width: 150px;
cursor: pointer;
background: #fff;
&:hover {
border-color: #40a9ff;
}
}
.queryBtn,
.resetBtn,
.addBtn,
.exportBtn {
padding: 8px 16px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
background: #fff;
transition: all 0.3s;
&:hover {
border-color: #40a9ff;
color: #40a9ff;
}
}
.queryBtn,
.addBtn {
background: #1890ff;
color: #fff;
border-color: #1890ff;
&:hover {
background: #40a9ff;
border-color: #40a9ff;
}
}
}
}
.tableWrapper {
overflow-x: auto;
.dataTable {
width: 100%;
border-collapse: collapse;
thead {
background: #fafafa;
th {
padding: 12px;
text-align: left;
font-weight: 600;
color: #333;
border-bottom: 2px solid #f0f0f0;
white-space: nowrap;
}
}
tbody {
tr {
border-bottom: 1px solid #f0f0f0;
transition: background 0.3s;
&:hover {
background: #fafafa;
}
td {
padding: 12px;
color: #666;
white-space: nowrap;
.tag {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
}
.tagGold {
background: #fffbe6;
color: #faad14;
border: 1px solid #ffe58f;
}
.tagBlue {
background: #e6f7ff;
color: #1890ff;
border: 1px solid #91d5ff;
}
.tagGreen {
background: #f6ffed;
color: #52c41a;
border: 1px solid #b7eb8f;
}
.tagOrange {
background: #fff7e6;
color: #fa8c16;
border: 1px solid #ffd591;
}
.stars {
display: flex;
gap: 2px;
.starFull {
color: #faad14;
font-size: 16px;
}
.starHalf {
color: #faad14;
font-size: 16px;
opacity: 0.5;
}
.starEmpty {
color: #d9d9d9;
font-size: 16px;
}
}
.actionBtns {
display: flex;
gap: 8px;
.actionBtn {
padding: 4px 8px;
border: none;
background: transparent;
color: #1890ff;
cursor: pointer;
font-size: 12px;
border-radius: 4px;
transition: all 0.3s;
&:hover {
background: #e6f7ff;
}
&.deleteBtn {
color: #ff4d4f;
&:hover {
background: #fff1f0;
}
}
}
}
}
}
}
}
}
.pagination {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid #f0f0f0;
.paginationInfo {
display: flex;
align-items: center;
gap: 8px;
color: #666;
font-size: 14px;
.pageSizeSelect {
padding: 4px 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
margin-left: 8px;
}
}
.paginationControls {
display: flex;
gap: 4px;
align-items: center;
.pageBtn {
min-width: 32px;
height: 32px;
padding: 0 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
background: #fff;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
&:hover:not(:disabled) {
border-color: #40a9ff;
color: #40a9ff;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
&.pageBtnActive {
background: #1890ff;
color: #fff;
border-color: #1890ff;
}
}
.pageEllipsis {
padding: 0 8px;
color: #666;
}
}
}
}
}

@ -1,133 +1,102 @@
import React from 'react';
import { Card, Table, Input, Button, Space } from 'antd';
import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
import React, { useState } from 'react';
import { Select } from 'antd';
import styles from './DataModeling.less';
import BasicAttribute from './second_datamodel_components/BasicAttribute';
import HierarchyStructure from './second_datamodel_components/HierarchyStructure';
import RealtimeData from './second_datamodel_components/RealtimeData';
import HistoryTrend from './second_datamodel_components/HistoryTrend';
import ChangeRecord from './second_datamodel_components/ChangeRecord';
const DataModeling = () => {
const onSearch = (value) => {
console.log('搜索内容:', value);
};
// 顶部一行选择:第一个为"基本属性/层级结构",其余占位
const [firstMenu, setFirstMenu] = useState('basic');
const [secondMenu, setSecondMenu] = useState(undefined);
const [thirdMenu, setThirdMenu] = useState(undefined);
const [fourthMenu, setFourthMenu] = useState(undefined);
const [fifthMenu, setFifthMenu] = useState(undefined);
const columns = [
{
title: '编号111',
dataIndex: 'id',
key: 'id',
width: 80,
},
{
title: '模型名称',
dataIndex: 'modelName',
key: 'modelName',
width: 150,
},
{
title: '模型类型',
dataIndex: 'modelType',
key: 'modelType',
width: 120,
},
{
title: '数据源',
dataIndex: 'dataSource',
key: 'dataSource',
width: 150,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 100,
render: (text) => {
const statusMap = {
'运行中': { color: '#52c41a', bg: '#f6ffed' },
'已停止': { color: '#ff4d4f', bg: '#fff1f0' },
'待启动': { color: '#faad14', bg: '#fffbe6' },
};
const style = statusMap[text] || {};
return (
<span
style={{
color: style.color,
backgroundColor: style.bg,
padding: '2px 8px',
borderRadius: '4px',
fontSize: '12px',
}}
>
{text}
</span>
);
},
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 180,
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
width: 200,
render: (text, record) => (
<Space>
<Button type="link" size="small">编辑</Button>
<Button type="link" size="small">运行</Button>
<Button type="link" size="small" danger>删除</Button>
</Space>
),
},
];
const firstMenuLabelMap = {
basic: '基本属性',
hierarchy: '层级结构',
realtime: '实时数据',
history: '历史趋势',
change: '变更记录',
};
const tableData = [
{
key: '1',
id: '001',
modelName: '销售预测模型',
modelType: '预测模型',
dataSource: '销售数据表',
status: '运行中',
createTime: '2024-12-20 10:00:00',
},
{
key: '2',
id: '002',
modelName: '库存分析模型',
modelType: '分析模型',
dataSource: '库存数据表',
status: '已停止',
createTime: '2024-12-20 10:00:00',
},
];
const renderFirstMenuContent = () => {
switch (firstMenu) {
case 'basic':
return <BasicAttribute />;
case 'hierarchy':
return <HierarchyStructure />;
case 'realtime':
return <RealtimeData />;
case 'history':
return <HistoryTrend />;
case 'change':
return <ChangeRecord />;
default:
return null;
}
};
return (
<div className={styles.container}>
<Card>
<div className={styles.header}>
<div className={styles.title}>数据建模</div>
<Space>
<Input.Search
placeholder="搜索模型名称..."
onSearch={onSearch}
style={{ width: 200 }}
prefix={<SearchOutlined />}
/>
<Button type="primary" icon={<PlusOutlined />}>
新建模型
</Button>
</Space>
<div className={styles.topBar}>
<div
className={styles.currentLabel}
>
当前{firstMenuLabelMap[firstMenu] || '未选择'}
</div>
<Table
columns={columns}
dataSource={tableData}
pagination={{
pageSize: 10,
showTotal: (total) => `${total}`,
}}
/>
</Card>
<div className={styles.selectsWrapper}>
<Select
className={styles.topSelect}
value={firstMenu}
onChange={setFirstMenu}
options={[
{ label: '基本属性', value: 'basic' },
{ label: '层级结构', value: 'hierarchy' },
{ label: '实时数据', value: 'realtime' },
{ label: '历史趋势', value: 'history' },
{ label: '变更记录', value: 'change' },
]}
/>
<Select
className={styles.topSelect}
value={secondMenu}
onChange={setSecondMenu}
placeholder="层级结构"
options={[]}
disabled
/>
<Select
className={styles.topSelect}
value={thirdMenu}
onChange={setThirdMenu}
placeholder="实时数据"
options={[]}
disabled
/>
<Select
className={styles.topSelect}
value={fourthMenu}
onChange={setFourthMenu}
placeholder="历史趋势"
options={[]}
disabled
/>
<Select
className={styles.topSelect}
value={fifthMenu}
onChange={setFifthMenu}
placeholder="变更记录"
options={[]}
disabled
/>
</div>
</div>
{renderFirstMenuContent()}
</div>
);
};

@ -1,19 +1,138 @@
.container {
padding: 20px;
// background: #f5f5f5;
padding: 15px 0px;
min-height: 100%;
.header {
.topBar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.title {
font-size: 18px;
font-weight: 600;
color: #333;
height: 46px;
margin-bottom: 16px;
.currentLabel {
border-top-left-radius: 20px;
height: 100%;
width: 230px;
display: flex;
align-items: center;
padding-left: 22px;
color: #fff;
font-size: 17px;
font-weight: 450;
background: pink;
background-image: url('@/assets/business_basic/bgOil.png');
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center center;
}
.selectsWrapper {
height: 100%;
// width: 230px;
background-color: #fff;
border: 1px solid transparent;
border-image-source: linear-gradient(96.54deg, #FFFFFF -0.94%, rgba(255, 255, 255, 0) 25.28%, rgba(167, 229, 228, 0) 59.69%, #A7E5E4 79.76%);
border-image-slice: 1;
display: flex;
align-items: center;
gap: 12px;
flex: 1;
}
.topSelect {
width: 130px;
display: flex;
align-items: center;
text-align: center;
box-shadow: none;
:global(.ant-select-selector) {
border: transparent !important;
background-image: url('@/assets/business_basic/Union.svg');
background-repeat: no-repeat;
background-position: center center;
font-size: 12px;
color: rgba(0, 102, 101, 1);
background-size: 100% 100%;
box-shadow: none !important;
}
:global(.ant-select-focused .ant-select-selector),
:global(.ant-select-selector:hover) {
border: transparent !important;
box-shadow: none !important;
}
:global(.ant-select-arrow) {
right: 25px;
color: rgba(0, 102, 101, 1);
}
}
}
}
.section {
margin-bottom: 16px;
.blockTitle {
font-size: 16px;
font-weight: 600;
color: #2f4f4f;
margin-bottom: 12px;
}
.formGrid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-column-gap: 16px;
grid-row-gap: 12px;
.formItem {
display: flex;
flex-direction: column;
.label {
color: #666;
font-size: 12px;
margin-bottom: 6px;
}
}
.span2 {
grid-column: 1 / span 2;
}
}
.actionsRight {
display: flex;
justify-content: flex-end;
margin-top: 12px;
}
.listHeader {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.filterRow {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 12px;
.filterItem {
display: flex;
align-items: center;
gap: 8px;
.filterLabel {
color: #666;
font-size: 12px;
white-space: nowrap;
}
}
}
}
}

@ -1,11 +1,11 @@
import React, { useState } from 'react';
import { Select } from 'antd';
import styles from './OilDataManagement.less';
import BasicInfo from './BasicInfo';
import PhysChem from './PhysChem';
import SafetyReasonable from './SafetyReasonable';
import BusinessAttributeInfo from './BusinessAttributeInfo';
import AuditDiary from './AuditDiary';
import BasicInfo from './second_oil_components/BasicInfo';
import PhysChem from './second_oil_components/PhysChem';
import SafetyReasonable from './second_oil_components/SafetyReasonable';
import BusinessAttributeInfo from './second_oil_components/BusinessAttributeInfo';
import AuditDiary from './second_oil_components/AuditDiary';
const OilDataManagement = () => {
// 顶部一行选择:第一个为“基本信息/理化性质”,其余占位

@ -0,0 +1,13 @@
import React from 'react';
import styles from './BasicAttribute.less';
const BasicAttribute = () => {
return (
<div className={styles.container}>
<div>待开发</div>
</div>
);
};
export default BasicAttribute;

@ -0,0 +1,13 @@
import React from 'react';
import styles from './ChangeRecord.less';
const ChangeRecord = () => {
return (
<div className={styles.container}>
<div>待开发</div>
</div>
);
};
export default ChangeRecord;

@ -0,0 +1,13 @@
import React from 'react';
import styles from './HierarchyStructure.less';
const HierarchyStructure = () => {
return (
<div className={styles.container}>
<div>待开发</div>
</div>
);
};
export default HierarchyStructure;

@ -0,0 +1,13 @@
import React from 'react';
import styles from './HistoryTrend.less';
const HistoryTrend = () => {
return (
<div className={styles.container}>
<div>待开发</div>
</div>
);
};
export default HistoryTrend;

@ -0,0 +1,13 @@
import React from 'react';
import styles from './RealtimeData.less';
const RealtimeData = () => {
return (
<div className={styles.container}>
<div>待开发</div>
</div>
);
};
export default RealtimeData;
Loading…
Cancel
Save