diff --git a/config/routes.js b/config/routes.js index e1ea3f6..3f53f1a 100644 --- a/config/routes.js +++ b/config/routes.js @@ -29,6 +29,12 @@ export default [ path: '/topnavbar00/business/basic', name: 'basic', component: './business_basic/basic', + }, + // 计划管理 + { + path: '/topnavbar00/business/planmanage', + name: 'planmanage', + component: './business_planmanage/PlanManage', } ], }, diff --git a/src/assets/img/icon2.svg b/src/assets/img/icon2.svg new file mode 100644 index 0000000..9f9baf6 --- /dev/null +++ b/src/assets/img/icon2.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/pages/business_basic/components/CustomerInfoManagement.js b/src/pages/business_basic/components/CustomerInfoManagement.js index 0e66b33..a858afe 100644 --- a/src/pages/business_basic/components/CustomerInfoManagement.js +++ b/src/pages/business_basic/components/CustomerInfoManagement.js @@ -98,8 +98,8 @@ const CustomerInfoManagement = () => { barWidth: 26, itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: '#7FC8B6' }, - { offset: 1, color: '#008F8E' }, + { offset: 0, color: 'rgba(4, 95, 94, 0.6)' }, + { offset: 1, color: 'rgba(4, 95, 94, 0.5)' }, ]), // barBorderRadius: [6, 6, 0, 0], shadowColor: 'rgba(0,0,0,0.08)', diff --git a/src/pages/business_basic/components/CustomerInfoManagement.less b/src/pages/business_basic/components/CustomerInfoManagement.less index 79dad47..aa54f80 100644 --- a/src/pages/business_basic/components/CustomerInfoManagement.less +++ b/src/pages/business_basic/components/CustomerInfoManagement.less @@ -92,9 +92,9 @@ .activityCard { flex: 1; background: #F3F9F8; - border-radius: 8px; + border-radius: 4px; padding: 16px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + box-shadow: 0 4px 6px rgba(118, 194, 181, 0.3); border: 1px solid #76C2B5; .chartHeader { diff --git a/src/pages/business_planmanage/PlanManage.js b/src/pages/business_planmanage/PlanManage.js new file mode 100644 index 0000000..05da653 --- /dev/null +++ b/src/pages/business_planmanage/PlanManage.js @@ -0,0 +1,55 @@ +import React, { useState } from 'react'; +import { Card, Row, Col, Statistic, Progress, Button, Space } from 'antd'; +import styles from './PlanManage.less'; +import BusinessPlanManagement from './components/BusinessPlanManagement'; +import ProductionPlanManagement from './components/ProductionPlanManagement'; +import PlanApprovalProcess from './components/PlanApprovalProcess'; + +const PlanManage = () => { + const [activeModule, setActiveModule] = useState('businessPlan'); + + const handleModuleClick = (module) => { + setActiveModule(module) + } + + const renderModule = () => { + switch (activeModule) { + case 'businessPlan': + return ; + case 'productionPlan': + return ; + case 'planApprovalProcess': + return ; + default: + return ; + } + }; + + + return ( +
+
+ + + +
+
+ {renderModule()} +
+
+ ); +}; + +export default PlanManage; diff --git a/src/pages/business_planmanage/PlanManage.less b/src/pages/business_planmanage/PlanManage.less new file mode 100644 index 0000000..1d5e7ea --- /dev/null +++ b/src/pages/business_planmanage/PlanManage.less @@ -0,0 +1,65 @@ +.container { + width: 100%; + height: 89vh; + overflow: hidden; + display: flex; + flex-direction: column; + + .TopButton { + background-color: #FFFFFF; + width: 100%; + padding: 10px 30px; + display: flex; + gap: 24px; + margin-left: 6px; + + .TopButtonItem { + background-color: transparent !important; + color: #333333 !important; + font-family: 'PingFang SC', sans-serif !important; + font-weight: 500 !important; + font-size: 14px !important; + line-height: 100% !important; + border-radius: 8px !important; + padding: 6px 10px !important; + height: auto !important; + border: none !important; + box-shadow: none !important; + position: relative !important; + + &:hover { + color: #333333 !important; + border: none !important; + } + + &:focus { + color: #006665 !important; + border: none !important; + } + + &.active { + color: #006665 !important; + + &::after { + content: ''; + position: absolute; + bottom: -10px; + left: 0; + right: 0; + width: 100%; + height: 4px; + background-color: #006665; + border-radius: 0; + opacity: 1; + } + } + } + } + + .content { + // ======== 内容区域样式 ======== + flex: 1; // ======== 占据剩余空间 ======== + overflow-y: auto; // ======== 允许垂直滚动 ======== + padding: 0; // ======== 无内边距 ======== + } +} \ No newline at end of file diff --git a/src/pages/business_planmanage/components/BusinessPlanManagement.js b/src/pages/business_planmanage/components/BusinessPlanManagement.js new file mode 100644 index 0000000..370e0a3 --- /dev/null +++ b/src/pages/business_planmanage/components/BusinessPlanManagement.js @@ -0,0 +1,297 @@ +import React, { useState, useMemo, useLayoutEffect } from 'react'; +import styles from './BusinessPlanManagement.less'; +import { Select, Space, Button, Input } from 'antd'; +import { PlusOutlined, SearchOutlined, ReloadOutlined } from '@ant-design/icons'; +import StandardTable from '@/components/StandardTable'; +import topIcon from '@/assets/business_basic/top_icon1.svg'; +import topIcon2 from '@/assets/business_basic/top_icon2.svg'; +import topIcon3 from '@/assets/business_basic/top_icon3.svg'; +import topIcon4 from '@/assets/business_basic/top_icon4.svg'; +const BusinessPlanManagement = () => { + const [searchKeyword, setSearchKeyword] = useState(''); + const [selectedRows, setSelectedRows] = useState([]); + const [currentPage, setCurrentPage] = useState(1); + const [pageSize, setPageSize] = useState(10); + // 列表筛选与数据(演示数据,可替换为接口) + const [filters, setFilters] = useState({ + customerType: '', + customerGrade: '', + cooperationStatus: '', + }); + // 新增:详情页面切换状态 + const [showDetail, setShowDetail] = useState(false); + const [detailData, setDetailData] = useState(null); + const [prevScrollY, setPrevScrollY] = useState(0); + + + // KPI数据 + const kpiData = { + totalCustomers: 389, + highValueCustomers: 180, + inCooperation: 360, + newThisMonth: 8, + }; + + + // 返回列表时恢复滚动位置,确保布局稳定后再滚动 + useLayoutEffect(() => { + if (!showDetail) { + // 等待本帧布局完成 + requestAnimationFrame(() => { + window.scrollTo(0, prevScrollY || 0); + }); + } + }, [showDetail]); + + + // 表格数据 + const tableData = [ + { + id: 'CUST-2023-001', + customerName: '中国石化销售股份有限公司', + contact: '钱亚男', + phone: '18901563341', + classification: '高价值', + monthlyAmount: 1250000, + cooperationStatus: '合作中', + satisfaction: 4.5, + }, + { + id: 'CUST-2023-002', + customerName: '中石化华东分公司', + contact: '郑宇雅', + phone: '15341731282', + classification: '常规客户', + monthlyAmount: 1250000, + cooperationStatus: '合作中', + satisfaction: 4.0, + }, + { + id: 'CUST-2023-003', + customerName: '海南石油贸易有限公司', + contact: '孙向明', + phone: '13252257033', + classification: '高价值', + monthlyAmount: 850000, + cooperationStatus: '合作中', + satisfaction: 4.5, + }, + { + id: 'CUST-2023-004', + customerName: '东莞石化有限公司', + contact: '何思颖', + phone: '18931788771', + classification: '高价值', + monthlyAmount: 980000, + cooperationStatus: '合作中', + satisfaction: 4.5, + }, + { + id: 'CUST-2023-005', + customerName: '中国石油化工集团有限公司', + contact: '钱佳仪', + phone: '13743378254', + classification: '常规客户', + monthlyAmount: 980000, + cooperationStatus: '暂停合作', + satisfaction: 4.0, + }, + ]; + + // 列配置(用于 StandardTable) + const columns = useMemo(() => { + return [ + { title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 220 }, + { title: '联系人', dataIndex: 'contact', key: 'contact', width: 120 }, + { title: '联系电话', dataIndex: 'phone', key: 'phone', width: 140 }, + { + title: '分类', dataIndex: 'classification', key: 'classification', width: 110, + render: (val) => ( + {val} + ) + }, + { + title: '交易额度(月)', dataIndex: 'monthlyAmount', key: 'monthlyAmount', width: 150, + render: (v) => `¥${Number(v).toLocaleString()}` + }, + { + title: '合作状态', dataIndex: 'cooperationStatus', key: 'cooperationStatus', width: 110, + render: (val) => ( + {val} + ) + }, + { + title: '满意度', dataIndex: 'satisfaction', key: 'satisfaction', width: 120, + }, + { + title: '操作', key: 'action', fixed: 'right', width: 200, + render: (_, row) => ( + + + + + + ) + }, + ]; + }, []); + + // 处理选择 + const handleSelectRow = (id) => { + if (selectedRows.includes(id)) { + setSelectedRows(selectedRows.filter(rowId => rowId !== id)); + } else { + setSelectedRows([...selectedRows, id]); + } + }; + + return ( +
+
+ {/* KPI卡片区域 */} +
+
+
+
{kpiData.totalCustomers}
+
总客户数
+
+ icon +
+
+
+
{kpiData.highValueCustomers}
+
高价值客户
+
+ icon +
+
+
+
{kpiData.inCooperation}
+
合作中
+
+ icon +
+
+
+
{kpiData.newThisMonth}
+
本月新增
+
+ icon +
+
+ {/* 客户列表区域 */} +
+
+ + 客户列表 +
+
+
+ setSearchKeyword(e.target.value)} + onSearch={(val) => setSearchKeyword(val)} + style={{ minWidth: 150 }} + /> +
+
+ 客户类型: + setFilters({ ...filters, customerGrade: v })} + placeholder="全部" + options={[ + { label: '全部', value: '' }, + ]} + allowClear + /> +
+
+ 合作状态: +