1741 lines
43 KiB
JavaScript
1741 lines
43 KiB
JavaScript
import React, {
|
||
useRef,
|
||
useEffect,
|
||
useState,
|
||
useCallback,
|
||
useMemo,
|
||
} from "react";
|
||
import moment from "moment";
|
||
import _ from "lodash";
|
||
import Footer from "../../../components/screen/Footer";
|
||
import Header from "../../../components/screen/Header";
|
||
import Row from "../../../components/screen/Row";
|
||
import Card from "../../../components/screen/Card";
|
||
import Chart from "../../../components/screen/Chart";
|
||
import io from "../../../utils/socket.io.js";
|
||
import { getDailyBoard } from "../../../reportUtils/getQueryData";
|
||
import { parse } from "postcss";
|
||
|
||
const gutter = 20;
|
||
const bottom = 20;
|
||
const socketEmit = "timePerformanceGoodProduct";
|
||
const socketScreenType = "DailyPlanType";
|
||
|
||
// 调试方式: local 本地完整数据调试, server 接口调试, dev 开发期调试
|
||
const dataType = "server";
|
||
|
||
function PlanDailyBoard(props) {
|
||
const { config: { ioSocketUrl, planDailyConfig = {} } = {} } = global;
|
||
const { reloadTime = 5000, isSocket = true } = planDailyConfig;
|
||
// 月份
|
||
const [titlePrev, setTitlePrev] = useState("");
|
||
// 页面数据
|
||
const [pageData, setPageData] = useState(dataType === "dev" ? devData : {});
|
||
|
||
const socket = useRef();
|
||
|
||
// 当前时间
|
||
const curDateOpt = useMemo(() => {
|
||
const { curDate } = pageData;
|
||
if (curDate) {
|
||
setTitlePrev(`${moment(curDate).format("M")}月`);
|
||
return moment(curDate).format("YYYY-MM-DD");
|
||
} else return "";
|
||
}, [pageData.curDate]);
|
||
const materialInventoryAvailableDaysOpt = useMemo(() => {
|
||
const { materialInventoryAvailableDays } = pageData;
|
||
return materialInventoryAvailableDays;
|
||
}, [pageData.materialInventoryAvailableDays]);
|
||
// 当前时间
|
||
const goalAchievementRateDateOpt = useMemo(() => {
|
||
const { goalAchievementRateDate } = pageData;
|
||
if (!goalAchievementRateDate) return curDateOpt;
|
||
return goalAchievementRateDate;
|
||
}, [pageData.goalAchievementRateDate]);
|
||
// 上个月
|
||
const lastYearMonthOpt = useMemo(() => {
|
||
const { lastYearMonth } = pageData;
|
||
if (lastYearMonth) {
|
||
return lastYearMonth;
|
||
} else return "";
|
||
}, [pageData.lastYearMonth]);
|
||
|
||
// 月总产出
|
||
const mouthProdChart = useRef();
|
||
const mouthProdOpt = useMemo(
|
||
() => chartConfig("mouthProd").init(pageData.mouthProd),
|
||
[pageData]
|
||
);
|
||
|
||
// 月生产目标达成
|
||
const mouthAchieveChart = useRef();
|
||
const mouthAchieveOpt = useMemo(
|
||
() => chartConfig("mouthAchieve").init(pageData.mouthAchieve),
|
||
[pageData]
|
||
);
|
||
|
||
// 出货当月
|
||
const mouthOutputMemo = useMemo(
|
||
() =>
|
||
pageData.mouthOutput || {
|
||
total: 0,
|
||
totalRate: 0,
|
||
data: [],
|
||
names: [],
|
||
rates: [],
|
||
},
|
||
[pageData]
|
||
);
|
||
|
||
// 出货汇总
|
||
const totalOutputChart = useRef();
|
||
const totalOutputOpt = useMemo(
|
||
() => chartConfig("totalOutput").init(pageData.totalOutput),
|
||
[pageData]
|
||
);
|
||
|
||
// 生产目标达成
|
||
const prodPlanAchieveChart = useRef();
|
||
const prodPlanAchieveOpt = useMemo(
|
||
() => chartConfig("prodPlanAchieve").init(pageData.prodPlanAchieve),
|
||
[pageData]
|
||
);
|
||
|
||
// 原材料库存
|
||
const rawMaterialInventoryChart = useRef();
|
||
const rawMaterialInventoryOpt = useMemo(
|
||
() =>
|
||
chartConfig("rawMaterialInventory").init(pageData.rawMaterialInventory),
|
||
[pageData]
|
||
);
|
||
|
||
// 产品库存
|
||
const prodInventory = useRef();
|
||
const prodInventoryOpt = useMemo(() => {
|
||
let option = chartConfig("prodInventory").init(pageData.prodInventory);
|
||
option && (option.getRes = () => pageData.prodInventory);
|
||
return option;
|
||
}, [pageData]);
|
||
const prodInventoryTableOpt = useMemo(() => {
|
||
let { category = [], data = {} } = prodInventoryOpt?.getRes() || {};
|
||
let res = { cloumns: [...category, "合计"], data: [] };
|
||
let rowData = [];
|
||
let total = 0;
|
||
// Object.keys(data).forEach((key) => {
|
||
// data[key].forEach((val, index) => {
|
||
// if (rowData[index] === undefined || isNaN(rowData[index]))
|
||
// rowData[index] = 0;
|
||
// rowData[index] += val === undefined ? 0 : val;
|
||
// let ccval = parseFloat(parseFloat(rowData[index]).toFixed(0));
|
||
// rowData[index] = isNaN(ccval) ? 0 : ccval;
|
||
// total += val === undefined ? 0 : val;
|
||
// let tptalccval = parseFloat(parseFloat(total).toFixed(0));
|
||
// total = isNaN(tptalccval) ? 0 : tptalccval;
|
||
// });
|
||
// });
|
||
pageData.productInventoryTable?.forEach((item, index) => {
|
||
if (rowData[index] === undefined || isNaN(rowData[index])) {
|
||
rowData[index] = 0;
|
||
}
|
||
rowData[index] = parseFloat(parseFloat(item.inventoryQty).toFixed(0));
|
||
total += item.inventoryQty;
|
||
});
|
||
total = parseFloat(parseFloat(total).toFixed(0));
|
||
rowData.push(<span className="c-red">{total}</span>);
|
||
res.data[0] = rowData;
|
||
return res;
|
||
}, [prodInventoryOpt]);
|
||
|
||
// 历史库存
|
||
const historyInventory = useRef();
|
||
const historyInventoryOpt = useMemo(
|
||
() => chartConfig("historyInventory").init(pageData.historyInventory),
|
||
[pageData]
|
||
);
|
||
|
||
// 数据更新
|
||
useEffect(() => {
|
||
// 月总产出
|
||
mouthProdOpt && mouthProdChart.current.setOption(mouthProdOpt);
|
||
// 月目标达成
|
||
mouthAchieveOpt && mouthAchieveChart.current.setOption(mouthAchieveOpt);
|
||
// 出货汇总
|
||
totalOutputOpt && totalOutputChart.current.setOption(totalOutputOpt);
|
||
// 生产目标达成
|
||
prodPlanAchieveOpt &&
|
||
prodPlanAchieveChart.current.setOption(prodPlanAchieveOpt);
|
||
// 原材料库存
|
||
rawMaterialInventoryOpt &&
|
||
rawMaterialInventoryChart.current.setOption(rawMaterialInventoryOpt);
|
||
// 产品库存
|
||
prodInventoryOpt && prodInventory.current.setOption(prodInventoryOpt);
|
||
// 历史库存
|
||
historyInventoryOpt &&
|
||
historyInventory.current.setOption(historyInventoryOpt);
|
||
}, [
|
||
mouthProdOpt,
|
||
mouthAchieveOpt,
|
||
totalOutputOpt,
|
||
prodPlanAchieveOpt,
|
||
rawMaterialInventoryOpt,
|
||
prodInventoryOpt,
|
||
historyInventoryOpt,
|
||
]);
|
||
|
||
// 收到数据
|
||
const update = useCallback((data) => {
|
||
if (dataType === "local") data = localDataParse;
|
||
console.log("data", data);
|
||
|
||
let consoleError = (e, name, key) => {
|
||
console.log("--------------", name, " error", e);
|
||
console.log("localData: --------------", localDataParse[key]);
|
||
console.log("requestData: --------------", data[key]);
|
||
};
|
||
// 月总产出
|
||
let mouthProd;
|
||
try {
|
||
let res = {
|
||
category: [],
|
||
data: { prod: [], pect: [] },
|
||
};
|
||
let { goalAchievementDiagram = [] } = data;
|
||
goalAchievementDiagram
|
||
.sort((a, b) => b.productName.localeCompare(a.productName))
|
||
.forEach(({ productName, achievingRate, actualQty }) => {
|
||
res.category.push(productName);
|
||
res.data.prod.push(actualQty);
|
||
res.data.pect.push(achievingRate);
|
||
});
|
||
mouthProd = res;
|
||
} catch (e) {
|
||
consoleError(e, "月总产出", "goalAchievementDiagram");
|
||
}
|
||
// 月生产目标达成
|
||
let mouthAchieve;
|
||
try {
|
||
let res = {
|
||
category: [],
|
||
data: { plan: [], infect: [], achievement: [] },
|
||
};
|
||
let { goalAchievementHistogram = [] } = data;
|
||
var goalAchievementHistogramtmp = goalAchievementHistogram;
|
||
var llist = goalAchievementHistogramtmp.filter(
|
||
(x) => x.workLineName.substring(0, 1) === "L"
|
||
);
|
||
var otherlist = goalAchievementHistogramtmp.filter(
|
||
(x) => x.workLineName.substring(0, 1) !== "L"
|
||
);
|
||
llist.push(...otherlist);
|
||
var finallist = llist;
|
||
finallist.forEach(
|
||
({ workLineName, goalQty, actualQty, monthGoalQty }) => {
|
||
res.category.push(workLineName);
|
||
res.data.infect.push(actualQty);
|
||
res.data.plan.push(monthGoalQty);
|
||
res.data.achievement.push(goalQty === 0 ? 0 : actualQty / goalQty);
|
||
}
|
||
);
|
||
mouthAchieve = res;
|
||
} catch (e) {
|
||
consoleError(e, "月生产目标达成", "goalAchievementHistogram");
|
||
}
|
||
// 出货当月
|
||
let mouthOutput;
|
||
try {
|
||
let res = {
|
||
total: 0,
|
||
totalRate: 0,
|
||
data: [],
|
||
names: [],
|
||
rates: [],
|
||
};
|
||
let { shipmentDashBoard = {} } = data;
|
||
let { summary = {} } = shipmentDashBoard;
|
||
let { totalShipmentQty = 0, dtl = [], totalAchievingRate } = summary;
|
||
res.total = totalShipmentQty.toFixed(0);
|
||
res.totalRate = totalAchievingRate;
|
||
dtl
|
||
.sort((a, b) => b.customerName.localeCompare(a.customerName))
|
||
.forEach(({ customerName, shipmentQty, achievingRate, goalQty }) => {
|
||
res.names.push(customerName);
|
||
res.data.push(shipmentQty.toFixed(0));
|
||
res.rates.push(achievingRate);
|
||
});
|
||
mouthOutput = res;
|
||
// console.log("mouthOutput", mouthOutput, summary);
|
||
} catch (e) {
|
||
consoleError(e, "出货当月", "shipmentDashBoard");
|
||
}
|
||
// 出货汇总
|
||
let totalOutput;
|
||
try {
|
||
let { shipmentDashBoard = {} } = data;
|
||
let { shipmentPie = [] } = shipmentDashBoard;
|
||
totalOutput = shipmentPie.map(({ customerName: name, rate: value }) => ({
|
||
name,
|
||
value,
|
||
}));
|
||
//演示代码,后面要删除
|
||
// totalOutput.forEach((item) => {
|
||
// if (item.name === "C客户") {
|
||
// item.value = 0.78;
|
||
// } else if (item.name === "非C客户") {
|
||
// item.value = 0.9;
|
||
// }
|
||
// });
|
||
console.log("-----------totalOutput", totalOutput);
|
||
} catch (e) {
|
||
consoleError(e, "出货汇总", "shipmentPie");
|
||
}
|
||
// 生产目标达成
|
||
let prodPlanAchieve;
|
||
try {
|
||
let res = {
|
||
category: [],
|
||
data: { reach: [] },
|
||
};
|
||
let { goalAchievementRate = [] } = data;
|
||
goalAchievementRate.forEach(({ workCenterName, achievingRate }) => {
|
||
res.category.push(workCenterName);
|
||
res.data.reach.push(achievingRate);
|
||
});
|
||
prodPlanAchieve = res;
|
||
} catch (e) {
|
||
consoleError(e, "生产目标达成", "goalAchievementRate");
|
||
}
|
||
// 原材料库存
|
||
let rawMaterialInventory;
|
||
try {
|
||
let res = {
|
||
category: [],
|
||
names: [],
|
||
data: [],
|
||
};
|
||
let { materialInventoryDiagram = [] } = data;
|
||
let [data0, data1] = materialInventoryDiagram;
|
||
let dates = _.cloneDeep(data0.inventoryDate);
|
||
res.category = dates || [];
|
||
materialInventoryDiagram.forEach((item) => {
|
||
res.names.push(item.materialName);
|
||
res.data.push(item.inventoryQty);
|
||
});
|
||
|
||
rawMaterialInventory = res;
|
||
// }
|
||
} catch (e) {
|
||
consoleError(e, "原材料库存", "materialInventoryDiagram");
|
||
}
|
||
// 产品库存
|
||
let prodInventory;
|
||
try {
|
||
let res = {
|
||
category: [],
|
||
data: { qualified: [], review: [], inspecting: [], inspected: [] },
|
||
};
|
||
let { productInventoryHistogram = [] } = data;
|
||
productInventoryHistogram.forEach(
|
||
({
|
||
productName,
|
||
okQty,
|
||
reviewQty,
|
||
pendingInspectionQty,
|
||
inspectionQty,
|
||
}) => {
|
||
res.category.push(productName);
|
||
res.data.qualified.push(okQty);
|
||
res.data.review.push(reviewQty);
|
||
res.data.inspecting.push(pendingInspectionQty);
|
||
res.data.inspected.push(inspectionQty);
|
||
}
|
||
);
|
||
prodInventory = res;
|
||
} catch (e) {
|
||
consoleError(e, "产品库存", "productInventoryHistogram");
|
||
}
|
||
// 历史库存
|
||
let historyInventory;
|
||
try {
|
||
let res = {
|
||
category: [],
|
||
data: [],
|
||
};
|
||
let { historyInventory: history = [] } = data;
|
||
history.forEach(({ inventoryDate, inventoryQty },index) => {
|
||
//只保留8天的数据
|
||
//只保留8天所以计算下
|
||
let ca=history.length- 8 ;
|
||
if (index<ca) {
|
||
return;
|
||
}
|
||
res.category.push(inventoryDate);
|
||
res.data.push(inventoryQty);
|
||
});
|
||
historyInventory = res;
|
||
} catch (e) {
|
||
consoleError(e, "历史库存", "historyInventory");
|
||
}
|
||
|
||
let resData = {
|
||
curDate: data.curDate,
|
||
goalAchievementRateDate: data?.goalAchievementRateDate,
|
||
productInventoryTable: data?.productInventoryTable,
|
||
lastYearMonth: data?.lastYearMonth,
|
||
materialInventoryAvailableDays: data?.materialInventoryAvailableDays,
|
||
mouthProd,
|
||
mouthAchieve,
|
||
mouthOutput,
|
||
totalOutput,
|
||
prodPlanAchieve,
|
||
rawMaterialInventory,
|
||
prodInventory,
|
||
historyInventory,
|
||
};
|
||
console.log("resData", resData);
|
||
setPageData(resData);
|
||
}, []);
|
||
|
||
// 获取数据
|
||
const timeoutRef = useRef();
|
||
const getData = useCallback(() => {
|
||
// let workCenterCode = getQueryVariable("workCenterCode");
|
||
let date = getQueryVariable("date");
|
||
// if (!workCenterCode) return;
|
||
|
||
let query = {
|
||
// workCenterCode,
|
||
screenType: socketScreenType,
|
||
};
|
||
if (date) query.date = date;
|
||
console.log("fetch", socketEmit, { query });
|
||
|
||
if (dataType === "server") {
|
||
if (isSocket) {
|
||
socket.current.emit(socketEmit, "channel", { query });
|
||
} else {
|
||
getDailyBoard(date)
|
||
.then((res) => {
|
||
update(JSON.stringify(res));
|
||
})
|
||
.catch((err) => console.log(err));
|
||
}
|
||
} else if (dataType === "local") {
|
||
update();
|
||
}
|
||
clearTimeout(timeoutRef.current);
|
||
timeoutRef.current = setTimeout(getData, reloadTime);
|
||
}, []);
|
||
|
||
// 初始化加载
|
||
useEffect(() => {
|
||
if (dataType === "server") {
|
||
socket.current = io.connect(ioSocketUrl, {transports:['websocket']});
|
||
socket.current.on("connect", function () {
|
||
console.log("msg页面连接成功!");
|
||
getData();
|
||
});
|
||
if (isSocket)
|
||
socket.current.on(socketEmit, function (data) {
|
||
try {
|
||
data = JSON.parse(data);
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
update(data.data);
|
||
});
|
||
} else if (dataType === "local") {
|
||
setTimeout(getData, 1000);
|
||
}
|
||
}, [isSocket]);
|
||
|
||
useEffect(() => {
|
||
return () => {
|
||
clearTimeout(timeoutRef.current);
|
||
};
|
||
}, []);
|
||
|
||
return (
|
||
<div className="screen-container">
|
||
<Header title={"计划日报看板"} time={curDateOpt} />
|
||
<div className="screen-container-content">
|
||
<Row style={{ height: "100%" }} gutter={gutter} bottom={bottom}>
|
||
<Row.Col style={{ width: "504px" }}>
|
||
<Row>
|
||
<Row.Col style={{ height: "268px", marginBottom: `${bottom}px` }}>
|
||
<Card
|
||
title={`${titlePrev}总产出(t)`}
|
||
titleSpace={false}
|
||
overVisible={true}
|
||
>
|
||
<Chart ref={mouthProdChart} />
|
||
</Card>
|
||
</Row.Col>
|
||
<Row.Col style={{ height: "604px" }}>
|
||
<Card
|
||
title={`${titlePrev}生产目标达成`}
|
||
titleSpace={false}
|
||
overVisible={true}
|
||
>
|
||
<Chart ref={mouthAchieveChart} />
|
||
</Card>
|
||
</Row.Col>
|
||
</Row>
|
||
</Row.Col>
|
||
<Row.Col style={{ width: "892px" }}>
|
||
<Row>
|
||
<Row.Col style={{ height: "210px", marginBottom: `${bottom}px` }}>
|
||
<Card
|
||
title={`${titlePrev}总出货(t)`}
|
||
titleSpace={true}
|
||
overVisible={true}
|
||
withBorder={false}
|
||
withBg={false}
|
||
>
|
||
<Row style={{ height: "100%" }}>
|
||
<Row.Col className="left" style={{ width: "60%" }}>
|
||
<div className="title">当月总交付情况</div>
|
||
<Row>
|
||
<Row.Col span={12}>
|
||
<NumCard data={mouthOutputMemo.total} />
|
||
<div className="monthInfo-total">
|
||
<div className="box">
|
||
进度达成:
|
||
{parseFloat(
|
||
(mouthOutputMemo.totalRate * 100).toFixed(1)
|
||
)}
|
||
%
|
||
</div>
|
||
</div>
|
||
</Row.Col>
|
||
<Row.Col span={12}>
|
||
<div className="monthInfo">
|
||
<div className="item">
|
||
<span className="title">
|
||
{mouthOutputMemo.names[0]}交货
|
||
</span>
|
||
<span className="num c-red">
|
||
{mouthOutputMemo.data[0]}
|
||
</span>
|
||
</div>
|
||
<div className="item m-b">
|
||
<span className="title">进度达成</span>
|
||
<span className="num">
|
||
{parseFloat(
|
||
(mouthOutputMemo.rates[0] * 100).toFixed(1)
|
||
)}
|
||
%
|
||
</span>
|
||
</div>
|
||
<div className="item">
|
||
<span className="title">
|
||
{mouthOutputMemo.names[1]}交货
|
||
</span>
|
||
<span className="num">
|
||
{mouthOutputMemo.data[1]}
|
||
</span>
|
||
</div>
|
||
<div className="item">
|
||
<span className="title">进度达成</span>
|
||
<span className="num">
|
||
{parseFloat(
|
||
(mouthOutputMemo.rates[1] * 100).toFixed(1)
|
||
)}
|
||
%
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</Row.Col>
|
||
</Row>
|
||
</Row.Col>
|
||
<Row.Col className="right" style={{ width: "40%" }}>
|
||
<div className="title pl-[42px] pr-[25px] text-center">
|
||
1-{lastYearMonthOpt}月汇总
|
||
</div>
|
||
<Chart ref={totalOutputChart} />
|
||
</Row.Col>
|
||
</Row>
|
||
</Card>
|
||
</Row.Col>
|
||
<Row.Col style={{ height: "304px", marginBottom: `${bottom}px` }}>
|
||
<Card
|
||
title={goalAchievementRateDateOpt + " 生产目标达成"}
|
||
titleSpace={true}
|
||
overVisible={true}
|
||
>
|
||
<Chart ref={prodPlanAchieveChart} />
|
||
</Card>
|
||
</Row.Col>
|
||
<Row.Col style={{ height: "338px" }}>
|
||
<Card
|
||
title="原材料库存情况(t)"
|
||
titleSpace={false}
|
||
overVisible={true}
|
||
>
|
||
<div className=" ml-44 text-lg absolute text-white">
|
||
{materialInventoryAvailableDaysOpt !== undefined ? (
|
||
Object.keys(materialInventoryAvailableDaysOpt).map(
|
||
(item, index) => {
|
||
console.log(item);
|
||
return (
|
||
<span>
|
||
{item}可用
|
||
<span className="m-2 text-xl text-red-600">
|
||
{materialInventoryAvailableDaysOpt[item]}
|
||
</span>
|
||
天{index === 0 ? "," : ""}
|
||
</span>
|
||
);
|
||
}
|
||
)
|
||
) : (
|
||
<></>
|
||
)}
|
||
</div>
|
||
<Chart ref={rawMaterialInventoryChart} />
|
||
</Card>
|
||
</Row.Col>
|
||
</Row>
|
||
</Row.Col>
|
||
<Row.Col style={{ width: "504px" }}>
|
||
<Row>
|
||
<Row.Col style={{ height: "436px", marginBottom: `${bottom}px` }}>
|
||
<Card title="产品库存情况" titleSpace={true} overVisible={true}>
|
||
<div style={{ height: "20%", padding: "16px 20px 0" }}>
|
||
<SimpleTable {...prodInventoryTableOpt} />
|
||
</div>
|
||
<div style={{ height: "80%" }}>
|
||
<Chart ref={prodInventory} />
|
||
</div>
|
||
</Card>
|
||
</Row.Col>
|
||
<Row.Col style={{ height: "436px" }}>
|
||
<Card title="历史库存情况" titleSpace={true} overVisible={true}>
|
||
<Chart ref={historyInventory} />
|
||
</Card>
|
||
</Row.Col>
|
||
</Row>
|
||
</Row.Col>
|
||
</Row>
|
||
</div>
|
||
{/* <Footer withTime={false} showDate={curDateOpt} /> */}
|
||
<style jsx>{`
|
||
.screen-container {
|
||
height: 100vh;
|
||
min-height: 1080px;
|
||
min-width: 1920px;
|
||
overflow: auto;
|
||
background: url("/img/bg.png") center center;
|
||
position: relative;
|
||
padding-top: 96px;
|
||
padding-bottom: 82px;
|
||
overflow: hidden;
|
||
}
|
||
.screen-container-content {
|
||
height: 100%;
|
||
padding: 0 ${gutter}px;
|
||
}
|
||
.title {
|
||
font-size: 14px;
|
||
color: #fff;
|
||
line-height: 22px;
|
||
padding-top: 16px;
|
||
margin-bottom: 6px;
|
||
}
|
||
.monthInfo-total {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
line-height: 28px;
|
||
text-align: center;
|
||
padding: 8px 4px 0;
|
||
}
|
||
.monthInfo-total .box {
|
||
background: rgba(36, 53, 184, 0.5);
|
||
color: #00f7fb;
|
||
}
|
||
.monthInfo {
|
||
border-right: 2px solid rgba(255, 255, 255, 0.2);
|
||
}
|
||
.monthInfo .item.m-b {
|
||
margin-bottom: 14px;
|
||
}
|
||
.monthInfo .num,
|
||
.monthInfo .title {
|
||
line-height: 30px;
|
||
font-size: 18px;
|
||
display: inline-block;
|
||
vertical-align: middle;
|
||
}
|
||
.monthInfo .title {
|
||
text-align: right;
|
||
width: 130px;
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
.monthInfo .num {
|
||
font-weight: bold;
|
||
margin-left: 16px;
|
||
}
|
||
.monthInfo .num:not(.c-red) {
|
||
color: #00f7fb;
|
||
}
|
||
`}</style>
|
||
<style jsx global>{`
|
||
.c-red {
|
||
color: #ff005a;
|
||
}
|
||
`}</style>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
function NumCard(props) {
|
||
let { data = 0 } = props;
|
||
const dataArr = useMemo(() => {
|
||
let res = data + "";
|
||
res = res.split("");
|
||
while (res.length < 4) res.unshift("");
|
||
return res;
|
||
}, [data]);
|
||
return (
|
||
<div className="num-card">
|
||
{dataArr.map((num, index) => (
|
||
<div className="num-card-item" key={index}>
|
||
<div className="text">{num}</div>
|
||
</div>
|
||
))}
|
||
<style jsx>{`
|
||
.num-card {
|
||
height: 100px;
|
||
line-height: 100px;
|
||
text-align: center;
|
||
color: #00f7fb;
|
||
font-size: 44px;
|
||
font-weight: bold;
|
||
}
|
||
.num-card-item {
|
||
float: left;
|
||
height: 100%;
|
||
width: ${100 / dataArr.length}%;
|
||
position: relative;
|
||
padding: 0 4px;
|
||
}
|
||
.num-card-item::before {
|
||
content: "";
|
||
display: block;
|
||
background: linear-gradient(
|
||
to bottom,
|
||
rgba(0, 76, 167, 0.2),
|
||
rgba(36, 53, 184, 0.5)
|
||
);
|
||
height: 100%;
|
||
width: 100%;
|
||
}
|
||
.text {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
`}</style>
|
||
</div>
|
||
);
|
||
}
|
||
function SimpleTable(props) {
|
||
let { cloumns = [], data = [] } = props;
|
||
|
||
return (
|
||
<div className="simple-table">
|
||
<div className="simple-table-header row">
|
||
{cloumns.map((text) => {
|
||
return (
|
||
<div key={text} className="item">
|
||
{text}
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
<div className="simple-table-body">
|
||
{data.map((rowData, index) => {
|
||
return (
|
||
<div key={index} className="row">
|
||
{rowData.map((text) => {
|
||
return (
|
||
<div key={text} className="item">
|
||
{text}
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
<style jsx>{`
|
||
.simple-table {
|
||
line-height: 32px;
|
||
text-align: center;
|
||
font-size: 14px;
|
||
}
|
||
.simple-table-header {
|
||
overflow: hidden;
|
||
background: rgba(40, 163, 255, 25%);
|
||
color: rgba(255, 255, 255, 85%);
|
||
}
|
||
.simple-table-body {
|
||
overflow: hidden;
|
||
background: rgba(40, 163, 255, 10%);
|
||
color: #fff;
|
||
}
|
||
.simple-table .item {
|
||
width: ${100 / (cloumns.length || 1)}%;
|
||
float: left;
|
||
}
|
||
.simple-table .row:not(:last-child) {
|
||
border-bottom: 1px solid;
|
||
}
|
||
.simple-table .item:not(:last-child) {
|
||
border-right: 1px solid;
|
||
}
|
||
.simple-table .row:not(:last-child),
|
||
.simple-table .item:not(:last-child) {
|
||
border-color: #09213d;
|
||
}
|
||
`}</style>
|
||
</div>
|
||
);
|
||
}
|
||
const getQueryVariable = (variable) => {
|
||
let query = window.location.search.substring(1);
|
||
let vars = query.split("&");
|
||
for (let i = 0; i < vars.length; i++) {
|
||
let pair = vars[i].split("=");
|
||
if (pair[0] == variable) {
|
||
return pair[1];
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
export default PlanDailyBoard;
|
||
|
||
// 月总产出
|
||
let mouthProd = {
|
||
grid: {
|
||
bottom: 30,
|
||
top: 60,
|
||
left: 60,
|
||
right: 70,
|
||
},
|
||
legend: {
|
||
top: 15,
|
||
right: 10,
|
||
textStyle: {
|
||
fontSize: 14,
|
||
},
|
||
},
|
||
xAxis: {
|
||
type: "category",
|
||
data: [],
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisTick: {
|
||
show: true,
|
||
alignWithLabel: true,
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
},
|
||
yAxis: [
|
||
{
|
||
type: "value",
|
||
min: 0,
|
||
axisLine: {
|
||
show: false,
|
||
},
|
||
axisTick: {
|
||
show: false,
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
},
|
||
{
|
||
type: "value",
|
||
min: 0,
|
||
axisLine: {
|
||
show: false,
|
||
},
|
||
axisTick: {
|
||
show: false,
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
formatter: (value) => `${100 * value}%`,
|
||
},
|
||
},
|
||
],
|
||
series: [
|
||
{
|
||
data: [],
|
||
type: "bar",
|
||
barWidth: 28,
|
||
name: "实际",
|
||
itemStyle: {
|
||
color: "#2D99FF",
|
||
},
|
||
label: {
|
||
show: true,
|
||
align: "center",
|
||
width: 200,
|
||
position: ["50%", "50%"],
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
},
|
||
},
|
||
{
|
||
data: [],
|
||
yAxisIndex: 1,
|
||
type: "line",
|
||
name: "达成率",
|
||
itemStyle: {
|
||
color: "#F5A623",
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: "top",
|
||
textBorderColor: "transparent",
|
||
color: "#F5A623",
|
||
formatter: (data) => `${parseInt(100 * data.value)}%`,
|
||
},
|
||
},
|
||
],
|
||
};
|
||
mouthProd.init = (res) => {
|
||
if (!res) return;
|
||
let opt = _.cloneDeep(mouthProd);
|
||
let { category, data } = res;
|
||
let { pect, prod } = data;
|
||
prod = prod.map((i) => parseInt(i));
|
||
pect = pect.map((i) => i);
|
||
// 分类
|
||
opt.xAxis.data = category;
|
||
// 实际生产数据
|
||
opt.series[0].data = prod;
|
||
// 达成率
|
||
opt.series[1].data = pect;
|
||
|
||
return opt;
|
||
};
|
||
|
||
// 月生产目标达成
|
||
let mouthAchieve = {
|
||
legend: {
|
||
top: 15,
|
||
right: 10,
|
||
textStyle: {
|
||
fontSize: 14,
|
||
},
|
||
},
|
||
|
||
barWidth: 10,
|
||
barGap: "40%",
|
||
grid: {
|
||
bottom: 40,
|
||
top: 60,
|
||
left: 60,
|
||
right: 70,
|
||
},
|
||
xAxis: {
|
||
type: "value",
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
},
|
||
yAxis: {
|
||
type: "category",
|
||
inverse: true,
|
||
axisTick: {
|
||
show: true,
|
||
alignWithLabel: true,
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
data: [],
|
||
},
|
||
series: [
|
||
{
|
||
name: "目标",
|
||
type: "bar",
|
||
data: [],
|
||
label: {
|
||
show: true,
|
||
position: "right",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
},
|
||
itemStyle: {
|
||
color: "#2D99FF",
|
||
},
|
||
},
|
||
{
|
||
name: "实际",
|
||
type: "bar",
|
||
data: [],
|
||
label: {
|
||
show: true,
|
||
position: "right",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
},
|
||
itemStyle: {
|
||
color: "#6FE621",
|
||
},
|
||
},
|
||
{
|
||
name: "达成率",
|
||
type: "line",
|
||
data: [],
|
||
symbolSize: 0,
|
||
lineStyle: {
|
||
width: 0,
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: "right",
|
||
textBorderColor: "transparent",
|
||
offset: [30, 0],
|
||
color: "#F6BD16",
|
||
},
|
||
itemStyle: {
|
||
color: "#F6BD16",
|
||
},
|
||
},
|
||
],
|
||
};
|
||
mouthAchieve.init = (res) => {
|
||
if (!res) return;
|
||
let opt = _.cloneDeep(mouthAchieve);
|
||
let { category, data } = res;
|
||
let { achievement, infect, plan } = data;
|
||
// 分类
|
||
opt.yAxis.data = category;
|
||
// 目标 数据
|
||
opt.series[0].data = plan.map((i) => parseFloat(i));
|
||
// 实际 数据
|
||
opt.series[1].data = infect.map((i) => parseFloat(i));
|
||
// 达成率 数据
|
||
opt.series[2].data = plan
|
||
.map((planVal, index) => Math.max(planVal, infect[index]))
|
||
.map((i) => parseFloat(i));
|
||
opt.series[2].label.formatter = ({ dataIndex }) =>
|
||
` ${(100 * achievement[dataIndex]).toFixed(0)}%`;
|
||
|
||
return opt;
|
||
};
|
||
|
||
// 出货汇总
|
||
let totalOutputBase = {
|
||
type: "gauge",
|
||
startAngle: 90,
|
||
radius: "70%",
|
||
max: 1,
|
||
endAngle: -270,
|
||
pointer: {
|
||
show: false,
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
width: 16,
|
||
color: [[1, "#28A3FF"]],
|
||
opacity: 0.15,
|
||
},
|
||
},
|
||
splitLine: {
|
||
show: false,
|
||
},
|
||
axisTick: {
|
||
show: false,
|
||
},
|
||
axisLabel: {
|
||
show: false,
|
||
},
|
||
progress: {
|
||
show: true,
|
||
overlap: false,
|
||
clip: true,
|
||
itemStyle: {
|
||
color: "#2D99FF",
|
||
},
|
||
},
|
||
title: {
|
||
fontSize: 14,
|
||
offsetCenter: [0, -14],
|
||
color: "#fff",
|
||
},
|
||
detail: {
|
||
width: 50,
|
||
height: 14,
|
||
fontSize: 20,
|
||
formatter: (val) => `${parseInt(100 * val)}%`,
|
||
valueAnimation: true,
|
||
offsetCenter: [0, 10],
|
||
color: "#fff",
|
||
},
|
||
};
|
||
let totalOutput = {
|
||
series: [
|
||
Object.assign({ center: ["30%", "36%"] }, totalOutputBase),
|
||
Object.assign({ center: ["75%", "36%"] }, totalOutputBase),
|
||
],
|
||
};
|
||
totalOutput.init = (res) => {
|
||
if (!res) return;
|
||
let opt = _.cloneDeep(totalOutput);
|
||
let [res0, res1] = res;
|
||
opt.series[0].data = [res0];
|
||
opt.series[1].data = [res1];
|
||
return opt;
|
||
};
|
||
|
||
// 生产目标达成
|
||
let prodPlanAchieve = {
|
||
grid: {
|
||
bottom: 40,
|
||
top: 30,
|
||
left: 70,
|
||
right: 40,
|
||
},
|
||
xAxis: {
|
||
type: "category",
|
||
data: [],
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisTick: {
|
||
show: true,
|
||
alignWithLabel: true,
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
},
|
||
yAxis: {
|
||
type: "value",
|
||
max: 1,
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
formatter: (value) => `${parseInt(100 * value)}%`,
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
},
|
||
series: {
|
||
data: [],
|
||
type: "bar",
|
||
barWidth: 28,
|
||
showBackground: true,
|
||
itemStyle: {
|
||
color: "#6FE621",
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: "top",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
formatter: (data) => `${parseInt(100 * data.value)}%`,
|
||
},
|
||
backgroundStyle: {
|
||
color: "rgba(45, 153, 255, 0.3)",
|
||
},
|
||
},
|
||
};
|
||
prodPlanAchieve.init = (res) => {
|
||
if (!res) return;
|
||
let opt = _.cloneDeep(prodPlanAchieve);
|
||
let { category, data } = res;
|
||
let { reach } = data;
|
||
|
||
opt.xAxis.data = category;
|
||
opt.series.data = reach.map((i) => parseFloat(i.toFixed(2)));
|
||
return opt;
|
||
};
|
||
|
||
// 原材料库存
|
||
let rawMaterialInventory = {
|
||
grid: {
|
||
bottom: 40,
|
||
top: 80,
|
||
left: 70,
|
||
right: 70,
|
||
},
|
||
legend: {
|
||
top: 15,
|
||
right: 10,
|
||
textStyle: {
|
||
fontSize: 14,
|
||
},
|
||
},
|
||
xAxis: {
|
||
type: "category",
|
||
data: [],
|
||
axisTick: {
|
||
show: true,
|
||
alignWithLabel: true,
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
interval: 0,
|
||
// rotate:45,
|
||
formatter: function (value) {
|
||
//x轴的文字改为竖版显示
|
||
// var str = value.split("");
|
||
return value.replace("-", "/");
|
||
},
|
||
},
|
||
},
|
||
yAxis: [
|
||
{
|
||
type: "value",
|
||
// splitNumber: 3,
|
||
axisTick: {
|
||
show: false,
|
||
},
|
||
axisLine: {
|
||
show: false,
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
formatter: (value) => parseFloat(value.toFixed(1)),
|
||
},
|
||
},
|
||
{
|
||
type: "value",
|
||
// splitNumber: 3,
|
||
axisTick: {
|
||
show: false,
|
||
},
|
||
axisLine: {
|
||
show: false,
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
formatter: (value) => parseFloat(value.toFixed(1)),
|
||
},
|
||
},
|
||
],
|
||
series: [
|
||
{
|
||
name: "",
|
||
type: "line",
|
||
symbol: "rect",
|
||
symbolSize: 0,
|
||
smooth: 0.5,
|
||
lineStyle: {
|
||
width: 0,
|
||
},
|
||
areaStyle: {
|
||
opacity: 0.6,
|
||
color: "#2D99FF",
|
||
},
|
||
data: [],
|
||
label: {
|
||
show: true,
|
||
position: "insideTop",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
|
||
// padding:[100,0,0,0], //调整上的位置
|
||
},
|
||
},
|
||
{
|
||
name: "",
|
||
type: "line",
|
||
yAxisIndex: 1,
|
||
label: {
|
||
show: true,
|
||
position: "top",
|
||
textBorderColor: "transparent",
|
||
color: "#F5A623",
|
||
},
|
||
data: [],
|
||
},
|
||
],
|
||
};
|
||
rawMaterialInventory.init = (res) => {
|
||
if (!res) return;
|
||
let opt = _.cloneDeep(rawMaterialInventory);
|
||
let { category, names, data } = res;
|
||
|
||
opt.xAxis.data = category.map((date) => moment(date).format("M-D"));
|
||
opt.series[0].data = data[0].map((i) => {
|
||
if (i === null) return i;
|
||
return parseFloat(i.toFixed(1));
|
||
});
|
||
opt.series[0].name = names[0] + " 库存量";
|
||
data[1] &&
|
||
(opt.series[1].data = data[1].map((i) => {
|
||
if (i === null) return i;
|
||
return parseFloat(i.toFixed(1));
|
||
}));
|
||
names[1] && (opt.series[1].name = names[1] + " 库存量");
|
||
|
||
return opt;
|
||
};
|
||
|
||
// 产品库存
|
||
let prodInventory = {
|
||
grid: {
|
||
bottom: 40,
|
||
top: 60,
|
||
left: 70,
|
||
right: 30,
|
||
},
|
||
barWidth: 32,
|
||
legend: {
|
||
top: 15,
|
||
right: 10,
|
||
textStyle: {
|
||
fontSize: 14,
|
||
},
|
||
},
|
||
xAxis: {
|
||
type: "category",
|
||
data: [],
|
||
axisTick: {
|
||
show: true,
|
||
alignWithLabel: true,
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
},
|
||
yAxis: {
|
||
type: "value",
|
||
axisTick: {
|
||
show: true,
|
||
alignWithLabel: true,
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
name: "合格数量",
|
||
type: "bar",
|
||
stack: "Ad",
|
||
data: [],
|
||
itemStyle: {
|
||
color: "#6FE621",
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: "inside",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
},
|
||
},
|
||
{
|
||
name: "待评审数量",
|
||
type: "bar",
|
||
stack: "Ad",
|
||
data: [],
|
||
itemStyle: {
|
||
color: "#2D99FF",
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: "inside",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
},
|
||
},
|
||
{
|
||
name: "在检未出数据",
|
||
type: "bar",
|
||
stack: "Ad",
|
||
data: [],
|
||
itemStyle: {
|
||
color: "#F6BD16",
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: "inside",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
},
|
||
},
|
||
{
|
||
name: "已评审待处理",
|
||
type: "bar",
|
||
stack: "Ad",
|
||
data: [],
|
||
itemStyle: {
|
||
color: "#95D8B9",
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: "inside",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
},
|
||
},
|
||
],
|
||
};
|
||
prodInventory.init = (res) => {
|
||
if (!res) return;
|
||
let opt = _.cloneDeep(prodInventory);
|
||
let { category, data } = res;
|
||
let { qualified, review, inspecting, inspected } = data;
|
||
|
||
opt.xAxis.data = category;
|
||
opt.series[0].data = qualified;
|
||
opt.series[1].data = review;
|
||
opt.series[2].data = inspecting;
|
||
opt.series[3].data = inspected;
|
||
|
||
return opt;
|
||
};
|
||
|
||
// 历史库存
|
||
let historyInventory = {
|
||
grid: {
|
||
bottom: 40,
|
||
top: 30,
|
||
left: 70,
|
||
right: 30,
|
||
},
|
||
barWidth: 16,
|
||
xAxis: {
|
||
type: "category",
|
||
data: [],
|
||
axisTick: {
|
||
show: true,
|
||
alignWithLabel: true,
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
},
|
||
yAxis: {
|
||
type: "value",
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: "rgba(255,255,255,0.65)",
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: "rgba(255,255,255,0.85)",
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
name: "碳酸铁 库存量",
|
||
type: "bar",
|
||
data: [],
|
||
itemStyle: {
|
||
color: "#F6BD16",
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: "top",
|
||
textBorderColor: "transparent",
|
||
color: "#fff",
|
||
},
|
||
},
|
||
],
|
||
};
|
||
historyInventory.init = (res) => {
|
||
if (!res) return;
|
||
let opt = _.cloneDeep(historyInventory);
|
||
let { category, data } = res;
|
||
|
||
opt.xAxis.data = category.map((date) => moment(date).format("M/D"));
|
||
opt.series[0].data = data.map((i) => parseFloat(i.toFixed(0)));
|
||
|
||
return opt;
|
||
};
|
||
|
||
let chartConfig = (() => {
|
||
let chartOpt = {
|
||
mouthProd,
|
||
mouthAchieve,
|
||
totalOutput,
|
||
prodPlanAchieve,
|
||
rawMaterialInventory,
|
||
prodInventory,
|
||
historyInventory,
|
||
};
|
||
let getOpt = (type) => chartOpt[type];
|
||
return getOpt;
|
||
})();
|
||
|
||
// dev 数据
|
||
let dates1 = [];
|
||
for (let i = 0; i < 20; i++) dates1.push(`7-${i + 1}`);
|
||
let dates2 = [];
|
||
for (let i = 0; i < 10; i++) dates2.push(`7-${i + 1}`);
|
||
const devData = {
|
||
curDate: "2022-08-03",
|
||
mouthProd: {
|
||
category: ["磷酸锂铁", "磷酸铁", "高镍三元"],
|
||
data: {
|
||
prod: [1269, 452, 852],
|
||
pect: [0.89, 0.56, 0.763],
|
||
},
|
||
},
|
||
mouthAchieve: {
|
||
category: [
|
||
"L1-A",
|
||
"L1-B",
|
||
"L2-A",
|
||
"L2-B",
|
||
"L3-B",
|
||
"L3-B",
|
||
"L4-A",
|
||
"L4-B",
|
||
"L5-A",
|
||
"L5-B",
|
||
"L6-B",
|
||
"L6-B",
|
||
"F1",
|
||
"F2",
|
||
"F3",
|
||
"N1",
|
||
],
|
||
data: {
|
||
plan: [
|
||
890, 600, 580, 720, 580, 580, 580, 890, 600, 580, 720, 580, 580, 890,
|
||
600, 580,
|
||
],
|
||
infect: [
|
||
600, 200, 600, 384, 799, 600, 600, 600, 200, 600, 384, 799, 600, 600,
|
||
200, 600,
|
||
],
|
||
achievement: [
|
||
0.6123, 0.6356, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6,
|
||
0.6, 0.6, 0.6,
|
||
],
|
||
},
|
||
},
|
||
mouthOutput: {
|
||
total: 319 + 271,
|
||
totalRate: 0.12,
|
||
data: [319, 271],
|
||
names: ["C公司", "非C公司"],
|
||
rates: [0.12, 0.12],
|
||
},
|
||
totalOutput: [
|
||
{ value: 0.234, name: "C公司" },
|
||
{ value: 0.234, name: "非C公司" },
|
||
],
|
||
prodPlanAchieve: {
|
||
category: ["L1", "L2", "L3", "L4", "L5", "L6", "F1", "F2", "F3", "N1"],
|
||
data: {
|
||
reach: [0.79, 0.4, 1.09, 0.33, 0.4, 0.56, 0.4, 0.86, 0.49, 0.79],
|
||
},
|
||
},
|
||
rawMaterialInventory: {
|
||
category: dates1,
|
||
names: ["碳酸铁", "碳酸锂"],
|
||
data: [
|
||
[
|
||
3900,
|
||
4900,
|
||
null,
|
||
4900,
|
||
4300,
|
||
3900,
|
||
null,
|
||
5100,
|
||
null,
|
||
4300,
|
||
3900,
|
||
4900,
|
||
5100,
|
||
4900,
|
||
4300,
|
||
4900,
|
||
5100,
|
||
null,
|
||
4300,
|
||
4300,
|
||
],
|
||
[
|
||
5100,
|
||
6200,
|
||
6400,
|
||
5500,
|
||
null,
|
||
6200,
|
||
6400,
|
||
5500,
|
||
5100,
|
||
null,
|
||
6400,
|
||
null,
|
||
5100,
|
||
6200,
|
||
6400,
|
||
5500,
|
||
5100,
|
||
null,
|
||
6400,
|
||
6200,
|
||
],
|
||
],
|
||
},
|
||
prodInventory: {
|
||
category: ["E80", "E80A", "E70", "E90", "W80S"],
|
||
data: {
|
||
qualified: [3900, 4900, 5100, 4900, 4300],
|
||
review: [5100, 6200, 6400, 5500, 5100],
|
||
inspecting: [5100, 6200, 6400, 5500, 5100],
|
||
inspected: [5100, 6200, 6400, 5500, 5100],
|
||
},
|
||
},
|
||
historyInventory: {
|
||
category: dates2,
|
||
data: [3900, 4900, 5100, 4900, 4300, 5100, 4900, 4300, 4900, 4300],
|
||
},
|
||
};
|
||
|
||
// local 数据
|
||
const localDataParse = {
|
||
// #当前日期
|
||
curDate: "2022-06-03",
|
||
// #8月产出
|
||
goalAchievementDiagram: [
|
||
{
|
||
productName: "磷酸铁锂",
|
||
achievingRate: 0.57,
|
||
actualQty: 1268,
|
||
},
|
||
],
|
||
// #8月份生产目标达成
|
||
goalAchievementHistogram: [
|
||
{
|
||
workLineName: "L1-A",
|
||
goalQty: 890,
|
||
actualQty: 600,
|
||
},
|
||
],
|
||
// #生产目标达成
|
||
goalAchievementRate: [
|
||
{
|
||
workCenterName: "L1",
|
||
achievingRate: 0.57,
|
||
},
|
||
],
|
||
// #产品库存情况
|
||
productInventoryTable: [
|
||
{
|
||
productName: "E80",
|
||
inventoryQty: 1000,
|
||
},
|
||
],
|
||
// #产品库存柱状图
|
||
productInventoryHistogram: [
|
||
{
|
||
productName: "E80",
|
||
okQty: 600,
|
||
reviewQty: 300,
|
||
pendingInspectionQty: 100,
|
||
},
|
||
],
|
||
// #原材料库存情况
|
||
materialInventoryDiagram: [
|
||
{
|
||
inventoryDate: ["2022-08-02"],
|
||
materialName: "磷酸铁锂",
|
||
inventoryQty: [3532.45],
|
||
},
|
||
{
|
||
inventoryDate: ["2022-08-02"],
|
||
materialName: "碳酸锂",
|
||
inventoryQty: [3932.45],
|
||
},
|
||
],
|
||
// #8月份出货
|
||
shipmentDashBoard: {
|
||
// #1-7月汇总
|
||
shipmentPie: [
|
||
{
|
||
customerName: "C公司",
|
||
rate: 0.76,
|
||
},
|
||
{
|
||
customerName: "非C公司",
|
||
rate: 1.76,
|
||
},
|
||
],
|
||
// #当月情况
|
||
summary: {
|
||
totalShipmentQty: 7339,
|
||
totalAchievingRate: 1.11, //进度达成
|
||
dtl: [
|
||
{
|
||
achievingRate: 1.11, //进度达成
|
||
customerName: "C公司",
|
||
shipmentQty: 4132,
|
||
goalQty: 4500.0,
|
||
},
|
||
{
|
||
achievingRate: 1.01, //进度达成
|
||
customerName: "非C公司",
|
||
shipmentQty: 4132,
|
||
goalQty: 4400.0,
|
||
},
|
||
],
|
||
},
|
||
},
|
||
// #历史库存情况
|
||
historyInventory: [
|
||
{
|
||
inventoryDate: "5/31",
|
||
inventoryQty: 200,
|
||
},
|
||
],
|
||
};
|
||
const localData = JSON.stringify(localDataParse);
|