Commit 531917e2 authored by 沈翠玲's avatar 沈翠玲

第四个看板

parent 74a8b3d0
......@@ -125,13 +125,13 @@ export default [
layout: false,
component: './kanban/ProductionProgress',
},
// {
// path: 'materialSynthesisKanban',
// name: 'materialSynthesisKanban',
// target: '_blank',
// layout: false,
// component: './kanban/materialSynthesis',
// },
{
path: 'materialSynthesisKanban',
name: 'materialSynthesisKanban',
target: '_blank',
layout: false,
component: './kanban/materialSynthesis',
},
// {
// path: 'weldingProcessKanban',
// name: 'weldingProcessKanban',
......
......@@ -58,7 +58,31 @@ export default {
'日期': 'วันที่',
'产品': 'ผลิตภัณฑ์',
'计划数': 'จำนวนแผน',
'工序': 'ขั้นตอนการทำงาน'
'工序': 'ขั้นตอนการทำงาน',
'物料综合看板': 'กระดานสังเคราะห์วัสดุ',
'物料配送完成率': 'อัตราการจัดส่งวัสดุเสร็จสิ้น',
'生产入库完成率': 'อัตราการผลิตเข้าคลังสินค้า',
'采购到货完成率': 'อัตราความสมบูรณ์ของการซื้อมาถึง',
'销售发货及时率': 'การขายและการจัดส่งทันเวลา',
'当月销售出库计划': 'แผนการขายออกจากคลังสินค้าในเดือน',
'总数量': 'จำนวนรวม',
'已出库': 'ออกจากคลังแล้ว',
'产品数量': 'จำนวนสินค้า',
'计划出库时间': 'กำหนดเวลาออกจากคลังสินค้า',
'订货数量': 'ปริมาณการสั่งซื้อ',
'已出库数量': 'จำนวนห้องสมุดที่ออกแล้ว',
'当月生产入库计划': 'มีกำหนดเก็บผลผลิตในเดือน',
'完成数': 'จำนวนเสร็จสิ้น',
'通知单号': 'หมายเลขใบรับแจ้ง',
'生产工单': 'ใบสั่งงานผลิต',
'产品名称': 'ชื่อผลิตภัณฑ์',
'计划完成时间': 'กำหนดเวลาเสร็จสิ้น',
'计划数量': 'จำนวนแผน',
'完成数量': 'จำนวนเสร็จสิ้น',
'当月库存趋势图': 'กราฟแนวโน้มสินค้าคงคลังของเดือน',
'当月生产入库趋势图': 'กราฟแนวโน้มการผลิตสินค้าคงคลังในเดือน',
'当月发货出库趋势图': 'แผนที่แนวโน้มการจัดส่งสินค้าคงคลังในเดือน',
}
;
\ No newline at end of file
......@@ -58,6 +58,31 @@ export default {
'日期': '日期',
'产品': '产品',
'计划数': '计划数',
'工序': '工序'
'工序': '工序',
'物料综合看板': '物料综合看板',
'物料配送完成率': '物料配送完成率',
'生产入库完成率': '生产入库完成率',
'订单上线准时率': '订单上线准时率',
'采购到货完成率': '采购到货完成率',
'销售发货及时率': '销售发货及时率',
'当月销售出库计划': '当月销售出库计划',
'总数量': '总数量',
'已出库': '已出库',
'产品数量': '产品数量',
'计划出库时间': '计划出库时间',
'订货数量': '订货数量',
'已出库数量': '已出库数量',
'当月生产入库计划': '当月生产入库计划',
'完成数': '完成数',
'通知单号': '通知单号',
'生产工单': '生产工单',
'产品名称': '产品名称',
'计划完成时间': '计划完成时间',
'计划数量': '计划数量',
'完成数量': '完成数量',
'当月库存趋势图': '当月库存趋势图',
'当月生产入库趋势图': '当月生产入库趋势图',
'当月发货出库趋势图': '当月发货出库趋势图',
};
\ No newline at end of file
......@@ -40,6 +40,7 @@
width: 100%;
padding: 50px 100px 0 100px;
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
......@@ -49,6 +50,7 @@
cursor: pointer;
border-radius: 10px;
margin-right: 60px;
margin-bottom: 60px;
overflow: hidden;
background-color: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.3);
......@@ -72,6 +74,11 @@
background-image: url('./img/3.png');
}
}
&:nth-child(4) {
.imgWapper {
background-image: url('./img/4.png');
}
}
}
.logout {
position: absolute;
......@@ -101,8 +108,8 @@
text-align: center
}
.imgWapper {
width: 452px;
height: 257px;
width: 508px;
height: 285px;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
......
import React, { useRef, useState } from 'react';
import { DrawerForm, ProFormCheckbox, ProFormDigit, ProFormSelect } from '@ant-design/pro-form';
import type { ProFormInstance } from '@ant-design/pro-form';
import { queryMaterialChKanbanSettingList } from '../../services/api';
type MaterialChKanbanSettingDto = KANBAN.MaterialSynthesis.MaterialChKanbanSettingDto;
export type Setting = {
......@@ -21,7 +20,6 @@ export type SettingFormProps = {
const SettingForm: React.FC<SettingFormProps> = (props) => {
const formRef = useRef<ProFormInstance>();
const [kanbanSettingList, setKanbanSettingList] = useState<MaterialChKanbanSettingDto[]>([]);
return (
<DrawerForm
......@@ -32,17 +30,13 @@ const SettingForm: React.FC<SettingFormProps> = (props) => {
onVisibleChange={(visible: boolean) => {
if (visible) {
formRef?.current?.setFieldsValue({
...props.values,
productionProgressKanbanSettingId: props.values.productionProgressKanbanSetting?.id,
...props.values
});
}
props.onVisibleChange(visible);
}}
onFinish={async (values: Setting) => {
const productionProgressKanbanSetting = kanbanSettingList.find(
(a) => a.id === values.kanbanId,
);
props.onSubmitting({ ...values, productionProgressKanbanSetting });
props.onSubmitting({ ...values });
props.onVisibleChange(false);
}}
>
......@@ -63,17 +57,6 @@ const SettingForm: React.FC<SettingFormProps> = (props) => {
min={1}
fieldProps={{ precision: 0 }}
/>
<ProFormSelect
name="kanbanId"
label="看板设置"
required
width="xl"
request={async () => {
const { data } = await queryMaterialChKanbanSettingList();
setKanbanSettingList(data);
return data.map((a) => ({ label: a.kanbTitle, value: a.id }));
}}
/>
</DrawerForm>
);
};
......
import React, { useEffect, useRef } from 'react';
import { queryMaterialReqOrderInfo } from '@/pages/kanban/productionComprehens/services/api';
import ProTable, { ActionType } from '@ant-design/pro-table';
type MaterialReqOrderInfoCriteria = KANBAN.ProductionComprehens.MaterialReqOrderInfoCriteria;
export type InfoProps = {
values: MaterialReqOrderInfoCriteria;
};
const MaterialOrderModalTable: React.FC<InfoProps> = (props) => {
const actionRef = useRef<ActionType>();
useEffect(() => {
actionRef.current?.reload();
}, [props.values]);
const columns = [
{
title: '单号',
dataIndex: 'materialReqorderNo',
key: 'materialReqorderNo',
},
{
title: '需求日期',
dataIndex: 'requiredDate',
key: 'requiredDate',
},
{
title: '配送地点',
dataIndex: 'ltxa1',
key: 'ltxa1',
},
{
title: '创建时间',
dataIndex: 'createdDate',
key: 'createdDate',
},
{
title: '物料编号',
dataIndex: 'matnr',
key: 'matnr',
},
{
title: '物料描述',
dataIndex: 'maktx',
key: 'maktx',
},
{
title: '库存地点',
dataIndex: 'lgort',
key: 'lgort',
},
{
title: 'BOM定额',
dataIndex: 'bomMenge',
key: 'bomMenge',
},
{
title: '计划数量',
dataIndex: 'planMenge',
key: 'planMenge',
},
{
title: '过账总数量',
dataIndex: 'totalMenge',
key: 'totalMenge',
},
{
title: '过账时间',
dataIndex: 'executedDate',
key: 'executedDate',
},
];
return (
<>
<ProTable
options={false}
search={false}
actionRef={actionRef}
request={async (params: MaterialReqOrderInfoCriteria) => {
const sr = await queryMaterialReqOrderInfo({
...props.values,
pageSize: params.pageSize,
current: params.current,
});
const pageResult: Common.PageResult<any> = {
current: params.current,
pageSize: params.pageSize,
total: sr.data.total,
data: sr.data.data,
};
return pageResult;
}}
pagination={{
pageSize: 10,
}}
columns={columns}
size={'middle'}
bordered
scroll={{ x: 2000 }}
/>
</>
);
};
export default MaterialOrderModalTable;
.efficiency-container {
border: 2px solid #00ffff;
border-radius: 15px;
width: 100%;
.row {
display: flex;
......
......@@ -5,12 +5,8 @@ import * as echarts from 'echarts/lib/echarts';
import type { ECharts } from 'echarts';
import { getInstanceByDom } from 'echarts';
import { useEffect, useRef, useState } from 'react';
import { Modal } from 'antd';
import OrderInfo from './orderInfo';
import MaterialOrderInfo from './MaterialOrderInfo';
import moment from 'moment';
import { useIntl } from 'umi';
type MaterialReqOrderInfoCriteria = KANBAN.ProductionComprehens.MaterialReqOrderInfoCriteria;
type EfficiencyKanbanSetting = KANBAN.MaterialSynthesis.EfficiencyKanbanSetting;
const PeiSongPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> = ({
......@@ -18,8 +14,6 @@ const PeiSongPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
setting,
}) => {
const chartRef = useRef<HTMLDivElement>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [criteria, setCriteria] = useState<MaterialReqOrderInfoCriteria>();
useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;
......@@ -41,33 +35,6 @@ const PeiSongPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
window.removeEventListener('resize', resizeChart);
};
}, []);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
chart?.off('click');
if (!setting.werks) {
return;
}
chart?.on('click', () => {
setIsModalOpen(true);
setCriteria({
werks: setting.werks,
startDateFrom: moment()
.date(1)
.hour(0)
.minute(0)
.second(0)
.millisecond(0)
.format('YYYY-MM-DD HH:mm'),
startDateTo: moment().format('YYYY-MM-DD HH:mm'),
current: 1,
status: 1,
pageSize: 10,
});
});
}
}, [setting]);
const closeModal = () => setIsModalOpen(false);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
......@@ -104,15 +71,6 @@ const PeiSongPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
return (
<>
<div ref={chartRef} style={{ height: '210px' }} />
<Modal
title={'领料单明细'}
visible={isModalOpen}
footer={null}
width={'70%'}
onCancel={closeModal}
>
<MaterialOrderInfo values={criteria} />
</Modal>
</>
);
};
......@@ -122,8 +80,6 @@ const ZhunshiPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
setting,
}) => {
const chartRef = useRef<HTMLDivElement>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [criteria, setCriteria] = useState<MaterialReqOrderInfoCriteria>();
useEffect(() => {
// Initialize chart
......@@ -147,35 +103,6 @@ const ZhunshiPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
};
}, []);
useEffect(() => {
// Initialize chart
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
chart?.off('click');
if (!setting.werks) {
return;
}
chart?.on('click', () => {
setIsModalOpen(true);
setCriteria({
werks: setting.werks,
startDateFrom: moment()
.date(1)
.hour(0)
.minute(0)
.second(0)
.millisecond(0)
.format('YYYY-MM-DD HH:mm'),
startDateTo: moment().format('YYYY-MM-DD HH:mm'),
onTime: 2,
current: 1,
pageSize: 10,
});
});
}
}, [setting]);
const closeModal = () => setIsModalOpen(false);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
......@@ -212,15 +139,6 @@ const ZhunshiPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
return (
<>
<div ref={chartRef} style={{ height: '210px' }} />
<Modal
title={'领料单明细'}
visible={isModalOpen}
footer={null}
width={'70%'}
onCancel={closeModal}
>
<MaterialOrderInfo values={criteria} />
</Modal>
</>
);
};
......@@ -230,13 +148,6 @@ const ShangxianPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }>
setting,
}) => {
const chartRef = useRef<HTMLDivElement>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [batchInfoParams, setBatchInfoParams] = useState({
current: 1,
pageSize: 10,
type: 1,
kanbanSettingId: '',
});
useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;
......@@ -258,23 +169,6 @@ const ShangxianPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }>
window.removeEventListener('resize', resizeChart);
};
}, []);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
chart?.off('click');
chart?.on('click', () => {
if (!setting.kanbanId) return;
setBatchInfoParams({
...batchInfoParams,
type: 1,
kanbanSettingId: setting.kanbanId as string,
});
setIsModalOpen(true);
});
}
}, [setting]);
const closeModal = () => setIsModalOpen(false);
useEffect(() => {
if (chartRef.current !== null) {
......@@ -283,7 +177,7 @@ const ShangxianPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }>
grid: {
width: '100%',
},
color: ['#004af2', '#213045'],
color: ['#249ab5', '#213045'],
series: [
{
name: 'Access From',
......@@ -312,15 +206,6 @@ const ShangxianPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }>
return (
<>
<div ref={chartRef} style={{ height: '210px' }} />
<Modal
title={'工单明细'}
visible={isModalOpen}
footer={null}
width={'70%'}
onCancel={closeModal}
>
<OrderInfo params={batchInfoParams} />
</Modal>
</>
);
};
......@@ -330,13 +215,6 @@ const XiaxianPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
setting,
}) => {
const chartRef = useRef<HTMLDivElement>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [batchInfoParams, setBatchInfoParams] = useState({
current: 1,
pageSize: 10,
type: 2,
kanbanSettingId: '',
});
useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;
......@@ -358,22 +236,6 @@ const XiaxianPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
window.removeEventListener('resize', resizeChart);
};
}, []);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
chart?.off('click');
chart?.on('click', () => {
if (!setting.kanbanId) return;
setBatchInfoParams({
...batchInfoParams,
type: 2,
kanbanSettingId: setting.kanbanId as string,
});
setIsModalOpen(true);
});
}
}, [setting]);
const closeModal = () => setIsModalOpen(false);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
......@@ -381,7 +243,7 @@ const XiaxianPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
grid: {
width: '100%',
},
color: ['#004af2', '#213045'],
color: ['#249ab5', '#213045'],
series: [
{
name: 'Access From',
......@@ -410,15 +272,6 @@ const XiaxianPie: React.FC<{ data: number; setting: EfficiencyKanbanSetting }> =
return (
<>
<div ref={chartRef} style={{ height: '210px' }} />
<Modal
title={'订单明细'}
visible={isModalOpen}
footer={null}
width={'70%'}
onCancel={closeModal}
>
<OrderInfo params={batchInfoParams} />
</Modal>
</>
);
};
......@@ -428,26 +281,29 @@ const Main: React.FC<{ punctual: any; delivery: any; setting: EfficiencyKanbanSe
delivery,
setting,
}) => {
const intl = useIntl();
return (
<div className="efficiency-container">
<div className="row" style={{ marginBottom: '40px' }}>
<div className="row" style={{ marginBottom: '8px' }}>
<div className="item" style={{ marginLeft: '0' }}>
<h2>物料配送完成率</h2>
<PeiSongPie data={delivery.finishedRate} setting={setting} />
<h2>
{intl.formatMessage({id: '物料配送完成率'})}
</h2>
<PeiSongPie data={delivery.stockInCompleteRatio} setting={setting} />
</div>
<div className="item">
<h2>物料准时配送率</h2>
<ZhunshiPie data={delivery.punctualRate} setting={setting} />
<h2>{intl.formatMessage({id: '生产入库完成率'})}</h2>
<ZhunshiPie data={punctual} setting={setting} />
</div>
</div>
<div className="row">
<div className="item" style={{ marginLeft: '0' }}>
<h2>订单上线准时率</h2>
<ShangxianPie data={punctual.orderOnlinePunctualRate} setting={setting} />
<h2>{intl.formatMessage({id: '采购到货完成率'})}</h2>
<ShangxianPie data={delivery.materialDistRatio} setting={setting} />
</div>
<div className="item">
<h2>订单下线准时率</h2>
<XiaxianPie data={punctual.orderOfflinePunctualRate} setting={setting} />
<h2>{intl.formatMessage({id: '销售发货及时率'})}</h2>
<XiaxianPie data={delivery.salesTimelyDeliveryRatio} setting={setting} />
</div>
</div>
</div>
......
import { queryPageByKanbanPenetrating } from '@/pages/kanban/productionComprehens/services/api';
import ProTable, { ActionType } from '@ant-design/pro-table';
import { useEffect, useRef } from 'react';
const OrderModalTable: React.FC<{ params: any }> = ({ params }) => {
const actionRef = useRef<ActionType>();
useEffect(() => {
actionRef.current?.setPageInfo({
current: 1,
});
actionRef.current?.reload();
}, [params]);
const columns = [
{
title: '批号',
dataIndex: 'lotNo',
key: 'lotNo',
width: 100,
},
{
title: '生产订单',
dataIndex: 'aufnr',
key: 'aufnr',
width: 100,
},
{
title: '工厂',
dataIndex: 'werks',
key: 'werks',
width: 60,
},
{
title: '生产管理员',
dataIndex: 'fevor',
key: 'fevor',
width: 60,
},
{
title: '基本开始日期',
dataIndex: 'gstrp',
key: 'gstrp',
width: 110,
},
{
title: '基本结束日期',
dataIndex: 'gltrp',
key: 'gstrp',
width: 110,
},
{
title: '实际开始日期',
dataIndex: 'actualStartDate',
key: 'actualStartDate',
width: 110,
},
{
title: '实际结束日期',
dataIndex: 'actualEndDate',
key: 'actualEndDate',
width: 110,
},
{
title: '入库时间',
dataIndex: 'stockInDate',
key: 'stockInDate',
width: 110,
},
{
title: '评估类',
dataIndex: 'pglei',
key: 'pglei',
width: 60,
},
];
return (
<>
<ProTable
options={false}
search={false}
actionRef={actionRef}
request={async (pms: any) => {
console.log(pms, 'pms');
const sr = await queryPageByKanbanPenetrating({
...params,
pageSize: pms.pageSize,
current: pms.current,
});
// const sr = await queryPageByKanbanPenetrating({ ...params });
sr.data.data.forEach((v, i) => (v.key = i + 1));
const pageResult: Common.PageResult<any> = {
current: pms.current,
pageSize: pms.pageSize,
total: sr.data.total,
data: sr.data.data,
};
return pageResult;
}}
pagination={{
pageSize: 10,
}}
columns={columns}
size={'middle'}
bordered
scroll={{ x: 1100 }}
/>
</>
);
};
export default OrderModalTable;
.missingMaterial-container {
padding: 5px 20px 10px;
border: 2px solid #00ffff;
border-radius: 15px;
.title {
h2 {
position: relative;
......@@ -20,32 +23,23 @@
}
}
}
.bar-container {
.line-container {
display: flex;
flex-direction: column;
height: 224px;
margin-top: 10px;
.item {
display: flex;
flex: 1;
flex-direction: column;
height: 210px;
margin-right: 10px;
padding: 5px 0 0 0px;
background: #031024;
&:last-child {
margin-right: 0;
}
p {
margin-bottom: 0px;
font-size: 16px;
text-align: center;
}
padding: 10px;
background: #031024;
p {
font-size: 16px;
}
}
.line-container {
.line-container1 {
display: flex;
flex-direction: column;
height: 210px;
margin-top: 10px;
height: 224px;
margin-top: 4px;
padding: 10px;
background: #031024;
p {
......
import type { LineConfig } from '@ant-design/charts';
import { Line } from '@ant-design/plots';
import './index.less';
import * as echarts from 'echarts/lib/echarts';
// import * as echarts from 'echarts/lib/echarts';
import { useEffect, useRef, useState } from 'react';
import { ECharts, getInstanceByDom } from 'echarts';
import MissingMaterialInfo from './missingMaterialInfo';
import { Modal } from 'antd';
// import { ECharts, getInstanceByDom } from 'echarts';
import { useIntl } from 'umi';
type MissProps = {
month: KANBAN.MaterialSynthesis.CountCurrentMonthLackMaterialKanbanDto[];
lack: KANBAN.MaterialSynthesis.CountCurrentLackMaterialKanbanDto[];
};
type CommonProps = {
data: MissProps['lack'];
onClickBar: (workLine: string, flag: number) => void;
};
const lendTemp = {
缺料种类: 1,
超期一周: 2,
当月缺料: 3,
};
const formatOptions = (data: any, label = '高压', isLenged = false) => {
const option = {
color: [
{
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#00214d', // 100% 处的颜色
},
{
offset: 0,
color: '#4ad4fe', // 0% 处的颜色
},
],
global: false, // 缺省为 false
},
{
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#00214d',
},
{
offset: 0,
color: '#ffc000',
},
],
global: false, // 缺省为 false
},
{
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#00214d',
},
{
offset: 0,
color: '#ff0000',
},
],
global: false, // 缺省为 false
},
{
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#213045',
},
{
offset: 0,
color: '#ff0000',
},
],
global: false, // 缺省为 false
},
],
legend: {
show: isLenged,
orient: 'vertical',
bottom: 0,
right: 5,
selectedMode: false,
itemWidth: 10,
itemHeight: 10,
textStyle: {
color: '#fff',
fontSize: 14,
},
},
grid: {
bottom: 30,
top: -30,
left: 10,
},
xAxis: {
type: 'value',
show: false,
},
yAxis: {
type: 'category',
data: [label],
show: false,
axisLabel: {
color: '#fff',
fontSize: 16,
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
},
series: [],
};
const temp = {
type: 'bar',
name: '',
barGap: 0,
label: {
show: true,
position: 'right',
color: '#fff',
},
barWidth: 30,
data: [],
};
const i = data.findIndex((item) => item.workLine === label);
if (i > -1) {
option.series.push({ ...temp, name: '缺料种类', data: [data[i].normalNumber] });
option.series.push({ ...temp, name: '超期一周', data: [data[i].beyondDayNumber] });
option.series.push({ ...temp, name: '当月缺料', data: [data[i].currentMonthNumber] });
}
return option;
};
const HeightBar: React.FC<CommonProps> = ({ data, onClickBar }) => {
const chartRef = useRef<HTMLDivElement>(null);
useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;
if (chartRef.current !== null) {
chart = echarts.init(chartRef.current);
}
// Add chart resize listener
// ResizeObserver is leading to a bit janky UX
function resizeChart() {
chart?.resize();
}
window.addEventListener('resize', resizeChart);
// Return cleanup function
return () => {
chart?.dispose();
chart?.off('click');
window.removeEventListener('resize', resizeChart);
};
}, []);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
const option = formatOptions(data, '高压');
chart?.setOption(option);
chart?.off('click');
chart?.on('click', (params) => {
onClickBar('高压', lendTemp[params.seriesName as string]);
});
}
}, [data]);
return <div ref={chartRef} style={{ height: '170px' }}></div>;
};
const DowntBar: React.FC<CommonProps> = ({ data, onClickBar }) => {
const chartRef = useRef<HTMLDivElement>(null);
useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;
if (chartRef.current !== null) {
chart = echarts.init(chartRef.current);
}
// Add chart resize listener
// ResizeObserver is leading to a bit janky UX
function resizeChart() {
chart?.resize();
}
window.addEventListener('resize', resizeChart);
// Return cleanup function
return () => {
chart?.dispose();
chart?.off('click');
window.removeEventListener('resize', resizeChart);
};
}, []);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
const option = formatOptions(data, '中压');
chart?.setOption(option);
chart?.off('click');
chart?.on('click', (params) => {
onClickBar('中压', lendTemp[params.seriesName as string]);
});
}
}, [data]);
return <div ref={chartRef} style={{ height: '170px' }}></div>;
};
const CarBar: React.FC<CommonProps> = ({ data, onClickBar }) => {
const chartRef = useRef<HTMLDivElement>(null);
useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;
if (chartRef.current !== null) {
chart = echarts.init(chartRef.current);
}
// Add chart resize listener
// ResizeObserver is leading to a bit janky UX
function resizeChart() {
chart?.resize();
}
window.addEventListener('resize', resizeChart);
// Return cleanup function
return () => {
chart?.dispose();
chart?.off('click');
window.removeEventListener('resize', resizeChart);
};
}, []);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
const option = formatOptions(data, '低温车箱');
chart?.setOption(option);
chart?.off('click');
chart?.on('click', (params) => {
onClickBar('低温车箱', lendTemp[params.seriesName as string]);
});
}
}, [data]);
return <div ref={chartRef} style={{ height: '170px' }}></div>;
};
const TankBar: React.FC<CommonProps> = ({ data, onClickBar }) => {
const chartRef = useRef<HTMLDivElement>(null);
useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;
if (chartRef.current !== null) {
chart = echarts.init(chartRef.current);
}
// Add chart resize listener
// ResizeObserver is leading to a bit janky UX
function resizeChart() {
chart?.resize();
}
window.addEventListener('resize', resizeChart);
// Return cleanup function
return () => {
chart?.dispose();
chart?.off('click');
window.removeEventListener('resize', resizeChart);
};
}, []);
useEffect(() => {
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
const option = formatOptions(data, '低温罐', true);
chart?.setOption(option);
chart?.off('click');
chart?.on('click', (params) => {
onClickBar('低温罐', lendTemp[params.seriesName as string]);
});
}
}, [data]);
return <div ref={chartRef} style={{ height: '170px' }}></div>;
};
const MonthLine: React.FC<{ month: MissProps['month'] }> = ({ month }) => {
const [data, setData] = useState([]);
const countMax = () => {
return Math.max(...data.map((item) => item.number)) * 1.2;
return Math.max(...data.map((item) => item.value)) * 1.2;
};
useEffect(() => {
setData(
......@@ -321,6 +22,7 @@ const MonthLine: React.FC<{ month: MissProps['month'] }> = ({ month }) => {
.sort((a, b) => a.day - b.day)
.map((item) => {
item.day += '';
item['type'] = '数量'
return item;
}),
);
......@@ -330,7 +32,7 @@ const MonthLine: React.FC<{ month: MissProps['month'] }> = ({ month }) => {
width: 946,
height: 110,
xField: 'day',
yField: 'number',
yField: 'value',
smooth: true,
lineStyle: {
stroke: '#1b46df',
......@@ -357,6 +59,13 @@ const MonthLine: React.FC<{ month: MissProps['month'] }> = ({ month }) => {
fill: '#fff',
},
},
seriesField: 'type',
legend: {
position: 'right-top',
style: {
fill: '#fff',
}
},
yAxis: {
tickLine: null,
line: null,
......@@ -374,63 +83,20 @@ const MonthLine: React.FC<{ month: MissProps['month'] }> = ({ month }) => {
};
const Main: React.FC<MissProps> = ({ month, lack }) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [missingInfoParams, setMissingInfoParams] = useState({
workLine: '',
flag: 1,
});
const intl = useIntl();
const closeModal = () => setIsModalOpen(false);
const clickBar = (workLine: string, flag: number) => {
setMissingInfoParams({
workLine,
flag,
});
setIsModalOpen(true);
};
return (
<div className="missingMaterial-container">
<div className="title">
<h2>当前缺料分布</h2>
<h2>{intl.formatMessage({id:'当月库存趋势图'})}</h2>
</div>
<div className="bar-container">
<div className="item">
<p>高压</p>
<HeightBar data={lack} onClickBar={clickBar} />
</div>
<div className="item">
<p>中压</p>
<DowntBar data={lack} onClickBar={clickBar} />
</div>
<div className="item">
<p>低温车箱</p>
<CarBar data={lack} onClickBar={clickBar} />
</div>
<div className="item">
<p>低温罐</p>
<TankBar data={lack} onClickBar={clickBar} />
</div>
<Modal
title={
missingInfoParams.workLine +
(missingInfoParams.flag === 1
? '缺料种类'
: missingInfoParams.flag === 2
? '超期一周'
: '当月缺料')
}
visible={isModalOpen}
footer={null}
width={'70%'}
onCancel={closeModal}
>
<MissingMaterialInfo params={missingInfoParams} />
</Modal>
<div className="line-container1">
<p>{intl.formatMessage({id:'当月生产入库趋势图'})}</p>
<MonthLine month={month} />
</div>
<div className="line-container">
<p>当月缺料趋势图</p>
<MonthLine month={month} />
<p>{intl.formatMessage({id:'当月发货出库趋势图'})}</p>
<MonthLine month={lack} />
</div>
</div>
);
......
import { queryMaterialComprehensiveKanbanDataByWorkLine } from '@/pages/kanban/materialSynthesis/services/api';
import ProTable, { ActionType } from '@ant-design/pro-table';
import { useEffect, useRef } from 'react';
const MissingMaterialInfo: React.FC<{ params: any }> = ({ params }) => {
const actionRef = useRef<ActionType>();
useEffect(() => {
actionRef.current?.reload();
}, [params]);
const columns = [
{
title: '施工号',
dataIndex: 'sgNo',
key: 'sgNo',
width: 200,
},
{
title: '物料名称',
dataIndex: 'partName',
key: 'partName',
width: 200,
},
{
title: '超期天数',
dataIndex: 'beyondDays',
key: 'beyondDays',
width: 100,
},
{
title: '回厂时间',
dataIndex: 'backDate',
key: 'backDate',
},
];
return (
<>
<ProTable
options={false}
search={false}
actionRef={actionRef}
request={async () => {
const sr = await queryMaterialComprehensiveKanbanDataByWorkLine({ ...params });
// const sr = await queryPageByKanbanPenetrating({ ...params });
sr.data.forEach((v, i) => (v.key = i + 1));
const pageResult = {
data: sr.data,
};
return pageResult;
}}
pagination={{ pageSize: 10 }}
columns={columns}
size={'middle'}
bordered
scroll={{ x: 1100 }}
/>
</>
);
};
export default MissingMaterialInfo;
.partProgress-container {
flex: 1;
margin-top: 10px;
padding: 10px 20px 20px;
border: 2px solid #00ffff;
border-radius: 15px;
background: #031024;
.title {
display: flex;
......@@ -47,6 +50,12 @@
}
}
.table-body {
overflow: auto;
-ms-overflow-style: none; /* IE 和 Edge */
scrollbar-width: none; /* Firefox */
&::-webkit-scrollbar {
display: none; /* Chrome, Safari 和 Opera */
}
.row {
display: flex;
line-height: 60px;
......
import React, { useEffect, useRef, useState } from 'react';
import './index.less';
import PartModalTable from './modal';
import { Modal } from 'antd';
import { useIntl } from 'umi';
type PartProgressDetailSetting = KANBAN.MaterialSynthesis.PartProgressDetailSetting;
type PartProgressDetailCriteria = KANBAN.MaterialSynthesis.PartProgressDetailCriteria;
type PartScheduleIndexDataDto = KANBAN.MaterialSynthesis.PartScheduleIndexDataDto;
const Main: React.FC<{ data: PartScheduleIndexDataDto[]; setting: PartProgressDetailSetting }> = ({
const Main: React.FC<{ data: PartScheduleIndexDataDto[]; rowMovingTime: any }> = ({
data,
setting,
rowMovingTime,
}) => {
const intl = useIntl();
const [nums, setNums] = useState({ total: 0, unfinish: 0 });
let timer: NodeJS.Timer | null = null;
const leftScroll = useRef<HTMLDivElement>(null);
useEffect(() => {
setNums(
data.reduce(
(pre, cur) => {
pre.total += cur.totalQuantity;
pre.unfinish += cur.unFinishQuantity;
pre.total += cur.planQuantity;
pre.unfinish += cur.outQuantity;
return pre;
},
{ total: 0, unfinish: 0 },
),
);
}, [data]);
const [isModalOpen, setIsModalOpen] = useState(false);
const closeModal = () => setIsModalOpen(false);
const [criteria, setCriteria] = useState<PartProgressDetailCriteria>();
const openModal = (wkname) => {
setIsModalOpen(true);
setCriteria({
fevor: setting.conf
.filter((s) => s.workShop == wkname)
.map((s) => s.fevor)
.join(','),
werks: setting.werks,
pageSize: 10,
current: 1,
});
stopLoop()
startLoop()
return () => {
stopLoop()
}
}, [rowMovingTime, data]);
const stopLoop = () => {
if (timer) {
clearInterval(timer);
timer = null;
}
};
const onMouseEnter = () => {
stopLoop()
}
const onMouseLeave = () => {
startLoop()
}
const startLoop = () => {
stopLoop();
if (leftScroll && leftScroll.current) {
timer = setInterval(() => {
let scrollTop = leftScroll.current.scrollTop
console.log(scrollTop, leftScroll.current.offsetHeight, leftScroll.current.scrollHeight)
if (scrollTop + leftScroll.current.offsetHeight + 5 >= leftScroll.current.scrollHeight) {
leftScroll.current.scrollTo({
top: 0,
behavior: 'instant',
});
} else {
leftScroll.current.scrollTop += 30
}
}, rowMovingTime * 1000)
}
};
return (
<>
<div className="partProgress-container">
<div className="partProgress-container" onMouseEnter={onMouseEnter}//移出关闭
onMouseLeave={onMouseLeave}>
<div className="title">
<h2>零部件进度</h2>
<h2>{intl.formatMessage({id: '当月销售出库计划'})}</h2>
<div className="num">
<span>总数量{nums.total}</span>
<span>未完成{nums.unfinish}</span>
<span>{intl.formatMessage({id: '总数量'})}{nums.total}</span>
<span>{intl.formatMessage({id: '已出库'})}{nums.unfinish}</span>
</div>
</div>
<div className="table-container">
<div className="table-header">
<div className="item">车间</div>
<div className="item">总数量</div>
<div className="item">未完成数量</div>
<div className="item" style={{flex: 0.7}}>{intl.formatMessage({id: '通知单号'})}</div>
<div className="item" style={{flex: 0.9}}>{intl.formatMessage({id: '产品名称'})}</div>
<div className="item">{intl.formatMessage({id: '计划出库时间'})}</div>
<div className="item" style={{flex: 0.7}}>{intl.formatMessage({id: '订货数量'})}</div>
<div className="item" style={{flex: 0.88}}>{intl.formatMessage({id: '已出库数量'})}</div>
</div>
<div className="table-body">
<div className="table-body" style={{height: '225px'}} ref={leftScroll}>
{data?.map((item, index) => {
return (
<div className="row" key={index}>
<div className="item">{item.workshopName}</div>
<div className="item">{item.totalQuantity}</div>
<div className="item" style={{flex: 0.7}}>{item.outApplyNo}</div>
<div className="item" style={{flex: 0.9}}>{item.itemName}</div>
<div className="item">{item.planOutDate}</div>
<div className="item" style={{flex: 0.7}}>{item.planQuantity}</div>
<div
className="item"
onClick={() => {
openModal(item.workshopName);
}}
className="item" style={{flex: 0.88}}
>
{item.unFinishQuantity}
{item.outQuantity}
</div>
</div>
);
......@@ -77,15 +100,6 @@ const Main: React.FC<{ data: PartScheduleIndexDataDto[]; setting: PartProgressDe
</div>
</div>
</div>
<Modal
title={'零部件进度'}
visible={isModalOpen}
footer={null}
width={'70%'}
onCancel={closeModal}
>
<PartModalTable values={criteria} />
</Modal>
</>
);
};
......
import ProTable, { ActionType } from '@ant-design/pro-table';
import React, { useEffect, useRef } from 'react';
import { queryPartProgress } from '@/pages/kanban/materialSynthesis/services/api';
type PartProgressDetailCriteria = KANBAN.MaterialSynthesis.PartProgressDetailCriteria;
export type InfoProps = {
values: PartProgressDetailCriteria;
};
const PartModalTable: React.FC<InfoProps> = (props) => {
const actionRef = useRef<ActionType>();
useEffect(() => {
actionRef.current?.reload();
}, [props.values]);
const columns = [
{
title: '批号',
dataIndex: 'lotNo',
key: 'lotNo',
width: 120,
},
{
title: '物料编码',
dataIndex: 'partCode',
key: 'partCode',
width: 120,
},
{
title: '物料描述',
dataIndex: 'partName',
key: 'partName',
width: 120,
},
{
title: '工序名称',
dataIndex: 'operationName',
key: 'operationName',
width: 120,
},
];
return (
<>
<ProTable
options={false}
search={false}
actionRef={actionRef}
request={async (params: PartProgressDetailCriteria) => {
const sr = await queryPartProgress({
...props.values,
pageSize: params.pageSize,
current: params.current,
});
const pageResult: Common.PageResult<any> = {
current: params.current,
pageSize: params.pageSize,
total: sr.data.total,
data: sr.data.data,
};
return pageResult;
}}
pagination={{
pageSize: 10,
}}
columns={columns}
size={'middle'}
bordered
scroll={{ x: 400 }}
/>
</>
);
};
export default PartModalTable;
.partProgress-container {
flex: 1;
margin-top: 10px;
padding: 10px 20px 20px;
border: 2px solid #00ffff;
border-radius: 15px;
background: #031024;
.title {
display: flex;
justify-content: space-between;
line-height: 50px;
h2 {
position: relative;
margin-bottom: 0;
padding-left: 30px;
color: #00ffff;
font-weight: 700;
font-size: 26px;
line-height: 50px;
background: #031024;
&::before {
position: absolute;
top: 10px;
left: 10px;
width: 10px;
height: 30px;
background: #00ffff;
content: '';
}
}
.num {
font-size: 18px;
span {
margin-right: 40px;
}
}
}
.table-container {
margin: 0 10px;
border-top: 2px solid #00ffff;
border-bottom: 2px solid #00ffff;
.table-header {
display: flex;
line-height: 60px;
border-bottom: 2px solid #00ffff;
.item {
flex: 1;
font-size: 18px;
text-align: center;
}
}
.table-body {
overflow: auto;
-ms-overflow-style: none; /* IE 和 Edge */
scrollbar-width: none; /* Firefox */
&::-webkit-scrollbar {
display: none; /* Chrome, Safari 和 Opera */
}
.row {
display: flex;
line-height: 60px;
.item {
flex: 1;
font-size: 18px;
text-align: center;
}
}
}
}
}
import React, { useEffect, useRef, useState } from 'react';
import './index.less';
import { useIntl } from 'umi';
type PartScheduleIndexDataDto1 = KANBAN.MaterialSynthesis.PartScheduleIndexDataDto1;
const Main: React.FC<{ data: PartScheduleIndexDataDto1[]; rowMovingTime: any }> = ({
data,
rowMovingTime,
}) => {
const intl = useIntl();
const [nums, setNums] = useState({ total: 0, unfinish: 0 });
let timer: NodeJS.Timer | null = null;
const leftScroll = useRef<HTMLDivElement>(null);
useEffect(() => {
setNums(
data.reduce(
(pre, cur) => {
pre.total += cur.planQuantity;
pre.unfinish += cur.finishQuantity;
return pre;
},
{ total: 0, unfinish: 0 },
),
);
stopLoop()
startLoop()
return () => {
stopLoop()
}
}, [rowMovingTime, data]);
const stopLoop = () => {
if (timer) {
clearInterval(timer);
timer = null;
}
};
const onMouseEnter = () => {
stopLoop()
}
const onMouseLeave = () => {
startLoop()
}
const startLoop = () => {
stopLoop();
if (leftScroll && leftScroll.current) {
timer = setInterval(() => {
let scrollTop = leftScroll.current.scrollTop
console.log(scrollTop, leftScroll.current.offsetHeight, leftScroll.current.scrollHeight)
if (scrollTop + leftScroll.current.offsetHeight + 5 >= leftScroll.current.scrollHeight) {
leftScroll.current.scrollTo({
top: 0,
behavior: 'instant',
});
} else {
leftScroll.current.scrollTop += 30
}
}, rowMovingTime * 1000)
}
};
return (
<>
<div className="partProgress-container" onMouseEnter={onMouseEnter}//移出关闭
onMouseLeave={onMouseLeave}>
<div className="title">
<h2>{intl.formatMessage({id: '当月生产入库计划'})}</h2>
<div className="num">
<span>{intl.formatMessage({id: '总数量'})}{nums.total}</span>
<span>{intl.formatMessage({id: '完成数'})}{nums.unfinish}</span>
</div>
</div>
<div className="table-container">
<div className="table-header">
<div className="item">{intl.formatMessage({id: '生产工单'})}</div>
<div className="item">{intl.formatMessage({id: '产品名称'})}</div>
<div className="item">{intl.formatMessage({id: '计划完成时间'})}</div>
<div className="item">{intl.formatMessage({id: '计划数量'})}</div>
<div className="item">{intl.formatMessage({id: '完成数量'})}</div>
</div>
<div className="table-body" style={{height: '225px'}} ref={leftScroll}>
{data?.map((item, index) => {
return (
<div className="row" key={index}>
<div className="item">{item.workorderNo}</div>
<div className="item">{item.itemName }</div>
<div className="item">{item.planFinishDate}</div>
<div
className="item"
>
{item.planQuantity}
</div>
<div
className="item"
>
{item.finishQuantity}
</div>
</div>
);
})}
</div>
</div>
</div>
</>
);
};
export default Main;
......@@ -15,8 +15,5 @@
flex: 1;
flex-direction: column;
margin-left: 30px;
padding: 10px 20px 20px;
border: 2px solid #00ffff;
border-radius: 15px;
}
}
......@@ -4,11 +4,12 @@ import './index.less';
import Efficiency from './components/efficiency';
import MissingMaterial from './components/missingMaterial';
import PartProgress from './components/partProgress';
import PartProgressLeft from './components/partProgressLeft';
import Abnormal from './components/abnormal';
import type { Setting } from './components/SettingForm';
import SettingForm from './components/SettingForm';
import { useIntl } from 'umi';
import {
queryPartScheduleIndexData,
queryCountCurrentLackMaterialKanban,
queryCountCurrentMonthLackMaterialKanban,
queryCountMaterialDeliveryRate,
......@@ -46,131 +47,46 @@ const Main: React.FC = () => {
>([]);
const [settingFormVisible, setSettingFormVisible] = useState(false);
const [partScheduleIndexData, setPartScheduleIndexData] = useState<PartScheduleIndexData[]>([]);
const [abnormalOverdueSetting, setAbnormalOverdueSetting] = useState<AbnormalOverdueSetting>({
diffDayProduction: 0,
diffDayEquipment: 0,
diffDayQuality: 0,
});
const [partScheduleIndexData1, setPartScheduleIndexData1] = useState<PartScheduleIndexData[]>([]);
const [deliveryRateData, setDeliveryRateData] = useState({
finishedRate: 0,
punctualRate: 0,
});
const [punctualRateData, setPunctualRateData] = useState({
orderOnlinePunctualRate: 0,
orderOfflinePunctualRate: 0,
});
// 设备异常
const [abnormalDeviceData, setAbnormalDeviceData] = useState<ComprehensiveDeviceEcpDataCount>({
createIssueNumber: 0,
beyondNumber: 0,
currentMonthNumber: 0,
deviceEcpNumber: 0,
deviceNorNumber: 0,
});
// 生产异常
const [abnormalProdData, setAbnormalProdData] = useState<ComprehensiveDataCount>({
createIssueNumber: 0, //未关闭
beyondNumber: 0, //超期
currentMonthNumber: 0, //当月异常
});
// 质量异常
const [abnormalQualityData, setAbnormalQualityData] = useState<ComprehensiveDataCount>({
createIssueNumber: 0, //未关闭
beyondNumber: 0, //超期
currentMonthNumber: 0, //当月异常
materialDistRatio: 0,
salesTimelyDeliveryRatio: 0,
stockInCompleteRatio: 0
});
const [punctualRateData, setPunctualRateData] = useState(0);
useEffect(() => {
const { kanbanId, intervalTime } = setting;
const { intervalTime } = setting;
let t: NodeJS.Timer | null = null;
if (!kanbanId) {
setMissingMaterialMonthData([]);
setMissingMaterialLackData([]);
setPartScheduleIndexData([]);
setDeliveryRateData({
finishedRate: 0,
punctualRate: 0,
});
setPunctualRateData({
orderOnlinePunctualRate: 0,
orderOfflinePunctualRate: 0,
});
const tmp = {
createIssueNumber: 0, //未关闭
beyondNumber: 0, //超期
currentMonthNumber: 0,
};
setAbnormalQualityData(tmp);
setAbnormalProdData(tmp);
setAbnormalDeviceData({ ...tmp, deviceEcpNumber: 0, deviceNorNumber: 0 });
if (t !== null) {
clearInterval(t);
const requestRate = async () => {
const { data: erpData, code: erpCode } = await queryCountMaterialDeliveryRate();
const { data: mesData, code: mesCode } = await queryCountOrderPunctualRate();
if (erpCode === 200) {
const {materialDistRatio, salesTimelyDeliveryRatio, salesOutboundPlanList, stockInCompleteRatio, inventoryTrend} = erpData
setDeliveryRateData({
materialDistRatio,
salesTimelyDeliveryRatio,
stockInCompleteRatio
});
setPartScheduleIndexData(salesOutboundPlanList || []);
if (inventoryTrend) {
setMissingMaterialMonthData(inventoryTrend['stockInTrend']);
setMissingMaterialLackData(inventoryTrend['stockOutTrend']);
}
}
return;
}
// 零部件
const requestPartScheduleIndexData = async (kanbanSettingId: string) => {
const { data } = await queryPartScheduleIndexData({ kanbanSettingId });
setPartScheduleIndexData(data);
};
// 缺料分布 和 趋势图
const requestMissMaterialData = async () => {
const { data } = await queryCountCurrentMonthLackMaterialKanban();
const { data: lack } = await queryCountCurrentLackMaterialKanban();
setMissingMaterialMonthData(data);
setMissingMaterialLackData(lack);
if (mesCode === 200) {
const { orderInfoList, stockInCompleteRatio } = mesData
setPartScheduleIndexData1(orderInfoList)
setPunctualRateData(stockInCompleteRatio);
}
};
// 获取四个饼图
const requestRate = async (settingId: string) => {
const { data: deliveryRate } = await queryCountMaterialDeliveryRate({ settingId });
const { data: punctualRate } = await queryCountOrderPunctualRate({ settingId });
setDeliveryRateData(deliveryRate);
setPunctualRateData(punctualRate);
};
// 异常分布
const requestAbnormal = async (settingId: string) => {
// 异常超期天数获取
const abnormalOverdueSettingList = await findAbnormalOverdueSetting();
const tt: AbnormalOverdueSetting = {
diffDayEquipment: 0,
diffDayQuality: 0,
diffDayProduction: 0,
};
abnormalOverdueSettingList.forEach((s) => {
if (s.werks === setting.productionProgressKanbanSetting?.werks) {
if (s.type.id == 1) {
//生产
tt.diffDayProduction = s.overdueDays;
} else if (s.type.id == 2) {
//质量
tt.diffDayQuality = s.overdueDays;
} else if (s.type.id == 3) {
//设备
tt.diffDayEquipment = s.overdueDays;
}
}
});
setAbnormalOverdueSetting(tt);
// 质量异常
const { data: quality } = await queryComprehensiveQualityEcpData({ settingId });
// 设备异常
const { data: device } = await queryComprehensiveDeviceEcpData({ settingId });
// 生产异常
const { data: prod } = await queryComprehensiveProdEcpData({ settingId });
setAbnormalDeviceData(device);
setAbnormalProdData(prod);
setAbnormalQualityData(quality);
};
const refresh = () => {
requestPartScheduleIndexData(kanbanId);
requestMissMaterialData();
requestRate(kanbanId);
requestAbnormal(kanbanId);
requestRate();
};
refresh();
......@@ -184,11 +100,14 @@ const Main: React.FC = () => {
}
};
}, [setting]);
const intl = useIntl();
// @ts-ignore
return (
<>
<KanbanStyle
headerText="物料综合看板"
headerText={intl.formatMessage({
id: '物料综合看板'
})}
subTitle={setting.productionProgressKanbanSetting?.kanbTitle}
autoResize={setting.autoResize}
onHeaderClick={() => {
......@@ -206,31 +125,16 @@ const Main: React.FC = () => {
kanbanId: setting.kanbanId,
}}
/>
{/* 异常分布 */}
<Abnormal
quality={abnormalQualityData}
prod={abnormalProdData}
device={abnormalDeviceData}
setting={{
workshopName: setting.productionProgressKanbanSetting?.productDeviceException,
werks: setting.productionProgressKanbanSetting?.werks || '',
fevors:
setting.productionProgressKanbanSetting?.productionManagerProgressStepList
.map((s) => s.fevor)
.join(',') || '',
abnormalOverdueSetting: abnormalOverdueSetting,
}}
<PartProgressLeft
data={partScheduleIndexData1}
rowMovingTime={setting.rowMovingTime}
/>
</div>
<div className="right-container">
{/* 缺料部分 */}
<MissingMaterial month={missingMaterialMonthData} lack={missingMaterialLackData} />
<PartProgress
data={partScheduleIndexData}
setting={{
conf: setting.productionProgressKanbanSetting?.progressStepList || [],
werks: setting.productionProgressKanbanSetting?.werks || '',
}}
rowMovingTime={setting.rowMovingTime}
/>
</div>
</div>
......
......@@ -17,13 +17,16 @@ type KanbanDataByWorkLineDto = {
backDate: number;
};
type CountMaterialDeliveryRateDto = {
finishedRate: number;
punctualRate: number;
materialDistRatio: number;
salesTimelyDeliveryRatio: number;
salesOutboundPlanList: Array<any>;
inventoryTrend: object;
stockInCompleteRatio: number
};
type CountOrderPunctualRateDto = {
orderOnlinePunctualRate: number;
orderOfflinePunctualRate: number;
orderInfoList: Array<any>;
stockInCompleteRatio: number;
};
export async function queryMaterialChKanbanSettingList() {
......@@ -73,28 +76,26 @@ export async function queryCountCurrentMonthLackMaterialKanban() {
}
// 物料配送完成率 物料准时配送率
export async function queryCountMaterialDeliveryRate(body: { settingId: string }) {
export async function queryCountMaterialDeliveryRate() {
return request<Api.ServiceResult<CountMaterialDeliveryRateDto>>(
'/api/countMaterialDeliveryRate/count',
'/kanban/material/erpData',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
params: body,
}
},
);
}
// 订单上线,下限准时率
export async function queryCountOrderPunctualRate(body: { settingId: string }) {
export async function queryCountOrderPunctualRate() {
return request<Api.ServiceResult<CountOrderPunctualRateDto>>(
'/api/batchInfo/countOrderPunctualRate',
'/kanban/material/mesData',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
params: body,
}
},
);
}
......
......@@ -22,10 +22,18 @@ declare namespace KANBAN.MaterialSynthesis {
workShop: string;
};
type PartScheduleIndexDataDto = {
workshopName: string;
totalQuantity: number;
outApplyNo: string;
itemName: string;
planOutDate: string;
planQuantity: number;
outQuantity: number;
};
type PartScheduleIndexDataDto1 = {
workorderNo: string;
itemName: string;
planFinishDate: string;
planQuantity: number;
finishQuantity: number;
unFinishQuantity: number;
};
type CountCurrentLackMaterialKanbanDto = {
......
import React, { useState } from 'react';
import styles from '../../index.less';
import { Modal } from 'antd';
import OrderInfo from '../../../materialSynthesis/components/efficiency/orderInfo';
import AnnualPlanBar from './annualPlan';
import MonthlyPlanChart from './monthlyPlanChart';
import MonthRateChart from './monthRateChart';
......@@ -152,16 +151,6 @@ const Main: React.FC<{ data: MonthlyPlanProps; kanbanId: string | undefined }> =
<PunctualChart data={chartData} />
</Modal>
<Modal
title={numTemp[visibleNumType]}
visible={visibleNum}
footer={null}
width={'70%'}
onCancel={closeVisibleNum}
>
<OrderInfo params={batchInfoParams} />
</Modal>
<Modal
title={'工单年度计划量'}
visible={visibleAnnualPlan}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment