Commit d6c32192 authored by 沈翠玲's avatar 沈翠玲

设备看板

parent e39eba93
...@@ -25,6 +25,7 @@ export default defineConfig({ ...@@ -25,6 +25,7 @@ export default defineConfig({
locale: { locale: {
// default zh-CN // default zh-CN
default: 'zh-CN', default: 'zh-CN',
useLocalStorage: true,
antd: true, antd: true,
// default true, when it is true, will use `navigator.language` overwrite default // default true, when it is true, will use `navigator.language` overwrite default
baseNavigator: true, baseNavigator: true,
......
...@@ -40,6 +40,19 @@ export default { ...@@ -40,6 +40,19 @@ export default {
'星期四': 'วันพฤหัสบดี', '星期四': 'วันพฤหัสบดี',
'星期五': 'วันศุกร์', '星期五': 'วันศุกร์',
'星期六': 'วันเสาร์', '星期六': 'วันเสาร์',
'总产量': 'ผลผลิตทั้งหมด',
'利用率': 'อัตราการใช้ประโยชน์',
'设备数': 'จำนวนอุปกรณ์',
'异常率': 'อัตราความผิดปกติ',
'异常数': 'ค่าคงที่แตกต่างกัน',
'待处理': 'เพื่อดำเนินการ',
'全厂': 'โรงงานทั้งหมด',
'当日设备生产综合看板': 'การผลิตอุปกรณ์ที่ครอบคลุมของวัน Kanban',
'设备号': 'หมายเลขอุปกรณ์',
'处理中':'ในการประมวลผล',
'原因': 'เหตุผล',
'状态': 'สถานะ',
'产线选择': 'การเลือกสายการผลิต'
} }
; ;
\ No newline at end of file
...@@ -40,5 +40,18 @@ export default { ...@@ -40,5 +40,18 @@ export default {
'星期四': '星期四', '星期四': '星期四',
'星期五': '星期五', '星期五': '星期五',
'星期六': '星期六', '星期六': '星期六',
'总产量': '总产量',
'利用率': '利用率',
'设备数': '设备数',
'异常率': '异常率',
'异常数': '异常数',
'待处理': '待处理',
'全厂': '全厂',
'当日设备生产综合看板': '当日设备生产综合看板',
'设备号': '设备号',
'处理中':'处理中',
'原因': '原因',
'状态': '状态',
'产线选择': '产线选择'
}; };
\ No newline at end of file
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
transition: transform 0.3s ease, box-shadow 0.3s ease; transition: transform 0.3s ease, box-shadow 0.3s ease;
cursor: pointer; cursor: pointer;
border-radius: 10px; border-radius: 10px;
margin-right: 30px; margin-right: 60px;
overflow: hidden; overflow: hidden;
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.3); border: 1px solid rgba(255, 255, 255, 0.3);
...@@ -62,6 +62,11 @@ ...@@ -62,6 +62,11 @@
background-image: url('./img/1.png'); background-image: url('./img/1.png');
} }
} }
&:nth-child(2) {
.imgWapper {
background-image: url('./img/2.png');
}
}
} }
.logout { .logout {
position: absolute; position: absolute;
......
...@@ -50,8 +50,8 @@ ...@@ -50,8 +50,8 @@
.subTitle { .subTitle {
position: absolute; position: absolute;
bottom: 10px; bottom: 10px;
left: 0; right: 0;
font-weight: 500; font-weight: 400;
font-size: 36px; font-size: 36px;
text-shadow: 0 0 4px #9fc4f5, 0 0 4px #9fc4f5; text-shadow: 0 0 4px #9fc4f5, 0 0 4px #9fc4f5;
} }
......
...@@ -7,6 +7,8 @@ export type Style1Props = { ...@@ -7,6 +7,8 @@ export type Style1Props = {
autoResize: boolean; autoResize: boolean;
headerText: string; headerText: string;
subTitle?: string; subTitle?: string;
headerStyle?: object;
style?: object;
onHeaderClick?: () => void; onHeaderClick?: () => void;
}; };
const intl = getIntl(); const intl = getIntl();
...@@ -18,6 +20,8 @@ function getWeekDayString(weekDay: number) { ...@@ -18,6 +20,8 @@ function getWeekDayString(weekDay: number) {
const Style1: React.FC<Style1Props> = ({ const Style1: React.FC<Style1Props> = ({
autoResize, autoResize,
headerText, headerText,
headerStyle,
style,
subTitle, subTitle,
children, children,
onHeaderClick, onHeaderClick,
...@@ -68,6 +72,7 @@ const Style1: React.FC<Style1Props> = ({ ...@@ -68,6 +72,7 @@ const Style1: React.FC<Style1Props> = ({
<div <div
className={styles.container} className={styles.container}
style={{ style={{
...style,
transform: `scale(${scaleWidth},${scaleHeight})`, transform: `scale(${scaleWidth},${scaleHeight})`,
}} }}
> >
...@@ -78,7 +83,7 @@ const Style1: React.FC<Style1Props> = ({ ...@@ -78,7 +83,7 @@ const Style1: React.FC<Style1Props> = ({
<br /> <br />
{currentWeek} {currentTime} {currentWeek} {currentTime}
</div> </div>
<div className={styles.centerheader}> <div className={styles.centerheader} style={headerStyle}>
{headerText} {headerText}
<div className={styles.subTitle}>{subTitle}</div> <div className={styles.subTitle}>{subTitle}</div>
</div> </div>
......
...@@ -30,25 +30,37 @@ const Abnormal: React.FC<{ ...@@ -30,25 +30,37 @@ const Abnormal: React.FC<{
status: type, status: type,
}); });
}; };
useEffect(() => { let timer: NodeJS.Timer | null = null;
let timer: NodeJS.Timer | null = null; const stopLoop = () => {
let leftScroll = document.getElementById('leftScroll') if (timer) {
clearInterval(timer);
timer = null;
}
};
const startLoop = () => {
stopLoop();
let leftScroll = document.getElementById('leftScroll') as HTMLElement
if (leftScroll) { if (leftScroll) {
if (timer !== null) clearInterval(timer);
timer = setInterval(() => { timer = setInterval(() => {
leftScroll.scrollTop += 40 leftScroll.scrollTop += 60
if (leftScroll.scrollTop + leftScroll.offsetHeight >= leftScroll.scrollHeight) { if (leftScroll.scrollTop + leftScroll.offsetHeight >= leftScroll.scrollHeight) {
leftScroll.scrollTop = 0 leftScroll.scrollTop = 0
} }
}, setting.rowMovingTime * 1000) }, setting.rowMovingTime * 1000)
} }
};
useEffect(() => {
stopLoop()
startLoop()
return () => { return () => {
if (timer !== null) clearInterval(timer); stopLoop()
} }
}, [setting]); }, [setting]);
return ( return (
<> <>
<div className={styles.leftWrapper} id="leftScroll"> <div className={styles.leftWrapper} id="leftScroll" onMouseOver={stopLoop}//移出关闭
onMouseOut={startLoop}>
{factoryLine.map((factory) => ( {factoryLine.map((factory) => (
<div className={styles.Factorycard} > <div className={styles.Factorycard} >
<div>{factory.name}</div> <div>{factory.name}</div>
......
...@@ -4,140 +4,86 @@ import type { ECharts } from 'echarts'; ...@@ -4,140 +4,86 @@ import type { ECharts } from 'echarts';
import { getInstanceByDom } from 'echarts'; import { getInstanceByDom } from 'echarts';
type ProcessOutProps = { type ProcessOutProps = {
data: KANBAN.ProductionComprehens.ProcessYieldData[]; data: Number;
setting: any; setting: any;
}; };
const formatOptions = (data: any) => { const formatOptions = (data: any) => {
const option = { const option = {
color: [ tooltip: {
{ formatter: "{a} <br/>{b} : {c}%"
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#011126', // 100% 处的颜色
},
{
offset: 0,
color: '#00ced3', // 0% 处的颜色
},
],
global: false, // 缺省为 false
},
{
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#011126',
},
{
offset: 0,
color: '#3ba7cc',
},
],
global: false, // 缺省为 false
},
{
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#011126',
},
{
offset: 0,
color: '#7bb249',
},
],
global: false, // 缺省为 false
},
],
tooltip: {},
xAxis: {
type: 'value',
show: false,
}, },
dataZoom: [ series: [
{ {
type: 'slider', name: '利用率',
orient: 'vertical', type: 'gauge',
show: false, detail: { formatter: '{value}%' },
startValue: 0, data: [{ value: data, name: '利用率' }],
endValue: 3, radius: '110%',
}, center: ['50%', '60%'],
], startAngle: 225,
grid: { endAngle: -45,
left: 82, splitNumber: 10, // 分割线的数量
bottom: 30, axisLine: {
right: 40, lineStyle: {
}, width: 18,
legend: { color: [
show: false [0.5, '#ff0000'],
}, [0.8, '#fef000'],
yAxis: { [1, '#00b58f']
type: 'category', ]
triggerEvent: true, }
data: [], },
axisLabel: { axisLabel: {
color: '#fff', color: '#fff'
fontSize: 14, },
formatter: function (value: string) { axisTick: {
return (value.length > 4 ? (value.slice(0,4)+"...") : value ) length: 12,
} lineStyle: {
}, color: 'auto',
axisTick: { }
show: false, },
}, splitLine: {
axisLine: { length: 20,
show: false, lineStyle: {
}, color: 'auto',
}, }
series: [], },
pointer: {
width: 5,
length: '80%',
shadowColor: '#ccc', //默认透明
shadowBlur: 5,
shadowOffsetX: 3,
shadowOffsetY: 3
},
title: {
show: true,
offsetCenter: [0, '-30%'],
textStyle: {
color: '#fff',
fontSize: 30
}
},
detail: {
show: true,
offsetCenter: [0, '40%'],
textStyle: {
color: 'auto',
fontSize: 40
}
},
data: [{ value: data, name: '' }],
animationDuration: 4000, // 仪表盘动画时间
}
]
}; };
if (data && data.length) {
const xAxisData = data.map((item: any) => item.cause);
const series = [{
type: 'bar',
barGap: 0,
label: {
show: true,
position: 'right',
color: '#fff',
},
data: data.map((item: any) => item.ct),
}];
option.yAxis.data = xAxisData;
option.series = series;
}
console.log('option', option)
return option; return option;
}; };
const Main: React.FC<ProcessOutProps> = ({ data, setting }) => { const Main: React.FC<ProcessOutProps> = ({ data, setting }) => {
const chartRef = useRef<HTMLDivElement>(null); const chartRef = useRef<HTMLDivElement>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const closeModal = () => setIsModalOpen(false);
const [processParams, setProcessParams] = useState({
dataRange: 1,
processName: '',
current: 1,
pageSize: 10,
kanbanSettingId: '',
});
useEffect(() => { useEffect(() => {
// Initialize chart // Initialize chart
let chart: ECharts | undefined; let chart: ECharts | undefined;
...@@ -168,31 +114,6 @@ const Main: React.FC<ProcessOutProps> = ({ data, setting }) => { ...@@ -168,31 +114,6 @@ const Main: React.FC<ProcessOutProps> = ({ data, setting }) => {
const chart = getInstanceByDom(chartRef.current); const chart = getInstanceByDom(chartRef.current);
const option = formatOptions(data); const option = formatOptions(data);
chart?.setOption(option); chart?.setOption(option);
chart?.off('click');
chart?.on('click', (p) => {
if (p.seriesName === '完成量') {
console.log(setting.productionComprehensKanbanSettingId, '----');
setProcessParams({
dataRange: setting.dataRange,
processName: p.name,
current: 1,
pageSize: 10,
kanbanSettingId: setting.productionComprehensKanbanSettingId,
});
setIsModalOpen(true);
}
});
// 如果数据工序大于5那么需要自动轮训播放
if (option.yAxis.data.length > 4 && setting.rowMovingTime > 0) {
timer = setInterval(() => {
option.dataZoom[0].startValue++;
if (option.dataZoom[0].endValue++ >= option.yAxis.data.length - 1) {
option.dataZoom[0].startValue = 0;
option.dataZoom[0].endValue = 3;
}
chart?.setOption(option);
}, setting.rowMovingTime * 1000);
}
} }
return () => { return () => {
if (timer !== null) clearInterval(timer); if (timer !== null) clearInterval(timer);
......
import { Modal } from 'antd'; import React, { useEffect, useRef } from 'react';
import { ECharts, getInstanceByDom } from 'echarts'; import { useIntl } from 'umi';
import * as echarts from 'echarts/lib/echarts'; import ProTable, { ActionType } from '@ant-design/pro-table';
import React, { useEffect, useRef, useState } from 'react';
import ModalChart from './modalChart';
import QualityErrorTable from './qualityErrorTable';
import { queryPunctualityPenetratingByKanban } from '../../services/api';
import { getIntl } from 'umi';
type ProcessFailProps = { type ProcessFailProps = {
data: KANBAN.ProductionComprehens.ProcessDefectRatioData[]; data: KANBAN.ProductionComprehens.ProcessDefectRatioData[];
setting: any; setting: any;
}; };
const formatOptions = (data: any) => {
const intl = getIntl();
const option = {
color: [
{
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#011126', // 100% 处的颜色
},
{
offset: 0,
color: '#2f8eb9', // 0% 处的颜色
},
],
global: false, // 缺省为 false
},
{
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: '#011126',
},
{
offset: 0,
color: '#ffc000',
},
],
global: false, // 缺省为 false
},
],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
valueFormatter: (v) => v + '%',
},
xAxis: {
type: 'value',
show: false,
},
dataZoom: [
{
type: 'slider',
orient: 'vertical',
show: false,
startValue: 0,
endValue: 3,
},
],
grid: {
left: 70,
bottom: 30,
right: 40,
},
legend: {
orient: 'vertical',
selectedMode: false,
right: 0,
itemWidth: 10,
itemHeight: 10,
textStyle: {
color: '#fff',
fontSize: 14,
},
},
yAxis: {
type: 'category',
triggerEvent: true,
data: [],
axisLabel: {
color: '#fff',
fontSize: 14,
formatter: function (value: string) {
return (value.length > 4 ? (value.slice(0,4)+"...") : value )
}
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
},
series: [],
};
if (data && data.length) {
const lenged = [
{ label: intl.formatMessage({id: '合格率'}), field: 'qualifiedRate' }
];
const xAxisData = data.map((item: any) => item.processName);
const series = lenged.map((item) => {
return {
type: 'bar',
name: item.label,
barGap: 0,
label: {
show: true,
position: 'right',
color: '#fff',
formatter: '{c}%',
},
data: data.map((v) => v[item.field]),
};
});
option.yAxis.data = xAxisData;
option.series = series;
}
return option;
};
const Main: React.FC<ProcessFailProps> = ({ data, setting }) => { const Main: React.FC<ProcessFailProps> = ({ data, setting }) => {
const chartRef = useRef<HTMLDivElement>(null); const intl = useIntl();
const [modalData, setModalData] = useState<KANBAN.ProductionComprehens.PassRateTrendChart[]>([]); const actionRef = useRef<ActionType>();
const [isModalOpen, setIsModalOpen] = useState(false);
const [isModalTableOpen, setIsModalTableOpen] = useState(false);
const [proName, setProName] = useState('');
const closeModal = () => setIsModalOpen(false);
const closeModalTable = () => setIsModalTableOpen(false);
const [processParams, setProcessParams] = useState({
processName: '',
kanbanSettingId: '',
});
useEffect(() => { useEffect(() => {
// Initialize chart actionRef.current?.reload();
let chart: ECharts | undefined; }, [data]);
if (chartRef.current !== null) {
chart = echarts.init(chartRef.current);
}
// Add chart resize listener const columns = [
// ResizeObserver is leading to a bit janky UX {
function resizeChart() { title: intl.formatMessage({
chart?.resize(); id: '设备号'
} }),
window.addEventListener('resize', resizeChart); dataIndex: 'equipmentNo',
key: 'equipmentNo',
// Return cleanup function width: 80,
return () => { },
chart?.off('click'); {
chart?.dispose(); title: intl.formatMessage({
window.removeEventListener('resize', resizeChart); id: '设备'
}; }),
}, []); dataIndex: 'equipmentName',
key: 'equipmentName',
useEffect(() => { width: 80,
let timer: NodeJS.Timer | null = null; },
// Update chart {
if (chartRef.current !== null) { title: intl.formatMessage({
if (timer !== null) clearInterval(timer); id: '原因'
const chart = getInstanceByDom(chartRef.current); }),
const option = formatOptions(data); dataIndex: 'cause',
chart?.setOption(option); key: 'cause',
chart?.off('click'); width: 80,
chart?.on('click', (p) => { },
if (p.targetType === 'axisLabel') { {
// 显示弹窗 title: intl.formatMessage({
queryPunctualityPenetratingByKanban({ id: '状态'
kanbanSettingId: setting.productionComprehensKanbanSettingId, }),
processName: p.value as string, dataIndex: 'state',
}).then(({ data: cData }) => { key: 'state',
setProName(p.value as string); width: 80,
setModalData(cData); valueEnum: {
setIsModalOpen(true); 'NOT': {
setIsModalTableOpen(false); text: intl.formatMessage({
}); id: '待处理'
} }),
if (p.seriesName === '未通过率') { status: 'Error'
setProcessParams({ },
processName: p.name, 'SUBMIT': {
kanbanSettingId: setting.productionComprehensKanbanSettingId, text: intl.formatMessage({
}); id: '处理中'
setIsModalTableOpen(true); })
setIsModalOpen(false);
} }
});
// 如果数据工序大于5那么需要自动轮训播放
if (option.yAxis.data.length > 4 && setting.rowMovingTime > 0) {
timer = setInterval(() => {
option.dataZoom[0].startValue++;
if (option.dataZoom[0].endValue++ >= option.yAxis.data.length - 1) {
option.dataZoom[0].startValue = 0;
option.dataZoom[0].endValue = 3;
}
chart?.setOption(option);
}, setting.rowMovingTime * 1000);
} }
} }
return () => { ];
if (timer !== null) clearInterval(timer);
};
}, [data, setting]);
return ( return (
<> <>
<Modal <ProTable
title={proName + '当月工序合格率'} options={false}
visible={isModalOpen} search={false}
footer={null} actionRef={actionRef}
width={'70%'} dataSource={data}
onCancel={closeModal} columns={columns}
> size={'middle'}
<ModalChart data={modalData} /> bordered
</Modal> pagination={false}
<Modal scroll={{ y: 450 }}
title={'质量异常'} />
visible={isModalTableOpen}
footer={null}
width={'70%'}
onCancel={closeModalTable}
>
<QualityErrorTable params={processParams} />
</Modal>
<div ref={chartRef} style={{ height: '370px' }} />
</> </>
); );
}; };
......
...@@ -40,7 +40,7 @@ export type SettingFormProps = { ...@@ -40,7 +40,7 @@ export type SettingFormProps = {
const SettingForm: React.FC<SettingFormProps> = (props) => { const SettingForm: React.FC<SettingFormProps> = (props) => {
const formRef = useRef<ProFormInstance>(); const formRef = useRef<ProFormInstance>();
const intl = useIntl(); const intl = useIntl();
const [productionProgressKanbanSettings, setProductionProgressKanbanSettings] = useState< const [lineName, setLineName] = useState<
KanbanSetting[] KanbanSetting[]
>([]); >([]);
...@@ -59,17 +59,13 @@ const SettingForm: React.FC<SettingFormProps> = (props) => { ...@@ -59,17 +59,13 @@ const SettingForm: React.FC<SettingFormProps> = (props) => {
onVisibleChange={(visible: boolean) => { onVisibleChange={(visible: boolean) => {
if (visible) { if (visible) {
formRef?.current?.setFieldsValue({ formRef?.current?.setFieldsValue({
...props.values, ...props.values
productionComprehensKanbanSettingId: props.values.productionComprehensKanbanSetting?.id,
}); });
} }
props.onVisibleChange(visible); props.onVisibleChange(visible);
}} }}
onFinish={async (values: FormSettingDto) => { onFinish={async (values: FormSettingDto) => {
const productionComprehensKanbanSetting = productionProgressKanbanSettings props.onSubmitting({ ...values });
.filter((a) => a.id === values.productionComprehensKanbanSettingId)
.pop();
props.onSubmitting({ ...values, productionComprehensKanbanSetting });
props.onVisibleChange(false); props.onVisibleChange(false);
}} }}
> >
...@@ -90,17 +86,23 @@ const SettingForm: React.FC<SettingFormProps> = (props) => { ...@@ -90,17 +86,23 @@ const SettingForm: React.FC<SettingFormProps> = (props) => {
min={1} min={1}
fieldProps={{ precision: 0 }} fieldProps={{ precision: 0 }}
/> />
{/* <ProFormSelect <ProFormSelect
name="productionComprehensKanbanSettingId" name="lineName"
label="看板设置" label={intl.formatMessage({id: '产线选择'})}
required required
width="xl" width="xl"
request={async () => { request={async () => {
const { data } = await queryProductionComprehensKanbanData(); const { data } = await queryProductionComprehensKanbanData();
setProductionProgressKanbanSettings(data); if (Array.isArray(data)) {
return data.map((a) => ({ label: a.kanbTitle, value: a.id })); data.unshift(intl.formatMessage({
id: '全厂'
}))
}
setLineName(data);
return data.map((a) => ({ label: a, value: a }));
}} }}
/> />
{/*
<ProFormRadio.Group <ProFormRadio.Group
label="工序产量" label="工序产量"
name="dataRange" name="dataRange"
......
...@@ -219,11 +219,9 @@ ...@@ -219,11 +219,9 @@
} }
.rightTopContainer { .rightTopContainer {
width: 100%; width: 100%;
height: 430px; height: 288px;
padding: 50px 44px; background: #001855;
background-image: url('./images/bg3.png'); margin-bottom: 10px;
background-repeat: no-repeat;
background-size: 100% 100%;
} }
.rightTopTitle { .rightTopTitle {
width: 100%; width: 100%;
...@@ -263,7 +261,7 @@ ...@@ -263,7 +261,7 @@
} }
.rightTopBottomContainer { .rightTopBottomContainer {
width: 100%; width: 100%;
background: #040f24; background: #001855;
margin-top: 5px; margin-top: 5px;
} }
.rightTopBottomItem { .rightTopBottomItem {
...@@ -283,18 +281,87 @@ ...@@ -283,18 +281,87 @@
.rightBottomContent { .rightBottomContent {
width: 100%; width: 100%;
height: 100%; height: 100%;
background-image: url('./images/bg7.png'); background: #001855;
background-repeat: no-repeat; :global {
background-size: 100% 100%;
}
.ant-table-header > table {
border-top: none !important;
}
.ant-table, .ant-card {
background: transparent !important;
}
.ant-table-body::-webkit-scrollbar {
display: none; /* Chrome, Safari 和 Opera */
}
.ant-table-body {
-ms-overflow-style: none; /* IE 和 Edge */
scrollbar-width: none; /* Firefox */
}
.ant-table-cell-scrollbar {
display: none;
}
.ant-table-container {
border: none !important;
}
.ant-table-thead > tr > th {
color: #0d72c3;
background: transparent;
border-bottom: 1px solid #0d72c3;
}
.ant-table-cell {
border-right: none !important;
}
.ant-table-tbody > tr > td {
color: #4d9baa;
border-bottom: none;
}
.ant-empty-img-simple {
display: none;
}
.ant-empty-normal {
color: #4d9baa;
}
tr.ant-table-placeholder {
pointer-events: none;
}
.ant-badge-status-error {
display: none;
}
.ant-badge-status-text {
color: #ff4d4f;
}
.ant-table-tbody > tr > td.ant-table-cell-row-hover {
background: transparent !important;
}
}
}
.rightCenterContainer {
background: #001855;
margin-bottom: 10px;
width: 100%;
padding: 15px 10px 0 10px;
height: 148px;
line-height: 18px;
display: flex;
flex-wrap: wrap;
}
.rightCenterInner {
width: calc(100% / 2);
padding-left: 30px;
}
.rightLabel {
font-weight: 600;
font-size: 18px;
}
.rightValue {
font-weight: 600;
font-size: 17px;
}
.rightBottomContainer { .rightBottomContainer {
width: 100%; width: 100%;
height: 526px; height: 526px;
padding: 50px 44px; background: #001855;
background-image: url('./images/bg6.png');
background-repeat: no-repeat;
background-size: 100% 100%;
} }
.rightBottomTitle { .rightBottomTitle {
padding: 10px 0 0 65px; padding: 10px 0 0 65px;
......
...@@ -14,25 +14,23 @@ import { ...@@ -14,25 +14,23 @@ import {
} from './services/api'; } from './services/api';
type AbnormalOverdueSetting = KANBAN.ProductionComprehens.AbnormalOverdueSetting; type AbnormalOverdueSetting = KANBAN.ProductionComprehens.AbnormalOverdueSetting;
type ProcessDefectRatioData = KANBAN.ProductionComprehens.ProcessDefectRatioData[];
type ProcessYieldData = KANBAN.ProductionComprehens.ProcessYieldData[];
type ComprehensiveDeviceEcpDataCount = KANBAN.ProductionComprehens.ComprehensiveDeviceEcpDataCount; type ComprehensiveDeviceEcpDataCount = KANBAN.ProductionComprehens.ComprehensiveDeviceEcpDataCount;
type ComprehensiveDataCount = KANBAN.ProductionComprehens.ComprehensiveDataCount; type ComprehensiveDataCount = KANBAN.ProductionComprehens.ComprehensiveDataCount;
type CountWeldingPassRate = KANBAN.ProductionComprehens.CountWeldingPassRate;
const Main: React.FC = () => { const Main: React.FC = () => {
const intl = useIntl();
const [setting, setSetting] = useState<Setting>({ const [setting, setSetting] = useState<Setting>({
autoResize: true, autoResize: true,
intervalTime: 600, intervalTime: 600,
rowMovingTime: 5, rowMovingTime: 5,
productionComprehensKanbanSetting: undefined, lineName: intl.formatMessage({
productionComprehensKanbanSettingId: undefined, id: '全厂'
}),
dataRange: 1, dataRange: 1,
planSource: 1, planSource: 1,
}); });
// 月度计划指标 // 月度计划指标
const [monthData, setMonthData] = useState<KANBAN.ProductionComprehens.WorkOrderMonthlyIndexData>( const [monthData, setMonthData] = useState<any>(
{ {
startOnTimeRatio: 0, //上线准时率 startOnTimeRatio: 0, //上线准时率
endOnTimeRatio: 0, //下线准时率 endOnTimeRatio: 0, //下线准时率
...@@ -53,9 +51,9 @@ const Main: React.FC = () => { ...@@ -53,9 +51,9 @@ const Main: React.FC = () => {
// 设备列表 // 设备列表
const [equipMap, setEquipMap] = useState<any>([]); const [equipMap, setEquipMap] = useState<any>([]);
// 工序未通过率 // 工序未通过率
const [processDefectRatioData, setProcessDefectRatioData] = useState<ProcessDefectRatioData>([]); const [processDefectRatioData, setProcessDefectRatioData] = useState<Array<any>>([]);
// 不合格分布 // 不合格分布
const [countWeldingPassRate, setCountWeldingPassRate] = useState<Array<any>>([]); const [countWeldingPassRate, setCountWeldingPassRate] = useState<Number>(0);
// 设备异常 // 设备异常
const [abnormalDeviceData, setAbnormalDeviceData] = useState<ComprehensiveDeviceEcpDataCount>({ const [abnormalDeviceData, setAbnormalDeviceData] = useState<ComprehensiveDeviceEcpDataCount>({
unCloseCt: 0, unCloseCt: 0,
...@@ -78,52 +76,29 @@ const Main: React.FC = () => { ...@@ -78,52 +76,29 @@ const Main: React.FC = () => {
useEffect(() => { useEffect(() => {
// console.log('sadas执行' ) // console.log('sadas执行' )
let t: NodeJS.Timer | null = null; let t: NodeJS.Timer | null = null;
const { productionComprehensKanbanSettingId, dataRange, planSource, intervalTime } = setting; const { intervalTime } = setting;
// if (!productionComprehensKanbanSettingId) {
// // 清除定时器
// if (t !== null) {
// clearInterval(t);
// }
// // 重制图标
// setProcessYieldData([]);
// setProcessDefectRatioData([]);
// setMonthData({
// startOnTimeRatio: 0, //上线准时率
// endOnTimeRatio: 0, //下线准时率
// qualifiedRatio: 0, //产品合格率
// hisPendingQuantity: 0, //历史月待完工
// monthPlanQuantity: 0, //月计划
// expireFinishQuantity: 0, //超期完工
// actualFinishQuantity: 0, //实际完工
// monthPlanConcludeRatio: 0, //月计划达成率
// });
// setCountWeldingPassRate({
// wholeSetPassRate: 0,
// longitudinalJointRate: 0,
// transverseJointRate: 0,
// piecePassRate: 0,
// selectionRate: 0,
// longitudinalJointBasicRate: 0,
// selectionBasicRate: 0,
// transverseJointBasicRate: 0,
// });
// const tmp = {
// unCloseCt: 0, //未关闭
// expireUnClose: 0, //超期
// totalCt: 0,
// };
// setAbnormalQualityData(tmp);
// setAbnormalProdData(tmp);
// setAbnormalDeviceData({ ...tmp, equipErrorCt: 0, equipCt: 0 });
// return;
// }
// 查询工序产量 // 查询工序产量
const queryProcessYieldData1 = async () => { const queryProcessYieldData1 = async () => {
const body = { const body = {
lineName: null lineName: setting?.lineName === intl.formatMessage({
id: '全厂'
}) ? null : setting?.lineName
}; };
const { data: { equipMap } } = await queryEquipmentCurrentMonthStat(body); const { code: code, data: data } = await queryEquipmentCurrentMonthStat(body);
if (code !== 200 || !data) {
setMonthData({
abnormalNum: null,
equipNum: null,
qualifiedRatio: null,
totalOutput: null,
unProcessNum: null
});
setProcessDefectRatioData([])
setCountWeldingPassRate(0)
setEquipMap([])
return
}
const { equipMap, equipAvailability, abnormalInfoList, abnormalNum, equipNum, qualifiedRatio, totalOutput, unProcessNum } = data
const equipList = [] const equipList = []
for (let key in equipMap) { for (let key in equipMap) {
equipList.push({ equipList.push({
...@@ -131,35 +106,21 @@ const Main: React.FC = () => { ...@@ -131,35 +106,21 @@ const Main: React.FC = () => {
arr: equipMap[key] arr: equipMap[key]
}) })
} }
setEquipMap(equipList) setMonthData({
}; abnormalNum,
// 异常分布 equipNum,
const requestAbnormal = async (settingId: string) => { qualifiedRatio,
// 异常超期天数获取 totalOutput,
// const abnormalOverdueSettingList = await findAbnormalOverdueSetting(); unProcessNum
const tt: AbnormalOverdueSetting = {
diffDayEquipment: 0,
diffDayQuality: 0,
diffDayProduction: 0,
};
setAbnormalOverdueSetting(tt);
// 当月异常分布数据
const { data: {equipAbnormal, productAbnormal, equipErrorArr, equipCt, equipErrorCt} } = await currentMonthStat({ settingId });
setAbnormalDeviceData({
equipCt,
equipErrorCt,
...equipAbnormal
}); });
setAbnormalProdData(productAbnormal); setProcessDefectRatioData(abnormalInfoList)
setAbnormalQualityData(equipErrorArr); setCountWeldingPassRate(equipAvailability)
setEquipMap(equipList)
}; };
const refresh = () => { const refresh = () => {
queryProcessYieldData1(); queryProcessYieldData1();
requestAbnormal(productionComprehensKanbanSettingId);
}; };
refresh(); refresh();
...@@ -173,14 +134,16 @@ const Main: React.FC = () => { ...@@ -173,14 +134,16 @@ const Main: React.FC = () => {
} }
}; };
}, [setting]); }, [setting]);
const intl = useIntl();
return ( return (
<> <>
<KanbanStyle <KanbanStyle
headerText={intl.formatMessage({ headerText={intl.formatMessage({
id: '当日设备生产综合看板' id: '当日设备生产综合看板'
})} })}
subTitle={setting.productionComprehensKanbanSetting?.kanbTitle} style={{backgroundColor: '#00094f'}}
headerStyle={{fontSize: '30px'}}
subTitle={setting?.lineName}
autoResize={setting.autoResize} autoResize={setting.autoResize}
onHeaderClick={() => { onHeaderClick={() => {
setSettingFormVisible(true); setSettingFormVisible(true);
...@@ -212,7 +175,6 @@ const Main: React.FC = () => { ...@@ -212,7 +175,6 @@ const Main: React.FC = () => {
<div className={styles.rightContainer}> <div className={styles.rightContainer}>
{/* 焊接一次通过率 */} {/* 焊接一次通过率 */}
<div className={styles.rightTopContainer}> <div className={styles.rightTopContainer}>
<div className={styles.rightTopTitle}>{intl.formatMessage({id: '不合格分布'})}</div>
<div className={styles.rightTopBottomContainer}> <div className={styles.rightTopBottomContainer}>
<PassingRate <PassingRate
data={countWeldingPassRate} data={countWeldingPassRate}
...@@ -220,10 +182,59 @@ const Main: React.FC = () => { ...@@ -220,10 +182,59 @@ const Main: React.FC = () => {
/> />
</div> </div>
</div> </div>
<div className={styles.rightCenterContainer}>
<div className={styles.rightCenterInner}>
<span className={styles.rightLabel}>
{intl.formatMessage({ id: '总产量' })}
</span>
<span className={styles.rightValue} style={{color: '#00b88f'}}>
{monthData.totalOutput || 0}
</span>
</div>
<div className={styles.rightCenterInner}>
<span className={styles.rightLabel}>
{intl.formatMessage({ id: '利用率' })}
</span>
<span className={styles.rightValue} style={{color: '#f0f104'}}>
{monthData.equipAvailability ? monthData.equipAvailability + '%' : 0+ '%'}
</span>
</div>
<div className={styles.rightCenterInner}>
<span className={styles.rightLabel}>
{intl.formatMessage({ id: '设备数' })}
</span>
<span className={styles.rightValue} style={{color: '#00b88f'}}>
{monthData.equipNum || 0 }
</span>
</div>
<div className={styles.rightCenterInner}>
<span className={styles.rightLabel}>
{intl.formatMessage({ id: '合格率' })}
</span>
<span className={styles.rightValue} style={{color: '#00b88f'}}>
{monthData.qualifiedRatio ? monthData.qualifiedRatio + '%' : 0+ '%'}
</span>
</div>
<div className={styles.rightCenterInner}>
<span className={styles.rightLabel}>
{intl.formatMessage({ id: '异常数' })}
</span>
<span className={styles.rightValue} style={{color: '#f0f104'}}>
{monthData.abnormalNum || 0}
</span>
</div>
<div className={styles.rightCenterInner}>
<span className={styles.rightLabel}>
{intl.formatMessage({ id: '待处理' })}
</span>
<span className={styles.rightValue} style={{color: '#f0f104'}}>
{monthData.unProcessNum || 0}
</span>
</div>
</div>
{/* 当月工序合格率 */} {/* 当月工序合格率 */}
<div className={styles.rightBottomContainer}> <div className={styles.rightBottomContainer}>
<div className={styles.rightBottomContent}> <div className={styles.rightBottomContent}>
<div className={styles.rightBottomTitle}>{intl.formatMessage({id: '当月工序合格率'})}</div>
<div style={{ padding: '0 20px', height: '376px' }}> <div style={{ padding: '0 20px', height: '376px' }}>
<ProcessFail data={processDefectRatioData} setting={setting} /> <ProcessFail data={processDefectRatioData} setting={setting} />
</div> </div>
......
...@@ -34,9 +34,9 @@ type ChartData = { ...@@ -34,9 +34,9 @@ type ChartData = {
export async function queryProductionComprehensKanbanData() { export async function queryProductionComprehensKanbanData() {
return request<Api.ServiceResult<ProductionComprehensKanbanDataDto[]>>( return request<Api.ServiceResult<ProductionComprehensKanbanDataDto[]>>(
'/api/productionComprehensiveKanbanSetting/list', '/md/workunit/selectGroupLineName',
{ {
method: 'POST', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
......
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