计划管理-生产计划管理-发油生产计划

main
jiangxucong 1 month ago
parent 2c483417ac
commit f515939aa4

@ -0,0 +1,281 @@
import React, { useMemo, useState } from 'react';
import { Select, Space, Button, Switch, message, Input, Modal, InputNumber } from 'antd';
import { PlusOutlined, SearchOutlined, ReloadOutlined, ExportOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './HairOilProductionPlan.less';
const HairOilProductionPlan = () => {
const [searchKeyword, setSearchKeyword] = useState('');
// 列表筛选与数据(演示数据,可替换为接口)
const [filters, setFilters] = useState({
listCategory: undefined,
listStatus: undefined,
});
const columns = useMemo(() => {
return [
{ title: '计划编号', dataIndex: 'planNo', key: 'planNo', width: 100 },
{ title: '油品名称', dataIndex: 'planName', key: 'planName', width: 220 },
{ title: '计划类型', dataIndex: 'planType', key: 'planType', width: 100 },
{ title: '计划时间', dataIndex: 'planTime', key: 'planTime', width: 160 },
{ title: '数量(吨)', dataIndex: 'qty', key: 'qty', width: 100 },
{ title: '来源/目的地', dataIndex: 'sourceTarget', key: 'sourceTarget', width: 230 },
{ title: '状态', dataIndex: 'status', key: 'status', width: 100 },
{ title: '进度', dataIndex: 'progress', key: 'progress', width: 100 },
{ title: '创建人', dataIndex: 'creator', key: 'creator', width: 100 },
{
title: '操作',
key: 'action',
fixed: 'right',
width: 140,
render: (_, record) => (
<Space size={12}>
<Button
type="link"
size="small"
className={styles.primaryActionBtn}
onClick={() => handlePrimaryAction(record)}
>
{record.actionText}
</Button>
</Space>
),
},
];
}, []);
const [tableData, setTableData] = useState([
{
key: 'RV20230710001',
planNo: 'RV20230710001',
planName: '92#汽油',
planType: '管道收油',
planTime: '2024-05-01 14:00',
qty: 600,
sourceTarget: '来源: 炼油厂 目的地: 1号储罐',
status: '已审批',
progress: '45%',
creator: '郑双',
actionText: '更新进度',
},
{
key: 'RV20230710002',
planNo: 'RV20230710002',
planName: '95#汽油',
planType: '管道收油',
planTime: '2024-05-01 14:00',
qty: 500,
sourceTarget: '来源: 炼油厂 目的地: 2号储罐',
status: '已驳回',
progress: '40%',
creator: '钱亮丽',
actionText: '跟踪进度',
},
{
key: 'RV20230710003',
planNo: 'RV20230710003',
planName: '92#汽油',
planType: '铁路收油',
planTime: '2024-05-01 15:00',
qty: 300,
sourceTarget: '来源: 炼油厂 目的地: 3号储罐',
status: '已审批',
progress: '0%',
creator: '郑璞',
actionText: '开始执行',
},
{
key: 'RV20230710004',
planNo: 'RV20230710004',
planName: '95#汽油',
planType: '公路收油',
planTime: '2024-05-01 12:00',
qty: 200,
sourceTarget: '来源: 炼油厂 目的地: 4号储罐',
status: '已审批',
progress: '50%',
creator: '孙莲艳',
actionText: '开始执行',
},
{
key: 'RV20230710005',
planNo: 'RV20230710005',
planName: '92#汽油',
planType: '管道收油',
planTime: '2024-05-01 11:00',
qty: 100,
sourceTarget: '来源: 炼油厂 目的地: 5号储罐',
status: '已驳回',
progress: '90%',
creator: '李莉娜',
actionText: '更新进度',
},
{
key: 'RV20230710006',
planNo: 'RV20230710006',
planName: '95#汽油',
planType: '管道收油',
planTime: '2024-05-01 10:00',
qty: 150,
sourceTarget: '来源: 炼油厂 目的地: 6号储罐',
status: '已驳回',
progress: '30%',
creator: '李钰',
actionText: '查看详情',
},
]);
const [progressState, setProgressState] = useState({ open: false, value: 0, recordKey: null });
const handlePrimaryAction = (record) => {
const action = record.actionText;
if (action === '更新进度') {
const current = parseInt(String(record.progress).replace('%', ''), 10) || 0;
setProgressState({ open: true, value: current, recordKey: record.key });
} else if (action === '跟踪进度') {
message.info(`当前进度:${record.progress}`);
} else if (action === '开始执行') {
Modal.confirm({
title: '确认开始执行?',
onOk: () => {
setTableData((prev) => prev.map((item) =>
item.key === record.key
? { ...item, status: '执行中', progress: item.progress || '0%', actionText: '更新进度' }
: item
));
message.success('已开始执行');
},
});
} else if (action === '查看详情') {
Modal.info({
title: '计划详情',
content: (
<div>
<div>计划编号{record.planNo}</div>
<div>计划名称{record.planName}</div>
<div>计划类型{record.planType}</div>
<div>计划时间{record.planTime}</div>
<div>数量{record.qty}</div>
<div>来源/目的地{record.sourceTarget}</div>
<div>状态{record.status}</div>
<div>进度{record.progress}</div>
<div>创建人{record.creator}</div>
</div>
),
});
}
};
return (
<div className={styles.container}>
<div className={styles.searchSection}>
<div className={styles.sectionHeader}>
<span className={styles.sectionBar} />
<span className={styles.sectionTitle}>查询条件</span>
</div>
<div className={styles.filterContent}>
<div className={styles.filterItem}>
<Input.Search
placeholder="搜索关键词"
allowClear
value={searchKeyword}
onChange={(e) => setSearchKeyword(e.target.value)}
onSearch={(val) => setSearchKeyword(val)}
style={{ minWidth: 150 }}
/>
</div>
<div className={styles.filterItem}>
<span className={styles.filterLabel}>状态:</span>
<Select
value={filters.listStatus}
onChange={(v) => setFilters({ ...filters, listStatus: v })}
placeholder="全部"
options={[
{ label: '全部', value: undefined },
{ label: '启用', value: '启用' },
{ label: '停用', value: '停用' },
]}
allowClear
/>
</div>
<Space className={styles.filterButtons}>
<Button
type="primary"
icon={<SearchOutlined />}
className={styles.queryBtn}
>
查询
</Button>
<Button
icon={<ReloadOutlined />}
className={styles.resetBtn}
>
重置
</Button>
</Space>
</div>
</div>
<div className={styles.searchSection}>
<div className={styles.sectionHeader}>
<span className={styles.sectionBar} />
<span className={styles.sectionTitle}>发油生产计划列表</span>
<Space className={styles.headerActions}>
<Button
type="primary"
icon={<PlusOutlined />}
className={styles.addBtn}
>
新增计划
</Button>
</Space>
</div>
<div className={styles.tableWrapper}>
<StandardTable
rowKey="key"
columns={columns}
data={{
list: tableData,
pagination: {
total: tableData.length,
pageSize: 10,
current: 1,
showTotal: (total) => `${total}`,
},
}}
// selectionType="checkbox"
/>
</div>
<Modal
title="更新进度"
open={progressState.open}
onOk={() => {
setTableData((prev) => prev.map((item) =>
item.key === progressState.recordKey
? { ...item, progress: `${progressState.value}%` }
: item
));
setProgressState({ open: false, value: 0, recordKey: null });
message.success('进度已更新');
}}
onCancel={() => setProgressState({ open: false, value: 0, recordKey: null })}
>
<Space>
<span>当前进度%</span>
<InputNumber
min={0}
max={100}
value={progressState.value}
onChange={(v) => setProgressState((s) => ({ ...s, value: Number(v) || 0 }))}
/>
</Space>
</Modal>
</div>
</div>
);
};
export default HairOilProductionPlan;

@ -0,0 +1,233 @@
@section-border: rgba(118, 194, 181, 1);
@section-bg: rgba(243, 249, 248, 1);
.container {
margin: 0;
padding: 0;
background: #fff;
display: flex;
flex-direction: column;
gap: 15px;
width: 100%;
height: 100%;
// 底部区域 - 油品列表
.searchSection {
flex: 1;
display: flex;
flex-direction: column;
// border: 1px solid @section-border;
background: #fff;
padding: 30px 20px 0 20px;
// 区域头部
.sectionHeader {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 15px;
// 将右侧动作区推到最右侧
.headerActions {
display: flex;
gap: 12px;
margin-left: auto;
.addBtn {
background-image: url('@/assets/business_basic/Bt_bg1.png');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border: none;
}
}
// 装饰条
.sectionBar {
width: 2px;
height: 16px;
background: rgba(0, 102, 101, 1);
border-radius: 1px;
}
// 标题
.sectionTitle {
font-size: 18px;
font-weight: 600;
color: #333;
}
}
// 筛选内容区域
.filterContent {
display: flex;
align-items: center;
gap: 20px;
// margin-bottom: 20px;
flex-wrap: wrap;
// justify-content: space-between;
// 筛选项
.filterItem {
display: flex;
align-items: center;
gap: 12px;
// 筛选标签
.filterLabel {
color: #333;
font-size: 14px;
}
:global {
// 统一 Input.Search 边框颜色为绿主题
.ant-input-affix-wrapper {
border-radius: 0px !important;
border-color: rgba(44, 158, 157, 1) !important;
}
.ant-input-search-button {
border-radius: 0px !important;
border-color: rgba(44, 158, 157, 1) !important;
}
.ant-select {
min-width: 140px;
// 选择框样式
.ant-select-selector {
border-color: rgba(44, 158, 157, 1) !important;
border-radius: 2px !important;
}
&:hover .ant-select-selector {
border-color: rgba(44, 158, 157, 1) !important;
}
&.ant-select-focused .ant-select-selector {
border-color: rgba(44, 158, 157, 1) !important;
box-shadow: 0 0 0 2px rgba(44, 158, 157, 0.2) !important;
}
}
}
}
// 筛选按钮组
.filterButtons {
display: flex;
gap: 12px;
.queryBtn {
background-image: url('@/assets/business_basic/Bt_bg1.png');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border: none;
}
.resetBtn {
background-image: url('@/assets/business_basic/Bt_bg2.png');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border: none;
color: #006665;
}
}
}
// 表格包装器
.tableWrapper {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
.primaryActionBtn {
color: #2D9E9D;
}
:global(.ant-table-wrapper) {
flex: 1;
display: flex;
flex-direction: column;
}
// 表头样式
:global {
.ant-table-thead>tr>th {
color: rgba(51, 51, 51, 1) !important;
font-weight: 450 !important;
background-color: rgba(240, 247, 247, 1) !important;
text-align: center !important;
}
// 表体样式
.ant-table-tbody>tr>td {
color: rgba(78, 88, 86, 1) !important;
font-weight: 400 !important;
text-align: center !important;
}
// 操作列按钮样式
.viewDetailBtn {
color: rgba(0, 102, 101, 1) !important;
&:hover {
color: rgba(0, 102, 101, 1) !important;
}
}
.editBtn {
color: rgba(45, 158, 157, 1) !important;
&:hover {
color: rgba(45, 158, 157, 1) !important;
}
}
.deleteBtn {
color: rgba(255, 130, 109, 1) !important;
&:hover {
color: rgba(255, 130, 109, 1) !important;
}
}
// 状态列 Switch 样式
.statusSwitch {
// 启用状态背景色
&.ant-switch-checked {
background-color: rgba(20, 106, 89, 1) !important;
}
// 停用状态背景色
&:not(.ant-switch-checked) {
background-color: rgba(153, 153, 153, 1) !important;
}
}
// 复选框样式
.ant-checkbox-inner {
border-color: rgba(0, 102, 101, 1) !important;
&::after {
background-color: rgba(0, 102, 101, 1) !important;
}
}
.ant-checkbox-wrapper:hover .ant-checkbox-inner,
.ant-checkbox:hover .ant-checkbox-inner {
border-color: rgba(0, 102, 101, 1) !important;
}
.ant-checkbox-checked .ant-checkbox-inner {
background-color: rgba(0, 102, 101, 1) !important;
border-color: rgba(0, 102, 101, 1) !important;
}
}
}
}
}
Loading…
Cancel
Save