From ea2904d7ca03b42f5783cd659fe71c0fbedd2277 Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期一, 11 八月 2025 17:05:21 +0800 Subject: [PATCH] Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop --- rsf-admin/src/page/dashboard/welcome_illustration.svg | 1 rsf-admin/src/page/orders/wave/WaveList.jsx | 1 rsf-admin/src/page/dashboard/Welcome.jsx | 90 +++ rsf-admin/package.json | 5 rsf-admin/src/page/basicInfo/matnr/MatnrCreate.jsx | 387 ++++++++-------- rsf-admin/src/page/statistics/outStockNum/OutStockNumList.jsx | 10 rsf-admin/src/page/dashboard/NbChart.jsx | 117 +++++ rsf-admin/src/page/dashboard/NbList.jsx | 79 +++ rsf-admin/src/page/components/CardWithIcon.jsx | 60 ++ rsf-admin/src/page/dashboard/NbCard.jsx | 107 ++++ rsf-admin/src/page/statistics/stockStatisticNum/stockStatisticList.jsx | 24 rsf-admin/src/i18n/zh.js | 7 rsf-admin/package-lock.json | 284 ++++++++++++ rsf-admin/src/i18n/en.js | 5 rsf-admin/src/page/dashboard/index.jsx | 168 +++++++ rsf-admin/src/page/orders/wave/WavePanel.jsx | 4 16 files changed, 1,123 insertions(+), 226 deletions(-) diff --git a/rsf-admin/package-lock.json b/rsf-admin/package-lock.json index 2ccac71..fef3d13 100644 --- a/rsf-admin/package-lock.json +++ b/rsf-admin/package-lock.json @@ -39,6 +39,7 @@ "react-router-dom": "^6.26.1", "react-syntax-highlighter": "^15.5.0", "react-to-print": "^2.14.11", + "recharts": "^2.15.0", "svgpath": "^2.6.0", "three": "^0.155.0", "tweedle.js": "^2.1.0" @@ -2539,6 +2540,69 @@ "integrity": "sha512-x2tZZYkSxXqWvTDgveSynfjq/T2HyiZHXb00j/+gy19yp70PHCizM48XFdjBCWH7eHBD0R5i/pw9yMBP/BH5uA==", "license": "MIT" }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, "node_modules/@types/earcut": { "version": "2.1.4", "resolved": "https://registry.npmmirror.com/@types/earcut/-/earcut-2.1.4.tgz", @@ -3498,6 +3562,127 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -3584,6 +3769,12 @@ "optional": true } } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" }, "node_modules/decode-uri-component": { "version": "0.2.2", @@ -4241,6 +4432,15 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", + "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } }, "node_modules/fast-glob": { "version": "3.3.3", @@ -4939,6 +5139,15 @@ }, "engines": { "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" } }, "node_modules/is-alphabetical": { @@ -6607,6 +6816,21 @@ "react-dom": ">=16.8" } }, + "node_modules/react-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react-syntax-highlighter": { "version": "15.6.1", "resolved": "https://registry.npmmirror.com/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz", @@ -6652,6 +6876,44 @@ "react": ">=16.6.0", "react-dom": ">=16.6.0" } + }, + "node_modules/recharts": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", + "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.4", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" }, "node_modules/redux": { "version": "4.2.1", @@ -7591,6 +7853,28 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "node_modules/vite": { "version": "5.4.19", "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.19.tgz", diff --git a/rsf-admin/package.json b/rsf-admin/package.json index 4e1d8b2..4cc1046 100644 --- a/rsf-admin/package.json +++ b/rsf-admin/package.json @@ -45,7 +45,8 @@ "react-to-print": "^2.14.11", "svgpath": "^2.6.0", "three": "^0.155.0", - "tweedle.js": "^2.1.0" + "tweedle.js": "^2.1.0", + "recharts": "^2.15.0" }, "devDependencies": { "@types/node": "^20.10.7", @@ -63,4 +64,4 @@ "vite": "^5.3.5" }, "name": "rsf" -} +} \ No newline at end of file diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js index 501e315..33a5693 100644 --- a/rsf-admin/src/i18n/en.js +++ b/rsf-admin/src/i18n/en.js @@ -1207,6 +1207,11 @@ } }, page: { + dashboard: { + welcome: { + title: 'Welcome to the WMS website', + }, + }, welcome: { index: ' Welcome to the RSF Management System.', tech: ' Technology stack: Java 17, SpringBoot2.5.3, Mybatis-plus_3.4.1, Spring Security, Druid 1.2.6, Redis, Mysql5.7, Node18, ReactJs, Material UI5.16, Axios, React-Admin5.1' diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js index 320d013..2046fac 100644 --- a/rsf-admin/src/i18n/zh.js +++ b/rsf-admin/src/i18n/zh.js @@ -223,7 +223,7 @@ locDeadReport: '搴撳瓨鍋滄粸鎶ヨ〃', stockStatistic: '鏃ュ叆搴撴眹鎬绘煡璇�', outStatistic: '鏃ュ嚭搴撴眹鎬绘煡璇�', - inStatistic: '鏃ュ叆搴撴眹鎬绘煡璇�', + inStatistic: '鏃ュ叆搴撴眹鎬绘煡璇�', inStatisticItem: '鏃ュ叆搴撴槑缁嗘煡璇�', outStatisticItem: '鏃ュ嚭搴撴槑缁嗘煡璇�', statisticCount: '鏃ュ嚭鍏ュ簱姹囨�荤粺璁�', @@ -1219,6 +1219,11 @@ } }, page: { + dashboard: { + welcome: { + title: '娆㈣繋浣跨敤 WMS 绯荤粺', + }, + }, welcome: { index: ' 娆㈣繋浣跨敤RSF绠$悊绯荤粺', tech: ' 鎶�鏈爤: Java17, SpringBoot2.5.3, Mybatis-plus_3.4.1, Spring Security, Druid 1.2.6, Redis, Mysql5.7, Node18, ReactJs, Material UI5.16, Axios, React-Admin5.1' diff --git a/rsf-admin/src/page/basicInfo/matnr/MatnrCreate.jsx b/rsf-admin/src/page/basicInfo/matnr/MatnrCreate.jsx index e838adf..f62588a 100644 --- a/rsf-admin/src/page/basicInfo/matnr/MatnrCreate.jsx +++ b/rsf-admin/src/page/basicInfo/matnr/MatnrCreate.jsx @@ -127,7 +127,7 @@ aria-labelledby="form-dialog-title" fullWidth disableRestoreFocus - maxWidth="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' + maxWidth="xl" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' > <Form > <DialogTitle id="form-dialog-title" sx={{ @@ -150,150 +150,159 @@ </Tabs> <CustomTabPanel value={value} index={0}> <Grid container rowSpacing={2} columnSpacing={2}> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.name" - validate={[required()]} - source="name" - parse={v => v} - autoFocus - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.code" - validate={[required()]} - source="code" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <ReferenceInput source="shipperId" reference="companys" filter={{ type: 'shipper' }}> - <AutocompleteInput - label="table.field.matnr.shipperId" - optionText="name" - filterToQuery={(val) => ({ name: val })} + <Grid item xs={12} display="flex" gap={1}> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.name" + validate={[required()]} + source="name" + parse={v => v} + autoFocus /> - </ReferenceInput> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TreeSelectInput - label="table.field.matnr.groupId" - resource={'matnrGroup'} - source="groupId" - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.platCode" - source="platCode" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.spec" - source="spec" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.model" - source="model" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <NumberInput - label="table.field.matnr.weight" - source="weight" - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.color" - source="color" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.size" - source="size" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.describle" - source="describle" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <NumberInput - label="table.field.matnr.nromNum" - source="nromNum" - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.unit" - source="unit" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.purUnit" - source="purchaseUnit" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <TextInput - label="table.field.matnr.stockUnit" - source="stockUnit" - parse={v => v} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <SelectInput - label="table.field.matnr.stockLevel" - source="stockLevel" - choices={[ - { id: 0, name: ' A' }, - { id: 1, name: ' B' }, - { id: 2, name: 'C' }, - ]} - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <SelectInput - label="table.field.matnr.isLabelMange" - source="flagLabelMange" - choices={[ - { id: 0, name: ' 鍚�' }, - { id: 1, name: ' 鏄�' }, - ]} - /> - </Grid> - - {dynamicFields.map((item) => { - return ( - <Grid key={item.id} item xs={6} display="flex" gap={1}> - <TextInput - label={item.fieldsAlise} - source={item.fields} - validate={item.unique === 1 ? required() : false} + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.code" + validate={[required()]} + source="code" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <ReferenceInput source="shipperId" reference="companys" filter={{ type: 'shipper' }}> + <AutocompleteInput + label="table.field.matnr.shipperId" + optionText="name" + filterToQuery={(val) => ({ name: val })} /> - </Grid> - ) - })} + </ReferenceInput> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TreeSelectInput + label="table.field.matnr.groupId" + resource={'matnrGroup'} + source="groupId" + /> + </Grid> + </Grid> + <Grid item xs={12} display="flex" gap={1}> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.platCode" + source="platCode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.spec" + source="spec" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.model" + source="model" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.matnr.weight" + source="weight" + /> + </Grid> + </Grid> + <Grid item xs={12} display="flex" gap={1}> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.color" + source="color" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.size" + source="size" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.describle" + source="describle" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.matnr.nromNum" + source="nromNum" + /> + </Grid> + </Grid> + <Grid item xs={12} display="flex" gap={1}> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.unit" + source="unit" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.purUnit" + source="purchaseUnit" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.matnr.stockUnit" + source="stockUnit" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <SelectInput + label="table.field.matnr.stockLevel" + source="stockLevel" + choices={[ + { id: 0, name: ' A' }, + { id: 1, name: ' B' }, + { id: 2, name: 'C' }, + ]} + /> + </Grid> + </Grid> + <Grid item xs={12} display="flex" gap={1}> + <Grid item xs={6} display="flex" gap={1}> + <SelectInput + label="table.field.matnr.isLabelMange" + source="flagLabelMange" + choices={[ + { id: 0, name: ' 鍚�' }, + { id: 1, name: ' 鏄�' }, + ]} + /> + </Grid> - <Grid item xs={6} display="flex" gap={1}> - <StatusSelectInput /> + {dynamicFields.map((item) => { + return ( + <Grid key={item.id} item xs={6} display="flex" gap={1}> + <TextInput + label={item.fieldsAlise} + source={item.fields} + validate={item.unique === 1 ? required() : false} + /> + </Grid> + ) + })} + <Grid item xs={6} display="flex" gap={1}> + <StatusSelectInput /> + </Grid> </Grid> <Grid item xs={12} display="flex" gap={1}> <Stack direction="column" spacing={1} width={'100%'}> @@ -304,51 +313,57 @@ </CustomTabPanel> <CustomTabPanel value={value} index={1}> <Grid container rowSpacing={2} columnSpacing={2}> - <Grid item xs={6} display="flex" gap={1}> - <NumberInput - label="table.field.matnr.safeQty" - source="safeQty" - /> + <Grid item xs={12} display="flex" gap={1}> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.matnr.safeQty" + source="safeQty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.matnr.minQty" + source="minQty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.matnr.maxQty" + source="maxQty" + /> + </Grid> </Grid> - <Grid item xs={6} display="flex" gap={1}> - <NumberInput - label="table.field.matnr.minQty" - source="minQty" - /> + <Grid item xs={12} display="flex" gap={1}> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.matnr.stagn" + source="stagn" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.matnr.valid" + source="valid" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.matnr.validWarn" + source="validWarn" + /> + </Grid> </Grid> - <Grid item xs={6} display="flex" gap={1}> - <NumberInput - label="table.field.matnr.maxQty" - source="maxQty" - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <NumberInput - label="table.field.matnr.stagn" - source="stagn" - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <NumberInput - label="table.field.matnr.valid" - source="valid" - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <NumberInput - label="table.field.matnr.validWarn" - source="validWarn" - /> - </Grid> - <Grid item xs={6} display="flex" gap={1}> - <SelectInput - label="table.field.matnr.flagCheck" - source="flagCheck" - choices={[ - { id: 0, name: ' 鍚�' }, - { id: 1, name: ' 鏄�' }, - ]} - /> + <Grid item xs={12} display="flex" gap={1}> + <Grid item xs={4} display="flex" gap={1}> + <SelectInput + label="table.field.matnr.flagCheck" + source="flagCheck" + choices={[ + { id: 0, name: ' 鍚�' }, + { id: 1, name: ' 鏄�' }, + ]} + /> + </Grid> </Grid> </Grid> </CustomTabPanel> @@ -370,7 +385,7 @@ </CustomTabPanel> </DialogContent> <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> - <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} > + <Toolbar sx={{ width: '100%', justifyContent: 'flex-end' }} > <SaveButton /> </Toolbar> </DialogActions> diff --git a/rsf-admin/src/page/components/CardWithIcon.jsx b/rsf-admin/src/page/components/CardWithIcon.jsx new file mode 100644 index 0000000..606911e --- /dev/null +++ b/rsf-admin/src/page/components/CardWithIcon.jsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { FC, createElement } from 'react'; +import { Card, Box, Typography, Divider } from '@mui/material'; +import { Link } from 'react-router-dom'; + +const CardWithIcon = ({ icon, title, subtitle, to, children }) => ( + <Card + sx={{ + minHeight: 52, + display: 'flex', + flexDirection: 'column', + flex: '1', + '& a': { + textDecoration: 'none', + color: 'inherit', + }, + }} + > + <Box + sx={{ + position: 'relative', + overflow: 'hidden', + padding: '16px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + '& .icon': { + color: 'primary.main', + }, + '&:before': { + position: 'absolute', + top: '50%', + left: 0, + display: 'block', + content: `''`, + height: '200%', + aspectRatio: '1', + transform: 'translate(-30%, -60%)', + borderRadius: '50%', + backgroundColor: 'primary.main', + opacity: 0.15, + }, + }} + > + <Box width="3em" className="icon"> + {createElement(icon, { fontSize: 'large' })} + </Box> + <Box textAlign="right"> + <Typography color="textSecondary">{title}</Typography> + <Typography variant="h5" component="h2"> + {subtitle || '鈥�'} + </Typography> + </Box> + </Box> + {children && <Divider />} + {children} + </Card> +); + +export default CardWithIcon; \ No newline at end of file diff --git a/rsf-admin/src/page/dashboard/NbCard.jsx b/rsf-admin/src/page/dashboard/NbCard.jsx new file mode 100644 index 0000000..eb22c20 --- /dev/null +++ b/rsf-admin/src/page/dashboard/NbCard.jsx @@ -0,0 +1,107 @@ +import * as React from 'react'; +import { + Avatar, + Box, + Button, + List, + ListItem, + ListItemAvatar, + ListItemButton, + ListItemText, +} from '@mui/material'; +import CommentIcon from '@mui/icons-material/Comment'; +import { Link } from 'react-router-dom'; +import { + ReferenceField, + FunctionField, + useGetList, + useTranslate, + useIsDataLoaded, +} from 'react-admin'; +import CardWithIcon from '../components/CardWithIcon'; + +const NbCard = (props) => { + const { list, ...rest } = props; + const translate = useTranslate(); + const { + data: reviews, + total, + isPending, + } = useGetList('reviews', { + filter: { status: 'pending' }, + sort: { field: 'date', order: 'DESC' }, + pagination: { page: 1, perPage: 100 }, + }); + + const display = 'display'; + const newList = list.concat(list); + + return ( + <CardWithIcon + icon={CommentIcon} + title={translate('pos.dashboard.pending_reviews')} + subtitle={total} + {...rest} + > + <List sx={{ display }}> + {newList?.map((record) => ( + <ListItem key={record.id} disablePadding> + <ListItemButton + alignItems="flex-start" + component={Link} + to={`/task/${record.id}`} + > + {/* <ListItemAvatar> + <Avatar + sx={{ + // bgcolor: 'primary.main', + bgcolor: '#a2beeaff', + color: 'primary.contrastText', // 閬垮厤鐧藉瓧鐧藉簳 + // width: 40, + // height: 40, + // fontSize: 16, + }} + > + {record.id} + </Avatar> + </ListItemAvatar> */} + + <ListItemText + // primary={ + // <StarRatingField + // record={record} + // source="rating" + // /> + // } + primary={record.date + record.date} + secondary={record.total} + sx={{ + overflowY: 'hidden', + height: '3em', + display: '-webkit-box', + WebkitLineClamp: 2, + WebkitBoxOrient: 'vertical', + paddingRight: 0, + }} + /> + </ListItemButton> + </ListItem> + ))} + </List> + <Box flexGrow={1}> </Box> + <Button + sx={{ borderRadius: 0 }} + component={Link} + to="/task" + size="small" + color="primary" + > + <Box p={1} sx={{ color: 'primary.main' }}> + {translate('pos.dashboard.all_reviews')} + </Box> + </Button> + </CardWithIcon> + ); +}; + +export default NbCard; diff --git a/rsf-admin/src/page/dashboard/NbChart.jsx b/rsf-admin/src/page/dashboard/NbChart.jsx new file mode 100644 index 0000000..a0b6373 --- /dev/null +++ b/rsf-admin/src/page/dashboard/NbChart.jsx @@ -0,0 +1,117 @@ +import * as React from 'react'; +import { Card, CardHeader, CardContent } from '@mui/material'; +import { + ResponsiveContainer, + AreaChart, + Area, + XAxis, + YAxis, + CartesianGrid, + Tooltip, +} from 'recharts'; +import { useTranslate } from 'react-admin'; +import { format, subDays, addDays } from 'date-fns'; + +const lastDay = new Date(); +const lastMonthDays = Array.from({ length: 30 }, (_, i) => subDays(lastDay, i)); +const aMonthAgo = subDays(new Date(), 30); + +const dateFormatter = (date) => + new Date(date).toLocaleDateString(); + +const aggregateOrdersByDay = (orders) => + orders + .filter((order) => order.status !== 'cancelled') + .reduce( + (acc, curr) => { + const day = format(curr.date, 'yyyy-MM-dd'); + if (!acc[day]) { + acc[day] = 0; + } + acc[day] += curr.total; + return acc; + }, + {} + ); + +const getRevenuePerDay = (orders) => { + const daysWithRevenue = aggregateOrdersByDay(orders); + return lastMonthDays.map(date => ({ + date: date.getTime(), + total: daysWithRevenue[format(date, 'yyyy-MM-dd')] || 0, + })); +}; + +const NbChart = (props) => { + const { orders } = props; + const translate = useTranslate(); + if (!orders) return null; + + return ( + <Card> + <CardHeader title={translate('pos.dashboard.month_history')} /> + <CardContent> + <div style={{ width: '100%', height: 300 }}> + <ResponsiveContainer> + <AreaChart data={getRevenuePerDay(orders)}> + <defs> + <linearGradient + id="colorUv" + x1="0" + y1="0" + x2="0" + y2="1" + > + <stop + offset="5%" + stopColor="#5091abff" + stopOpacity={0.8} + /> + <stop + offset="95%" + stopColor="#5091abff" + stopOpacity={0} + /> + </linearGradient> + </defs> + <XAxis + dataKey="date" + name="Date" + type="number" + scale="time" + domain={[ + addDays(aMonthAgo, 1).getTime(), + new Date().getTime(), + ]} + tickFormatter={dateFormatter} + /> + <YAxis dataKey="total" name="Revenue" unit="鈧�" /> + <CartesianGrid strokeDasharray="3 3" /> + <Tooltip + cursor={{ strokeDasharray: '3 3' }} + formatter={(value) => + new Intl.NumberFormat(undefined, { + style: 'currency', + currency: 'USD', + }).format(value) + } + labelFormatter={(label) => + dateFormatter(label) + } + /> + <Area + type="monotone" + dataKey="total" + stroke="#5091abff" + strokeWidth={2} + fill="url(#colorUv)" + /> + </AreaChart> + </ResponsiveContainer> + </div> + </CardContent> + </Card> + ); +}; + +export default NbChart; diff --git a/rsf-admin/src/page/dashboard/NbList.jsx b/rsf-admin/src/page/dashboard/NbList.jsx new file mode 100644 index 0000000..9bb7024 --- /dev/null +++ b/rsf-admin/src/page/dashboard/NbList.jsx @@ -0,0 +1,79 @@ +import * as React from 'react'; +import { useTranslate, useReference } from 'react-admin'; +import { + ListItem, + ListItemSecondaryAction, + ListItemAvatar, + ListItemText, + Avatar, + Box, + ListItemButton, + Card, + CardHeader, + List, +} from '@mui/material'; +import { Link } from 'react-router-dom'; + +const NbList = (props) => { + const { orders = [] } = props; + const translate = useTranslate(); + + return ( + <Card sx={{ flex: 1 }}> + <CardHeader title={translate('pos.dashboard.pending_orders')} /> + <List dense={true}> + {orders.map(record => ( + <PendingOrder key={record.id} order={record} /> + ))} + </List> + </Card> + ); +}; + +export const PendingOrder = (props) => { + const { order } = props; + console.log(order); + + const translate = useTranslate(); + const { referenceRecord: customer, isPending } = useReference({ + reference: 'customers', + id: order.customer_id, + }); + + return ( + <ListItem disablePadding> + <ListItemButton component={Link} to={`/orders/${order.id}`}> + {/* <ListItemAvatar> + {isPending ? ( + <Avatar /> + ) : ( + <Avatar + src={`${customer?.avatar}?size=32x32`} + sx={{ bgcolor: 'background.paper' }} + alt={`${customer?.first_name} ${customer?.last_name}`} + /> + )} + </ListItemAvatar> */} + <ListItemText + primary={new Date(order.date).toLocaleString('en-GB')} + secondary={translate('pos.dashboard.order.items', { + name: order.name + })} + /> + <ListItemSecondaryAction> + <Box + component="span" + sx={{ + marginRight: '1em', + color: 'text.primary', + }} + > + {order.total}$ + </Box> + </ListItemSecondaryAction> + </ListItemButton> + </ListItem> + ); +}; + +export default NbList; \ No newline at end of file diff --git a/rsf-admin/src/page/dashboard/Welcome.jsx b/rsf-admin/src/page/dashboard/Welcome.jsx new file mode 100644 index 0000000..756ad55 --- /dev/null +++ b/rsf-admin/src/page/dashboard/Welcome.jsx @@ -0,0 +1,90 @@ +import * as React from 'react'; +import { Box, Card, CardActions, Button, Typography, useTheme } from '@mui/material'; +import { useNavigate } from 'react-router-dom'; +import { useTranslate } from 'react-admin'; +import AssignmentIcon from '@mui/icons-material/Assignment'; +import AccountCircleIcon from '@mui/icons-material/AccountCircle'; + +import publishArticleImage from './welcome_illustration.svg'; + +const Welcome = () => { + const translate = useTranslate(); + const navigate = useNavigate(); + const theme = useTheme(); + const isLight = theme.palette.mode === 'light'; + + return ( + <Card + sx={{ + background: theme => + `linear-gradient(45deg, + ${isLight ? theme.palette.secondary.dark : theme.palette.primary.dark} 0%, + ${isLight ? theme.palette.secondary.light : theme.palette.primary.light} 50%, + ${theme.palette.primary.dark} 100%)`, + color: theme => theme.palette.primary.contrastText, + padding: '20px', + // paddingBottom: '50px', + marginTop: 2, + marginBottom: '1em', + width: '100%', + overflow: 'visible' + }} + > + <Box display="flex"> + <Box flex="1"> + <Typography variant="h5" component="h2" gutterBottom> + {translate('page.dashboard.welcome.title')} + </Typography> + <Box maxWidth="40em"> + <Typography variant="body1" component="p" gutterBottom> + {translate('page.dashboard.welcome.title')} + </Typography> + </Box> + <CardActions + sx={{ + padding: { xs: 0, xl: null }, + flexWrap: { xs: 'wrap', xl: null }, + '& a': { + marginTop: { xs: '1em', xl: null }, + marginLeft: { xs: '0!important', xl: null }, + marginRight: { xs: '1em', xl: null }, + }, + marginTop: 3, + }} + > + <Button + variant="contained" + startIcon={<AssignmentIcon />} + onClick={() => { + navigate('/task') + }} + > + {translate('menu.task')} + </Button> + <Button + variant="contained" + startIcon={<AccountCircleIcon />} + onClick={() => { + navigate('/warehouseStock') + }} + > + {translate('menu.warehouseStock')} + </Button> + </CardActions> + </Box> + <Box + display={{ xs: 'none', sm: 'none', md: 'block' }} + sx={{ + background: `url(${publishArticleImage}) top right / cover`, + marginLeft: 'auto', + }} + width="16em" + height="9em" + overflow="hidden" + /> + </Box> + </Card> + ); +}; + +export default Welcome; \ No newline at end of file diff --git a/rsf-admin/src/page/dashboard/index.jsx b/rsf-admin/src/page/dashboard/index.jsx index 0ee3aa1..d8694e0 100644 --- a/rsf-admin/src/page/dashboard/index.jsx +++ b/rsf-admin/src/page/dashboard/index.jsx @@ -1,9 +1,26 @@ import React, { useState, useRef, useEffect, useMemo } from "react"; import { useNavigate } from 'react-router-dom'; import { useTheme } from '@mui/material/styles'; -import { useTranslate, useAuthProvider } from 'react-admin'; +import { useTranslate, useAuthProvider, Title, useNotify } from 'react-admin'; import { WordEffect } from './WordEffect'; import { getSystemDicts } from '@/api/auth' +import Welcome from "./Welcome"; +import CardWithIcon from '../components/CardWithIcon'; +import SensorOccupiedIcon from '@mui/icons-material/SensorOccupied'; +import WifiIcon from '@mui/icons-material/Wifi'; +import request from '@/utils/request'; +import { Box, Typography, LinearProgress, Stack } from '@mui/material'; +import NbChart from "./NbChart"; +import NbList from "./NbList"; +import NbCard from "./NbCard"; + +const styles = { + flex: { display: 'flex' }, + flexColumn: { display: 'flex', flexDirection: 'column' }, + leftCol: { flex: 1, marginRight: '0.5em' }, + rightCol: { flex: 1, marginLeft: '0.5em' }, + singleCol: { marginTop: '1em', marginBottom: '1em' }, +}; const Dashboard = () => { const authProvider = useAuthProvider(); @@ -22,6 +39,9 @@ return ( <> + <Title title={"menu.dashboard"} /> + <Welcome /> + <DashboardSummaryView /> <div style={{ boxSizing: 'border-box', @@ -34,17 +54,159 @@ padding: '2rem 1rem', }} > - <WordEffect + {/* <WordEffect words={translate('page.welcome.index')} color={theme.palette.mode === 'light' ? '#666' : '#eeeeee'} /> <WordEffect words={translate('page.welcome.tech')} color={theme.palette.mode === 'light' ? '#666' : '#eeeeee'} - /> + /> */} </div> </> ) } +const DashboardSummaryView = () => { + const translate = useTranslate(); + const notify = useNotify(); + const [statistic, setStatistic] = useState(null); + + useEffect(() => { + request.get('/dashboard/member/statistic', { + params: {} + }).then(res => { + const { code, msg, data } = res.data; + if (code === 200) { + setStatistic(data); + } else { + // notify(msg, { type: 'error', messageArgs: { _: msg } }); + } + }).catch((error) => { + // notify(error.message, { type: 'error', messageArgs: { _: error.message } }); + console.error(error); + }) + }, []) + + const recentOrders = [ + { + id: 1, + name: 'a', + date: "2025-08-10T12:23:56.959Z", + total: 138.94 + }, + { + id: 2, + name: 'b', + date: "2025-08-03T07:45:00.304Z", + total: 214.66 + }, + { + id: 3, + name: 'c', + date: "2025-07-28T00:20:10.968Z", + total: 68.19 + }, + { + id: 4, + name: 'd', + date: "2025-07-22T20:39:00.293Z", + total: 36.56 + }, + { + id: 5, + name: 'e', + date: "2025-07-16T17:40:24.791Z", + total: 100.82 + }, + ] + + return ( + <> + <div style={styles.flex}> + <div style={styles.leftCol}> + <div style={styles.flex}> + <CardWithIcon + icon={WifiIcon} + title={translate('page.member.header.onlineMembers')} + subtitle={`${statistic?.membersOnlineQua}`} + /> + <Spacer /> + <CardWithIcon + icon={SensorOccupiedIcon} + title={translate('page.member.header.totalMembers')} + subtitle={`${statistic?.membersTotalQua}`} + /> + </div> + <div style={styles.singleCol}> + <NbChart orders={recentOrders} /> + </div> + <div style={styles.singleCol}> + <NbList orders={recentOrders} /> + </div> + </div> + <div style={styles.rightCol}> + <div style={styles.flex}> + <NbCard + icon={WifiIcon} + title={translate('page.member.header.onlineMembers')} + subtitle={`${statistic?.membersOnlineQua}`} + to={{ + pathname: '/task', + search: JSON.stringify({ + filter: JSON.stringify({ status: 1 }), + }), + }} + list={recentOrders} + /> + <Spacer /> + <NbCard + icon={SensorOccupiedIcon} + title={translate('page.member.header.totalMembers')} + subtitle={`${statistic?.membersTotalQua}`} + to={{ + pathname: '/task', + search: JSON.stringify({ + filter: JSON.stringify({ status: 1 }), + }), + }} + list={recentOrders} + /> + </div> + </div> + </div> + + {/* <Box sx={{ + display: 'flex', + mt: 2, + gap: 2, + justifyContent: 'space-between', + }}> + <CardWithIcon + icon={WifiIcon} + title={translate('page.member.header.onlineMembers')} + subtitle={`${statistic?.membersOnlineQua}`} + /> + <CardWithIcon + icon={SensorOccupiedIcon} + title={translate('page.member.header.totalMembers')} + subtitle={`${statistic?.membersTotalQua}`} + /> + <CardWithIcon + icon={WifiIcon} + title={translate('page.member.header.onlineMembers')} + subtitle={`${statistic?.membersOnlineQua}`} + /> + <CardWithIcon + icon={SensorOccupiedIcon} + title={translate('page.member.header.totalMembers')} + subtitle={`${statistic?.membersTotalQua}`} + /> + </Box > */} + </> + ) +} + +const Spacer = () => <span style={{ width: '1em' }} />; + export default Dashboard; \ No newline at end of file diff --git a/rsf-admin/src/page/dashboard/welcome_illustration.svg b/rsf-admin/src/page/dashboard/welcome_illustration.svg new file mode 100644 index 0000000..5ad3b75 --- /dev/null +++ b/rsf-admin/src/page/dashboard/welcome_illustration.svg @@ -0,0 +1 @@ +<svg id="b66c9c51-8109-402d-a3f9-100a5bb3d153" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="890.30174" height="489.29978" viewBox="0 0 890.30174 489.29978"><title>work_together</title><rect x="182.97245" y="0.39886" width="703.57565" height="450.60114" fill="#e6e6e6"/><rect x="245.18701" y="60.90722" width="254" height="261" fill="#fff"/><rect x="594.18701" y="65.96874" width="254" height="317" fill="#fff"/><ellipse cx="844.80174" cy="477.2616" rx="45.5" ry="6.5" fill="#e6e6e6"/><ellipse cx="389.89961" cy="477.40722" rx="45.5" ry="6.5" fill="#e6e6e6"/><ellipse cx="104.42498" cy="470.90722" rx="104.42498" ry="5" fill="#e6e6e6"/><rect x="182.67203" width="703.57565" height="29.89047" fill="#567aae"/><circle cx="204.88423" cy="15.28159" r="5.53997" fill="#e6e6e6"/><circle cx="225.91256" cy="15.28159" r="5.53997" fill="#e6e6e6"/><circle cx="246.94089" cy="15.28159" r="5.53997" fill="#e6e6e6"/><path d="M947.03614,356.34879H945.4975V314.19823a24.3956,24.3956,0,0,0-24.39567-24.39563H831.80022a24.3956,24.3956,0,0,0-24.39567,24.39563V545.43948a24.3956,24.3956,0,0,0,24.39567,24.39563h89.30161a24.3956,24.3956,0,0,0,24.39567-24.39563V386.35227h1.53864Z" transform="translate(-154.84913 -205.35011)" fill="#3f3d56"/><path d="M921.08621,296.1495H909.42939a8.6555,8.6555,0,0,1-8.01381,11.92446H850.25579A8.65552,8.65552,0,0,1,842.242,296.1495H831.35448a18.21836,18.21836,0,0,0-18.21838,18.21834v230.902a18.21836,18.21836,0,0,0,18.21838,18.21836h89.73173a18.21837,18.21837,0,0,0,18.21839-18.21836v-230.902A18.21837,18.21837,0,0,0,921.08621,296.1495Z" transform="translate(-154.84913 -205.35011)" fill="#fff"/><rect x="284.09023" y="225.77561" width="176.5444" height="8.05267" fill="#e6e6e6"/><rect x="284.09023" y="251.77561" width="176.5444" height="8.05267" fill="#567aae"/><rect x="284.09023" y="277.77561" width="176.5444" height="8.05267" fill="#e6e6e6"/><rect x="670.83934" y="243.34556" width="103.06376" height="8.05267" fill="#e6e6e6"/><rect x="670.83934" y="268.34556" width="103.06376" height="8.05267" fill="#e6e6e6"/><rect x="670.83934" y="293.34556" width="103.06376" height="8.05267" fill="#e6e6e6"/><rect x="922.35071" y="606.56341" width="17.17729" height="17.17729" transform="translate(1391.24229 -521.13741) rotate(90)" fill="#3f3d56"/><rect x="894.67619" y="606.56341" width="17.17729" height="17.17729" transform="translate(1363.56776 -493.46289) rotate(90)" fill="#567aae"/><rect x="867.00166" y="606.56341" width="17.17729" height="17.17729" transform="translate(1335.89323 -465.78836) rotate(90)" fill="#3f3d56"/><rect x="839.32713" y="606.56341" width="17.17729" height="17.17729" transform="translate(1308.2187 -438.11383) rotate(90)" fill="#3f3d56"/><rect x="811.6526" y="606.56341" width="17.17729" height="17.17729" transform="translate(1280.54418 -410.4393) rotate(90)" fill="#3f3d56"/><rect x="692.7424" y="138.9903" width="57.25764" height="57.25764" fill="#567aae"/><path d="M504.45442,480.943l-.74114,1.48227-2.2234-11.117s-2.96454-11.85815,2.96454-11.85815,4.4468,11.85815,4.4468,11.85815v8.15248Z" transform="translate(-154.84913 -205.35011)" fill="#a0616a"/><path d="M601.69555,479.42524l.74113,1.48227,2.22341-11.117s2.96454-11.85815-2.96454-11.85815-4.44681,11.85815-4.44681,11.85815V477.943Z" transform="translate(-154.84913 -205.35011)" fill="#a0616a"/><polygon points="382.215 358.94 373.322 413.784 377.768 467.145 388.144 462.699 386.662 422.677 397.038 390.808 399.261 428.606 394.815 467.886 408.155 469.369 417.79 388.585 417.049 361.163 382.215 358.94" fill="#2f2e41"/><path d="M537.06434,665.82526l-5.18794,8.15248V692.194a2.209,2.209,0,0,0,1.85635,2.18045c2.5428.41721,6.97037.71364,8.51954-1.86831,2.2234-3.70567.74113-11.85816.74113-11.85816s2.96454-5.92907,1.48227-10.37588-2.96454-5.18794-2.96454-5.18794Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><path d="M559.29839,673.23661l1.48227,2.2234s2.2234,2.22341.74113,3.70568a28.96565,28.96565,0,0,0-2.96454,3.70567s-8.15248,2.2234-8.15248-.74114v-9.63475Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><circle cx="401.77827" cy="288.79506" r="9.82427" fill="#a0616a"/><polygon points="395.185 291.867 394.444 305.949 407.784 306.69 407.043 292.608 395.185 291.867" fill="#a0616a"/><path d="M564.48633,512.41037l-2.10384-5.13957s-9.75432-3.75405-12.71885-.04838l-1.48227,4.44681-11.85816-2.96454-6.67021,14.8227,5.92908,42.24468s15.56382,20.01064,36.3156.74113l5.92908-40.02127L573.38,510.9281Z" transform="translate(-154.84913 -205.35011)" fill="#575a89"/><polygon points="417.049 308.543 418.531 305.578 433.354 296.684 442.4 269.907 449.4 272.907 441.506 304.837 420.013 324.847 417.049 308.543" fill="#575a89"/><polygon points="382.956 304.837 381.474 303.355 365.91 293.72 354.793 271.486 345.9 274.45 355.534 301.872 379.251 321.142 382.956 304.837" fill="#575a89"/><path d="M563.91892,479.10047l1.60629-.80315-2.40943-.80314V476.691s-12.04715-4.81886-13.65343,3.21257a16.14329,16.14329,0,0,0,0,19.27544v2.40942l12.85029,1.60629,1.60628-4.81886S571.95036,483.91933,563.91892,479.10047Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><path d="M269.93891,565.15978l-2.85542,1.42771s-11.42168,5.23493-8.09036,8.09035,12.37349-2.85542,12.37349-2.85542l1.90361-2.37952Z" transform="translate(-154.84913 -205.35011)" fill="#ffb8b8"/><polygon points="198.633 359.099 189.807 418.346 176.481 459.749 169.343 456.418 176.005 399.786 156.969 383.605 158.397 359.81 198.633 359.099" fill="#2f2e41"/><path d="M323.24006,663.19583s8.09036-4.28313,8.56626,1.90361l-.95181,6.18674s2.85542,10.94578-6.66264,8.56626-2.85542-9.51806-2.85542-9.51806Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><path d="M318.00513,583.72l-6.18674,5.23493s0,32.36142,4.28312,37.12045,31.40961,29.0301,32.36142,29.9819,5.23494-9.51806,5.23494-9.51806l-25.69878-29.9819,1.90362-18.56023Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><path d="M350.84245,645.11151s7.61445-1.42771,7.61445,3.80722a115.23116,115.23116,0,0,0,.9518,12.37349s1.90362,16.65661-4.28313,14.27709-8.56625-19.03612-8.56625-19.03612a7.08933,7.08933,0,0,1,2.85542-3.33133C351.31835,652.25006,350.84245,645.11151,350.84245,645.11151Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><polygon points="172.198 288.424 173.626 306.033 169.819 312.695 159.349 302.701 158.397 289.376 172.198 288.424" fill="#ffb8b8"/><circle cx="163.6319" cy="282.71335" r="11.42168" fill="#ffb8b8"/><polygon points="168.391 305.557 173.15 291.756 181.716 301.274 197.421 361.713 185.523 368.852 180.289 361.237 179.337 371.231 156.017 366.472 154.114 302.701 158.87 296.002 168.391 305.557" fill="#d0cde1"/><polygon points="161.728 373.135 158.873 296.039 152.686 300.798 141.264 308.412 148.879 335.539 151.258 364.093 161.728 373.135" fill="#2f2e41"/><polygon points="144.596 308.888 141.264 308.412 131.746 336.49 112.71 360.286 119.849 367.9 141.74 346.484 149.831 328.876 144.596 308.888" fill="#2f2e41"/><path d="M351.4174,565.59536l-.64933,3.12573s-2.97081,12.20793,1.33475,11.36336,5.4281-11.48008,5.4281-11.48008l-.68754-2.96869Z" transform="translate(-154.84913 -205.35011)" fill="#ffb8b8"/><polygon points="172.406 290.983 195.993 300.322 193.138 328.876 198.849 360.286 193.138 366.472 172.022 295.028 172.406 290.983" fill="#2f2e41"/><path d="M319.079,468.8806l3.35262-1.6763v1.6763l2.23507-1.11753v2.79384s8.38153,6.14645,6.70522,13.41044-1.67631,7.82276-1.67631,7.82276-2.11922-13.81412-10.50074-11.57905-9.05615,2.63876-11.29122,8.78521l-.60636,2.63647S297.84583,469.99814,319.079,468.8806Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><polygon points="192.662 300.322 196.469 567aae300.322 202.656 333.635 202.656 362.665 195.042 361.237 188.855 317.454 192.662 300.322" fill="#2f2e41"/><rect x="3.53501" y="370.77159" width="140.32096" height="97.51118" fill="#567aae"/><path d="M228.54462,595.14827a29.729,29.729,0,1,0,29.729,29.729A29.81642,29.81642,0,0,0,228.54462,595.14827Zm0,8.9187a8.91871,8.91871,0,1,1-8.91871,8.91871,8.94863,8.94863,0,0,1,8.91871-8.91871Zm0,42.93556a21.65737,21.65737,0,0,1-17.83742-9.519c.14293-5.94581,11.89161-9.21886,17.83742-9.21886s17.69448,3.27305,17.8374,9.21886a21.69344,21.69344,0,0,1-17.83741,9.519Z" transform="translate(-154.84913 -205.35011)" fill="#fff"/><rect x="284.18701" y="90.90722" width="176" height="101" fill="#e6e6e6"/><path d="M963.0513,496.58366l.81548-5.25988s4.75311-10.80516.99606-11.38765-6.89084,9.70426-6.89084,9.70426l1.37467,10.98574Z" transform="translate(-154.84913 -205.35011)" fill="#ffb8b8"/><polygon points="846.67 321.051 813.089 314.306 809.187 289.847 799.302 289.084 799.785 320.707 828.962 336.004 846.67 321.051" fill="#575a89"/><polygon points="846.67 321.051 813.089 314.306 809.187 289.847 799.302 289.084 799.785 320.707 828.962 336.004 846.67 321.051" opacity="0.2"/><rect x="910.1623" y="482.06175" width="103.06376" height="8.05267" transform="translate(1768.53923 766.82607) rotate(-180)" fill="#567aae"/><path d="M956.49034,494.78044l.00669-5.32271s3.05587-11.402-.74606-11.40676-5.33608,10.63873-5.33608,10.63873l3.02818,10.64924Z" transform="translate(-154.84913 -205.35011)" fill="#ffb8b8"/><path d="M1000.2023,510.02489l4.60746-1.12311a11.86169,11.86169,0,0,0,11.64163-14.21088h0a15.50416,15.50416,0,0,0-15.48468-15.52363h0A15.50417,15.50417,0,0,0,985.443,494.65194v0A12.32065,12.32065,0,0,0,1000.2023,510.02489Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><polygon points="818.254 381.458 822.005 422.524 828.797 462.833 840.203 462.847 838.732 423.305 832.709 375.393 818.254 381.458" fill="#2f2e41"/><path d="M985.17015,665.90379l-7.6096,4.55277s-12.1681,1.50549-9.89171,5.31029,28.89279,1.55707,28.8947.03629-.748-9.886-2.26874-9.88789Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><path d="M1006.77139,583.2605s-.21394,5.87095-5.54811,14.98891l.72505,28.13527,27.33,35.01218-9.89553,8.35184-33.40927-38.06137-8.307-45.63372,10.65879-10.63205Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><path d="M1026.99716,661.394s9.12274,1.53224,7.59719,5.33226-5.34945,21.28415-15.23162,18.99057c0,0-4.56232-.00573-3.03773-3.04536a55.0044,55.0044,0,0,1,3.04824-5.31889l.01241-9.885Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><circle cx="840.41522" cy="294.04136" r="11.40581" fill="#ffb8b8"/><polygon points="845.728 301.652 845.712 314.578 833.546 314.563 835.083 301.639 845.728 301.652" fill="#ffb8b8"/><path d="M985.35926,515.34718l3.68652-.9056,11.52122.9247s6.07545,6.09074,5.31316,7.61055-4.611,38.774-4.611,38.774l6.81006,26.62213-24.33429,1.49021-12.16428-1.53605,2.34133-47.90151s-5.30647-12.93326,1.54178-16.7266A29.95429,29.95429,0,0,0,985.35926,515.34718Z" transform="translate(-154.84913 -205.35011)" fill="#575a89"/><polygon points="844.193 313.056 809.978 311.492 802.404 287.911 792.518 288.658 797.801 319.841 828.964 330.526 844.193 313.056" fill="#575a89"/><circle cx="862.43241" cy="278.27937" r="7.35883" fill="#2f2e41"/><path d="M1010.49168,479.67357a7.35536,7.35536,0,0,1,8.807-7.20494A7.3554,7.3554,0,1,0,1014.711,486.331,7.35277,7.35277,0,0,1,1010.49168,479.67357Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><path d="M1004.17862,483.847l-9.92079-1.82669-7.62952,4.78184a11.57336,11.57336,0,0,0-5.33128,11.29456l7.64125-1.93681,1.71106-4.29045,2.03787,3.34024,8.26714,14.45412,8.37-4.55181,5.33322-8.35757Z" transform="translate(-154.84913 -205.35011)" fill="#2f2e41"/><rect x="526.03635" y="245.29674" width="1.99958" height="202.92117" transform="translate(-190.8885 425.93087) rotate(-60.15005)" fill="#fff"/><rect x="425.57556" y="345.75754" width="202.92117" height="1.99958" transform="translate(-257.51689 102.92685) rotate(-29.84553)" fill="#fff"/><rect x="875.53625" y="332.45224" width="1.99979" height="80.61017" transform="translate(-161.69687 523.63263) rotate(-45)" fill="#fff"/><rect x="836.23106" y="371.75743" width="80.61017" height="1.99979" transform="translate(-161.69687 523.63263) rotate(-45)" fill="#fff"/></svg> \ No newline at end of file diff --git a/rsf-admin/src/page/orders/wave/WaveList.jsx b/rsf-admin/src/page/orders/wave/WaveList.jsx index e59f4f3..9717a8a 100644 --- a/rsf-admin/src/page/orders/wave/WaveList.jsx +++ b/rsf-admin/src/page/orders/wave/WaveList.jsx @@ -165,7 +165,6 @@ <TextField source="updateBy$" label="common.field.updateBy" /> <DateField source="updateTime" label="common.field.updateTime" showTime /> <TextField source="createBy$" label="common.field.createBy" /> - <CustomProcess source="progress" label="table.field.wave.progress" /> <TextField source="memo" label="common.field.memo" sortable={false} /> <TextField source="exceStatus$" label="table.field.wave.exceStatus" sortable={false} /> diff --git a/rsf-admin/src/page/orders/wave/WavePanel.jsx b/rsf-admin/src/page/orders/wave/WavePanel.jsx index ff8f739..dbe6128 100644 --- a/rsf-admin/src/page/orders/wave/WavePanel.jsx +++ b/rsf-admin/src/page/orders/wave/WavePanel.jsx @@ -35,9 +35,9 @@ const WavePanel = () => { const record = useRecordContext(); if (!record) return null; - const translate = useTranslate(); const [createDialog, setCreateDialog] = useState(false); const [drawerVal, setDrawerVal] = useState(false); + const translate = useTranslate(); const { data, total, isPending, error, refetch, meta } = useGetList('/waveOrderRela', { filter: { waveId: record?.id } }); const listContext = useList({ data, isPending }); @@ -71,7 +71,7 @@ omit={['id', 'createTime', 'createBy', 'memo', 'taskId', 'orderId', 'orderItemId', 'matnrId']} > <NumberField source="id" />, - <TextField source="asnCode" label="table.field.asnOrderItem.asnCode" /> + <TextField source="asnCode" label="table.field.asnOrderItem.orderCode" /> <TextField source="matnrCode" label="table.field.asnOrderItem.matnrCode" /> <TextField source="maktx" label="table.field.asnOrderItem.maktx" /> <TextField source="splrBatch" label="table.field.asnOrderItem.splrBatch" /> diff --git a/rsf-admin/src/page/statistics/outStockNum/OutStockNumList.jsx b/rsf-admin/src/page/statistics/outStockNum/OutStockNumList.jsx index 574553a..0f68b3e 100644 --- a/rsf-admin/src/page/statistics/outStockNum/OutStockNumList.jsx +++ b/rsf-admin/src/page/statistics/outStockNum/OutStockNumList.jsx @@ -73,19 +73,10 @@ const translate = useTranslate(); const [createDialog, setCreateDialog] = useState(false); const [drawerVal, setDrawerVal] = useState(false); - // const dict = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_task_type' && dict.group == 3)) || []; - const filters = [ <SearchInput source="condition" alwaysOn />, <DateInput label='common.time.before' source="dayTime" alwaysOn />, - // <AutocompleteInput optionText="label" - // choices={dict} - // optionValue="value" - // label="table.field.stockStatistic.taskType" - // filter - // source="taskType" - // alwaysOn />, <TextInput source="maktx" label="table.field.locItem.maktx" />, <TextInput source="matnrCode" label="table.field.locItem.matnrCode" alwaysOn/>, <TextInput source="batch" label="table.field.locItem.batch" />, @@ -124,7 +115,6 @@ omit={['id', 'memo']} > <NumberField source="id" key="id-key"/> - {/* <TextField source="taskType$" label="table.field.stockStatistic.taskType" /> */} <TextField source="dayTime" label="table.field.stockStatistic.dayTime" /> <TextField source="matnrCode" label="table.field.locItem.matnrCode" /> <TextField source="maktx" label="table.field.locItem.maktx" /> diff --git a/rsf-admin/src/page/statistics/stockStatisticNum/stockStatisticList.jsx b/rsf-admin/src/page/statistics/stockStatisticNum/stockStatisticList.jsx index e6eeff5..97ac3f0 100644 --- a/rsf-admin/src/page/statistics/stockStatisticNum/stockStatisticList.jsx +++ b/rsf-admin/src/page/statistics/stockStatisticNum/stockStatisticList.jsx @@ -46,22 +46,14 @@ cursor: 'auto' }, - '& .column-dayTime': { - width: 120, - textAlign: 'center', - }, - - '& .column-taskType$': { - width: 130, - }, - - '& .column-matnrCode': { - width: 150, + '& .RaDatagrid-rowCell': { + color: 'black', textAlign: 'center', }, '& .RaDatagrid-headerCell': { color: 'black', + textAlign: 'center', }, '& .column-maktx': { @@ -73,19 +65,10 @@ const translate = useTranslate(); const [createDialog, setCreateDialog] = useState(false); const [drawerVal, setDrawerVal] = useState(false); - // const dict = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_task_type' && dict.group == 3)) || []; - const filters = [ <SearchInput source="condition" alwaysOn />, <DateInput label='common.time.before' source="dayTime" alwaysOn />, - // <AutocompleteInput optionText="label" - // choices={dict} - // optionValue="value" - // label="table.field.stockStatistic.taskType" - // filter - // source="taskType" - // alwaysOn />, <TextInput source="maktx" label="table.field.locItem.maktx" />, <TextInput source="matnrCode" label="table.field.locItem.matnrCode" alwaysOn />, <TextInput source="batch" label="table.field.locItem.batch" />, @@ -104,7 +87,6 @@ }} title={false} empty={false} - filter={{ taskType: 101, taskStatus: 200 }} filters={filters} sort={{ field: "day_time", order: "desc" }} actions={( -- Gitblit v1.9.1