From b810251a0c4c2ba72a4d4e56a43ae2baed92a638 Mon Sep 17 00:00:00 2001 From: RTGK Date: Thu, 20 Jun 2024 11:26:44 +0800 Subject: [PATCH] first commit --- .eslintrc.json | 19 + .gitignore | 35 + README.md | 34 + components/client/Button.js | 124 + components/client/FormItem.js | 148 + .../client/PackagingOperation/ModalClient.js | 555 ++ components/client/PackagingOperation/hooks.js | 199 + components/client/PackagingOperation/index.js | 619 ++ components/client/PackagingOperation/logo.js | 2 + components/client/utils.js | 17 + components/screen/Card/index.js | 97 + components/screen/Chart/echarts-liquidfill.js | 1688 ++++ components/screen/Chart/index.js | 38 + components/screen/Chart/theme.json | 440 + components/screen/CircleProcess/index.js | 162 + components/screen/Footer/DateItem.js | 60 + components/screen/Footer/index.js | 105 + components/screen/Header/index.js | 63 + components/screen/InfoCardList/InfoCard.js | 138 + components/screen/InfoCardList/index.js | 361 + components/screen/Row/index.js | 207 + components/screen/Table/index.js | 181 + components/screen/TableProgress/index.js | 82 + components/screen/TimerShaft/index.js | 141 + components/screen/WithConfig/index.js | 12 + next.config.js | 11 + package-lock.json | 8361 +++++++++++++++++ package.json | 39 + pages/_app.js | 34 + pages/api/hello.js | 5 + pages/client/PackagingOperation/index.js | 2 + pages/components/Alert/index.js | 107 + pages/components/Card/index.js | 367 + pages/components/Combobox/index.js | 84 + pages/components/Header/Header.js | 163 + pages/components/Header/LabelCheck.js | 55 + pages/components/Header/StateCheck.js | 10 + pages/components/Header/VLabel.js | 8 + pages/components/Modal/index.js | 119 + pages/components/ProcessCard/index.js | 107 + pages/components/Switch/index.js | 24 + pages/components/Tab/index.js | 75 + pages/components/processTaskCard/index.js | 167 + pages/index.js | 984 ++ pages/reports/curveParam/index.js | 216 + pages/reports/equipmentCurve/index.js | 592 ++ pages/reports/homePage/index.js | 981 ++ pages/reports/picView/data.json | 14 + pages/reports/picView/index.js | 108 + pages/reports/xmr/DemoDualAxes.js | 335 + pages/reports/xmr/DemoLine.js | 216 + pages/reports/xmr/index.js | 1359 +++ pages/screen/comprehensive/index.js | 438 + pages/screen/equipment/index.js | 978 ++ pages/screen/planBoard/index.js | 668 ++ pages/screen/planDailyBoard/index.js | 1740 ++++ pages/screen/processBoard/index.js | 416 + pages/screen/processItem/index.js | 809 ++ pages/screen/qualityBoard/index.js | 1087 +++ postcss.config.js | 6 + public/config.js | 179 + public/favicon.ico | Bin 0 -> 4286 bytes public/font/PingFang SC Regular.ttf | Bin 0 -> 10244 bytes public/font/PingFang SC.ttf | Bin 0 -> 13609012 bytes public/font/UnidreamLED.ttf | Bin 0 -> 31600 bytes public/font/rubik/Rubik-Black.ttf | Bin 0 -> 211696 bytes public/font/rubik/Rubik-BlackItalic.ttf | Bin 0 -> 192004 bytes public/font/rubik/Rubik-Bold.ttf | Bin 0 -> 212840 bytes public/font/rubik/Rubik-BoldItalic.ttf | Bin 0 -> 191132 bytes public/font/rubik/Rubik-Italic.ttf | Bin 0 -> 211768 bytes public/font/rubik/Rubik-Light.ttf | Bin 0 -> 216812 bytes public/font/rubik/Rubik-LightItalic.ttf | Bin 0 -> 208068 bytes public/font/rubik/Rubik-Medium.ttf | Bin 0 -> 216244 bytes public/font/rubik/Rubik-MediumItalic.ttf | Bin 0 -> 193052 bytes public/font/rubik/Rubik-Regular.ttf | Bin 0 -> 220600 bytes public/font/rubik/SIL Open Font License.txt | 48 + public/img/arrow.png | Bin 0 -> 3340 bytes public/img/bg.png | Bin 0 -> 5270 bytes public/img/dc.png | Bin 0 -> 1767 bytes public/img/eqimg.jpeg | Bin 0 -> 18715 bytes public/img/footerBg.png | Bin 0 -> 61179 bytes public/img/headerBg.png | Bin 0 -> 107527 bytes public/img/hpPercent.png | Bin 0 -> 10639 bytes public/img/img1.png | Bin 0 -> 2468 bytes public/img/jt.png | Bin 0 -> 707 bytes public/img/logo.png | Bin 0 -> 30896 bytes public/img/noImg.png | Bin 0 -> 96888 bytes public/img/process/L7-BZ-SB.png | Bin 0 -> 261798 bytes public/img/process/L7-BZ-ZZP.png | Bin 0 -> 167043 bytes public/img/process/L7-BZ.png | Bin 0 -> 85476 bytes public/img/process/L7-CC-SB.png | Bin 0 -> 307558 bytes public/img/process/L7-CC-ZZP.png | Bin 0 -> 165390 bytes public/img/process/L7-CC.png | Bin 0 -> 92987 bytes public/img/process/L7-CM-SB.png | Bin 0 -> 311417 bytes public/img/process/L7-CM-ZZP.png | Bin 0 -> 141454 bytes public/img/process/L7-CM.png | Bin 0 -> 93750 bytes public/img/process/L7-FS-SB.png | Bin 0 -> 256019 bytes public/img/process/L7-FS-ZZP.png | Bin 0 -> 180572 bytes public/img/process/L7-FS.png | Bin 0 -> 83332 bytes public/img/process/L7-HL-SB.png | Bin 0 -> 188303 bytes public/img/process/L7-HL-ZZP.png | Bin 0 -> 144946 bytes public/img/process/L7-HL.png | Bin 0 -> 65371 bytes public/img/process/L7-PWGZ-SB.png | Bin 0 -> 292737 bytes public/img/process/L7-PWGZ-ZZP.png | Bin 0 -> 176130 bytes public/img/process/L7-PWGZ.png | Bin 0 -> 88749 bytes public/img/process/L7-SCCC.png | Bin 0 -> 72453 bytes public/img/process/L7-SJ-SB.png | Bin 0 -> 232682 bytes public/img/process/L7-SJ-ZZP.png | Bin 0 -> 174570 bytes public/img/process/L7-SJ.png | Bin 0 -> 74824 bytes public/img/process/L7-TL-SB.png | Bin 0 -> 316342 bytes public/img/process/L7-TL-ZZP.png | Bin 0 -> 150834 bytes public/img/process/L7-TL.png | Bin 0 -> 89639 bytes public/img/process/L7-XM-SB.png | Bin 0 -> 311417 bytes public/img/process/L7-XM-ZZP.png | Bin 0 -> 141454 bytes public/img/process/L7-XM.png | Bin 0 -> 88909 bytes public/img/process/L7-YH-SB.png | Bin 0 -> 304742 bytes public/img/process/L7-YH-ZZP.png | Bin 0 -> 96025 bytes public/img/process/L7-YH.png | Bin 0 -> 95264 bytes public/img/processBg/baozhuang.png | Bin 0 -> 326779 bytes public/img/processBg/chuci.png | Bin 0 -> 265986 bytes public/img/processBg/fensui.png | Bin 0 -> 362099 bytes public/img/processBg/penwu.png | Bin 0 -> 370232 bytes public/img/processBg/shaojie.png | Bin 0 -> 349401 bytes public/img/processBg/total.png | Bin 0 -> 471811 bytes public/img/processBg/touliao.png | Bin 0 -> 364010 bytes public/img/processBg/yanmo.png | Bin 0 -> 274484 bytes public/img/sz.png | Bin 0 -> 1787 bytes public/img/tc.png | Bin 0 -> 1774 bytes reportUtils/getHomePageData.js | 105 + reportUtils/getQueryData.js | 343 + reportUtils/request.js | 74 + reportUtils/theme.json | 396 + styles/globals.css | 158 + styles/homecss.module.css | 322 + tailwind.config.js | 45 + utils/checks.js | 8 + utils/eqs.js | 456 + utils/hooks.js | 68 + utils/requests.js | 113 + utils/socket.io.js | 6619 +++++++++++++ 140 files changed, 35146 insertions(+) create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 README.md create mode 100644 components/client/Button.js create mode 100644 components/client/FormItem.js create mode 100644 components/client/PackagingOperation/ModalClient.js create mode 100644 components/client/PackagingOperation/hooks.js create mode 100644 components/client/PackagingOperation/index.js create mode 100644 components/client/PackagingOperation/logo.js create mode 100644 components/client/utils.js create mode 100644 components/screen/Card/index.js create mode 100644 components/screen/Chart/echarts-liquidfill.js create mode 100644 components/screen/Chart/index.js create mode 100644 components/screen/Chart/theme.json create mode 100644 components/screen/CircleProcess/index.js create mode 100644 components/screen/Footer/DateItem.js create mode 100644 components/screen/Footer/index.js create mode 100644 components/screen/Header/index.js create mode 100644 components/screen/InfoCardList/InfoCard.js create mode 100644 components/screen/InfoCardList/index.js create mode 100644 components/screen/Row/index.js create mode 100644 components/screen/Table/index.js create mode 100644 components/screen/TableProgress/index.js create mode 100644 components/screen/TimerShaft/index.js create mode 100644 components/screen/WithConfig/index.js create mode 100644 next.config.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 pages/_app.js create mode 100644 pages/api/hello.js create mode 100644 pages/client/PackagingOperation/index.js create mode 100644 pages/components/Alert/index.js create mode 100644 pages/components/Card/index.js create mode 100644 pages/components/Combobox/index.js create mode 100644 pages/components/Header/Header.js create mode 100644 pages/components/Header/LabelCheck.js create mode 100644 pages/components/Header/StateCheck.js create mode 100644 pages/components/Header/VLabel.js create mode 100644 pages/components/Modal/index.js create mode 100644 pages/components/ProcessCard/index.js create mode 100644 pages/components/Switch/index.js create mode 100644 pages/components/Tab/index.js create mode 100644 pages/components/processTaskCard/index.js create mode 100644 pages/index.js create mode 100644 pages/reports/curveParam/index.js create mode 100644 pages/reports/equipmentCurve/index.js create mode 100644 pages/reports/homePage/index.js create mode 100644 pages/reports/picView/data.json create mode 100644 pages/reports/picView/index.js create mode 100644 pages/reports/xmr/DemoDualAxes.js create mode 100644 pages/reports/xmr/DemoLine.js create mode 100644 pages/reports/xmr/index.js create mode 100644 pages/screen/comprehensive/index.js create mode 100644 pages/screen/equipment/index.js create mode 100644 pages/screen/planBoard/index.js create mode 100644 pages/screen/planDailyBoard/index.js create mode 100644 pages/screen/processBoard/index.js create mode 100644 pages/screen/processItem/index.js create mode 100644 pages/screen/qualityBoard/index.js create mode 100644 postcss.config.js create mode 100644 public/config.js create mode 100644 public/favicon.ico create mode 100644 public/font/PingFang SC Regular.ttf create mode 100644 public/font/PingFang SC.ttf create mode 100644 public/font/UnidreamLED.ttf create mode 100644 public/font/rubik/Rubik-Black.ttf create mode 100644 public/font/rubik/Rubik-BlackItalic.ttf create mode 100644 public/font/rubik/Rubik-Bold.ttf create mode 100644 public/font/rubik/Rubik-BoldItalic.ttf create mode 100644 public/font/rubik/Rubik-Italic.ttf create mode 100644 public/font/rubik/Rubik-Light.ttf create mode 100644 public/font/rubik/Rubik-LightItalic.ttf create mode 100644 public/font/rubik/Rubik-Medium.ttf create mode 100644 public/font/rubik/Rubik-MediumItalic.ttf create mode 100644 public/font/rubik/Rubik-Regular.ttf create mode 100644 public/font/rubik/SIL Open Font License.txt create mode 100644 public/img/arrow.png create mode 100644 public/img/bg.png create mode 100644 public/img/dc.png create mode 100644 public/img/eqimg.jpeg create mode 100644 public/img/footerBg.png create mode 100644 public/img/headerBg.png create mode 100644 public/img/hpPercent.png create mode 100644 public/img/img1.png create mode 100644 public/img/jt.png create mode 100644 public/img/logo.png create mode 100644 public/img/noImg.png create mode 100644 public/img/process/L7-BZ-SB.png create mode 100644 public/img/process/L7-BZ-ZZP.png create mode 100644 public/img/process/L7-BZ.png create mode 100644 public/img/process/L7-CC-SB.png create mode 100644 public/img/process/L7-CC-ZZP.png create mode 100644 public/img/process/L7-CC.png create mode 100644 public/img/process/L7-CM-SB.png create mode 100644 public/img/process/L7-CM-ZZP.png create mode 100644 public/img/process/L7-CM.png create mode 100644 public/img/process/L7-FS-SB.png create mode 100644 public/img/process/L7-FS-ZZP.png create mode 100644 public/img/process/L7-FS.png create mode 100644 public/img/process/L7-HL-SB.png create mode 100644 public/img/process/L7-HL-ZZP.png create mode 100644 public/img/process/L7-HL.png create mode 100644 public/img/process/L7-PWGZ-SB.png create mode 100644 public/img/process/L7-PWGZ-ZZP.png create mode 100644 public/img/process/L7-PWGZ.png create mode 100644 public/img/process/L7-SCCC.png create mode 100644 public/img/process/L7-SJ-SB.png create mode 100644 public/img/process/L7-SJ-ZZP.png create mode 100644 public/img/process/L7-SJ.png create mode 100644 public/img/process/L7-TL-SB.png create mode 100644 public/img/process/L7-TL-ZZP.png create mode 100644 public/img/process/L7-TL.png create mode 100644 public/img/process/L7-XM-SB.png create mode 100644 public/img/process/L7-XM-ZZP.png create mode 100644 public/img/process/L7-XM.png create mode 100644 public/img/process/L7-YH-SB.png create mode 100644 public/img/process/L7-YH-ZZP.png create mode 100644 public/img/process/L7-YH.png create mode 100644 public/img/processBg/baozhuang.png create mode 100644 public/img/processBg/chuci.png create mode 100644 public/img/processBg/fensui.png create mode 100644 public/img/processBg/penwu.png create mode 100644 public/img/processBg/shaojie.png create mode 100644 public/img/processBg/total.png create mode 100644 public/img/processBg/touliao.png create mode 100644 public/img/processBg/yanmo.png create mode 100644 public/img/sz.png create mode 100644 public/img/tc.png create mode 100644 reportUtils/getHomePageData.js create mode 100644 reportUtils/getQueryData.js create mode 100644 reportUtils/request.js create mode 100644 reportUtils/theme.json create mode 100644 styles/globals.css create mode 100644 styles/homecss.module.css create mode 100644 tailwind.config.js create mode 100644 utils/checks.js create mode 100644 utils/eqs.js create mode 100644 utils/hooks.js create mode 100644 utils/requests.js create mode 100644 utils/socket.io.js diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..9c600d2 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "extends": "next/core-web-vitals", + "rules": { + "react-hooks/exhaustive-deps": "off", + "react/display-name": "off", + "react/jsx-key": "off", + "@next/next/no-sync-scripts": "off", + "react/no-unknown-property": [ + 2, + { + "ignore": [ + "jsx", + "global" + ] + } + ] + } +} + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..601f8c8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel diff --git a/README.md b/README.md new file mode 100644 index 0000000..b12f3e3 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/components/client/Button.js b/components/client/Button.js new file mode 100644 index 0000000..e1cb38f --- /dev/null +++ b/components/client/Button.js @@ -0,0 +1,124 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { Spin } from "antd"; +import { LoadingOutlined } from "@ant-design/icons"; +import { useRule } from "./PackagingOperation/hooks" + +const btnTyps = [ + { type: "primary", color: "#0185FF" }, + { type: "danger", color: "#F5222D" }, + { type: "warning", color: "#FAAB0C" }, + { type: "success", color: "#85C700" }, + { type: "info", color: "#26c1e1" }, + { type: "default", color: "rgba(0,0,0,.85)" }, +]; +export const Button = React.memo((props) => { + const { + visible = true, + enable = true, + title, + type = "primary", + ghost = false, + size, + onClick = () => { }, + ruleCode, + } = props; + + const rule = useRule(ruleCode); + // useEffect(() => { + // console.log("rule", rule) + // }, [rule]) + + const types = useRef(btnTyps.map(({ type }) => type)); + + const sizes = useRef(["large"]); + const className = useMemo(() => { + let res = "client-btn"; + if (type && types.current.includes(type)) res += ` btn-${type}`; + if (ghost === true) res += ` btn-ghost`; + if (size && sizes.current.includes(size)) res += ` btn-${size}`; + if (enable === false) res += ` btn-disabled`; + return res; + }, [type, ghost, size, enable]); + + const [loading, setLoading] = useState(false); + const handleClick = useCallback(() => { + if (enable && !loading) { + let res = onClick(); + if (res && typeof res.then == "function" && typeof res.finally == "function") { + setLoading(true); + res.finally(() => setLoading(false)) + } + } + }, [enable, onClick, loading]); + + if (!rule) return null; + if (!visible) return null; + return ( +
enable && handleClick()}> + {title} + } + /> + + +
+ ); +}); diff --git a/components/client/FormItem.js b/components/client/FormItem.js new file mode 100644 index 0000000..551fb56 --- /dev/null +++ b/components/client/FormItem.js @@ -0,0 +1,148 @@ +import React, { + useMemo, +} from "react"; + +export const FormItem = React.memo((props) => { + const { + title, + value = "", + readonly = true, + horizontal = true, + type, + ...otherProps + } = props; + + const valueMemo = useMemo(() => { + if (readonly) { + if (["", undefined, null].includes(value)) return "-"; + return value; + } + if (type === "number") { + return ; + } + return value; + }, [readonly, value, type, otherProps]); + + return ( +
+
{title}
+
{valueMemo}
+ +
+ ); +}); + +const FormItemNumber = React.memo((props) => { + const { value, onChange = () => {}, min } = props; + const onInputChange = (e) => { + onChange(e.target.value); + }; + const onInputBlur = (e) => { + let res = parseFloat(e.target.value); + if (isNaN(res)) res = "-"; + onChange(res + ""); + }; + const onBtnClick = (add) => { + let res = parseFloat(value); + if (isNaN(res)) res = add; + res = res + add; + if (min !== undefined && res < min) res = min; + onChange(res + ""); + }; + const btnDisabled = useMemo(() => [value <= min], [value, min]); + return ( +
+
value > min && onBtnClick(-1)} + > + - +
+ +
onBtnClick(1)}> + + +
+ +
+ ); +}); + diff --git a/components/client/PackagingOperation/ModalClient.js b/components/client/PackagingOperation/ModalClient.js new file mode 100644 index 0000000..28dbadd --- /dev/null +++ b/components/client/PackagingOperation/ModalClient.js @@ -0,0 +1,555 @@ +import React, { + useCallback, + useEffect, + useImperativeHandle, + useRef, + useState, +} from "react"; +import { Modal, Row, Col, Form, Input, Select, message } from "antd"; +import { Button } from "../Button"; +import { request } from "../utils"; + +const ModalClient = React.memo((props) => { + const { + visible = false, + title, + onOk = () => {}, + onCancel = () => {}, + children, + } = props; + return ( + +
{title}
+
{children}
+
+
+ + +
+ ); +}); + +// 设置 +export const ModelSetting = React.forwardRef((props, ref) => { + const {} = props; + const callbackRef = useRef(() => {}); + const [form] = Form.useForm(); + const [visible, setVisible] = useState(false); + + const handleCancel = useCallback(() => setVisible(false), []); + + const [equipList, setEquipList] = useState([]); + const [operationList, setOperationList] = useState([]); + const [workShopList, setWorkShopList] = useState([]); + + // 查询包装机 + const getEquip = useCallback((gid) => { + if (gid) { + request({ + method: "POST", + url: `${window.config.mesUrl}/mdgeneric/md/bmWorkCenter/getEquipByOperationGid?operationGid=${gid}`, + }).then(({ data, success } = {}) => { + if (!success) data = []; + setEquipList(data); + }); + } + }, []); + + // 工序变化 + const onOperationChange = useCallback( + (code, a, data) => { + if (!data) data = operationList; + // console.log("val", key, value, data); + let {gid: operationGid, name} = data.find((item) => item.code === code) || {}; + getEquip(operationGid); + form.setFieldsValue({ + operationName: name, + operationCode: code, + equipName: undefined, + equipCode: undefined, + }); + setEquipList([]); + }, + [operationList, form, getEquip] + ); + + // 查询工序 + const getOperation = useCallback( + (gid, callback) => { + if (gid) { + request({ + method: "POST", + url: `${window.config.mesUrl}/mdgeneric/md/bmWorkCenter/getOpByWorkCenter?workCenterGid=${gid}`, + }).then(({ data, success } = {}) => { + if (!success) data = []; + setOperationList(data); + if (callback) { + callback(data); + } else if (data.length) { + let { name, code } = data[0]; + form.setFieldsValue({ + operationName: name, + equipName: code, + }); + onOperationChange(code,undefined, data) + } + }); + } else setOperationList([]); + }, + [onOperationChange] + ); + + // 车间变化 + const onWorkShopChange = useCallback( + (key = {}) => { + let { gid: workShopGid, name: value } = workShopList.find(({ code }) => code === key) || {}; + getOperation(workShopGid); + form.setFieldsValue({ + workCenterCode: key, + workCenterName: value, + operationName: undefined, + operationCode: undefined, + equipName: undefined, + equipCode: undefined, + }); + setOperationList([]); + setEquipList([]); + }, + [workShopList, form, getOperation] + ); + + // 查询车间 + const getWorkShop = useCallback((callback) => { + request({ + method: "POST", + url: `${window.config.mesUrl}/mdgeneric/md/bmWorkCenter/findAllWithPage`, + bodys: { + // removePermission: true, + page: -1, + pageSize: -1, + sorted: "createTime desc", + filter: "type eq 'workshop'", + }, + }).then(({ data, success } = {}) => { + if (!success) data = []; + setWorkShopList(data); + callback && callback(data); + }); + }, []); + + // 设备变化 + const onEquipChange = useCallback( + (key) => { + let { name: value} = equipList.find(({ code }) => code === key) || {} + form.setFieldsValue({ + equipName: value, + equipCode: key, + }); + }, + [form, equipList] + ); + + // 初始化 + const init = useCallback( + (data, callback) => { + setVisible(true); + form.resetFields(); + form.setFieldsValue(data); + callbackRef.current = callback; + let { workCenterCode, operationCode } = data; + getWorkShop((res) => { + if (workCenterCode) { + let gid = res.find(({ code }) => code === workCenterCode)?.gid; + getOperation(gid, (res) => { + if (operationCode) { + let gid = res.find(({ code }) => code === operationCode)?.gid; + getEquip(gid); + } + }); + } + }); + }, + [form, getWorkShop, getOperation, getEquip] + ); + + const handleOk = useCallback(() => { + let formData = form.getFieldValue(); + if (["", null, undefined].includes(formData.workCenterCode)) + return message.error("请完善车间!"); + if (["", null, undefined].includes(formData.equipCode)) + return message.error("请完善包装机!"); + if (["", null, undefined].includes(formData.bagWeight)) + return message.error("请完善包装袋重量!"); + if (["", null, undefined].includes(formData.packSpecs)) + return message.error("请完包装规格!"); + if (["", null, undefined].includes(formData.upperLimit)) + return message.error("请完善上限值!"); + if (["", null, undefined].includes(formData.lowerLimit)) + return message.error("请完善下限值!"); + // console.log("form", formData); + return new Promise((resolve, reject) => { + request({ + url: `${window.config.mesUrl}/prodexec/prodexec/packageEquipment/setPackInfo`, + bodys: formData, + }).then((res) => { + handleCancel(); + callbackRef.current(); + }) + .finally(() => { + resolve(); + }); + }); + }, [handleCancel, form, workShopList, equipList]); + + useImperativeHandle( + ref, + () => ({ + show: init, + }), + [init] + ); + return ( + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
-
+ + + + + + +
+
+
+
+
+ ); +}); + +// 中断 +export const ModelBreak = React.forwardRef((props, ref) => { + const {} = props; + const callbackRef = useRef(() => {}); + const [form] = Form.useForm(); + const [visible, setVisible] = useState(false); + + const handleCancel = useCallback(() => setVisible(false), []); + + const handleOk = useCallback(() => { + let formData = form.getFieldValue(); + if (["", null, undefined].includes(formData.reason)) + return message.error("请完善中断原因!"); + return new Promise((resolve, reject) => { + request({ + url: `${window.config.mesUrl}/prodexec/prodexec/packageEquipment/interruptPack`, + bodys: { + gid: formData.gid, + }, + }) + .then((res) => { + if (res.success) { + handleCancel(); + callbackRef.current(); + } else message.error(res.message || "操作失败!"); + }) + .finally(() => { + resolve(); + }); + }); + }, [handleCancel]); + useImperativeHandle( + ref, + () => ({ + show() { + setVisible(true); + }, + show: (data, callback) => { + setVisible(true); + form.resetFields(); + form.setFieldsValue(data); + callbackRef.current = callback; + }, + }), + [form] + ); + return ( + +
+ + + +
+
+ ); +}); + +// 结束 +export const ModelFinish = React.forwardRef((props, ref) => { + const {} = props; + const [form, setForm] = useState([]); + const callbackRef = useRef(() => {}); + const [visible, setVisible] = useState(false); + const handleCancel = useCallback(() => setVisible(false), []); + const handleOk = useCallback(() => { + return new Promise((resolve, reject) => { + request({ + url: `${window.config.mesUrl}/prodexec/prodexec/packageEquipment/endPack`, + bodys: form, + }) + .then((res) => { + if (res.success) { + handleCancel(); + callbackRef.current(); + message.success("包装完成!"); + } else message.error(res.message || "操作失败!"); + }) + .finally(() => { + resolve(); + }); + }); + }, [handleCancel, form]); + useImperativeHandle( + ref, + () => ({ + show: (data, callback) => { + setVisible(true); + setForm(data); + callbackRef.current = callback; + }, + }), + [] + ); + return ( + +

是否确认结束?

+
+ ); +}); + +// 超产 +export const ModelOverproductionBatch = React.forwardRef((props, ref) => { + const { } = props; + const [form] = Form.useForm(); + const codeRef = useRef(); + const callbackRef = useRef(() => {}); + const [visible, setVisible] = useState(false); + const handleCancel = useCallback(() => setVisible(false), []); + const handleOk = useCallback(() => { + let formData = form.getFieldValue(); + if (codeRef.current && codeRef.current === formData.outBatch) { + message.error("超产批号不能与原单号一致!"); + } else { + callbackRef.current && callbackRef.current(formData.outBatch); + handleCancel(); + }; + }, [handleCancel, form]); + useImperativeHandle( + ref, + () => ({ + show(code, callback) { + codeRef.current = code; + callbackRef.current = callback; + setVisible(true); + }, + }), + [] + ); + return ( + +
+ + + +
+
+ ); +}); + +// 超量打印 +export const ModelOverPrint = React.forwardRef((props, ref) => { + const {} = props; + const [form, setForm] = useState(""); + const callbackRef = useRef(() => {}); + const [visible, setVisible] = useState(false); + const handleCancel = useCallback(() => setVisible(false), []); + const handleOk = useCallback(() => { + return callbackRef.current(handleCancel); + }, [handleCancel, form]); + useImperativeHandle( + ref, + () => ({ + show: (data, callback) => { + setVisible(true); + setForm(data); + callbackRef.current = callback; + }, + }), + [] + ); + return ( + +

{ form }

+
+ ); +}); \ No newline at end of file diff --git a/components/client/PackagingOperation/hooks.js b/components/client/PackagingOperation/hooks.js new file mode 100644 index 0000000..4a3acfd --- /dev/null +++ b/components/client/PackagingOperation/hooks.js @@ -0,0 +1,199 @@ +import React, { useCallback, useEffect, useState, useRef } from "react"; +import { message } from "antd"; +import { request, getQueryVariable } from "../utils"; + +export const isDev = false; + +let rules = (function () { + let data = []; + let callback = () => {}; + let setData = (res) => { + setData = () => {}; + data = res; + callback({ success: true, data: res }); + }; + return { + setData, + getData: () => data, + loaded: new Promise((resolve, reject) => { + callback = resolve; + }), + }; +})(); + +let getRule = () => { + getRule = () => rules.loaded; + return request({ + method: "get", + url: `${window.config.mesUrl}/console/getpermissions`, + }); +}; + +export const useRule = (code) => { + const [ruleList, setRuleList] = useState(rules.getData()); + useEffect(() => { + getRule().then(({ success, data } = {}) => { + if (success) { + setRuleList(data); + rules.setData(data); + } + }); + }, []); + + if (code) return ruleList.includes(code); + return true; +}; + +export const useUser = () => { + const [data, setData] = useState(); + const getUser = useCallback(() => { + // let user = localStorage.getItem("userInfo"); + // try { + // user = JSON.parse(user) + // } catch (e) { + // console.log(e); + // user = {}; + // } + // console.log("user", user, localStorage.getItem("userInfo")) + // setData(user); + request({ + method: "get", + url: `${window.config.mesUrl}/console/currentinfo`, + }).then(({ success, data } = {}) => { + if (success) { + setData(data); + } else setData(); + }); + }, []) + // useEffect(() => { + // getUser(); + // }, [getUser]); + return [data, getUser]; +}; + +export const useEquipKey = () => { + const [equipKey, setEquipKey] = useState(); + const getEquipKey = useCallback(() => { + let ip = getQueryVariable("ip"); + console.log("ip", ip); + if (!ip || ip === "null") { + message.error("获取 ip 失败!"); + } else { + setEquipKey(ip); + } + }, []); + useEffect(() => { + getEquipKey(); + }, [getEquipKey]); + return { equipKey, getEquipKey }; +}; + +export const useSetting = (equipKey) => { + const [settingData, setSettingData] = useState({}); + + const getSettingData = useCallback(() => { + if (equipKey) { + request({ + method: "post", + url: `${window.config.mesUrl}/prodexec/prodexec/packageEquipment/getPackInfoByKey?equipKey=${equipKey}`, + }).then(({ success, data } = {}) => { + if (success) setSettingData(data || {}); + }); + } else setSettingData({}); + }, [equipKey]); + + useEffect(() => { + getSettingData(); + }, [getSettingData]); + return { settingData, getSettingData }; +}; + +export const useMetaInfo = (equipCode) => { + const [data, setData] = useState({}); // bagNo outBagNo + const timmerRef = useRef(); + const getData = useCallback(() => { + if (timmerRef.current) { + clearTimeout(timmerRef.current); + timmerRef.current = undefined; + } + if (equipCode) { + request({ + method: "post", + url: `${window.config.mesUrl}/prodexec/prodexec/packageEquipment/getEquipRecord?equipCode=${equipCode}`, + }).then(({ success, data, message: msg } = {}) => { + if (success) { + let { status } = data || {}; + // 没有数据,或者数据为中断状态,尝试定时重复请求 + if (!data || status === "INTERRUPT") { + if (!data) { + data = { status: "no_job" }; + message.error("请先分配任务!"); + } + let { reloadTime } = window.config.packagingOperaConfig || {}; + if (reloadTime !== undefined) { + timmerRef.current = setTimeout(getData, reloadTime); + } + } + setData(data); + } else { + message.error(msg); + } + }); + } else setData({}); + }, [equipCode]); + + useEffect(() => { + getData(); + }, [getData]); + return [data, getData]; +}; + +export const useWsInfo = (equipCode, isEdit) => { + const [data, setData] = useState({}); + useEffect(() => { + if (equipCode) { + let url = window.config.edgewsUrl; + if (isDev) { + url = "ws://120.202.38.15:8081/rongtong-edge-application-ws/"; + } + if (!isEdit) { + console.log("link: ", url); + let ws = new WebSocket(url); + ws.onmessage = (evt) => { + let res = evt.data; + // if (isDev) { + // res = { + // czzl: 1.11, + // fczl: 2.22, + // } + // } + if (typeof res === "string") { + try { + res = JSON.parse(res); + } catch (e) { + console.log("ws", res); + res = {}; + } + } + console.log("ws res:", res); + setData(res); + }; + ws.onopen = () => { + if (isDev) { + // 01 02 03 + equipCode = "L5-BZ-02"; + } + console.log("Connection open ... send:", equipCode); + ws.send(equipCode); + }; + } + return () => { + if (!isEdit) { + console.log("ws close:", equipCode); + ws.close(); + } + }; + } + }, [equipCode, isEdit]); + return [data]; +}; diff --git a/components/client/PackagingOperation/index.js b/components/client/PackagingOperation/index.js new file mode 100644 index 0000000..31bcaec --- /dev/null +++ b/components/client/PackagingOperation/index.js @@ -0,0 +1,619 @@ +import React, { + useCallback, + useRef, + useReducer, + useEffect, + useState, + useMemo, +} from "react"; +import { message } from "antd"; +import moment from "moment"; +import Decimal from "decimal.js" +import Row from "../../../components/screen/Row"; +import { FormItem } from "../FormItem"; +import { Button } from "../Button"; +import { + ModelSetting, + ModelBreak, + ModelOverproductionBatch, + ModelFinish, + ModelOverPrint, +} from "./ModalClient"; +import { logo } from "./logo"; +import { request } from "../utils"; +import { + useEquipKey, + useSetting, + useMetaInfo, + useWsInfo, + useUser, + isDev, +} from "./hooks"; + +const headerHeight = 56; + +/** + * url获取token + * 获取用户信息 + * 获取权限信息 + * + * url获取ip + * ip - 设置信息 + * 设置信息 - 产品信息 + * 设置信息 - socket 重量信息 + * + * 任务状态: + * 无任务 待包装 包装中 中断 包装完成 + */ + +function formReducer(state, action) { + let { type, value } = action; + // console.log("action", action); + if (type === "FROM_INIT") return value; + if (type === "FROM_CHANGE") return Object.assign({}, state, value); + return state; +} + +function PackagingOperation(props) { + const ModelSettingRef = useRef(); + const ModelBreakRef = useRef(); + const ModelOverproductionBatchRef = useRef(); + const ModelFinishRef = useRef(); + + const [isEdit, setIsEdit] = useState(false); + + const { equipKey, getEquipKey } = useEquipKey(); + const { settingData, getSettingData } = useSetting(equipKey); + const [metaInfo, getMetaInfo] = useMetaInfo(settingData?.equipCode); + const [wsData] = useWsInfo(settingData?.equipCode, isEdit); + const [user, getUser] = useUser(); + + // 页面表单变化 + const [form, dispatch] = useReducer(formReducer, {}); + const onFormChange = useCallback((type, value) => { + dispatch({ type: "FROM_CHANGE", value: { [type]: value } }); + }, []); + + // 更新当前登录用户 + useEffect(() => { + dispatch({ type: "FROM_CHANGE", value: { userName: user?.userName } }); + }, [user]); + + // 初始化表单 + useEffect(() => { + dispatch({ type: "FROM_INIT", value: metaInfo }); + getUser(); + }, [metaInfo, getUser]); + + // ws更新表单 + useEffect(() => { + let { czzl, fczl } = wsData || {}; + dispatch({ type: "FROM_CHANGE", value: { czzl, fczl } }); + }, [wsData]); + + // 更新净重 + const netWeight = useMemo(() => { + let { bagWeight } = settingData; + let { fczl } = form; + if (isNaN(parseFloat(fczl))) return ""; + if (isNaN(parseFloat(bagWeight))) return ""; + let res = Decimal(fczl).sub(Decimal(bagWeight)).toNumber(); + if (isNaN(res)) return ""; + return res; + }, [form, settingData]); + + // 更新持续时长 + const [durationTime, setDurationTime] = useState(0); + useEffect(() => { + let getTime = () => { + let { + startTime, + status, + recoverDate, + interruptDate, + intrptDuration = 0, + } = metaInfo; + // console.log("metaInfo", metaInfo, {startTime, status, recoverDate, interruptDate, intrptDuration }) + /** + * 无任务 “” + * 待包装 “” + * 包装中 currentDate - startTime - intrptDuration + * 中断 interruptDate - startTime - intrptDuration + * 包装完成 endTime - startTime - intrptDuration + */ + if (["no_job", "TO_BE_PACKAGED"].includes(status)) return ""; + let dif = new Date(startTime).getTime() + intrptDuration * 1000; + if (status === "IN_PACKAGING") return new Date().getTime() - dif; + if (status === "INTERRUPT") + return new Date(interruptDate).getTime() - dif; + if (status === "PACKAGING_COMPLETED") + return new Date(endTime).getTime() - dif; + }; + let timmer; + let run = () => { + setDurationTime(getTime()); + timmer = setTimeout(() => { + run(); + }, 1000); + }; + run(); + return () => { + clearTimeout(timmer); + }; + }, [metaInfo]); + const durationTimeStr = useMemo(() => { + let time = moment.duration(durationTime); + let res = ""; + let sec = time.seconds(); + let min = time.minutes(); + let hor = time.hours(); + let day = time.days(); + let m = time.months(); + let y = time.years(); + let flag = false; + let arr = [y, m, day, hor, min, sec]; + let unt = ["年", "月", "日", "时", "分", "秒"]; + arr.forEach((val, index) => { + if (val) { + flag = true; + res += val + unt[index]; + } else if (flag) { + res += 0 + unt[index]; + } + }); + return res; + }, [durationTime]); + + // 包装袋数 + const [realBagNo, setRealBagNo] = useState(1); + useEffect(() => { + let { bagNo, outBagNo, outBatch } = form; + let res = 0; + if (outBatch) { + res = parseFloat(outBagNo) + 1; + } else { + res = parseFloat(bagNo) + 1; + } + setRealBagNo(isNaN(res) ? 0 : res); + }, [form.bagNo, form.outBagNo, form.outBatch]); + + // 设备状态 + const equipStatus = useMemo(() => { + if (form.status === "no_job") return "无任务"; + if (form.status === "INTERRUPT") return "中断"; + if (form.status === "TO_BE_PACKAGED") return "待包装"; + if (form.status === "IN_PACKAGING") return "包装中"; + if (form.status === "PACKAGING_COMPLETED") return "包装完成"; + return "-"; + }, [form.status]); + + // 按钮启用禁用 + const btnEnable = useMemo(() => { + /** + * 超产批号 ? + * 设置 - 权限 + * 历史记录 - 非无任务 + * 开始 - 待包装 + * 打印 - 包装中 + * 结束 - 包装中 中断 + * 中断 - 包装中 + * 编辑 - 权限 包装中 + * 编辑完成 - 权限 包装中 + */ + return { + overPro: true, + setting: true, + history: ["中断", "待包装", "包装中", "包装完成"].includes(equipStatus), + start: ["待包装"].includes(equipStatus), + print: ["包装中"].includes(equipStatus), + finish: ["包装中", "中断"].includes(equipStatus), + break: ["包装中"].includes(equipStatus), + edit: ["包装中"].includes(equipStatus), + }; + }, [equipStatus]); + + // 退出 + const handleCancel = useCallback(() => { + window.parent.postMessage({ type: "logOut" }, window.config.mesHost); + }, []); + + // 设置 + const handleSetting = useCallback(() => { + if (equipKey) { + let settingRes = Object.assign({}, settingData || {}, { equipKey }); + ModelSettingRef.current.show(settingRes, getSettingData); + } + }, [equipKey, getSettingData, settingData]); + + // 超产批号 + const handleOverproduct = useCallback(() => { + ModelOverproductionBatchRef.current.show( + metaInfo.workOrderCode, + (outBatch) => { + onFormChange("outBatch", outBatch); + } + ); + }, [metaInfo.workOrderCode, onFormChange]); + + // 历史记录 + const handleHistory = useCallback(() => { + window.parent.postMessage( + { type: "history", data: metaInfo }, + window.config.mesHost + ); + }, [metaInfo]); + + // 开始 + const handleStart = useCallback(() => { + if (metaInfo.gid) + return new Promise((resolve, reject) => { + request({ + url: `${window.config.mesUrl}/prodexec/prodexec/packageEquipment/startPack`, + bodys: { gid: metaInfo.gid }, + }) + .then((res) => { + if (res.success) { + message.success("开始成功!"); + getMetaInfo(); + } + }) + .finally(() => { + resolve(); + }); + }); + }, [metaInfo.gid, getMetaInfo]); + + // 打印 + const ModelOverPrintRef = useRef(); + const [isGT, setIsGT] = useState(false) + const handlePrint = useCallback((GT, callback) => { + if (GT === undefined) GT = isGT; + let { gid: recordGid } = metaInfo; + let { gid: setInfoGid, bagWeight } = settingData; + let { + fczl, + czzl, + outBatch, + materialCode, + productLevel, + startTime, + materialName, + workOrderCode, + } = form; + // collectValue 页面可见数据 除自定义字段外的 对象json 字符串 + let collectValue = { + materialCode, + productLevel, + startTime, + materialName, + workOrderCode, + czzl, + fczl, + bagWeight, + yetWeight: netWeight, + bagNo: realBagNo, + }; + let data = { + recordGid, + mark: GT? "GT": undefined, + fczl, + bagNo: realBagNo, + setInfoGid, + yetWeight: netWeight, + outBatch, + collectValue: JSON.stringify(collectValue), + }; + if (recordGid) + return new Promise((resolve, reject) => { + request({ + url: `${window.config.mesUrl}/prodexec/prodexec/packageEquipment/print`, + bodys: data, + }) + .then((res) => { + // if (isDev) { + // if (res.message.indexOf('打印命令发送失败') > -1) { + // res = { + // success: false, + // data: "GT", + // message: "message text" + // } + // } + // } + if (res && res.success) { + message.success("打印成功!"); + setRealBagNo(parseFloat(realBagNo) + 1); + } else { + if (res?.data === "GT") { + ModelOverPrintRef.current.show(res.message, (close) => { + setIsGT(true); + return handlePrint(true, close); + }) + }else message.error(res?.message); + } + }) + .finally(() => { + resolve(); + callback && callback(); + }); + }); + }, [metaInfo, settingData, form, netWeight, realBagNo, isGT]); + + // 结束 + const handleFinish = useCallback(() => { + ModelFinishRef.current.show({ gid: metaInfo.gid }, getMetaInfo); + }, [metaInfo.gid, getMetaInfo]); + + // 中断 + const handleBreak = useCallback(() => { + ModelBreakRef.current.show({ gid: metaInfo.gid }, getMetaInfo); + }, [metaInfo.gid, getMetaInfo]); + + // 编辑 + const handleEdit = useCallback(() => { + // console.log("handleEdit"); + if (isEdit) { + setIsEdit(false); + } else { + setIsEdit(true); + } + }, [isEdit]); + + return ( +
+
+
+ logo +
+
+
+ 退出 +
+
+
+
+
+
+ 产品信息 +
+
+
+
+
{equipStatus}
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ 生产信息 +
+
+
+
+ + + onFormChange("czzl", val)} + /> + + + onFormChange("fczl", val)} + /> + + + + + + + + + + + + setRealBagNo(val)} + /> + + +
+
+
+
+
+ +
+ ); +} + +export default PackagingOperation; diff --git a/components/client/PackagingOperation/logo.js b/components/client/PackagingOperation/logo.js new file mode 100644 index 0000000..e251606 --- /dev/null +++ b/components/client/PackagingOperation/logo.js @@ -0,0 +1,2 @@ +export const logo = +"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABAAAAACqCAYAAAAz1T0YAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDYuMC1jMDA2IDc5LmRhYmFjYmIsIDIwMjEvMDQvMTQtMDA6Mzk6NDQgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCAyMi40IChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjQ1RkRGRDRBRDhFMzExRUNBMEZCRERCQzk5NzNEQTRBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjQ1RkRGRDRCRDhFMzExRUNBMEZCRERCQzk5NzNEQTRBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NDVGREZENDhEOEUzMTFFQ0EwRkJEREJDOTk3M0RBNEEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NDVGREZENDlEOEUzMTFFQ0EwRkJEREJDOTk3M0RBNEEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4gabteAAB1IElEQVR42uy9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"; diff --git a/components/client/utils.js b/components/client/utils.js new file mode 100644 index 0000000..31a4dc9 --- /dev/null +++ b/components/client/utils.js @@ -0,0 +1,17 @@ +import {default as reportRequest} from "../../reportUtils/request" + + +export 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 const request = (params) => { + let token = getQueryVariable("token"); + return reportRequest(params, token) +} \ No newline at end of file diff --git a/components/screen/Card/index.js b/components/screen/Card/index.js new file mode 100644 index 0000000..5a16961 --- /dev/null +++ b/components/screen/Card/index.js @@ -0,0 +1,97 @@ +import React from 'react'; + +const titleSize = 28; + +function Card(props) { + const { + full = true, + title, + titleSpace, + overVisible, + padding, + withBorder = true, + withBg = "rgba(6,36,109,0.80)" + } = props; + return ( +
+ {title &&
+ {title} +
} +
+
+ {React.Children.map(props.children, item => item)} +
+
+ +
+ ); +} + +export default Card; \ No newline at end of file diff --git a/components/screen/Chart/echarts-liquidfill.js b/components/screen/Chart/echarts-liquidfill.js new file mode 100644 index 0000000..f7f377d --- /dev/null +++ b/components/screen/Chart/echarts-liquidfill.js @@ -0,0 +1,1688 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("echarts")); + else if(typeof define === 'function' && define.amd) + define(["echarts"], factory); + else if(typeof exports === 'object') + exports["echarts-liquidfill"] = factory(require("echarts")); + else + root["echarts-liquidfill"] = factory(root["echarts"]); +})(this, function(__WEBPACK_EXTERNAL_MODULE_echarts_lib_echarts__) { +return /******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "./index.js": +/*!******************************!*\ + !*** ./index.js + 6 modules ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// EXTERNAL MODULE: external "echarts" +var external_echarts_ = __webpack_require__("echarts/lib/echarts"); +;// CONCATENATED MODULE: ./src/liquidFillSeries.js + + +external_echarts_.extendSeriesModel({ + + type: 'series.liquidFill', + + optionUpdated: function () { + var option = this.option; + option.gridSize = Math.max(Math.floor(option.gridSize), 4); + }, + + getInitialData: function (option, ecModel) { + var dimensions = external_echarts_.helper.createDimensions(option.data, { + coordDimensions: ['value'] + }); + var list = new external_echarts_.List(dimensions, this); + list.initData(option.data); + return list; + }, + + defaultOption: { + color: ['#294D99', '#156ACF', '#1598ED', '#45BDFF'], + center: ['50%', '50%'], + radius: '50%', + amplitude: '8%', + waveLength: '80%', + phase: 'auto', + period: 'auto', + direction: 'right', + shape: 'circle', + + waveAnimation: true, + animationEasing: 'linear', + animationEasingUpdate: 'linear', + animationDuration: 2000, + animationDurationUpdate: 1000, + + outline: { + show: true, + borderDistance: 8, + itemStyle: { + color: 'none', + borderColor: '#294D99', + borderWidth: 8, + shadowBlur: 20, + shadowColor: 'rgba(0, 0, 0, 0.25)' + } + }, + + backgroundStyle: { + color: '#E3F7FF' + }, + + itemStyle: { + opacity: 0.95, + shadowBlur: 50, + shadowColor: 'rgba(0, 0, 0, 0.4)' + }, + + label: { + show: true, + color: '#294D99', + insideColor: '#fff', + fontSize: 50, + fontWeight: 'bold', + + align: 'center', + baseline: 'middle', + position: 'inside' + }, + + emphasis: { + itemStyle: { + opacity: 0.8 + } + } + } +}); + +;// CONCATENATED MODULE: ./node_modules/zrender/lib/core/util.js +var BUILTIN_OBJECT = { + '[object Function]': true, + '[object RegExp]': true, + '[object Date]': true, + '[object Error]': true, + '[object CanvasGradient]': true, + '[object CanvasPattern]': true, + '[object Image]': true, + '[object Canvas]': true +}; +var TYPED_ARRAY = { + '[object Int8Array]': true, + '[object Uint8Array]': true, + '[object Uint8ClampedArray]': true, + '[object Int16Array]': true, + '[object Uint16Array]': true, + '[object Int32Array]': true, + '[object Uint32Array]': true, + '[object Float32Array]': true, + '[object Float64Array]': true +}; +var objToString = Object.prototype.toString; +var arrayProto = Array.prototype; +var nativeForEach = arrayProto.forEach; +var nativeFilter = arrayProto.filter; +var nativeSlice = arrayProto.slice; +var nativeMap = arrayProto.map; +var ctorFunction = function () { }.constructor; +var protoFunction = ctorFunction ? ctorFunction.prototype : null; +var methods = {}; +function $override(name, fn) { + methods[name] = fn; +} +var idStart = 0x0907; +function guid() { + return idStart++; +} +function logError() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (typeof console !== 'undefined') { + console.error.apply(console, args); + } +} +function clone(source) { + if (source == null || typeof source !== 'object') { + return source; + } + var result = source; + var typeStr = objToString.call(source); + if (typeStr === '[object Array]') { + if (!isPrimitive(source)) { + result = []; + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } + else if (TYPED_ARRAY[typeStr]) { + if (!isPrimitive(source)) { + var Ctor = source.constructor; + if (Ctor.from) { + result = Ctor.from(source); + } + else { + result = new Ctor(source.length); + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } + } + else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) { + result = {}; + for (var key in source) { + if (source.hasOwnProperty(key)) { + result[key] = clone(source[key]); + } + } + } + return result; +} +function merge(target, source, overwrite) { + if (!isObject(source) || !isObject(target)) { + return overwrite ? clone(source) : target; + } + for (var key in source) { + if (source.hasOwnProperty(key)) { + var targetProp = target[key]; + var sourceProp = source[key]; + if (isObject(sourceProp) + && isObject(targetProp) + && !isArray(sourceProp) + && !isArray(targetProp) + && !isDom(sourceProp) + && !isDom(targetProp) + && !isBuiltInObject(sourceProp) + && !isBuiltInObject(targetProp) + && !isPrimitive(sourceProp) + && !isPrimitive(targetProp)) { + merge(targetProp, sourceProp, overwrite); + } + else if (overwrite || !(key in target)) { + target[key] = clone(source[key]); + } + } + } + return target; +} +function mergeAll(targetAndSources, overwrite) { + var result = targetAndSources[0]; + for (var i = 1, len = targetAndSources.length; i < len; i++) { + result = merge(result, targetAndSources[i], overwrite); + } + return result; +} +function extend(target, source) { + if (Object.assign) { + Object.assign(target, source); + } + else { + for (var key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key]; + } + } + } + return target; +} +function defaults(target, source, overlay) { + var keysArr = keys(source); + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + if ((overlay ? source[key] != null : target[key] == null)) { + target[key] = source[key]; + } + } + return target; +} +var createCanvas = function () { + return methods.createCanvas(); +}; +methods.createCanvas = function () { + return document.createElement('canvas'); +}; +function indexOf(array, value) { + if (array) { + if (array.indexOf) { + return array.indexOf(value); + } + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + } + return -1; +} +function inherits(clazz, baseClazz) { + var clazzPrototype = clazz.prototype; + function F() { } + F.prototype = baseClazz.prototype; + clazz.prototype = new F(); + for (var prop in clazzPrototype) { + if (clazzPrototype.hasOwnProperty(prop)) { + clazz.prototype[prop] = clazzPrototype[prop]; + } + } + clazz.prototype.constructor = clazz; + clazz.superClass = baseClazz; +} +function mixin(target, source, override) { + target = 'prototype' in target ? target.prototype : target; + source = 'prototype' in source ? source.prototype : source; + if (Object.getOwnPropertyNames) { + var keyList = Object.getOwnPropertyNames(source); + for (var i = 0; i < keyList.length; i++) { + var key = keyList[i]; + if (key !== 'constructor') { + if ((override ? source[key] != null : target[key] == null)) { + target[key] = source[key]; + } + } + } + } + else { + defaults(target, source, override); + } +} +function isArrayLike(data) { + if (!data) { + return false; + } + if (typeof data === 'string') { + return false; + } + return typeof data.length === 'number'; +} +function each(arr, cb, context) { + if (!(arr && cb)) { + return; + } + if (arr.forEach && arr.forEach === nativeForEach) { + arr.forEach(cb, context); + } + else if (arr.length === +arr.length) { + for (var i = 0, len = arr.length; i < len; i++) { + cb.call(context, arr[i], i, arr); + } + } + else { + for (var key in arr) { + if (arr.hasOwnProperty(key)) { + cb.call(context, arr[key], key, arr); + } + } + } +} +function map(arr, cb, context) { + if (!arr) { + return []; + } + if (!cb) { + return slice(arr); + } + if (arr.map && arr.map === nativeMap) { + return arr.map(cb, context); + } + else { + var result = []; + for (var i = 0, len = arr.length; i < len; i++) { + result.push(cb.call(context, arr[i], i, arr)); + } + return result; + } +} +function reduce(arr, cb, memo, context) { + if (!(arr && cb)) { + return; + } + for (var i = 0, len = arr.length; i < len; i++) { + memo = cb.call(context, memo, arr[i], i, arr); + } + return memo; +} +function filter(arr, cb, context) { + if (!arr) { + return []; + } + if (!cb) { + return slice(arr); + } + if (arr.filter && arr.filter === nativeFilter) { + return arr.filter(cb, context); + } + else { + var result = []; + for (var i = 0, len = arr.length; i < len; i++) { + if (cb.call(context, arr[i], i, arr)) { + result.push(arr[i]); + } + } + return result; + } +} +function find(arr, cb, context) { + if (!(arr && cb)) { + return; + } + for (var i = 0, len = arr.length; i < len; i++) { + if (cb.call(context, arr[i], i, arr)) { + return arr[i]; + } + } +} +function keys(obj) { + if (!obj) { + return []; + } + if (Object.keys) { + return Object.keys(obj); + } + var keyList = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + keyList.push(key); + } + } + return keyList; +} +function bindPolyfill(func, context) { + var args = []; + for (var _i = 2; _i < arguments.length; _i++) { + args[_i - 2] = arguments[_i]; + } + return function () { + return func.apply(context, args.concat(nativeSlice.call(arguments))); + }; +} +var bind = (protoFunction && isFunction(protoFunction.bind)) + ? protoFunction.call.bind(protoFunction.bind) + : bindPolyfill; +function curry(func) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + return function () { + return func.apply(this, args.concat(nativeSlice.call(arguments))); + }; +} + +function isArray(value) { + if (Array.isArray) { + return Array.isArray(value); + } + return objToString.call(value) === '[object Array]'; +} +function isFunction(value) { + return typeof value === 'function'; +} +function isString(value) { + return typeof value === 'string'; +} +function isStringSafe(value) { + return objToString.call(value) === '[object String]'; +} +function isNumber(value) { + return typeof value === 'number'; +} +function isObject(value) { + var type = typeof value; + return type === 'function' || (!!value && type === 'object'); +} +function isBuiltInObject(value) { + return !!BUILTIN_OBJECT[objToString.call(value)]; +} +function isTypedArray(value) { + return !!TYPED_ARRAY[objToString.call(value)]; +} +function isDom(value) { + return typeof value === 'object' + && typeof value.nodeType === 'number' + && typeof value.ownerDocument === 'object'; +} +function isGradientObject(value) { + return value.colorStops != null; +} +function isPatternObject(value) { + return value.image != null; +} +function isRegExp(value) { + return objToString.call(value) === '[object RegExp]'; +} +function eqNaN(value) { + return value !== value; +} +function retrieve() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + for (var i = 0, len = args.length; i < len; i++) { + if (args[i] != null) { + return args[i]; + } + } +} +function retrieve2(value0, value1) { + return value0 != null + ? value0 + : value1; +} +function retrieve3(value0, value1, value2) { + return value0 != null + ? value0 + : value1 != null + ? value1 + : value2; +} +function slice(arr) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + return nativeSlice.apply(arr, args); +} +function normalizeCssArray(val) { + if (typeof (val) === 'number') { + return [val, val, val, val]; + } + var len = val.length; + if (len === 2) { + return [val[0], val[1], val[0], val[1]]; + } + else if (len === 3) { + return [val[0], val[1], val[2], val[1]]; + } + return val; +} +function assert(condition, message) { + if (!condition) { + throw new Error(message); + } +} +function trim(str) { + if (str == null) { + return null; + } + else if (typeof str.trim === 'function') { + return str.trim(); + } + else { + return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + } +} +var primitiveKey = '__ec_primitive__'; +function setAsPrimitive(obj) { + obj[primitiveKey] = true; +} +function isPrimitive(obj) { + return obj[primitiveKey]; +} +var HashMap = (function () { + function HashMap(obj) { + this.data = {}; + var isArr = isArray(obj); + this.data = {}; + var thisMap = this; + (obj instanceof HashMap) + ? obj.each(visit) + : (obj && each(obj, visit)); + function visit(value, key) { + isArr ? thisMap.set(value, key) : thisMap.set(key, value); + } + } + HashMap.prototype.get = function (key) { + return this.data.hasOwnProperty(key) ? this.data[key] : null; + }; + HashMap.prototype.set = function (key, value) { + return (this.data[key] = value); + }; + HashMap.prototype.each = function (cb, context) { + for (var key in this.data) { + if (this.data.hasOwnProperty(key)) { + cb.call(context, this.data[key], key); + } + } + }; + HashMap.prototype.keys = function () { + return keys(this.data); + }; + HashMap.prototype.removeKey = function (key) { + delete this.data[key]; + }; + return HashMap; +}()); + +function createHashMap(obj) { + return new HashMap(obj); +} +function concatArray(a, b) { + var newArray = new a.constructor(a.length + b.length); + for (var i = 0; i < a.length; i++) { + newArray[i] = a[i]; + } + var offset = a.length; + for (var i = 0; i < b.length; i++) { + newArray[i + offset] = b[i]; + } + return newArray; +} +function createObject(proto, properties) { + var obj; + if (Object.create) { + obj = Object.create(proto); + } + else { + var StyleCtor = function () { }; + StyleCtor.prototype = proto; + obj = new StyleCtor(); + } + if (properties) { + extend(obj, properties); + } + return obj; +} +function hasOwn(own, prop) { + return own.hasOwnProperty(prop); +} +function noop() { } + +;// CONCATENATED MODULE: ./node_modules/echarts/lib/util/number.js + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + + +/** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + +var RADIAN_EPSILON = 1e-4; + +function _trim(str) { + return str.replace(/^\s+|\s+$/g, ''); +} + +function linearMap(val, domain, range, clamp) { + var subDomain = domain[1] - domain[0]; + var subRange = range[1] - range[0]; + + if (subDomain === 0) { + return subRange === 0 ? range[0] : (range[0] + range[1]) / 2; + } + + if (clamp) { + if (subDomain > 0) { + if (val <= domain[0]) { + return range[0]; + } else if (val >= domain[1]) { + return range[1]; + } + } else { + if (val >= domain[0]) { + return range[0]; + } else if (val <= domain[1]) { + return range[1]; + } + } + } else { + if (val === domain[0]) { + return range[0]; + } + + if (val === domain[1]) { + return range[1]; + } + } + + return (val - domain[0]) / subDomain * subRange + range[0]; +} +function parsePercent(percent, all) { + switch (percent) { + case 'center': + case 'middle': + percent = '50%'; + break; + + case 'left': + case 'top': + percent = '0%'; + break; + + case 'right': + case 'bottom': + percent = '100%'; + break; + } + + if (typeof percent === 'string') { + if (_trim(percent).match(/%$/)) { + return parseFloat(percent) / 100 * all; + } + + return parseFloat(percent); + } + + return percent == null ? NaN : +percent; +} +function round(x, precision, returnStr) { + if (precision == null) { + precision = 10; + } + + precision = Math.min(Math.max(0, precision), 20); + x = (+x).toFixed(precision); + return returnStr ? x : +x; +} +function asc(arr) { + arr.sort(function (a, b) { + return a - b; + }); + return arr; +} +function getPrecision(val) { + val = +val; + + if (isNaN(val)) { + return 0; + } + + var e = 1; + var count = 0; + + while (Math.round(val * e) / e !== val) { + e *= 10; + count++; + } + + return count; +} +function getPrecisionSafe(val) { + var str = val.toString(); + var eIndex = str.indexOf('e'); + + if (eIndex > 0) { + var precision = +str.slice(eIndex + 1); + return precision < 0 ? -precision : 0; + } else { + var dotIndex = str.indexOf('.'); + return dotIndex < 0 ? 0 : str.length - 1 - dotIndex; + } +} +function getPixelPrecision(dataExtent, pixelExtent) { + var log = Math.log; + var LN10 = Math.LN10; + var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10); + var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10); + var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20); + return !isFinite(precision) ? 20 : precision; +} +function getPercentWithPrecision(valueList, idx, precision) { + if (!valueList[idx]) { + return 0; + } + + var sum = reduce(valueList, function (acc, val) { + return acc + (isNaN(val) ? 0 : val); + }, 0); + + if (sum === 0) { + return 0; + } + + var digits = Math.pow(10, precision); + var votesPerQuota = map(valueList, function (val) { + return (isNaN(val) ? 0 : val) / sum * digits * 100; + }); + var targetSeats = digits * 100; + var seats = map(votesPerQuota, function (votes) { + return Math.floor(votes); + }); + var currentSum = reduce(seats, function (acc, val) { + return acc + val; + }, 0); + var remainder = map(votesPerQuota, function (votes, idx) { + return votes - seats[idx]; + }); + + while (currentSum < targetSeats) { + var max = Number.NEGATIVE_INFINITY; + var maxId = null; + + for (var i = 0, len = remainder.length; i < len; ++i) { + if (remainder[i] > max) { + max = remainder[i]; + maxId = i; + } + } + + ++seats[maxId]; + remainder[maxId] = 0; + ++currentSum; + } + + return seats[idx] / digits; +} +var MAX_SAFE_INTEGER = 9007199254740991; +function remRadian(radian) { + var pi2 = Math.PI * 2; + return (radian % pi2 + pi2) % pi2; +} +function isRadianAroundZero(val) { + return val > -RADIAN_EPSILON && val < RADIAN_EPSILON; +} +var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d{1,2})(?::(\d{1,2})(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; +function parseDate(value) { + if (value instanceof Date) { + return value; + } else if (typeof value === 'string') { + var match = TIME_REG.exec(value); + + if (!match) { + return new Date(NaN); + } + + if (!match[8]) { + return new Date(+match[1], +(match[2] || 1) - 1, +match[3] || 1, +match[4] || 0, +(match[5] || 0), +match[6] || 0, +match[7] || 0); + } else { + var hour = +match[4] || 0; + + if (match[8].toUpperCase() !== 'Z') { + hour -= +match[8].slice(0, 3); + } + + return new Date(Date.UTC(+match[1], +(match[2] || 1) - 1, +match[3] || 1, hour, +(match[5] || 0), +match[6] || 0, +match[7] || 0)); + } + } else if (value == null) { + return new Date(NaN); + } + + return new Date(Math.round(value)); +} +function quantity(val) { + return Math.pow(10, quantityExponent(val)); +} +function quantityExponent(val) { + if (val === 0) { + return 0; + } + + var exp = Math.floor(Math.log(val) / Math.LN10); + + if (val / Math.pow(10, exp) >= 10) { + exp++; + } + + return exp; +} +function nice(val, round) { + var exponent = quantityExponent(val); + var exp10 = Math.pow(10, exponent); + var f = val / exp10; + var nf; + + if (round) { + if (f < 1.5) { + nf = 1; + } else if (f < 2.5) { + nf = 2; + } else if (f < 4) { + nf = 3; + } else if (f < 7) { + nf = 5; + } else { + nf = 10; + } + } else { + if (f < 1) { + nf = 1; + } else if (f < 2) { + nf = 2; + } else if (f < 3) { + nf = 3; + } else if (f < 5) { + nf = 5; + } else { + nf = 10; + } + } + + val = nf * exp10; + return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val; +} +function quantile(ascArr, p) { + var H = (ascArr.length - 1) * p + 1; + var h = Math.floor(H); + var v = +ascArr[h - 1]; + var e = H - h; + return e ? v + e * (ascArr[h] - v) : v; +} +function reformIntervals(list) { + list.sort(function (a, b) { + return littleThan(a, b, 0) ? -1 : 1; + }); + var curr = -Infinity; + var currClose = 1; + + for (var i = 0; i < list.length;) { + var interval = list[i].interval; + var close_1 = list[i].close; + + for (var lg = 0; lg < 2; lg++) { + if (interval[lg] <= curr) { + interval[lg] = curr; + close_1[lg] = !lg ? 1 - currClose : 1; + } + + curr = interval[lg]; + currClose = close_1[lg]; + } + + if (interval[0] === interval[1] && close_1[0] * close_1[1] !== 1) { + list.splice(i, 1); + } else { + i++; + } + } + + return list; + + function littleThan(a, b, lg) { + return a.interval[lg] < b.interval[lg] || a.interval[lg] === b.interval[lg] && (a.close[lg] - b.close[lg] === (!lg ? 1 : -1) || !lg && littleThan(a, b, 1)); + } +} +function numericToNumber(val) { + var valFloat = parseFloat(val); + return valFloat == val && (valFloat !== 0 || typeof val !== 'string' || val.indexOf('x') <= 0) ? valFloat : NaN; +} +function isNumeric(val) { + return !isNaN(numericToNumber(val)); +} +function getRandomIdBase() { + return Math.round(Math.random() * 9); +} +function getGreatestCommonDividor(a, b) { + if (b === 0) { + return a; + } + + return getGreatestCommonDividor(b, a % b); +} +function getLeastCommonMultiple(a, b) { + if (a == null) { + return b; + } + + if (b == null) { + return a; + } + + return a * b / getGreatestCommonDividor(a, b); +} +;// CONCATENATED MODULE: ./src/liquidFillShape.js + + +/* harmony default export */ const liquidFillShape = (external_echarts_.graphic.extendShape({ + type: 'ec-liquid-fill', + + shape: { + waveLength: 0, + radius: 0, + radiusY: 0, + cx: 0, + cy: 0, + waterLevel: 0, + amplitude: 0, + phase: 0, + inverse: false + }, + + buildPath: function (ctx, shape) { + if (shape.radiusY == null) { + shape.radiusY = shape.radius; + } + + /** + * We define a sine wave having 4 waves, and make sure at least 8 curves + * is drawn. Otherwise, it may cause blank area for some waves when + * wave length is large enough. + */ + var curves = Math.max( + Math.ceil(2 * shape.radius / shape.waveLength * 4) * 2, + 8 + ); + + // map phase to [-Math.PI * 2, 0] + while (shape.phase < -Math.PI * 2) { + shape.phase += Math.PI * 2; + } + while (shape.phase > 0) { + shape.phase -= Math.PI * 2; + } + var phase = shape.phase / Math.PI / 2 * shape.waveLength; + + var left = shape.cx - shape.radius + phase - shape.radius * 2; + + /** + * top-left corner as start point + * + * draws this point + * | + * \|/ + * ~~~~~~~~ + * | | + * +------+ + */ + ctx.moveTo(left, shape.waterLevel); + + /** + * top wave + * + * ~~~~~~~~ <- draws this sine wave + * | | + * +------+ + */ + var waveRight = 0; + for (var c = 0; c < curves; ++c) { + var stage = c % 4; + var pos = getWaterPositions(c * shape.waveLength / 4, stage, + shape.waveLength, shape.amplitude); + ctx.bezierCurveTo(pos[0][0] + left, -pos[0][1] + shape.waterLevel, + pos[1][0] + left, -pos[1][1] + shape.waterLevel, + pos[2][0] + left, -pos[2][1] + shape.waterLevel); + + if (c === curves - 1) { + waveRight = pos[2][0]; + } + } + + if (shape.inverse) { + /** + * top-right corner + * 2. draws this line + * | + * +------+ + * 3. draws this line -> | | <- 1. draws this line + * ~~~~~~~~ + */ + ctx.lineTo(waveRight + left, shape.cy - shape.radiusY); + ctx.lineTo(left, shape.cy - shape.radiusY); + ctx.lineTo(left, shape.waterLevel); + } + else { + /** + * top-right corner + * + * ~~~~~~~~ + * 3. draws this line -> | | <- 1. draws this line + * +------+ + * ^ + * | + * 2. draws this line + */ + ctx.lineTo(waveRight + left, shape.cy + shape.radiusY); + ctx.lineTo(left, shape.cy + shape.radiusY); + ctx.lineTo(left, shape.waterLevel); + } + + ctx.closePath(); + } +})); + + + +/** + * Using Bezier curves to fit sine wave. + * There is 4 control points for each curve of wave, + * which is at 1/4 wave length of the sine wave. + * + * The control points for a wave from (a) to (d) are a-b-c-d: + * c *----* d + * b * + * | + * ... a * .................. + * + * whose positions are a: (0, 0), b: (0.5, 0.5), c: (1, 1), d: (PI / 2, 1) + * + * @param {number} x x position of the left-most point (a) + * @param {number} stage 0-3, stating which part of the wave it is + * @param {number} waveLength wave length of the sine wave + * @param {number} amplitude wave amplitude + */ +function getWaterPositions(x, stage, waveLength, amplitude) { + if (stage === 0) { + return [ + [x + 1 / 2 * waveLength / Math.PI / 2, amplitude / 2], + [x + 1 / 2 * waveLength / Math.PI, amplitude], + [x + waveLength / 4, amplitude] + ]; + } + else if (stage === 1) { + return [ + [x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 2), + amplitude], + [x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 1), + amplitude / 2], + [x + waveLength / 4, 0] + ] + } + else if (stage === 2) { + return [ + [x + 1 / 2 * waveLength / Math.PI / 2, -amplitude / 2], + [x + 1 / 2 * waveLength / Math.PI, -amplitude], + [x + waveLength / 4, -amplitude] + ] + } + else { + return [ + [x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 2), + -amplitude], + [x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 1), + -amplitude / 2], + [x + waveLength / 4, 0] + ] + } +} + +;// CONCATENATED MODULE: ./src/liquidFillView.js + + + + +var liquidFillView_parsePercent = parsePercent; + +function isPathSymbol(symbol) { + return symbol && symbol.indexOf('path://') === 0 +} + +external_echarts_.extendChartView({ + + type: 'liquidFill', + + render: function (seriesModel, ecModel, api) { + var self = this; + var group = this.group; + group.removeAll(); + + var data = seriesModel.getData(); + + var itemModel = data.getItemModel(0); + + var center = itemModel.get('center'); + var radius = itemModel.get('radius'); + + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + // itemStyle + var outlineDistance = 0; + var outlineBorderWidth = 0; + var showOutline = seriesModel.get('outline.show'); + + if (showOutline) { + outlineDistance = seriesModel.get('outline.borderDistance'); + outlineBorderWidth = liquidFillView_parsePercent( + seriesModel.get('outline.itemStyle.borderWidth'), size + ); + } + + var cx = liquidFillView_parsePercent(center[0], width); + var cy = liquidFillView_parsePercent(center[1], height); + + var outterRadius; + var innerRadius; + var paddingRadius; + + var isFillContainer = false; + + var symbol = seriesModel.get('shape'); + if (symbol === 'container') { + // a shape that fully fills the container + isFillContainer = true; + + outterRadius = [ + width / 2, + height / 2 + ]; + innerRadius = [ + outterRadius[0] - outlineBorderWidth / 2, + outterRadius[1] - outlineBorderWidth / 2 + ]; + paddingRadius = [ + liquidFillView_parsePercent(outlineDistance, width), + liquidFillView_parsePercent(outlineDistance, height) + ]; + + radius = [ + Math.max(innerRadius[0] - paddingRadius[0], 0), + Math.max(innerRadius[1] - paddingRadius[1], 0) + ]; + } + else { + outterRadius = liquidFillView_parsePercent(radius, size) / 2; + innerRadius = outterRadius - outlineBorderWidth / 2; + paddingRadius = liquidFillView_parsePercent(outlineDistance, size); + + radius = Math.max(innerRadius - paddingRadius, 0); + } + + if (showOutline) { + var outline = getOutline(); + outline.style.lineWidth = outlineBorderWidth; + group.add(getOutline()); + } + + var left = isFillContainer ? 0 : cx - radius; + var top = isFillContainer ? 0 : cy - radius; + + var wavePath = null; + + group.add(getBackground()); + + // each data item for a wave + var oldData = this._data; + var waves = []; + data.diff(oldData) + .add(function (idx) { + var wave = getWave(idx, false); + + var waterLevel = wave.shape.waterLevel; + wave.shape.waterLevel = isFillContainer ? height / 2 : radius; + external_echarts_.graphic.initProps(wave, { + shape: { + waterLevel: waterLevel + } + }, seriesModel); + + wave.z2 = 2; + setWaveAnimation(idx, wave, null); + + group.add(wave); + data.setItemGraphicEl(idx, wave); + waves.push(wave); + }) + .update(function (newIdx, oldIdx) { + var waveElement = oldData.getItemGraphicEl(oldIdx); + + // new wave is used to calculate position, but not added + var newWave = getWave(newIdx, false, waveElement); + + // changes with animation + var shape = {}; + var shapeAttrs = ['amplitude', 'cx', 'cy', 'phase', 'radius', 'radiusY', 'waterLevel', 'waveLength']; + for (var i = 0; i < shapeAttrs.length; ++i) { + var attr = shapeAttrs[i]; + if (newWave.shape.hasOwnProperty(attr)) { + shape[attr] = newWave.shape[attr]; + } + } + + var style = {}; + var styleAttrs = ['fill', 'opacity', 'shadowBlur', 'shadowColor']; + for (var i = 0; i < styleAttrs.length; ++i) { + var attr = styleAttrs[i]; + if (newWave.style.hasOwnProperty(attr)) { + style[attr] = newWave.style[attr]; + } + } + + if (isFillContainer) { + shape.radiusY = height / 2; + } + + // changes with animation + external_echarts_.graphic.updateProps(waveElement, { + shape: shape, + x: newWave.x, + y: newWave.y + }, seriesModel); + + if (seriesModel.isUniversalTransitionEnabled && seriesModel.isUniversalTransitionEnabled()) { + external_echarts_.graphic.updateProps(waveElement, { + style: style + }, seriesModel); + } + else { + waveElement.useStyle(style); + } + + // instant changes + var oldWaveClipPath = waveElement.getClipPath(); + var newWaveClipPath = newWave.getClipPath(); + + waveElement.setClipPath(newWave.getClipPath()); + waveElement.shape.inverse = newWave.inverse; + + if (oldWaveClipPath && newWaveClipPath + && self._shape === symbol + // TODO use zrender morphing to apply complex symbol animation. + && !isPathSymbol(symbol) + ) { + // Can be animated. + external_echarts_.graphic.updateProps(newWaveClipPath, { + shape: oldWaveClipPath.shape + }, seriesModel, { isFrom: true }); + } + + setWaveAnimation(newIdx, waveElement, waveElement); + group.add(waveElement); + data.setItemGraphicEl(newIdx, waveElement); + waves.push(waveElement); + }) + .remove(function (idx) { + var wave = oldData.getItemGraphicEl(idx); + group.remove(wave); + }) + .execute(); + + if (itemModel.get('label.show')) { + group.add(getText(waves)); + } + + this._shape = symbol; + this._data = data; + + /** + * Get path for outline, background and clipping + * + * @param {number} r outter radius of shape + * @param {boolean|undefined} isForClipping if the shape is used + * for clipping + */ + function getPath(r, isForClipping) { + if (symbol) { + // customed symbol path + if (isPathSymbol(symbol)) { + var path = external_echarts_.graphic.makePath(symbol.slice(7), {}); + var bouding = path.getBoundingRect(); + var w = bouding.width; + var h = bouding.height; + if (w > h) { + h = r * 2 / w * h; + w = r * 2; + } + else { + w = r * 2 / h * w; + h = r * 2; + } + + var left = isForClipping ? 0 : cx - w / 2; + var top = isForClipping ? 0 : cy - h / 2; + path = external_echarts_.graphic.makePath( + symbol.slice(7), + {}, + new external_echarts_.graphic.BoundingRect(left, top, w, h) + ); + if (isForClipping) { + path.x = -w / 2; + path.y = -h / 2; + } + return path; + } + else if (isFillContainer) { + // fully fill the container + var x = isForClipping ? -r[0] : cx - r[0]; + var y = isForClipping ? -r[1] : cy - r[1]; + return external_echarts_.helper.createSymbol( + 'rect', x, y, r[0] * 2, r[1] * 2 + ); + } + else { + var x = isForClipping ? -r : cx - r; + var y = isForClipping ? -r : cy - r; + if (symbol === 'pin') { + y += r; + } + else if (symbol === 'arrow') { + y -= r; + } + return external_echarts_.helper.createSymbol(symbol, x, y, r * 2, r * 2); + } + } + + return new external_echarts_.graphic.Circle({ + shape: { + cx: isForClipping ? 0 : cx, + cy: isForClipping ? 0 : cy, + r: r + } + }); + } + /** + * Create outline + */ + function getOutline() { + var outlinePath = getPath(outterRadius); + outlinePath.style.fill = null; + + outlinePath.setStyle(seriesModel.getModel('outline.itemStyle') + .getItemStyle()); + + return outlinePath; + } + + /** + * Create background + */ + function getBackground() { + // Seperate stroke and fill, so we can use stroke to cover the alias of clipping. + var strokePath = getPath(radius); + strokePath.setStyle(seriesModel.getModel('backgroundStyle') + .getItemStyle()); + strokePath.style.fill = null; + + // Stroke is front of wave + strokePath.z2 = 5; + + var fillPath = getPath(radius); + fillPath.setStyle(seriesModel.getModel('backgroundStyle') + .getItemStyle()); + fillPath.style.stroke = null; + + var group = new external_echarts_.graphic.Group(); + group.add(strokePath); + group.add(fillPath); + + return group; + } + + /** + * wave shape + */ + function getWave(idx, isInverse, oldWave) { + var radiusX = isFillContainer ? radius[0] : radius; + var radiusY = isFillContainer ? height / 2 : radius; + + var itemModel = data.getItemModel(idx); + var itemStyleModel = itemModel.getModel('itemStyle'); + var phase = itemModel.get('phase'); + var amplitude = liquidFillView_parsePercent(itemModel.get('amplitude'), + radiusY * 2); + var waveLength = liquidFillView_parsePercent(itemModel.get('waveLength'), + radiusX * 2); + + var value = data.get('value', idx); + var waterLevel = radiusY - value * radiusY * 2; + phase = oldWave ? oldWave.shape.phase + : (phase === 'auto' ? idx * Math.PI / 4 : phase); + var normalStyle = itemStyleModel.getItemStyle(); + if (!normalStyle.fill) { + var seriesColor = seriesModel.get('color'); + var id = idx % seriesColor.length; + normalStyle.fill = seriesColor[id]; + } + + var x = radiusX * 2; + var wave = new liquidFillShape({ + shape: { + waveLength: waveLength, + radius: radiusX, + radiusY: radiusY, + cx: x, + cy: 0, + waterLevel: waterLevel, + amplitude: amplitude, + phase: phase, + inverse: isInverse + }, + style: normalStyle, + x: cx, + y: cy, + }); + wave.shape._waterLevel = waterLevel; + + var hoverStyle = itemModel.getModel('emphasis.itemStyle') + .getItemStyle(); + hoverStyle.lineWidth = 0; + + wave.ensureState('emphasis').style = hoverStyle; + external_echarts_.helper.enableHoverEmphasis(wave); + + // clip out the part outside the circle + var clip = getPath(radius, true); + // set fill for clipPath, otherwise it will not trigger hover event + clip.setStyle({ + fill: 'white' + }); + wave.setClipPath(clip); + + return wave; + } + + function setWaveAnimation(idx, wave, oldWave) { + var itemModel = data.getItemModel(idx); + + var maxSpeed = itemModel.get('period'); + var direction = itemModel.get('direction'); + + var value = data.get('value', idx); + + var phase = itemModel.get('phase'); + phase = oldWave ? oldWave.shape.phase + : (phase === 'auto' ? idx * Math.PI / 4 : phase); + + var defaultSpeed = function (maxSpeed) { + var cnt = data.count(); + return cnt === 0 ? maxSpeed : maxSpeed * + (0.2 + (cnt - idx) / cnt * 0.8); + }; + var speed = 0; + if (maxSpeed === 'auto') { + speed = defaultSpeed(5000); + } + else { + speed = typeof maxSpeed === 'function' + ? maxSpeed(value, idx) : maxSpeed; + } + + // phase for moving left/right + var phaseOffset = 0; + if (direction === 'right' || direction == null) { + phaseOffset = Math.PI; + } + else if (direction === 'left') { + phaseOffset = -Math.PI; + } + else if (direction === 'none') { + phaseOffset = 0; + } + else { + console.error('Illegal direction value for liquid fill.'); + } + + // wave animation of moving left/right + if (direction !== 'none' && itemModel.get('waveAnimation')) { + wave + .animate('shape', true) + .when(0, { + phase: phase + }) + .when(speed / 2, { + phase: phaseOffset + phase + }) + .when(speed, { + phase: phaseOffset * 2 + phase + }) + .during(function () { + if (wavePath) { + wavePath.dirty(true); + } + }) + .start(); + } + } + + /** + * text on wave + */ + function getText(waves) { + var labelModel = itemModel.getModel('label'); + + function formatLabel() { + var formatted = seriesModel.getFormattedLabel(0, 'normal'); + var defaultVal = (data.get('value', 0) * 100); + var defaultLabel = data.getName(0) || seriesModel.name; + if (!isNaN(defaultVal)) { + defaultLabel = defaultVal.toFixed(0) + '%'; + } + return formatted == null ? defaultLabel : formatted; + } + + var textRectOption = { + z2: 10, + shape: { + x: left, + y: top, + width: (isFillContainer ? radius[0] : radius) * 2, + height: (isFillContainer ? radius[1] : radius) * 2 + }, + style: { + fill: 'transparent' + }, + textConfig: { + position: labelModel.get('position') || 'inside' + }, + silent: true + }; + var textOption = { + style: { + text: formatLabel(), + textAlign: labelModel.get('align'), + textVerticalAlign: labelModel.get('baseline') + } + }; + Object.assign(textOption.style, external_echarts_.helper.createTextStyle(labelModel)); + + var outsideTextRect = new external_echarts_.graphic.Rect(textRectOption); + var insideTextRect = new external_echarts_.graphic.Rect(textRectOption); + insideTextRect.disableLabelAnimation = true; + outsideTextRect.disableLabelAnimation = true; + + var outsideText = new external_echarts_.graphic.Text(textOption); + var insideText = new external_echarts_.graphic.Text(textOption); + outsideTextRect.setTextContent(outsideText); + + insideTextRect.setTextContent(insideText); + var insColor = labelModel.get('insideColor'); + insideText.style.fill = insColor; + + var group = new external_echarts_.graphic.Group(); + group.add(outsideTextRect); + group.add(insideTextRect); + + // clip out waves for insideText + var boundingCircle = getPath(radius, true); + + wavePath = new external_echarts_.graphic.CompoundPath({ + shape: { + paths: waves + }, + x: cx, + y: cy + }); + + wavePath.setClipPath(boundingCircle); + insideTextRect.setClipPath(wavePath); + + return group; + } + }, + + dispose: function () { + // dispose nothing here + } +}); + +;// CONCATENATED MODULE: ./src/liquidFill.js + + +;// CONCATENATED MODULE: ./index.js + + + +/***/ }), + +/***/ "echarts/lib/echarts": +/*!**************************!*\ + !*** external "echarts" ***! + \**************************/ +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_MODULE_echarts_lib_echarts__; + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ if(__webpack_module_cache__[moduleId]) { +/******/ return __webpack_module_cache__[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +/******/ // module exports must be returned from runtime so entry inlining is disabled +/******/ // startup +/******/ // Load entry module and return exports +/******/ return __webpack_require__("./index.js"); +/******/ })() +; +}); +//# sourceMappingURL=echarts-liquidfill.js.map \ No newline at end of file diff --git a/components/screen/Chart/index.js b/components/screen/Chart/index.js new file mode 100644 index 0000000..064b0dc --- /dev/null +++ b/components/screen/Chart/index.js @@ -0,0 +1,38 @@ +import React, {useRef, useEffect, useImperativeHandle} from "react"; +import * as echarts from "echarts"; +import theme from "./theme.json"; +import './echarts-liquidfill' +// import('echarts-liquidfill'); + +echarts.registerTheme("darkBlue", theme); + +export default React.forwardRef(({option}, ref) => { + const chartRef = useRef(null); + const chart = useRef(); + + useEffect(() => { + chart.current = echarts.init(chartRef.current, "darkBlue"); + let resize = () => { + chart.current.resize(); + }; + window.addEventListener("resize", () => resize()); + return window.removeEventListener("resize", () => resize()); + }, []); + + useEffect(() => { + if (chart && option) { + // console.log("chart",chart) + chart.current.setOption(option); + } + }); + + useImperativeHandle(ref, () => ({ + setOption: (opt) => { + // chart.current.setOption(Object.assign(opt, option)); + chart.current.setOption(opt); + }, + getChart: () => chart.current, + })); + + return
; +}); diff --git a/components/screen/Chart/theme.json b/components/screen/Chart/theme.json new file mode 100644 index 0000000..9d8da9a --- /dev/null +++ b/components/screen/Chart/theme.json @@ -0,0 +1,440 @@ +{ + "color": [ + "#28a3ff", + "#ffc760", + "#6fe621", + "#f95757", + "#54c4f1", + "#fc8452", + "#9a60b4", + "#ea7ccc", + "#7289ab", + "#91ca8c", + "#f49f42" + ], + "backgroundColor": "rgba(4,20,87,0)", + "textStyle": {}, + "xAxis": { + "nameGap": 5 + }, + "yAxis": { + "nameGap": 5 + }, + "title": { + "textStyle": { + "color": "#eeeeee" + }, + "subtextStyle": { + "color": "#aaaaaa" + } + }, + "grid": { + "top": 30, + "left": 30, + "bottom": 30, + "right": 30 + }, + "line": { + "itemStyle": { + "borderWidth": 1 + }, + "lineStyle": { + "width": 2 + }, + "symbolSize": 10, + "symbol": "circle", + "smooth": false + }, + "radar": { + "itemStyle": { + "borderWidth": 1 + }, + "lineStyle": { + "width": 2 + }, + "symbolSize": 4, + "symbol": "circle", + "smooth": false + }, + "bar": { + "itemStyle": { + "barBorderWidth": 0, + "barBorderColor": "#ccc" + } + }, + "pie": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "scatter": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "boxplot": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "parallel": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "sankey": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "funnel": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "gauge": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "candlestick": { + "itemStyle": { + "color": "#fd1050", + "color0": "#0cf49b", + "borderColor": "#fd1050", + "borderColor0": "#0cf49b", + "borderWidth": 1 + } + }, + "graph": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "lineStyle": { + "width": 1, + "color": "#aaaaaa" + }, + "symbolSize": 4, + "symbol": "circle", + "smooth": false, + "color": [ + "#dd6b66", + "#759aa0", + "#e69d87", + "#8dc1a9", + "#ea7e53", + "#eedd78", + "#73a373", + "#73b9bc", + "#7289ab", + "#91ca8c", + "#f49f42" + ], + "label": { + "color": "#eeeeee" + } + }, + "map": { + "itemStyle": { + "normal": { + "areaColor": "#eee", + "borderColor": "#444", + "borderWidth": 0.5 + }, + "emphasis": { + "areaColor": "rgba(255,215,0,0.8)", + "borderColor": "#444", + "borderWidth": 1 + } + }, + "label": { + "normal": { + "textStyle": { + "color": "#000" + } + }, + "emphasis": { + "textStyle": { + "color": "rgb(100,0,0)" + } + } + } + }, + "geo": { + "itemStyle": { + "normal": { + "areaColor": "#eee", + "borderColor": "#444", + "borderWidth": 0.5 + }, + "emphasis": { + "areaColor": "rgba(255,215,0,0.8)", + "borderColor": "#444", + "borderWidth": 1 + } + }, + "label": { + "normal": { + "textStyle": { + "color": "#000" + } + }, + "emphasis": { + "textStyle": { + "color": "rgb(100,0,0)" + } + } + } + }, + "categoryAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#eeeeee" + } + }, + "axisTick": { + "show": true, + "lineStyle": { + "color": "#eeeeee" + } + }, + "axisLabel": { + "show": true, + "textStyle": { + "color": "#eeeeee" + } + }, + "splitLine": { + "show": false, + "lineStyle": { + "color": [ + "#aaaaaa" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "#eeeeee" + ] + } + } + }, + "valueAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#eeeeee" + } + }, + "axisTick": { + "show": true, + "lineStyle": { + "color": "#eeeeee" + } + }, + "axisLabel": { + "show": true, + "textStyle": { + "color": "#eeeeee" + } + }, + "splitLine": { + "show": false, + "lineStyle": { + "color": [ + "#aaaaaa" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "#eeeeee" + ] + } + } + }, + "logAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#eeeeee" + } + }, + "axisTick": { + "show": true, + "lineStyle": { + "color": "#eeeeee" + } + }, + "axisLabel": { + "show": true, + "textStyle": { + "color": "#eeeeee" + } + }, + "splitLine": { + "show": false, + "lineStyle": { + "color": [ + "#aaaaaa" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "#eeeeee" + ] + } + } + }, + "timeAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#eeeeee" + } + }, + "axisTick": { + "show": true, + "lineStyle": { + "color": "#eeeeee" + } + }, + "axisLabel": { + "show": true, + "textStyle": { + "color": "#eeeeee" + } + }, + "splitLine": { + "show": false, + "lineStyle": { + "color": [ + "#aaaaaa" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "#eeeeee" + ] + } + } + }, + "toolbox": { + "iconStyle": { + "normal": { + "borderColor": "rgba(153,153,153,1)" + }, + "emphasis": { + "borderColor": "rgba(102,102,102,1)" + } + } + }, + "legend": { + "show": true, + "left": "center", + "textStyle": { + "color": "#eeeeee" + } + }, + "tooltip": { + "axisPointer": { + "lineStyle": { + "color": "rgba(238,238,238,1)", + "width": "1" + }, + "crossStyle": { + "color": "rgba(238,238,238,1)", + "width": "1" + } + } + }, + "timeline": { + "lineStyle": { + "color": "#eeeeee", + "width": 1 + }, + "itemStyle": { + "normal": { + "color": "#dd6b66", + "borderWidth": 1 + }, + "emphasis": { + "color": "#a9334c" + } + }, + "controlStyle": { + "normal": { + "color": "#eeeeee", + "borderColor": "#eeeeee", + "borderWidth": 0.5 + }, + "emphasis": { + "color": "#eeeeee", + "borderColor": "#eeeeee", + "borderWidth": 0.5 + } + }, + "checkpointStyle": { + "color": "#e43c59", + "borderColor": "#c23531" + }, + "label": { + "normal": { + "textStyle": { + "color": "#eeeeee" + } + }, + "emphasis": { + "textStyle": { + "color": "#eeeeee" + } + } + } + }, + "visualMap": { + "color": [ + "#bf444c", + "#d88273", + "#f6efa6" + ] + }, + "dataZoom": { + "backgroundColor": "rgba(47,69,84,0)", + "dataBackgroundColor": "rgba(255,255,255,0.3)", + "fillerColor": "rgba(167,183,204,0.4)", + "handleColor": "#a7b7cc", + "handleSize": "100%", + "textStyle": { + "color": "#eeeeee" + } + }, + "markPoint": { + "label": { + "color": "#eeeeee" + }, + "emphasis": { + "label": { + "color": "#eeeeee" + } + } + } +} \ No newline at end of file diff --git a/components/screen/CircleProcess/index.js b/components/screen/CircleProcess/index.js new file mode 100644 index 0000000..4e0fb33 --- /dev/null +++ b/components/screen/CircleProcess/index.js @@ -0,0 +1,162 @@ +import React, { useRef, useEffect, useState, useMemo } from 'react' + +const imgHeight = 951; //图片原始高度 +const imgWidth = 184; //图片原始高度 +const circleBorder = 2; //圆环的宽度 +const baseSize = 170;//满状态宽度 +const itemHeight = 370; //单个高度(包含空白) +const waveHeight = 29; //波浪高度 +const colors = ["#8ee34d", "#f6c971", "#ea335d"]; //圆边框颜色 +const colorIndexTrans = [2, 1, 0]; //调换第一个和最后一个位置 + +function CircleProcess(props) { + const sizeRef = useRef(); + const outerRef = useRef(); + const innerRef = useRef(); + const [scale, setScale] = useState(1) + const [innerWidth, setInnerWidth] = useState(0) + + //接受外部参数 + let { percent:realPercent = 0.5, percentRule = [0, 0.8, 0.95], size = 0.9 } = props; + + const percent = useMemo(() => { + return realPercent > 1 ? 1 : realPercent + }, [realPercent]) + + //颜色的下标 + const colorIndex = useMemo(() => { + let res = 0; + percentRule.forEach((val, index) => { + if (percent > val) res = index; + }) + return colorIndexTrans[res]; + }, [percentRule, percent]) + + //颜色的位置 + const positionY = useMemo(() => { + return -(-innerWidth + percent * innerWidth + waveHeight * scale + colorIndex * scale * itemHeight) + }, [innerWidth, percent, scale, colorIndex]) + + //计算组件宽度以及比例 + const tableSetting = () => { + //组件实际宽度 + let comWidth = sizeRef.current.clientWidth; + outerRef.current.style.height = comWidth * size + 'px'; + outerRef.current.style.width = comWidth * size + 'px'; + //波浪实际宽度 + let innerWidth = innerRef.current.clientWidth; + setInnerWidth(innerWidth); + //计算比例 + setScale(innerWidth / baseSize); + } + + useEffect(() => { + //监听父级宽度变化 + let innerWindow = sizeRef.current.contentDocument.defaultView; + innerWindow.addEventListener("resize", tableSetting); + tableSetting(); + return () => { + innerWindow.removeEventListener("resize", tableSetting); + } + }, []) + + return ( +
+