计划管理-经营计划管理页面

main
wangyunfei888 4 weeks ago
parent fad1999dae
commit 300b83d44e

@ -1,12 +1,12 @@
import React, { useState, useMemo, useLayoutEffect } from 'react';
import React, { useState, useMemo } from 'react';
import styles from './BusinessPlanManagement.less';
import { Select, Space, Button, Input } from 'antd';
import { Select, Space, Button, Input, DatePicker } 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';
import topIcon from '@/assets/business_planmanage/jyjhgl1.svg';
import topIcon2 from '@/assets/business_planmanage/jyjhgl2.svg';
import topIcon3 from '@/assets/business_planmanage/jyjhgl3.svg';
import topIcon4 from '@/assets/business_planmanage/jyjhgl4.svg';
const BusinessPlanManagement = () => {
const [searchKeyword, setSearchKeyword] = useState('');
const [selectedRows, setSelectedRows] = useState([]);
@ -14,126 +14,98 @@ const BusinessPlanManagement = () => {
const [pageSize, setPageSize] = useState(10);
// 列表筛选与数据(演示数据,可替换为接口)
const [filters, setFilters] = useState({
customerType: '',
customerGrade: '',
cooperationStatus: '',
transportMethod: '',
transportStatus: '',
dateRange: [],
});
// 新增:详情页面切换状态
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,
};
const { RangePicker } = DatePicker;
// 返回列表时恢复滚动位置,确保布局稳定后再滚动
useLayoutEffect(() => {
if (!showDetail) {
// 等待本帧布局完成
requestAnimationFrame(() => {
window.scrollTo(0, prevScrollY || 0);
});
}
}, [showDetail]);
// KPI数据
const kpiData = [
{ title: '本月计划总数', value: 156, icon: topIcon },
{ title: '待审核计划', value: 110, icon: topIcon2 },
{ title: '执行中计划', value: 21, icon: topIcon3 },
{ title: '已完成计划', value: 25, icon: topIcon4 },
// { title: '异常计划', value: 6, icon: topIcon2 },
];
// 表格数据
const tableData = [
{
id: 'CUST-2023-001',
customerName: '中国石化销售股份有限公司',
contact: '钱亚男',
phone: '18901563341',
classification: '高价值',
monthlyAmount: 1250000,
cooperationStatus: '合作中',
satisfaction: 4.5,
planNo: 'PLN-20230512-001',
planName: '6月首批入库计划',
oilType: '92#汽油',
quantity: 5000,
transportMethod: '管道运输',
planDate: '2023-06-01',
supplier: '中石化华东分公司',
status: '已确认',
},
{
id: 'CUST-2023-002',
customerName: '中石化华东分公司',
contact: '郑宇雅',
phone: '15341731282',
classification: '常规客户',
monthlyAmount: 1250000,
cooperationStatus: '合作中',
satisfaction: 4.0,
planNo: 'PLN-20230510-024',
planName: '7月公路到货计划',
oilType: '0#柴油',
quantity: 2500,
transportMethod: '公路运输',
planDate: '2023-07-21',
supplier: '山东恒燃实业集团',
status: '审核中',
},
{
id: 'CUST-2023-003',
customerName: '海南石油贸易有限公司',
contact: '孙向明',
phone: '13252257033',
classification: '高价值',
monthlyAmount: 850000,
cooperationStatus: '合作中',
satisfaction: 4.5,
planNo: 'PLN-20230508-017',
planName: '8月铁路运输计划',
oilType: '航空煤油',
quantity: 8000,
transportMethod: '铁路运输',
planDate: '2023-08-13',
supplier: '中原储能科技公司',
status: '已拒绝',
},
{
id: 'CUST-2023-004',
customerName: '东莞石化有限公司',
contact: '何思颖',
phone: '18931788771',
classification: '高价值',
monthlyAmount: 980000,
cooperationStatus: '合作中',
satisfaction: 4.5,
planNo: 'PLN-20230505-012',
planName: '9月船舶运输计划',
oilType: '燃料油',
quantity: 15000,
transportMethod: '船舶运输',
planDate: '2023-09-22',
supplier: '中海油南方公司',
status: '已完成',
},
{
id: 'CUST-2023-005',
customerName: '中国石油化工集团有限公司',
contact: '钱佳仪',
phone: '13743378254',
classification: '常规客户',
monthlyAmount: 980000,
cooperationStatus: '暂停合作',
satisfaction: 4.0,
planNo: 'PLN-20230428-008',
planName: '10月管道入库计划',
oilType: '95#汽油',
quantity: 6500,
transportMethod: '管道运输',
planDate: '2023-10-30',
supplier: '中石化华北公司',
status: '已确认',
},
];
// 列配置(用于 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) => (
<span className={`${styles.tag} ${val === '高价值' ? styles.tagGold : styles.tagBlue}`}>{val}</span>
)
},
{ title: '计划编号', dataIndex: 'planNo', key: 'planNo', width: 160 },
{ title: '计划名称', dataIndex: 'planName', key: 'planName', width: 200 },
{ title: '油品类型', dataIndex: 'oilType', key: 'oilType', width: 120 },
{
title: '交易额度(月)', dataIndex: 'monthlyAmount', key: 'monthlyAmount', width: 150,
render: (v) => `¥${Number(v).toLocaleString()}`
title: '数量(吨)', dataIndex: 'quantity', key: 'quantity', width: 120,
render: (v) => Number(v).toLocaleString()
},
{ title: '运输方式', dataIndex: 'transportMethod', key: 'transportMethod', width: 120 },
{ title: '计划日期', dataIndex: 'planDate', key: 'planDate', width: 140 },
{ title: '供应商/客户', dataIndex: 'supplier', key: 'supplier', width: 200 },
{ title: '状态', dataIndex: 'status', key: 'status', width: 110 },
{
title: '合作状态', dataIndex: 'cooperationStatus', key: 'cooperationStatus', width: 110,
render: (val) => (
<span className={`${styles.tag} ${val === '合作中' ? styles.tagGreen : styles.tagOrange}`}>{val}</span>
)
},
{
title: '满意度', dataIndex: 'satisfaction', key: 'satisfaction', width: 120,
},
{
title: '操作', key: 'action', fixed: 'right', width: 200,
title: '操作', key: 'action', fixed: 'right', width: 160,
render: (_, row) => (
<Space size={12}>
<Button type="link" size="small" className="viewDetailBtn" onClick={() => {
setPrevScrollY(window.pageYOffset || document.documentElement.scrollTop || 0);
setDetailData(row);
setShowDetail(true);
}}>查看详情</Button>
<Button type="link" size="small" className="editBtn">修改</Button>
<Button type="link" size="small" danger className="deleteBtn">删除</Button>
<Button type="link" size="small" className="viewDetailBtn">查看详情</Button>
<Button type="link" size="small" className="editBtn">编辑</Button>
</Space>
)
},
@ -141,53 +113,39 @@ const BusinessPlanManagement = () => {
}, []);
// 处理选择
const handleSelectRow = (id) => {
if (selectedRows.includes(id)) {
setSelectedRows(selectedRows.filter(rowId => rowId !== id));
const handleSelectRow = (planNo) => {
if (selectedRows.includes(planNo)) {
setSelectedRows(selectedRows.filter(rowId => rowId !== planNo));
} else {
setSelectedRows([...selectedRows, id]);
setSelectedRows([...selectedRows, planNo]);
}
};
const handleReset = () => {
setSearchKeyword('');
setFilters({ transportMethod: '', transportStatus: '', dateRange: [] });
};
return (
<div className={styles.container}>
<div className={styles.mainCard}>
{/* KPI卡片区域 */}
<div className={styles.kpiGrid}>
<div className={styles.kpiCard}>
<div className={styles.kpiText}>
<div className={styles.kpiValue}>{kpiData.totalCustomers}</div>
<div className={styles.kpiTitle}>总客户数</div>
</div>
<img src={topIcon} alt="icon" className={styles.kpiIconImg} />
</div>
<div className={styles.kpiCard}>
<div className={styles.kpiText}>
<div className={styles.kpiValue}>{kpiData.highValueCustomers}</div>
<div className={styles.kpiTitle}>高价值客户</div>
{kpiData.map((item) => (
<div className={styles.kpiCard} key={item.title}>
<div className={styles.kpiText}>
<div className={styles.kpiValue}>{item.value}</div>
<div className={styles.kpiTitle}>{item.title}</div>
</div>
<img src={item.icon} alt="icon" className={styles.kpiIconImg} />
</div>
<img src={topIcon2} alt="icon" className={styles.kpiIconImg} />
</div>
<div className={styles.kpiCard}>
<div className={styles.kpiText}>
<div className={styles.kpiValue}>{kpiData.inCooperation}</div>
<div className={styles.kpiTitle}>合作中</div>
</div>
<img src={topIcon3} alt="icon" className={styles.kpiIconImg} />
</div>
<div className={styles.kpiCard}>
<div className={styles.kpiText}>
<div className={styles.kpiValue}>{kpiData.newThisMonth}</div>
<div className={styles.kpiTitle}>本月新增</div>
</div>
<img src={topIcon4} alt="icon" className={styles.kpiIconImg} />
</div>
))}
</div>
{/* 客户列表区域 */}
{/* 查询区域 */}
<div className={styles.bottomSection}>
<div className={styles.sectionHeader}>
<span className={styles.sectionBar} />
<span className={styles.sectionTitle}>客户列表</span>
<span className={styles.sectionTitle}>查询条件</span>
</div>
<div className={styles.filterContent}>
<div className={styles.filterItem}>
@ -197,43 +155,48 @@ const BusinessPlanManagement = () => {
value={searchKeyword}
onChange={(e) => setSearchKeyword(e.target.value)}
onSearch={(val) => setSearchKeyword(val)}
style={{ minWidth: 150 }}
style={{ minWidth: 200 }}
/>
</div>
<div className={styles.filterItem}>
<span className={styles.filterLabel}>客户类型:</span>
<span className={styles.filterLabel}>运输方式:</span>
<Select
value={filters.customerType}
onChange={(v) => setFilters({ ...filters, customerType: v })}
value={filters.transportMethod}
onChange={(v) => setFilters({ ...filters, transportMethod: v })}
placeholder="全部"
options={[
{ label: '全部', value: '' },
{ label: '管道运输', value: '管道运输' },
{ label: '公路运输', value: '公路运输' },
{ label: '铁路运输', value: '铁路运输' },
{ label: '船舶运输', value: '船舶运输' },
]}
allowClear
/>
</div>
<div className={styles.filterItem}>
<span className={styles.filterLabel}>客户等级:</span>
<span className={styles.filterLabel}>运输状态:</span>
<Select
value={filters.customerGrade}
onChange={(v) => setFilters({ ...filters, customerGrade: v })}
value={filters.transportStatus}
onChange={(v) => setFilters({ ...filters, transportStatus: v })}
placeholder="全部"
options={[
{ label: '全部', value: '' },
{ label: '待审核', value: '待审核' },
{ label: '执行中', value: '执行中' },
{ label: '已完成', value: '已完成' },
{ label: '已拒绝', value: '已拒绝' },
]}
allowClear
/>
</div>
<div className={styles.filterItem}>
<span className={styles.filterLabel}>合作状态:</span>
<Select
value={filters.cooperationStatus}
onChange={(v) => setFilters({ ...filters, cooperationStatus: v })}
placeholder="全部"
options={[
{ label: '全部', value: '' },
]}
allowClear
<span className={styles.filterLabel}>日期范围:</span>
<RangePicker
value={filters.dateRange}
onChange={(val) => setFilters({ ...filters, dateRange: val || [] })}
style={{ minWidth: 240 }}
placeholder={['年/月/日', '年/月/日']}
/>
</div>
<Space className={styles.filterButtons}>
@ -247,29 +210,35 @@ const BusinessPlanManagement = () => {
<Button
icon={<ReloadOutlined />}
className={styles.resetBtn}
onClick={handleReset}
>
重置
</Button>
</Space>
</div>
<div className={styles.listHeader}>
<div className={styles.sectionHeader}>
<span className={styles.sectionBar} />
<span className={styles.sectionTitle}>经营计划列表</span>
</div>
<Space className={styles.filterButtonsRight}>
<Button
type="primary"
icon={<PlusOutlined />}
className={styles.addBtn}
>
新增客户
新增计划
</Button>
<Button
// icon={<ExportOutlined />}
className={styles.exportBtn}
>
批量导出
<Button className={styles.exportBtn}>
导出
</Button>
</Space>
</div>
<div className={styles.tableWrapper}>
<StandardTable
rowKey="id"
rowKey="planNo"
columns={columns}
data={{
list: tableData,
@ -282,8 +251,8 @@ const BusinessPlanManagement = () => {
}}
selectionType="checkbox"
selectedRowKeys={selectedRows}
onSelectRow={(row) => handleSelectRow(row.id)}
onSelectAll={(checked) => checked ? setSelectedRows(tableData.map(i => i.id)) : setSelectedRows([])}
onSelectRow={(row) => handleSelectRow(row.planNo)}
onSelectAll={(checked) => checked ? setSelectedRows(tableData.map(i => i.planNo)) : setSelectedRows([])}
onChangePage={(page) => setCurrentPage(page)}
onChangePageSize={(size) => { setPageSize(size); setCurrentPage(1); }}
/>

@ -340,5 +340,38 @@
// }
}
}
.listHeader {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
.sectionHeader {
margin-bottom: 0;
}
.filterButtonsRight {
display: flex;
gap: 12px;
.addBtn {
background-image: url('@/assets/business_basic/Bt_bg1.png');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border: none;
}
.exportBtn {
background-image: url('@/assets/business_basic/Bt_bg2.png');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border: none;
color: #006665;
}
}
}
}
}
Loading…
Cancel
Save