Commit 7bc42c384518d25ba6d752eef928381dcc0bf650
Merge remote-tracking branch 'origin/master' into pms_partplane
Showing
43 changed files
with
1315 additions
and
1620 deletions
package.json
pnpm-lock.yaml
... | ... | @@ -128,6 +128,9 @@ dependencies: |
128 | 128 | react-copy-to-clipboard: |
129 | 129 | specifier: ^5.1.0 |
130 | 130 | version: 5.1.0(react@16.14.0) |
131 | + react-d3-tree: | |
132 | + specifier: 3.6.2 | |
133 | + version: 3.6.2(react-dom@16.14.0)(react@16.14.0) | |
131 | 134 | react-document-title: |
132 | 135 | specifier: ^2.0.3 |
133 | 136 | version: 2.0.3(react@16.14.0) |
... | ... | @@ -2386,6 +2389,22 @@ packages: |
2386 | 2389 | resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} |
2387 | 2390 | dev: true |
2388 | 2391 | |
2392 | + /@bkrem/react-transition-group@1.3.3(react-dom@16.14.0)(react@16.14.0): | |
2393 | + resolution: {integrity: sha512-nUZaumHu/MMolELv+MhEEQzQtKsnfpbKBHtam/NK53tGICwU19tuffEXW8BLhm9HhQfN1H3+C0bsJv8Z7vzwEA==} | |
2394 | + peerDependencies: | |
2395 | + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 | |
2396 | + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 | |
2397 | + dependencies: | |
2398 | + chain-function: 1.0.1 | |
2399 | + dom-helpers: 3.4.0 | |
2400 | + loose-envify: 1.4.0 | |
2401 | + prop-types: 15.8.1 | |
2402 | + react: 16.14.0 | |
2403 | + react-dom: 16.14.0(react@16.14.0) | |
2404 | + react-lifecycles-compat: 3.0.4 | |
2405 | + warning: 3.0.0 | |
2406 | + dev: false | |
2407 | + | |
2389 | 2408 | /@bloomberg/record-tuple-polyfill@0.0.3: |
2390 | 2409 | resolution: {integrity: sha512-sBnCqW0nqofE47mxFnw+lvx6kzsQstwaQMVkh66qm/A6IlsnH7WsyGuVXTou8RF2wL4W7ybOoHPvP2WgIo6rhQ==} |
2391 | 2410 | |
... | ... | @@ -3114,6 +3133,10 @@ packages: |
3114 | 3133 | '@types/node': 20.8.7 |
3115 | 3134 | dev: true |
3116 | 3135 | |
3136 | + /@types/d3-hierarchy@1.1.11: | |
3137 | + resolution: {integrity: sha512-lnQiU7jV+Gyk9oQYk0GGYccuexmQPTp08E0+4BidgFdiJivjEvf+esPSdZqCZ2C7UwTWejWpqetVaU8A+eX3FA==} | |
3138 | + dev: false | |
3139 | + | |
3117 | 3140 | /@types/eslint-scope@3.7.7: |
3118 | 3141 | resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} |
3119 | 3142 | dependencies: |
... | ... | @@ -5936,6 +5959,10 @@ packages: |
5936 | 5959 | lazy-cache: 1.0.4 |
5937 | 5960 | dev: false |
5938 | 5961 | |
5962 | + /chain-function@1.0.1: | |
5963 | + resolution: {integrity: sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg==} | |
5964 | + dev: false | |
5965 | + | |
5939 | 5966 | /chalk@1.1.3: |
5940 | 5967 | resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} |
5941 | 5968 | engines: {node: '>=0.10.0'} |
... | ... | @@ -6187,7 +6214,6 @@ packages: |
6187 | 6214 | /clone@2.1.2: |
6188 | 6215 | resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} |
6189 | 6216 | engines: {node: '>=0.8'} |
6190 | - dev: true | |
6191 | 6217 | |
6192 | 6218 | /cloneable-readable@1.1.3: |
6193 | 6219 | resolution: {integrity: sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==} |
... | ... | @@ -6697,6 +6723,14 @@ packages: |
6697 | 6723 | resolution: {integrity: sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==} |
6698 | 6724 | dev: false |
6699 | 6725 | |
6726 | + /d3-drag@3.0.0: | |
6727 | + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} | |
6728 | + engines: {node: '>=12'} | |
6729 | + dependencies: | |
6730 | + d3-dispatch: 1.0.6 | |
6731 | + d3-selection: 3.0.0 | |
6732 | + dev: false | |
6733 | + | |
6700 | 6734 | /d3-dsv@1.0.10: |
6701 | 6735 | resolution: {integrity: sha512-vqklfpxmtO2ZER3fq/B33R/BIz3A1PV0FaZRuFM8w6jLo7sUX1BZDh73fPlr0s327rzq4H6EN1q9U+eCBCSN8g==} |
6702 | 6736 | hasBin: true |
... | ... | @@ -6769,6 +6803,11 @@ packages: |
6769 | 6803 | resolution: {integrity: sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==} |
6770 | 6804 | dev: false |
6771 | 6805 | |
6806 | + /d3-selection@3.0.0: | |
6807 | + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} | |
6808 | + engines: {node: '>=12'} | |
6809 | + dev: false | |
6810 | + | |
6772 | 6811 | /d3-shape@1.3.7: |
6773 | 6812 | resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} |
6774 | 6813 | dependencies: |
... | ... | @@ -6790,10 +6829,35 @@ packages: |
6790 | 6829 | d3-timer: 1.0.10 |
6791 | 6830 | dev: false |
6792 | 6831 | |
6832 | + /d3-transition@3.0.1(d3-selection@3.0.0): | |
6833 | + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} | |
6834 | + engines: {node: '>=12'} | |
6835 | + peerDependencies: | |
6836 | + d3-selection: 2 - 3 | |
6837 | + dependencies: | |
6838 | + d3-color: 1.4.1 | |
6839 | + d3-dispatch: 1.0.6 | |
6840 | + d3-ease: 1.0.7 | |
6841 | + d3-interpolate: 1.4.0 | |
6842 | + d3-selection: 3.0.0 | |
6843 | + d3-timer: 1.0.10 | |
6844 | + dev: false | |
6845 | + | |
6793 | 6846 | /d3-voronoi@1.1.4: |
6794 | 6847 | resolution: {integrity: sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==} |
6795 | 6848 | dev: false |
6796 | 6849 | |
6850 | + /d3-zoom@3.0.0: | |
6851 | + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} | |
6852 | + engines: {node: '>=12'} | |
6853 | + dependencies: | |
6854 | + d3-dispatch: 1.0.6 | |
6855 | + d3-drag: 3.0.0 | |
6856 | + d3-interpolate: 1.4.0 | |
6857 | + d3-selection: 3.0.0 | |
6858 | + d3-transition: 3.0.1(d3-selection@3.0.0) | |
6859 | + dev: false | |
6860 | + | |
6797 | 6861 | /dagre@0.8.5: |
6798 | 6862 | resolution: {integrity: sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==} |
6799 | 6863 | dependencies: |
... | ... | @@ -6821,7 +6885,7 @@ packages: |
6821 | 6885 | resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} |
6822 | 6886 | engines: {node: '>=0.11'} |
6823 | 6887 | dependencies: |
6824 | - '@babel/runtime': 7.23.2 | |
6888 | + '@babel/runtime': 7.23.8 | |
6825 | 6889 | |
6826 | 6890 | /date-format@0.0.0: |
6827 | 6891 | resolution: {integrity: sha512-kAmAdtsjW5nQ02FERwI1bP4xe6HQBPwy5kpAF4CRSLOMUs/vgMIEEwpy6JqUs7NitTyhZiImxwAjgPpnteycHg==} |
... | ... | @@ -6991,6 +7055,11 @@ packages: |
6991 | 7055 | engines: {node: '>= 0.8'} |
6992 | 7056 | dev: true |
6993 | 7057 | |
7058 | + /dequal@2.0.3: | |
7059 | + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} | |
7060 | + engines: {node: '>=6'} | |
7061 | + dev: false | |
7062 | + | |
6994 | 7063 | /des.js@1.1.0: |
6995 | 7064 | resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} |
6996 | 7065 | dependencies: |
... | ... | @@ -7087,6 +7156,12 @@ packages: |
7087 | 7156 | /dom-align@1.12.4: |
7088 | 7157 | resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==} |
7089 | 7158 | |
7159 | + /dom-helpers@3.4.0: | |
7160 | + resolution: {integrity: sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==} | |
7161 | + dependencies: | |
7162 | + '@babel/runtime': 7.23.8 | |
7163 | + dev: false | |
7164 | + | |
7090 | 7165 | /dom-scroll-into-view@1.2.1: |
7091 | 7166 | resolution: {integrity: sha512-LwNVg3GJOprWDO+QhLL1Z9MMgWe/KAFLxVWKzjRTxNSPn8/LLDIfmuG71YHznXCqaqTjvHJDYO1MEAgX6XCNbQ==} |
7092 | 7167 | dev: false |
... | ... | @@ -7224,7 +7299,7 @@ packages: |
7224 | 7299 | peerDependencies: |
7225 | 7300 | redux: 4.x |
7226 | 7301 | dependencies: |
7227 | - '@babel/runtime': 7.23.2 | |
7302 | + '@babel/runtime': 7.23.8 | |
7228 | 7303 | flatten: 1.0.3 |
7229 | 7304 | global: 4.4.0 |
7230 | 7305 | invariant: 2.2.4 |
... | ... | @@ -9144,7 +9219,7 @@ packages: |
9144 | 9219 | /history-with-query@4.10.4: |
9145 | 9220 | resolution: {integrity: sha512-JnskQK8X+PbRFHSdDAExhoJyhLnlLZL+UuHQuQhys+Se9/ukRDRBWU4JVTjsiIfbv1fcEmR3oqKW56OYmk5M5w==} |
9146 | 9221 | dependencies: |
9147 | - '@babel/runtime': 7.23.2 | |
9222 | + '@babel/runtime': 7.23.8 | |
9148 | 9223 | loose-envify: 1.4.0 |
9149 | 9224 | query-string: 6.14.1 |
9150 | 9225 | resolve-pathname: 3.0.0 |
... | ... | @@ -9155,7 +9230,7 @@ packages: |
9155 | 9230 | /history@4.10.1: |
9156 | 9231 | resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} |
9157 | 9232 | dependencies: |
9158 | - '@babel/runtime': 7.23.2 | |
9233 | + '@babel/runtime': 7.23.8 | |
9159 | 9234 | loose-envify: 1.4.0 |
9160 | 9235 | resolve-pathname: 3.0.0 |
9161 | 9236 | tiny-invariant: 1.3.1 |
... | ... | @@ -11403,7 +11478,7 @@ packages: |
11403 | 11478 | prop-types: ^15.0.0 |
11404 | 11479 | react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 |
11405 | 11480 | dependencies: |
11406 | - '@babel/runtime': 7.23.2 | |
11481 | + '@babel/runtime': 7.23.8 | |
11407 | 11482 | prop-types: 15.8.1 |
11408 | 11483 | react: 16.14.0 |
11409 | 11484 | tiny-warning: 1.0.3 |
... | ... | @@ -13207,7 +13282,7 @@ packages: |
13207 | 13282 | react: '>=16.9.0' |
13208 | 13283 | react-dom: '>=16.9.0' |
13209 | 13284 | dependencies: |
13210 | - '@babel/runtime': 7.23.2 | |
13285 | + '@babel/runtime': 7.23.8 | |
13211 | 13286 | classnames: 2.3.2 |
13212 | 13287 | dom-align: 1.12.4 |
13213 | 13288 | rc-util: 5.38.0(react-dom@16.14.0)(react@16.14.0) |
... | ... | @@ -13515,7 +13590,7 @@ packages: |
13515 | 13590 | react: '>=16.9.0' |
13516 | 13591 | react-dom: '>=16.9.0' |
13517 | 13592 | dependencies: |
13518 | - '@babel/runtime': 7.23.2 | |
13593 | + '@babel/runtime': 7.23.8 | |
13519 | 13594 | classnames: 2.3.2 |
13520 | 13595 | rc-resize-observer: 1.4.0(react-dom@16.14.0)(react@16.14.0) |
13521 | 13596 | rc-util: 5.38.0(react-dom@16.14.0)(react@16.14.0) |
... | ... | @@ -13860,7 +13935,7 @@ packages: |
13860 | 13935 | react: '*' |
13861 | 13936 | react-dom: '*' |
13862 | 13937 | dependencies: |
13863 | - '@babel/runtime': 7.23.2 | |
13938 | + '@babel/runtime': 7.23.8 | |
13864 | 13939 | classnames: 2.3.2 |
13865 | 13940 | rc-resize-observer: 1.4.0(react-dom@16.14.0)(react@16.14.0) |
13866 | 13941 | rc-util: 5.38.0(react-dom@16.14.0)(react@16.14.0) |
... | ... | @@ -13908,6 +13983,25 @@ packages: |
13908 | 13983 | react: 16.14.0 |
13909 | 13984 | dev: false |
13910 | 13985 | |
13986 | + /react-d3-tree@3.6.2(react-dom@16.14.0)(react@16.14.0): | |
13987 | + resolution: {integrity: sha512-1ExQlmEnv5iOw9XfZ3EcESDjzGXVKPAmyDJTJbvVfiwkplZtP7CcNEY0tKZf4XSW0FzYJf4aFXprGJen+95yuw==} | |
13988 | + peerDependencies: | |
13989 | + react: 16.x || 17.x || 18.x | |
13990 | + react-dom: 16.x || 17.x || 18.x | |
13991 | + dependencies: | |
13992 | + '@bkrem/react-transition-group': 1.3.3(react-dom@16.14.0)(react@16.14.0) | |
13993 | + '@types/d3-hierarchy': 1.1.11 | |
13994 | + clone: 2.1.2 | |
13995 | + d3-hierarchy: 1.1.9 | |
13996 | + d3-selection: 3.0.0 | |
13997 | + d3-shape: 1.3.7 | |
13998 | + d3-zoom: 3.0.0 | |
13999 | + dequal: 2.0.3 | |
14000 | + react: 16.14.0 | |
14001 | + react-dom: 16.14.0(react@16.14.0) | |
14002 | + uuid: 8.3.2 | |
14003 | + dev: false | |
14004 | + | |
13911 | 14005 | /react-dev-utils@9.0.1(eslint@8.52.0)(typescript@5.3.3)(webpack@5.89.0): |
13912 | 14006 | resolution: {integrity: sha512-pnaeMo/Pxel8aZpxk1WwxT3uXxM3tEwYvsjCYn5R7gNxjhN1auowdcLDzFB8kr7rafAj2rxmvfic/fbac5CzwQ==} |
13913 | 14007 | engines: {node: '>=8.10'} |
... | ... | @@ -14073,7 +14167,7 @@ packages: |
14073 | 14167 | react: '>=15' |
14074 | 14168 | react-router: '>=5' |
14075 | 14169 | dependencies: |
14076 | - '@babel/runtime': 7.23.2 | |
14170 | + '@babel/runtime': 7.23.8 | |
14077 | 14171 | react: 16.14.0 |
14078 | 14172 | react-router: 5.2.0(react@16.14.0) |
14079 | 14173 | |
... | ... | @@ -14083,7 +14177,7 @@ packages: |
14083 | 14177 | react: '>=15' |
14084 | 14178 | react-router: '>=5' |
14085 | 14179 | dependencies: |
14086 | - '@babel/runtime': 7.23.2 | |
14180 | + '@babel/runtime': 7.23.8 | |
14087 | 14181 | react: 16.14.0 |
14088 | 14182 | react-router: 5.3.4(react@16.14.0) |
14089 | 14183 | |
... | ... | @@ -14092,7 +14186,7 @@ packages: |
14092 | 14186 | peerDependencies: |
14093 | 14187 | react: '>=15' |
14094 | 14188 | dependencies: |
14095 | - '@babel/runtime': 7.23.2 | |
14189 | + '@babel/runtime': 7.23.8 | |
14096 | 14190 | history: 4.10.1 |
14097 | 14191 | loose-envify: 1.4.0 |
14098 | 14192 | prop-types: 15.8.1 |
... | ... | @@ -14106,7 +14200,7 @@ packages: |
14106 | 14200 | peerDependencies: |
14107 | 14201 | react: '>=15' |
14108 | 14202 | dependencies: |
14109 | - '@babel/runtime': 7.23.2 | |
14203 | + '@babel/runtime': 7.23.8 | |
14110 | 14204 | history: 4.10.1 |
14111 | 14205 | loose-envify: 1.4.0 |
14112 | 14206 | prop-types: 15.8.1 |
... | ... | @@ -14121,7 +14215,7 @@ packages: |
14121 | 14215 | peerDependencies: |
14122 | 14216 | react: '>=15' |
14123 | 14217 | dependencies: |
14124 | - '@babel/runtime': 7.23.2 | |
14218 | + '@babel/runtime': 7.23.8 | |
14125 | 14219 | history: 4.10.1 |
14126 | 14220 | hoist-non-react-statics: 3.3.2 |
14127 | 14221 | loose-envify: 1.4.0 |
... | ... | @@ -14138,7 +14232,7 @@ packages: |
14138 | 14232 | peerDependencies: |
14139 | 14233 | react: '>=15' |
14140 | 14234 | dependencies: |
14141 | - '@babel/runtime': 7.23.2 | |
14235 | + '@babel/runtime': 7.23.8 | |
14142 | 14236 | history: 4.10.1 |
14143 | 14237 | hoist-non-react-statics: 3.3.2 |
14144 | 14238 | loose-envify: 1.4.0 |
... | ... | @@ -14405,7 +14499,7 @@ packages: |
14405 | 14499 | /regenerator-transform@0.15.2: |
14406 | 14500 | resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} |
14407 | 14501 | dependencies: |
14408 | - '@babel/runtime': 7.23.2 | |
14502 | + '@babel/runtime': 7.23.8 | |
14409 | 14503 | dev: true |
14410 | 14504 | |
14411 | 14505 | /regex-not@1.0.2: |
... | ... | @@ -17085,8 +17179,6 @@ packages: |
17085 | 17179 | resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} |
17086 | 17180 | hasBin: true |
17087 | 17181 | requiresBuild: true |
17088 | - dev: true | |
17089 | - optional: true | |
17090 | 17182 | |
17091 | 17183 | /v8-compile-cache@2.3.0: |
17092 | 17184 | resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} | ... | ... |
src/components/CarTableTreeAuth/index.tsx
... | ... | @@ -267,13 +267,8 @@ export default function Index({ onChange, value, disabled, brandMultiple = true, |
267 | 267 | render={(_, record: any, index) => { |
268 | 268 | return ( |
269 | 269 | <Space> |
270 | - <Button | |
271 | - type={record.brandId ? 'primary' : 'link'} | |
272 | - style={{ padding: 2 }} | |
273 | - onClick={() => onSelectSpec(record)} | |
274 | - disabled={disabled} | |
275 | - > | |
276 | - {record.brandId ? '编辑车系' : record.seriesId ? '编辑车型' : ''} | |
270 | + <Button type="link" style={{ padding: 2 }} onClick={() => onSelectSpec(record)} disabled={disabled}> | |
271 | + {record.brandId ? '选择车系' : record.seriesId ? '选择车型' : ''} | |
277 | 272 | </Button> |
278 | 273 | {/* <Popconfirm |
279 | 274 | title="确定删除?" |
... | ... | @@ -296,8 +291,8 @@ export default function Index({ onChange, value, disabled, brandMultiple = true, |
296 | 291 | |
297 | 292 | {/* 选择品牌和车系 */} |
298 | 293 | <Modal |
299 | - title="选择车辆信息" | |
300 | - visible={visible} | |
294 | + title={level === 2 ? '选择车系' : level === 3 ? '选择车型' : '选择品牌'} | |
295 | + open={visible} | |
301 | 296 | onOk={() => form.submit()} |
302 | 297 | onCancel={() => { |
303 | 298 | setVisible(false); | ... | ... |
src/components/Condition/CascaderSeries/SpecSelect.tsx
... | ... | @@ -4,13 +4,14 @@ import { CascaderOptionType } from 'antd/lib/cascader'; |
4 | 4 | import { getBrand, getSeriesApi, getSpecList, optionItem } from './api'; |
5 | 5 | |
6 | 6 | interface FilterProps { |
7 | - value?: { id: number, name: string }[], | |
8 | - onChange?: (value: { id: number, name: string, energyType?: number }[]) => any, | |
9 | - style?: any, | |
7 | + value?: { id: number; name: string }[]; | |
8 | + onChange?: (value: { id: number; name: string; energyType?: number }[]) => any; | |
9 | + style?: any; | |
10 | + placeHolder?: string; | |
10 | 11 | } |
11 | 12 | |
12 | 13 | export default function Filter(props: FilterProps) { |
13 | - const { value = [], onChange, style } = props; | |
14 | + const { value = [], onChange, style, placeHolder = '品牌/车系/车型' } = props; | |
14 | 15 | const [specOptions, setSpecOptions] = useState<any[]>([]); |
15 | 16 | |
16 | 17 | useEffect(() => { |
... | ... | @@ -19,12 +20,12 @@ export default function Filter(props: FilterProps) { |
19 | 20 | |
20 | 21 | function _brand() { |
21 | 22 | getBrand() |
22 | - .then(res => { | |
23 | + .then((res) => { | |
23 | 24 | const { data = [] } = res; |
24 | - const brandList = data.map(brand => ({ ...brand, isLeaf: false })); | |
25 | + const brandList = data.map((brand) => ({ ...brand, isLeaf: false })); | |
25 | 26 | setSpecOptions(brandList); |
26 | 27 | }) |
27 | - .catch(e => { | |
28 | + .catch((e) => { | |
28 | 29 | message.error(e.message); |
29 | 30 | }); |
30 | 31 | } |
... | ... | @@ -33,56 +34,61 @@ export default function Filter(props: FilterProps) { |
33 | 34 | if (specOptions && specOptions.length > 0) { |
34 | 35 | return options(specOptions); |
35 | 36 | } |
36 | - getBrand().then(res => { | |
37 | + getBrand().then((res) => { | |
37 | 38 | const { data = [] } = res; |
38 | - const brandList = data.map(brand => ({ ...brand, isLeaf: false })); | |
39 | + const brandList = data.map((brand) => ({ ...brand, isLeaf: false })); | |
39 | 40 | options(brandList); |
40 | - }) | |
41 | + }); | |
41 | 42 | } |
42 | 43 | |
43 | 44 | function options(brandList: optionItem[] = []) { |
44 | - brandList && brandList.forEach(brand => { | |
45 | - if (brand.id == value[0].id) { | |
46 | - brand.children = []; | |
47 | - getSeriesApi(value[0].id).then(res => { | |
48 | - const { data = [] } = res; | |
49 | - data.forEach((series, index) => { | |
50 | - if (series.id === value[1].id) { | |
51 | - getSpecList(value[1].id).then(res => { | |
52 | - const { data = [] } = res; | |
53 | - series.children = []; | |
54 | - data.forEach((item) => { | |
55 | - series.children.push({ | |
56 | - id: item.id, | |
57 | - name: item.name, | |
58 | - isLeaf: true, | |
59 | - children: [] | |
45 | + brandList && | |
46 | + brandList.forEach((brand) => { | |
47 | + if (brand.id == value[0].id) { | |
48 | + brand.children = []; | |
49 | + getSeriesApi(value[0].id) | |
50 | + .then((res) => { | |
51 | + const { data = [] } = res; | |
52 | + data.forEach((series, index) => { | |
53 | + if (series.id === value[1].id) { | |
54 | + getSpecList(value[1].id) | |
55 | + .then((res) => { | |
56 | + const { data = [] } = res; | |
57 | + series.children = []; | |
58 | + data.forEach((item) => { | |
59 | + series.children.push({ | |
60 | + id: item.id, | |
61 | + name: item.name, | |
62 | + isLeaf: true, | |
63 | + children: [], | |
64 | + }); | |
65 | + }); | |
66 | + brand.children.push({ | |
67 | + id: series.id, | |
68 | + name: series.name, | |
69 | + isLeaf: false, | |
70 | + children: series.children, | |
71 | + }); | |
72 | + setSpecOptions(brandList); | |
73 | + }) | |
74 | + .catch((e) => { | |
75 | + message.error(e.message); | |
76 | + }); | |
77 | + } else { | |
78 | + brand.children.push({ | |
79 | + id: series.id, | |
80 | + name: series.name, | |
81 | + isLeaf: false, | |
82 | + children: series.children, | |
60 | 83 | }); |
61 | - }); | |
62 | - brand.children.push({ | |
63 | - id: series.id, | |
64 | - name: series.name, | |
65 | - isLeaf: false, | |
66 | - children: series.children | |
67 | - }); | |
68 | - setSpecOptions(brandList); | |
69 | - }).catch(e => { | |
70 | - message.error(e.message); | |
71 | - }) | |
72 | - } else { | |
73 | - brand.children.push({ | |
74 | - id: series.id, | |
75 | - name: series.name, | |
76 | - isLeaf: false, | |
77 | - children: series.children | |
84 | + } | |
78 | 85 | }); |
79 | - } | |
80 | - }); | |
81 | - }).catch(e => { | |
82 | - message.error(e.message); | |
83 | - }) | |
84 | - } | |
85 | - }) | |
86 | + }) | |
87 | + .catch((e) => { | |
88 | + message.error(e.message); | |
89 | + }); | |
90 | + } | |
91 | + }); | |
86 | 92 | } |
87 | 93 | |
88 | 94 | function loadData(selectedOptions: CascaderOptionType) { |
... | ... | @@ -90,45 +96,47 @@ export default function Filter(props: FilterProps) { |
90 | 96 | const targetOption = selectedOptions[length - 1] || {}; |
91 | 97 | targetOption.loading = true; |
92 | 98 | if (length === 1) { |
93 | - targetOption.id && getSeriesApi(targetOption.id) | |
94 | - .then(res => { | |
95 | - const { data = [] } = res; | |
96 | - targetOption.loading = false; | |
97 | - targetOption.children = []; | |
98 | - data.forEach((list, index) => { | |
99 | - targetOption.children.push({ | |
100 | - id: list.id, | |
101 | - name: list.name, | |
102 | - isLeaf: false, | |
99 | + targetOption.id && | |
100 | + getSeriesApi(targetOption.id) | |
101 | + .then((res) => { | |
102 | + const { data = [] } = res; | |
103 | + targetOption.loading = false; | |
104 | + targetOption.children = []; | |
105 | + data.forEach((list, index) => { | |
106 | + targetOption.children.push({ | |
107 | + id: list.id, | |
108 | + name: list.name, | |
109 | + isLeaf: false, | |
110 | + }); | |
103 | 111 | }); |
112 | + setSpecOptions([...specOptions]); | |
113 | + }) | |
114 | + .catch((e) => { | |
115 | + message.error(e.message); | |
104 | 116 | }); |
105 | - setSpecOptions([...specOptions]); | |
106 | - }) | |
107 | - .catch(e => { | |
108 | - message.error(e.message); | |
109 | - }); | |
110 | 117 | targetOption.loading = false; |
111 | 118 | } |
112 | 119 | if (length === 2) { |
113 | - targetOption.id && getSpecList(targetOption.id) | |
114 | - .then(res => { | |
115 | - const { data = [] } = res; | |
116 | - targetOption.loading = false; | |
117 | - targetOption.children = []; | |
118 | - data.forEach((list, index) => { | |
119 | - targetOption.children.push({ | |
120 | - id: list.id, | |
121 | - name: list.name, | |
122 | - isLeaf: true, | |
123 | - /**能源类型 */ | |
124 | - energyType: list.energyType || false, | |
120 | + targetOption.id && | |
121 | + getSpecList(targetOption.id) | |
122 | + .then((res) => { | |
123 | + const { data = [] } = res; | |
124 | + targetOption.loading = false; | |
125 | + targetOption.children = []; | |
126 | + data.forEach((list, index) => { | |
127 | + targetOption.children.push({ | |
128 | + id: list.id, | |
129 | + name: list.name, | |
130 | + isLeaf: true, | |
131 | + /**能源类型 */ | |
132 | + energyType: list.energyType || false, | |
133 | + }); | |
125 | 134 | }); |
135 | + setSpecOptions([...specOptions]); | |
136 | + }) | |
137 | + .catch((e) => { | |
138 | + message.error(e.message); | |
126 | 139 | }); |
127 | - setSpecOptions([...specOptions]); | |
128 | - }) | |
129 | - .catch(e => { | |
130 | - message.error(e.message); | |
131 | - }); | |
132 | 140 | } |
133 | 141 | } |
134 | 142 | |
... | ... | @@ -147,8 +155,8 @@ export default function Filter(props: FilterProps) { |
147 | 155 | <Cascader |
148 | 156 | allowClear |
149 | 157 | changeOnSelect |
150 | - value={value.map(item => item.id)} | |
151 | - placeholder="品牌/车系/车型" | |
158 | + value={value.map((item) => item.id)} | |
159 | + placeholder={placeHolder} | |
152 | 160 | options={specOptions} |
153 | 161 | loadData={(selectedOptions: any) => loadData(selectedOptions)} |
154 | 162 | onChange={_onChange} | ... | ... |
src/pages/carinsur/InsuranceTradingGift/api.ts
1 | 1 | import type { http } from '@/typing/http'; |
2 | 2 | import request from '@/utils/request'; |
3 | -import qs from 'qs'; | |
4 | -import { ANGEL_Host, OOP_HOST } from '@/utils/host'; | |
3 | +import { ANGEL_Host } from '@/utils/host'; | |
4 | +import type { ValueNameOption } from '../entity'; | |
5 | 5 | |
6 | 6 | export interface TradingGiftConfig { |
7 | - conditions?: { label: string; value: string }[] | string[]; //前置条件 | |
8 | - exchangeMethod?: string[]; //礼品兑换方式 | |
9 | - vciReturnMoneyRate?: number; //商业险返现比例 | |
10 | - daiReturnMoneyRate?: number; //驾意险返现比例 | |
11 | - couponConfigList?: CouponResult[]; | |
12 | - key?: number; | |
7 | + conditions?: ValueNameOption[]; // 不传参到后端 | |
8 | + vciReturnMoneyRate?: number; // 返现比例 | |
9 | + cashCouponRate?: number; // 返现金券比例 | |
10 | + noCashBackVciPremiumAmount?: number; | |
13 | 11 | } |
14 | 12 | |
15 | 13 | export interface CouponResult { |
... | ... | @@ -55,15 +53,14 @@ export interface PageItem { |
55 | 53 | buyInsuranceGiftConfigId: number; //配置id |
56 | 54 | insurerName?: number; //保险公司名称 |
57 | 55 | type?: number; //成交类型,1新保、3续保(See: 保单类型枚举) |
58 | - shopsType?: number; //适用门店类型 1.表示全部门店 2.表示部分门店 | |
56 | + shopsType?: number; //适用门店类型 1.表示全部门店 2.表示适用门店 | |
59 | 57 | shops?: Shops[]; //适用门店 |
60 | - startDate?: number; //生效日期 | |
61 | - endDate?: number; //到期日期 | |
62 | 58 | brandName?: string; //品牌 |
63 | - status?: number; //状态,1草稿、2审批中、3审批拒绝、4审批超时、5待生效、6生效中、7已失效 | |
64 | - approvalOrderNo?: string; // 审批单号 | |
59 | + status?: number; //状态,1草稿、2审批中、3审批拒绝、4审批超时、5待生效、6生效中、7已失效 // 审批状态废弃 | |
60 | + approvalOrderNo?: string; // 审批单号 // 审批状态废弃 | |
65 | 61 | applyCarList?: ApplyCarList[]; //适用车辆 |
66 | 62 | insurers?: { insurerId: number; insurerName: string }[]; //保险公司集合 |
63 | + giftOptionList?: TradingGiftConfig[]; // 成交有礼条件配置 | |
67 | 64 | } |
68 | 65 | export interface Shops { |
69 | 66 | shopId?: number; //门店id |
... | ... | @@ -97,7 +94,7 @@ export interface DetailData { |
97 | 94 | insurerId?: number; //保险公司id |
98 | 95 | insurerName?: string; //保险公司名称 |
99 | 96 | type?: number; //成交类型,1新保、3续保(See: 保单类型枚举) |
100 | - shopsType?: number; //适用门店类型 1.表示全部门店 2.表示部分门店 | |
97 | + shopsType?: number; //适用门店类型 1.表示全部门店 2.表示适用门店 | |
101 | 98 | startDate?: number; //生效日期 |
102 | 99 | endDate?: number; //到期日期 |
103 | 100 | shops?: Shops[]; |
... | ... | @@ -127,7 +124,7 @@ export function getTradingGiftPage(params?: PageParams): http.PromisePageResp<Pa |
127 | 124 | /** |
128 | 125 | * 成交有礼前置条件 |
129 | 126 | */ |
130 | -export function getPreconditionList(params: any): http.PromiseResp<PreconditionItem[]> { | |
127 | +export function getPreconditionList(params: { type?: number }): http.PromiseResp<PreconditionItem[]> { | |
131 | 128 | return request.get(`${ANGEL_Host}/buyinsurancegiftconfig/giftConditions`, { params }); |
132 | 129 | } |
133 | 130 | /** |
... | ... | @@ -172,8 +169,3 @@ export interface TerminateGiftConfigReq { |
172 | 169 | export function terminateGiftConfig(params: TerminateGiftConfigReq): http.PromiseResp<boolean> { |
173 | 170 | return request.post(`${ANGEL_Host}/buyinsurancegiftconfig/terminate/early`, { ...params }); |
174 | 171 | } |
175 | - | |
176 | -/**成交有礼提交审批*/ | |
177 | -export function applyGiftConfig(params: Data): http.PromiseResp<null> { | |
178 | - return request.post(`${ANGEL_Host}/buyinsurancegiftconfig/apply`, { ...params }); | |
179 | -} | ... | ... |
src/pages/carinsur/InsuranceTradingGift/components/AddModal.tsx
1 | -import React, { useState, useEffect } from 'react'; | |
2 | -import { Modal, Form, Spin, Select, Radio, DatePicker, message } from 'antd'; | |
1 | +import React, { useState, useEffect, useMemo } from 'react'; | |
2 | +import { Modal, Form, Spin, Select, Radio, message, InputNumber, Row, Col } from 'antd'; | |
3 | 3 | import CarTableTreeAuth from '@/components/CarTableTreeAuth'; |
4 | -import { CarAuthList } from '@/components/CarTableTreeAuth/entity'; | |
5 | 4 | import { PlusSquareOutlined } from '@ant-design/icons'; |
6 | -import TradingGiftConfig from './TradingGiftConfig'; | |
7 | -import { typeList, carListFilter, businessCarListFilter, businessFilterGiftOption, filterGiftOption } from '../entity'; | |
5 | +import { typeList, carListFilter, businessCarListFilter } from '../entity'; | |
8 | 6 | import useInitail from '@/hooks/useInitail'; |
9 | 7 | import { useStore } from '../index'; |
10 | 8 | import * as API from '../api'; |
11 | -import moment from 'moment'; | |
12 | 9 | import _ from 'lodash'; |
10 | +import { useRequest } from 'umi'; | |
11 | +import type { LabeledValue } from 'antd/lib/select'; | |
12 | +import { BtnTypeEnum } from '../store'; | |
13 | +import ShopSelectNew from '@/components/ShopSelectNew'; | |
13 | 14 | |
14 | 15 | export default function AddModal() { |
15 | 16 | const { |
16 | 17 | insurerList, |
17 | - shopsList, | |
18 | 18 | addVisible, |
19 | 19 | buyInsuranceGiftConfigId, |
20 | - readOnly, | |
21 | - setReadOnly, | |
22 | - type, | |
23 | - setType, | |
24 | 20 | setBuyInsuranceGiftConfigId, |
25 | 21 | setAddVisible, |
26 | 22 | setLoading: setPageLoading, |
27 | - tradingGiftConfigList, | |
28 | - setTradingGiftConfigList, | |
23 | + btnType, | |
29 | 24 | } = useStore(); |
30 | 25 | const [form] = Form.useForm(); |
31 | - const [value, setValue] = useState<number>(1); | |
26 | + | |
32 | 27 | const [delay, setDelay] = useState<boolean>(true); |
33 | 28 | const [loading, setLoading] = useState<boolean>(false); |
34 | - const { data: detailData, setData: setDetailData, setParams } = useInitail(API.getTradingGiftDetail, {}, {}, delay); | |
29 | + const { data: detailData, setParams, loading: detailLoading } = useInitail(API.getTradingGiftDetail, {}, {}, delay); | |
35 | 30 | |
36 | - useEffect(() => { | |
37 | - if (buyInsuranceGiftConfigId) { | |
38 | - setParams({ buyInsuranceGiftConfigId }, true); | |
39 | - setDelay(false); | |
40 | - } | |
41 | - }, [buyInsuranceGiftConfigId]); | |
31 | + const getPreconditionListHook = useRequest(API.getPreconditionList, { | |
32 | + throwOnError: true, | |
33 | + manual: true, | |
34 | + }); | |
42 | 35 | |
43 | 36 | useEffect(() => { |
44 | - if (Object.keys(detailData).length) { | |
45 | - const { insurers, type, shopsType, shops, applyCarList, giftOptionList, startDate, endDate } = detailData; | |
46 | - const insurerIds = insurers?.map((it) => it.insurerId); | |
47 | - setValue(shopsType || 1); | |
48 | - form.setFieldsValue({ | |
49 | - insurer: insurerList.filter((i) => insurerIds?.includes(i.id || 0)).map((it) => ({ value: it.id, label: it.name })), | |
50 | - type: typeList.filter((i) => i.value === type)[0], | |
51 | - shopsType, | |
52 | - shops: shops?.length ? shops?.map((i) => ({ value: i.shopId, label: i.shopName })) : undefined, | |
53 | - applyCarList: applyCarList?.length ? businessCarListFilter(applyCarList) : undefined, | |
54 | - giftOptionList: giftOptionList?.length ? businessFilterGiftOption(giftOptionList) : undefined, | |
55 | - time: startDate && endDate && [moment(startDate), moment(endDate)], | |
56 | - }); | |
57 | - setType(type); | |
58 | - setTradingGiftConfigList(businessFilterGiftOption(giftOptionList || [])); | |
37 | + if (addVisible) { | |
38 | + if (buyInsuranceGiftConfigId && Object.keys(detailData).length) { | |
39 | + const { insurers, type, shopsType, shops, applyCarList, giftOptionList } = detailData; | |
40 | + const insurerIds = insurers?.map((it) => it.insurerId); | |
41 | + getPreconditionListHook.run({ type }); | |
42 | + let initialValues = { | |
43 | + insurer: insurerList.filter((i) => insurerIds?.includes(i.id || 0)).map((it) => ({ value: it.id, label: it.name })), | |
44 | + type: typeList.filter((i) => i.value === type)[0], | |
45 | + shopsType, | |
46 | + shops: shops ? shops.map((i) => ({ value: i.shopId, label: i.shopName })) : undefined, | |
47 | + applyCarList: applyCarList ? businessCarListFilter(applyCarList) : undefined, | |
48 | + } as any; | |
49 | + if (giftOptionList && giftOptionList.length > 0) { | |
50 | + const { noCashBackVciPremiumAmount, vciReturnMoneyRate, cashCouponRate } = giftOptionList[0]; | |
51 | + initialValues = { | |
52 | + ...initialValues, | |
53 | + noCashBackVciPremiumAmount, | |
54 | + vciReturnMoneyRate: vciReturnMoneyRate ? Number((vciReturnMoneyRate * 100).toFixed(4)) : undefined, | |
55 | + cashCouponRate: cashCouponRate ? Number((cashCouponRate * 100).toFixed(4)) : undefined, | |
56 | + }; | |
57 | + } | |
58 | + form.setFieldsValue(initialValues); | |
59 | + } else { | |
60 | + getPreconditionListHook.run({ type: 1 }); | |
61 | + } | |
62 | + } else { | |
63 | + form.resetFields(); | |
59 | 64 | } |
60 | - }, [detailData]); | |
65 | + }, [addVisible, detailData, buyInsuranceGiftConfigId]); | |
61 | 66 | |
62 | 67 | useEffect(() => { |
63 | - if (value === 1) { | |
64 | - form.resetFields(['shops']); | |
68 | + if (buyInsuranceGiftConfigId) { | |
69 | + setParams({ buyInsuranceGiftConfigId }, true); | |
70 | + setDelay(false); | |
65 | 71 | } |
66 | - }, [value]); | |
72 | + }, [buyInsuranceGiftConfigId]); | |
67 | 73 | |
68 | 74 | function handleSave(feildValue: any) { |
69 | - const { insurer, type, shops, shopsType, time, giftOptionList, applyCarList } = feildValue; | |
75 | + const { insurer, type, shops, shopsType, applyCarList, noCashBackVciPremiumAmount, vciReturnMoneyRate, cashCouponRate } = feildValue; | |
70 | 76 | const params = { |
71 | 77 | buyInsuranceGiftConfigId, |
72 | - insurerIds: insurer?.length && insurer.map((i) => i.value), | |
78 | + insurerIds: insurer ? insurer.map((it: LabeledValue) => it.value) : undefined, | |
73 | 79 | type: type?.value, |
74 | 80 | shopsType, |
75 | - shops: shops?.length && shops.map((it) => ({ shopId: it.value, shopName: it.label })), | |
76 | - startDate: time[0] && moment(time[0]).valueOf(), | |
77 | - endDate: time[1] && moment(time[1]).valueOf(), | |
78 | - giftOptionList: giftOptionList.length && filterGiftOption(giftOptionList), | |
79 | - applyCar: carListFilter(_.cloneDeep(applyCarList))[0], | |
81 | + shops: shops ? shops.map((it: LabeledValue) => ({ shopId: it.value, shopName: it.label })) : undefined, | |
82 | + giftOptionList: [ | |
83 | + { | |
84 | + noCashBackVciPremiumAmount, | |
85 | + vciReturnMoneyRate: Number((vciReturnMoneyRate / 100).toFixed(4)), | |
86 | + cashCouponRate: Number((cashCouponRate / 100).toFixed(4)), | |
87 | + }, | |
88 | + ], | |
89 | + applyCar: applyCarList ? carListFilter(_.cloneDeep(applyCarList))[0] : undefined, | |
80 | 90 | }; |
91 | + if (btnType === BtnTypeEnum.复制) { | |
92 | + delete params.buyInsuranceGiftConfigId; | |
93 | + } | |
81 | 94 | setLoading(true); |
82 | 95 | API.AddTradingGift({ ...params }) |
83 | 96 | .then((res) => { |
... | ... | @@ -91,50 +104,52 @@ export default function AddModal() { |
91 | 104 | setLoading(false); |
92 | 105 | }); |
93 | 106 | } |
107 | + | |
108 | + const tip = useMemo(() => { | |
109 | + if (getPreconditionListHook.data && getPreconditionListHook.data.length > 0) { | |
110 | + const tipObj = getPreconditionListHook.data.find((i) => i.name?.includes('商业险保费')); | |
111 | + return tipObj ? tipObj.name : ''; | |
112 | + } | |
113 | + return ''; | |
114 | + }, [getPreconditionListHook.data]); | |
115 | + | |
94 | 116 | return ( |
95 | 117 | <Modal |
96 | - title={`${readOnly ? '查看' : Object.keys(detailData).length ? '编辑' : '新增'}成交有礼配置`} | |
118 | + title={`${BtnTypeEnum[btnType ?? 0]}成交有礼配置`} | |
97 | 119 | open={addVisible} |
98 | 120 | maskClosable={false} |
99 | 121 | onCancel={() => setAddVisible(false)} |
122 | + destroyOnClose | |
100 | 123 | onOk={() => { |
101 | - if (readOnly) { | |
102 | - setAddVisible(false); | |
103 | - } else { | |
104 | - form.submit(); | |
105 | - } | |
124 | + form.submit(); | |
106 | 125 | }} |
107 | 126 | afterClose={() => { |
108 | 127 | form.resetFields(); |
109 | - setTradingGiftConfigList([]); | |
110 | 128 | setBuyInsuranceGiftConfigId(undefined); |
111 | - setValue(1); | |
112 | - setDetailData({}); | |
113 | - setDelay(false); | |
114 | - setType(undefined); | |
115 | - readOnly && setReadOnly(false); | |
116 | 129 | }} |
117 | 130 | width="68%" |
118 | 131 | > |
119 | - <Spin spinning={loading}> | |
132 | + <Spin spinning={loading || (buyInsuranceGiftConfigId ? detailLoading : false)}> | |
120 | 133 | <Form |
121 | 134 | form={form} |
122 | 135 | onFinish={handleSave} |
123 | 136 | wrapperCol={{ span: 20 }} |
124 | 137 | labelCol={{ span: 4 }} |
125 | - disabled={readOnly} | |
126 | 138 | initialValues={{ |
127 | 139 | shopsType: 1, |
140 | + type: { | |
141 | + label: '新保', | |
142 | + value: 1, | |
143 | + }, // 默认新保 | |
128 | 144 | }} |
129 | 145 | > |
130 | - <Form.Item label="保险公司:" name="insurer" rules={[{ required: true, message: '请选择保险公司' }]}> | |
146 | + <Form.Item label="保险公司" name="insurer" rules={[{ required: true, message: '请选择保险公司' }]}> | |
131 | 147 | <Select |
132 | 148 | placeholder="请选择保险公司" |
133 | 149 | mode="multiple" |
134 | 150 | showSearch |
135 | 151 | optionFilterProp="children" |
136 | 152 | labelInValue |
137 | - onSelect={(it: any) => {}} | |
138 | 153 | filterOption={(input, option: any) => option?.children.indexOf(input) >= 0} |
139 | 154 | > |
140 | 155 | {insurerList && |
... | ... | @@ -145,19 +160,19 @@ export default function AddModal() { |
145 | 160 | ))} |
146 | 161 | </Select> |
147 | 162 | </Form.Item> |
148 | - <Form.Item label="成交类型:" name="type" rules={[{ required: true, message: '请选择成交类型' }]}> | |
163 | + <Form.Item label="成交类型" name="type" rules={[{ required: true, message: '请选择成交类型' }]}> | |
149 | 164 | <Select |
150 | 165 | placeholder="请选择成交类型" |
151 | 166 | showSearch |
152 | 167 | optionFilterProp="children" |
153 | 168 | labelInValue |
169 | + filterOption={(input, option: any) => option?.children.indexOf(input) >= 0} | |
154 | 170 | onSelect={(it: any) => { |
155 | - setType(it.value); | |
156 | - if (type !== it.value && tradingGiftConfigList.length) { | |
157 | - setTradingGiftConfigList([]); | |
171 | + if (getPreconditionListHook.loading) { | |
172 | + getPreconditionListHook.cancel(); | |
158 | 173 | } |
174 | + getPreconditionListHook.run({ type: it.value }); | |
159 | 175 | }} |
160 | - filterOption={(input, option: any) => option?.children.indexOf(input) >= 0} | |
161 | 176 | > |
162 | 177 | {typeList && |
163 | 178 | typeList.map((item: any) => ( |
... | ... | @@ -167,60 +182,122 @@ export default function AddModal() { |
167 | 182 | ))} |
168 | 183 | </Select> |
169 | 184 | </Form.Item> |
170 | - <Form.Item label="适用门店:" name="shopsType" rules={[{ required: true, message: '请选择适用门店' }]}> | |
171 | - <Radio.Group onChange={({ target }) => setValue(target.value || 1)}> | |
185 | + <Form.Item label="适用门店" name="shopsType" rules={[{ required: true, message: '请选择适用门店' }]}> | |
186 | + <Radio.Group> | |
172 | 187 | <Radio value={1}>全部门店</Radio> |
173 | 188 | <Radio value={2}>部分门店</Radio> |
174 | 189 | </Radio.Group> |
175 | 190 | </Form.Item> |
176 | - {value === 2 && ( | |
177 | - <Form.Item label="门店:" name="shops" rules={[{ required: false, message: '请选择门店' }]}> | |
178 | - <Select | |
179 | - placeholder="请选择门店或输入关键字筛选" | |
180 | - showSearch | |
181 | - mode="multiple" | |
182 | - optionFilterProp="children" | |
183 | - labelInValue | |
184 | - onSelect={(it: any) => {}} | |
185 | - filterOption={(input, option: any) => option?.children.indexOf(input) >= 0} | |
186 | - > | |
187 | - {shopsList && | |
188 | - shopsList.map((item: any) => ( | |
189 | - <Select.Option value={item.id} key={item.id}> | |
190 | - {item.name} | |
191 | - </Select.Option> | |
192 | - ))} | |
193 | - </Select> | |
194 | - </Form.Item> | |
195 | - )} | |
196 | 191 | <Form.Item |
197 | - name="applyCarList" | |
198 | - label="适用车辆:" | |
199 | - rules={[{ required: true, message: '选择车辆' }]} | |
200 | - tooltip={ | |
201 | - <span style={{ color: '#ccc', fontSize: 12 }}> | |
202 | - 点击图标 | |
203 | - <PlusSquareOutlined /> | |
204 | - 展开详情 | |
205 | - </span> | |
206 | - } | |
192 | + noStyle | |
193 | + shouldUpdate={(prev, curr) => { | |
194 | + if (prev.shopsType !== curr.shopsType && curr.shopsType.value === 1) { | |
195 | + form.setFieldsValue({ | |
196 | + shops: [], | |
197 | + }); | |
198 | + } | |
199 | + return prev.shopsType !== curr.shopsType; | |
200 | + }} | |
207 | 201 | > |
208 | - <CarTableTreeAuth brandMultiple={false} /> | |
202 | + {({ getFieldValue }) => { | |
203 | + const shopsType = getFieldValue('shopsType'); | |
204 | + if (shopsType !== 2) return null; | |
205 | + return ( | |
206 | + <Row style={{ marginBottom: 24 }}> | |
207 | + <Col span={4} /> | |
208 | + <Col span={20}> | |
209 | + <Form.Item label="" name="shops" rules={[{ required: true, message: '请选择门店' }]}> | |
210 | + <ShopSelectNew multiple destroyOnClose placeholder="请选择门店" /> | |
211 | + </Form.Item> | |
212 | + </Col> | |
213 | + </Row> | |
214 | + ); | |
215 | + }} | |
209 | 216 | </Form.Item> |
210 | - <Form.Item name="time" label="签单日期:" rules={[{ required: true, message: '选择签单日期' }]}> | |
211 | - <DatePicker.RangePicker style={{ width: '100%' }} /> | |
217 | + <Form.Item | |
218 | + noStyle | |
219 | + shouldUpdate={(prev, curr) => { | |
220 | + return prev.type !== curr.type; | |
221 | + }} | |
222 | + > | |
223 | + {({ getFieldValue }) => { | |
224 | + const type = getFieldValue('type')?.value; | |
225 | + if (!type || type === 4) { | |
226 | + return null; | |
227 | + } | |
228 | + return ( | |
229 | + <Form.Item | |
230 | + name="applyCarList" | |
231 | + label="适用车辆" | |
232 | + rules={[{ required: true, message: '选择车辆' }]} | |
233 | + tooltip={ | |
234 | + <span style={{ color: '#ccc', fontSize: 12 }}> | |
235 | + 点击图标 | |
236 | + <PlusSquareOutlined /> | |
237 | + 展开详情 | |
238 | + </span> | |
239 | + } | |
240 | + > | |
241 | + <CarTableTreeAuth brandMultiple={false} /> | |
242 | + </Form.Item> | |
243 | + ); | |
244 | + }} | |
245 | + </Form.Item> | |
246 | + <Form.Item | |
247 | + name="noCashBackVciPremiumAmount" | |
248 | + label="不享受成交有礼情况" | |
249 | + style={{ marginBottom: 0 }} | |
250 | + rules={[ | |
251 | + { | |
252 | + required: true, | |
253 | + message: '请填写商业险保费', | |
254 | + }, | |
255 | + ]} | |
256 | + > | |
257 | + <Row align="middle"> | |
258 | + <span style={{ marginRight: 5 }}>{tip}</span> | |
259 | + <Form.Item name="noCashBackVciPremiumAmount" label="" style={{ marginBottom: 0 }}> | |
260 | + <InputNumber min={0.01} max={99999.99} placeholder="请输入" precision={2} addonAfter="元" /> | |
261 | + </Form.Item> | |
262 | + </Row> | |
263 | + </Form.Item> | |
264 | + {getPreconditionListHook.data && getPreconditionListHook.data.length > 0 && ( | |
265 | + <Row style={{ marginBottom: 24 }}> | |
266 | + <Col span={4} /> | |
267 | + <Col span={20}> | |
268 | + {getPreconditionListHook.data.map((i) => { | |
269 | + return i.name?.includes('商业险保费') ? null : ( | |
270 | + <div style={{ marginTop: 5 }} key={i.name}> | |
271 | + {i.name} | |
272 | + </div> | |
273 | + ); | |
274 | + })} | |
275 | + </Col> | |
276 | + </Row> | |
277 | + )} | |
278 | + <Form.Item | |
279 | + name="vciReturnMoneyRate" | |
280 | + label="返现比例" | |
281 | + rules={[ | |
282 | + { | |
283 | + required: true, | |
284 | + message: '请填写返现比例', | |
285 | + }, | |
286 | + ]} | |
287 | + > | |
288 | + <InputNumber min={0.01} max={99.99} placeholder="请输入" precision={2} addonAfter="%" /> | |
212 | 289 | </Form.Item> |
213 | 290 | <Form.Item |
214 | - name="giftOptionList" | |
215 | - label={ | |
216 | - <div> | |
217 | - <span>成交有礼选项</span> | |
218 | - </div> | |
219 | - } | |
220 | - rules={[{ required: true, message: '配置成交有礼条件' }]} | |
221 | - tooltip={<span style={{ color: '#ccc', fontSize: 12 }}>客户从符合条件的选项中任选其一</span>} | |
291 | + name="cashCouponRate" | |
292 | + label="返现金券比例" | |
293 | + rules={[ | |
294 | + { | |
295 | + required: true, | |
296 | + message: '请填写返现比例', | |
297 | + }, | |
298 | + ]} | |
222 | 299 | > |
223 | - <TradingGiftConfig /> | |
300 | + <InputNumber min={0.01} max={99.99} placeholder="请输入" precision={2} addonAfter="%" /> | |
224 | 301 | </Form.Item> |
225 | 302 | </Form> |
226 | 303 | </Spin> | ... | ... |
src/pages/carinsur/InsuranceTradingGift/components/AddTradingGiftModal.tsx deleted
1 | -import React, { useState, useEffect } from 'react'; | |
2 | -import { Modal, Form, Select, InputNumber, message } from 'antd'; | |
3 | -import useInitail from '@/hooks/useInitail'; | |
4 | -import CouponConfig from './CouponConfig'; | |
5 | -import { useStore } from '../index'; | |
6 | -import * as API from '../api'; | |
7 | - | |
8 | -export default function AddTradingGiftModal() { | |
9 | - const { | |
10 | - tradingGiftVisible, | |
11 | - setTradingGiftVisible, | |
12 | - couponList, | |
13 | - setCouponList, | |
14 | - tradingGiftConfigList, | |
15 | - setTradingGiftConfigList, | |
16 | - tradingGiftItem, | |
17 | - setTradingGiftItem, | |
18 | - type, | |
19 | - readOnly, | |
20 | - } = useStore(); | |
21 | - const [gift, setGift] = useState<string[]>([]); | |
22 | - const [delay, setDelay] = useState<boolean>(true); | |
23 | - const [form] = Form.useForm(); | |
24 | - const { data: preconditionList, setParams } = useInitail(API.getPreconditionList, [], { type }, delay); | |
25 | - const { data: exchangeList } = useInitail(API.getExchangeList, [], {}); | |
26 | - | |
27 | - useEffect(() => { | |
28 | - if (type) { | |
29 | - setParams({ type }, true); | |
30 | - setDelay(false); | |
31 | - } | |
32 | - }, [type]); | |
33 | - | |
34 | - useEffect(() => { | |
35 | - if (Object.keys(tradingGiftItem).length) { | |
36 | - const { conditions, exchangeMethod, vciReturnMoneyRate, couponConfigList } = tradingGiftItem; | |
37 | - form.setFieldsValue({ | |
38 | - conditions, | |
39 | - exchangeMethod, | |
40 | - vciReturnMoneyRate, | |
41 | - couponConfigList, | |
42 | - }); | |
43 | - setGift((exchangeMethod || ([] as string[])).map((i) => i.value)); | |
44 | - setCouponList(couponConfigList || []); | |
45 | - } | |
46 | - }, [tradingGiftItem]); | |
47 | - | |
48 | - useEffect(() => { | |
49 | - if (gift.length < 2) { | |
50 | - if (!gift.length) { | |
51 | - setCouponList([]); | |
52 | - form.resetFields(['vciReturnMoneyRate', 'discountCouponCodes']); | |
53 | - return; | |
54 | - } | |
55 | - if (gift[0] === 'COUPON') { | |
56 | - form.resetFields(['vciReturnMoneyRate']); | |
57 | - } else { | |
58 | - setCouponList([]); | |
59 | - form.resetFields(['discountCouponCodes']); | |
60 | - } | |
61 | - } | |
62 | - }, [gift]); | |
63 | - | |
64 | - function handleTrading(feildValue: any) { | |
65 | - if (couponList?.length) { | |
66 | - let noQuantitys: API.CouponResult[] = []; //未填数量 | |
67 | - let noValidityPeriodTypes: API.CouponResult[] = []; //有效期类型 | |
68 | - let noValidityPeriods: API.CouponResult[] = []; //未填有效期 | |
69 | - couponList.forEach((item: API.CouponResult) => { | |
70 | - if (!item.quantity) { | |
71 | - noQuantitys.push(item); | |
72 | - } else if (!item.validityPeriodType) { | |
73 | - noValidityPeriodTypes.push(item); | |
74 | - } else if (item.validityPeriodType !== 1 && !item.validityPeriod) { | |
75 | - noValidityPeriods.push(item); | |
76 | - } | |
77 | - }); | |
78 | - if (noQuantitys.length) { | |
79 | - message.error(`请配置${noQuantitys[0].alias}优惠券的数量`); | |
80 | - return; | |
81 | - } else if (noValidityPeriodTypes.length) { | |
82 | - message.error(`请配置${noValidityPeriodTypes[0].alias}优惠券的有效期类型`); | |
83 | - return; | |
84 | - } else if (noValidityPeriods.length) { | |
85 | - message.error(`请配置${noValidityPeriods[0].alias}优惠券的有效期`); | |
86 | - return; | |
87 | - } | |
88 | - } | |
89 | - if (Object.keys(tradingGiftItem).length) { | |
90 | - const { key } = tradingGiftItem; | |
91 | - const _tradingGiftConfigList = tradingGiftConfigList.map((it) => { | |
92 | - if (it.key === key) { | |
93 | - return { ...feildValue, key }; | |
94 | - } | |
95 | - return it; | |
96 | - }); | |
97 | - setTradingGiftConfigList([..._tradingGiftConfigList]); | |
98 | - } else { | |
99 | - setTradingGiftConfigList([...tradingGiftConfigList, { ...feildValue, key: tradingGiftConfigList.length + 1 }]); | |
100 | - } | |
101 | - setTradingGiftItem({}); | |
102 | - setCouponList([]); | |
103 | - form.resetFields(); | |
104 | - setTradingGiftVisible(false); | |
105 | - } | |
106 | - return ( | |
107 | - <Modal | |
108 | - title={`${readOnly ? '查看' : Object.keys(tradingGiftItem).length ? '编辑' : '新增'}成交有礼选项`} | |
109 | - open={tradingGiftVisible} | |
110 | - onCancel={() => { | |
111 | - setTradingGiftVisible(false); | |
112 | - }} | |
113 | - onOk={form.submit} | |
114 | - afterClose={() => { | |
115 | - form.resetFields(); | |
116 | - setCouponList([]); | |
117 | - setGift([]); | |
118 | - setTradingGiftItem({}); | |
119 | - }} | |
120 | - width="60%" | |
121 | - > | |
122 | - <Form form={form} onFinish={handleTrading}> | |
123 | - <Form.Item noStyle shouldUpdate> | |
124 | - {({ getFieldValue }) => { | |
125 | - const conditions: { value: string; label: string }[] = getFieldValue('conditions') || []; | |
126 | - const _conditions = conditions.map((i) => i.value); | |
127 | - const filterList = preconditionList.filter((i) => i.value && _conditions.includes(i.value)) || []; | |
128 | - const valueList = filterList.map((i) => i.value); | |
129 | - const batchNumberList = filterList.map((i) => i.batchNumber); | |
130 | - return ( | |
131 | - <Form.Item label="前置条件:" name="conditions" rules={[{ required: true, message: '请选择前置条件' }]}> | |
132 | - <Select | |
133 | - placeholder="请选择前置条件" | |
134 | - showSearch | |
135 | - mode="multiple" | |
136 | - optionFilterProp="children" | |
137 | - labelInValue | |
138 | - onSelect={(it: any) => {}} | |
139 | - filterOption={(input, option: any) => option?.children.indexOf(input) >= 0} | |
140 | - > | |
141 | - {preconditionList && | |
142 | - preconditionList.map((item: API.PreconditionItem) => ( | |
143 | - <Select.Option | |
144 | - disabled={batchNumberList.includes(item.batchNumber) && !valueList.includes(item.value)} | |
145 | - value={item.value} | |
146 | - key={item.value} | |
147 | - > | |
148 | - {item.name} | |
149 | - </Select.Option> | |
150 | - ))} | |
151 | - </Select> | |
152 | - </Form.Item> | |
153 | - ); | |
154 | - }} | |
155 | - </Form.Item> | |
156 | - <Form.Item label="礼品兑换方式:" name="exchangeMethod" rules={[{ required: true, message: '请选择礼品兑换方式' }]}> | |
157 | - <Select | |
158 | - placeholder="请选择礼品兑换方式" | |
159 | - showSearch | |
160 | - mode="multiple" | |
161 | - optionFilterProp="children" | |
162 | - labelInValue | |
163 | - onChange={(it) => { | |
164 | - setGift(it.map((i) => i.value)); | |
165 | - }} | |
166 | - onSelect={(it: any) => {}} | |
167 | - filterOption={(input, option: any) => option?.children.indexOf(input) >= 0} | |
168 | - > | |
169 | - {exchangeList && | |
170 | - exchangeList.map((item: any) => ( | |
171 | - <Select.Option value={item.value} key={item.value}> | |
172 | - {item.name} | |
173 | - </Select.Option> | |
174 | - ))} | |
175 | - </Select> | |
176 | - </Form.Item> | |
177 | - {gift.includes('CASH_BACK') && ( | |
178 | - <> | |
179 | - <Form.Item label="商业险返现比例:" name="vciReturnMoneyRate" rules={[{ required: true, message: '请填写续保商业险返现比例' }]}> | |
180 | - <InputNumber placeholder="请输入" addonAfter="%" style={{ width: '50%' }} max={100} min={0} maxLength={5} precision={2} /> | |
181 | - </Form.Item> | |
182 | - {/* <Form.Item label="驾乘险返现比例:" name="daiReturnMoneyRate" rules={[{ required: true, message: '请填写续保驾乘险返现比例' }]}> | |
183 | - <InputNumber placeholder="请输入" addonAfter="%" style={{ width: '50%' }} max={100} min={0} maxLength={5} precision={2} /> | |
184 | - </Form.Item> */} | |
185 | - </> | |
186 | - )} | |
187 | - {gift.includes('COUPON') && ( | |
188 | - <> | |
189 | - <Form.Item label="优惠券:" name="couponConfigList" rules={[{ required: true, message: '请配置优惠券' }]}> | |
190 | - <CouponConfig /> | |
191 | - </Form.Item> | |
192 | - </> | |
193 | - )} | |
194 | - </Form> | |
195 | - </Modal> | |
196 | - ); | |
197 | -} |
src/pages/carinsur/InsuranceTradingGift/components/ApprovalModal.tsx deleted
1 | -/* | |
2 | - * @Author: wangqiang@feewee.cn | |
3 | - * @Date: 2022-10-26 09:24:59 | |
4 | - * @LastEditors: 谢忠泽 xiezhongze@feewee.cn | |
5 | - * @LastEditTime: 2023-07-07 10:05:03 | |
6 | - */ | |
7 | -import ApprovalProgress from "@/components/ApprovalProgress"; | |
8 | -import { Button, Modal } from "antd"; | |
9 | -import React from "react"; | |
10 | -import { useStore } from "../index"; | |
11 | - | |
12 | -export default function ApprovalProgressModal() { | |
13 | - const { approvalProgressModalInfo, setApprovalProgressModalInfo } = | |
14 | - useStore(); | |
15 | - | |
16 | - const onCancel = () => setApprovalProgressModalInfo({ approvalOrderNo: '', visible: false }); | |
17 | - | |
18 | - return ( | |
19 | - <Modal | |
20 | - title={`${ | |
21 | - approvalProgressModalInfo.title | |
22 | - ? approvalProgressModalInfo.title + "-" | |
23 | - : "" | |
24 | - }审批进度`} | |
25 | - open={approvalProgressModalInfo.visible} | |
26 | - onCancel={onCancel} | |
27 | - maskClosable={false} | |
28 | - destroyOnClose | |
29 | - footer={[ | |
30 | - <Button key="cancel" onClick={onCancel}> | |
31 | - 关闭 | |
32 | - </Button>, | |
33 | - ]} | |
34 | - > | |
35 | - <ApprovalProgress orderNo={approvalProgressModalInfo.approvalOrderNo} /> | |
36 | - </Modal> | |
37 | - ); | |
38 | -} |
src/pages/carinsur/InsuranceTradingGift/components/CarModal.tsx
1 | -import React, { useState, useEffect } from "react"; | |
2 | -import { Button, Modal, Table } from "antd"; | |
1 | +import React, { useState, useEffect } from 'react'; | |
2 | +import { Button, Modal } from 'antd'; | |
3 | 3 | import CarTableTreeAuth from '@/components/CarTableTreeAuth'; |
4 | 4 | import { useStore } from '../index'; |
5 | 5 | import { businessCarListFilter } from '../entity'; |
6 | -import * as API from '../api'; | |
7 | 6 | |
8 | 7 | export default function CarModal() { |
9 | - const { carModalData, setCarModalData } = useStore(); | |
10 | - const { cars, visible } = carModalData; | |
11 | - const [carData, setCarData] = useState<any[]>([]); | |
12 | - useEffect(() => { | |
13 | - if (cars?.length) { | |
14 | - setCarData(businessCarListFilter(cars)); | |
15 | - } | |
16 | - }, [cars]); | |
17 | - return ( | |
18 | - <Modal | |
19 | - title="适用车辆" | |
20 | - width={600} | |
21 | - open={visible} | |
22 | - maskClosable={false} | |
23 | - onCancel={() => setCarModalData({cars: [], visible: false})} | |
24 | - footer={[ | |
25 | - <Button key="1" onClick={() => setCarModalData({cars: [], visible: false})}>取消</Button>, | |
26 | - ]} | |
27 | - > | |
28 | - <CarTableTreeAuth value={carData} disabled brandMultiple={false} /> | |
29 | - </Modal> | |
30 | - ); | |
31 | -} | |
32 | 8 | \ No newline at end of file |
9 | + const { carModalData, setCarModalData } = useStore(); | |
10 | + const { cars, visible } = carModalData; | |
11 | + const [carData, setCarData] = useState<any[]>([]); | |
12 | + useEffect(() => { | |
13 | + if (cars?.length) { | |
14 | + setCarData(businessCarListFilter(cars)); | |
15 | + } | |
16 | + }, [cars]); | |
17 | + return ( | |
18 | + <Modal | |
19 | + title="适用车辆" | |
20 | + width={600} | |
21 | + open={visible} | |
22 | + maskClosable={false} | |
23 | + onCancel={() => setCarModalData({ cars: [], visible: false })} | |
24 | + destroyOnClose | |
25 | + footer={[ | |
26 | + <Button key="1" onClick={() => setCarModalData({ cars: [], visible: false })}> | |
27 | + 取消 | |
28 | + </Button>, | |
29 | + ]} | |
30 | + > | |
31 | + <CarTableTreeAuth value={carData} disabled brandMultiple={false} /> | |
32 | + </Modal> | |
33 | + ); | |
34 | +} | ... | ... |
src/pages/carinsur/InsuranceTradingGift/components/CouponConfig.tsx deleted
1 | -import React, { useState, useEffect } from 'react'; | |
2 | -import { Table, Select, Card, Button, Input, message, Divider, Popconfirm } from 'antd'; | |
3 | -import CouponConfigModal from '@/pages/coupon/CouponConfig'; | |
4 | -import { PlusOutlined } from '@ant-design/icons'; | |
5 | -import { useStore } from '../index'; | |
6 | -import { divide, cloneDeep } from 'lodash'; | |
7 | -import * as API from '../api'; | |
8 | - | |
9 | -interface Props { | |
10 | - onChange?: (data: API.CouponResult[]) => void; | |
11 | - value?: API.CouponResult[]; | |
12 | -} | |
13 | - | |
14 | -const { Column } = Table; | |
15 | - | |
16 | -export default function CouponConfig({ onChange, value = [] }: Props) { | |
17 | - const [row, setRow] = useState<API.CouponResult>({}); | |
18 | - const { readOnly, couponConfigVisible, setCouponConfigVisible, couponList, setCouponList, confNo, setConfNo } = useStore(); | |
19 | - | |
20 | - function handleSaveCoupon(value: any) { | |
21 | - const { classifyName, classifyCode, aliasName, amount, confNo } = value; | |
22 | - const _couponList = cloneDeep(couponList); | |
23 | - const nos = couponList.map((i) => i.no); | |
24 | - let arr: API.CouponResult[] = []; | |
25 | - if (!nos.includes(confNo)) { | |
26 | - _couponList.push({ no: confNo, typeName: classifyName, typeNo: classifyCode, alias: aliasName, amount }); | |
27 | - arr = _couponList; | |
28 | - } else { | |
29 | - arr = _couponList.map((it) => { | |
30 | - if (it.no === confNo) { | |
31 | - const { quantity, validityPeriodType, validityPeriod, disabled } = row; | |
32 | - return { | |
33 | - no: confNo, | |
34 | - typeName: classifyName, | |
35 | - typeNo: classifyCode, | |
36 | - alias: aliasName, | |
37 | - amount, | |
38 | - quantity, | |
39 | - validityPeriodType, | |
40 | - validityPeriod, | |
41 | - disabled, | |
42 | - }; | |
43 | - } | |
44 | - return it; | |
45 | - }); | |
46 | - setRow({}); | |
47 | - } | |
48 | - setCouponList([...arr]); | |
49 | - onChange && onChange([...arr]); | |
50 | - setCouponConfigVisible(false); | |
51 | - } | |
52 | - | |
53 | - /** | |
54 | - * @description: 设置业务优惠卷配置 | |
55 | - * @param {*} | |
56 | - * @return {*} | |
57 | - */ | |
58 | - function handleCouponConfig(record: API.CouponResult, value: string, keyName: string) { | |
59 | - const { no } = record; | |
60 | - const _couponList = cloneDeep(couponList); | |
61 | - let newList: API.CouponResult[] = []; | |
62 | - | |
63 | - if (!value) { | |
64 | - newList = _couponList.map((item: API.CouponResult) => { | |
65 | - if (item.no === no) { | |
66 | - item[keyName] = null; | |
67 | - } | |
68 | - return item; | |
69 | - }); | |
70 | - } else { | |
71 | - const reg = /^[1-9]\d*$/; | |
72 | - if (!reg.test(String(value))) { | |
73 | - message.error('请填写正整数'); | |
74 | - return; | |
75 | - } | |
76 | - | |
77 | - newList = _couponList.map((item: API.CouponResult) => { | |
78 | - if (item.no === no) { | |
79 | - if (value) { | |
80 | - item[keyName] = Number(value); | |
81 | - } else { | |
82 | - item[keyName] = null; | |
83 | - } | |
84 | - } | |
85 | - return item; | |
86 | - }); | |
87 | - } | |
88 | - setCouponList([...newList]); | |
89 | - onChange && onChange([...newList]); | |
90 | - } | |
91 | - | |
92 | - /** | |
93 | - * @description: 选择有效期 | |
94 | - * @param {*} | |
95 | - * @return {*} | |
96 | - */ | |
97 | - function selectValidityPeriodType(record: API.CouponResult, value: any) { | |
98 | - const _couponList = cloneDeep(couponList); | |
99 | - const { no } = record; | |
100 | - const newList = _couponList.map((item: API.CouponResult) => { | |
101 | - if (item.no === no) { | |
102 | - item.validityPeriodType = value; | |
103 | - if (value === 1) { | |
104 | - delete item.validityPeriod; | |
105 | - item.disabled = true; | |
106 | - } else { | |
107 | - item.disabled = false; | |
108 | - } | |
109 | - } | |
110 | - return item; | |
111 | - }); | |
112 | - setCouponList([...newList]); | |
113 | - onChange && onChange([...newList]); | |
114 | - } | |
115 | - | |
116 | - /** | |
117 | - * @description: 删除优惠卷配置 | |
118 | - * @param {API} item | |
119 | - * @return {*} | |
120 | - */ | |
121 | - async function _delete(item: API.CouponResult) { | |
122 | - const { no = '' } = item; | |
123 | - try { | |
124 | - await API.delCoupon(no); | |
125 | - const _couponList = cloneDeep(couponList); | |
126 | - const filterList = _couponList.filter((it) => it.no !== no); | |
127 | - setCouponList([...filterList]); | |
128 | - onChange && onChange([...filterList]); | |
129 | - } catch (error: any) { | |
130 | - message.error(error.message); | |
131 | - } | |
132 | - } | |
133 | - /** | |
134 | - * @description: 编辑优惠卷配置 | |
135 | - * @param {API} item | |
136 | - * @return {*} | |
137 | - */ | |
138 | - function edit(item: API.CouponResult) { | |
139 | - const { no = '' } = item; | |
140 | - setRow({ ...item }); | |
141 | - setConfNo(no); | |
142 | - setCouponConfigVisible(true); | |
143 | - } | |
144 | - return ( | |
145 | - <Card | |
146 | - extra={ | |
147 | - <Button | |
148 | - type="primary" | |
149 | - icon={<PlusOutlined />} | |
150 | - onClick={() => { | |
151 | - setCouponConfigVisible(true); | |
152 | - }} | |
153 | - > | |
154 | - 新增 | |
155 | - </Button> | |
156 | - } | |
157 | - > | |
158 | - <Table dataSource={couponList || []} rowKey={(item) => `${item.no}`}> | |
159 | - <Column title="类型" dataIndex="typeName" width={135} /> | |
160 | - <Column title="别名" dataIndex="alias" width={130} /> | |
161 | - <Column title="券面金额(元)" dataIndex="amount" width={120} /> | |
162 | - <Column | |
163 | - title="数量(张)" | |
164 | - dataIndex="quantity" | |
165 | - width={120} | |
166 | - render={(text, record: any) => ( | |
167 | - <Input value={record.quantity} onChange={(value) => handleCouponConfig(record, value.target.value, 'quantity')} placeholder="请输入" /> | |
168 | - )} | |
169 | - /> | |
170 | - <Column | |
171 | - title="有效期类型" | |
172 | - dataIndex="validityPeriodType" | |
173 | - width={120} | |
174 | - render={(text, record: any) => ( | |
175 | - <Select placeholder="请选择" value={record.validityPeriodType} onChange={(value) => selectValidityPeriodType(record, value)}> | |
176 | - <Select.Option key="1_1" value={1}> | |
177 | - 当天有效 | |
178 | - </Select.Option> | |
179 | - <Select.Option key="2_2" value={2}> | |
180 | - 小时 | |
181 | - </Select.Option> | |
182 | - <Select.Option key="3_3" value={3}> | |
183 | - 天 | |
184 | - </Select.Option> | |
185 | - </Select> | |
186 | - )} | |
187 | - /> | |
188 | - <Column | |
189 | - title="有效期" | |
190 | - dataIndex="validityPeriod" | |
191 | - width={100} | |
192 | - render={(text, record: any) => ( | |
193 | - <Input | |
194 | - value={record.validityPeriod} | |
195 | - disabled={record.disabled} | |
196 | - onChange={(value) => handleCouponConfig(record, value.target.value, 'validityPeriod')} | |
197 | - placeholder="请输入" | |
198 | - /> | |
199 | - )} | |
200 | - /> | |
201 | - <Column | |
202 | - title="操作" | |
203 | - align="center" | |
204 | - width={120} | |
205 | - render={(text, _item: API.CouponResult) => ( | |
206 | - <span> | |
207 | - <a | |
208 | - onClick={() => { | |
209 | - edit(_item); | |
210 | - }} | |
211 | - style={{ marginLeft: 5 }} | |
212 | - > | |
213 | - {readOnly ? '查看' : '编辑'} | |
214 | - </a> | |
215 | - {!readOnly && ( | |
216 | - <> | |
217 | - <Divider type="vertical" /> | |
218 | - <Popconfirm title="是否删除?" onConfirm={() => _delete(_item)} okText="确定" cancelText="取消"> | |
219 | - <a | |
220 | - onClick={(e) => { | |
221 | - e.preventDefault(); | |
222 | - }} | |
223 | - style={{ color: 'red', marginLeft: 5 }} | |
224 | - > | |
225 | - 删除 | |
226 | - </a> | |
227 | - </Popconfirm> | |
228 | - </> | |
229 | - )} | |
230 | - </span> | |
231 | - )} | |
232 | - /> | |
233 | - </Table> | |
234 | - <CouponConfigModal | |
235 | - remark="成交有礼" | |
236 | - confNo={confNo} | |
237 | - visible={couponConfigVisible} | |
238 | - onSave={(value: any) => { | |
239 | - handleSaveCoupon(value); | |
240 | - setConfNo(''); | |
241 | - }} | |
242 | - onCancel={() => { | |
243 | - setCouponConfigVisible(false); | |
244 | - setConfNo(''); | |
245 | - setRow({}); | |
246 | - }} | |
247 | - /> | |
248 | - </Card> | |
249 | - ); | |
250 | -} |
src/pages/carinsur/InsuranceTradingGift/components/Filter.tsx
1 | 1 | import React, { useState } from 'react'; |
2 | -import { Select, DatePicker } from 'antd'; | |
3 | -import { getShopApi } from '@/common/api'; | |
4 | -import { getInsurerList } from '../api'; | |
5 | -import useInitail from '@/hooks/useInitail'; | |
2 | +import { Select } from 'antd'; | |
6 | 3 | import CascaderSpec from '@/components/Condition/CascaderSeries/SpecSelect'; |
7 | 4 | import { useStore } from '../index'; |
8 | 5 | import { debounce } from 'lodash'; |
9 | 6 | |
10 | 7 | interface Props { |
11 | - onChange?:(params:{})=> any; | |
8 | + onChange?: (params: {}) => any; | |
12 | 9 | } |
13 | 10 | |
14 | -function Filter({ onChange }:Props) { | |
15 | - const { insurerList, shopsList } = useStore(); | |
16 | - const [value, setValue] = useState<{ id: number, name: string }[]>([]); | |
17 | - const _onChange = debounce((params:any) => { | |
18 | - onChange && onChange(params); | |
19 | - }, 500); | |
20 | - return ( | |
21 | - <div> | |
22 | - <Select | |
23 | - style={{ marginRight: 20, minWidth: 250 }} | |
24 | - placeholder="请选择保险公司" | |
25 | - showSearch | |
26 | - optionFilterProp="children" | |
27 | - allowClear | |
28 | - onChange={(insurerId) => { | |
29 | - _onChange({insurerId}); | |
30 | - }} | |
31 | - > | |
32 | - { | |
33 | - insurerList && insurerList.map((item:any) => ( | |
34 | - <Select.Option value={item.id} key={item.id}> | |
35 | - {item.name} | |
36 | - </Select.Option> | |
37 | - )) | |
38 | - } | |
39 | - </Select> | |
40 | - <Select | |
41 | - style={{ marginRight: 20, minWidth: 200 }} | |
42 | - placeholder="请选择门店" | |
43 | - showSearch | |
44 | - optionFilterProp="children" | |
45 | - allowClear | |
46 | - onChange={(shopId) => { | |
47 | - _onChange({shopId}); | |
48 | - }} | |
49 | - > | |
50 | - { | |
51 | - shopsList && shopsList.map((item:any) => ( | |
52 | - <Select.Option value={item.id} key={item.id}> | |
53 | - {item.name} | |
54 | - </Select.Option> | |
55 | - )) | |
56 | - } | |
57 | - </Select> | |
58 | - <CascaderSpec | |
59 | - style={{minWidth: 250}} | |
60 | - value={value} | |
61 | - onChange={(v) => { | |
62 | - setValue([...v]); | |
63 | - const params = { brandId: v[0]?.id, seriesId: v[1]?.id, specId: v[2]?.id }; | |
64 | - _onChange({...params}); | |
65 | - }} | |
66 | - /> | |
67 | - </div> | |
68 | - ); | |
11 | +function Filter({ onChange }: Props) { | |
12 | + const { insurerList, shopsList } = useStore(); | |
13 | + const [value, setValue] = useState<{ id: number; name: string }[]>([]); | |
14 | + const _onChange = debounce((params: any) => { | |
15 | + onChange && onChange(params); | |
16 | + }, 500); | |
17 | + return ( | |
18 | + <div> | |
19 | + <Select | |
20 | + style={{ marginRight: 20, minWidth: 250 }} | |
21 | + placeholder="搜索保险公司" | |
22 | + showSearch | |
23 | + optionFilterProp="children" | |
24 | + allowClear | |
25 | + onChange={(insurerId) => { | |
26 | + _onChange({ insurerId }); | |
27 | + }} | |
28 | + > | |
29 | + {insurerList && | |
30 | + insurerList.map((item: any) => ( | |
31 | + <Select.Option value={item.id} key={item.id}> | |
32 | + {item.name} | |
33 | + </Select.Option> | |
34 | + ))} | |
35 | + </Select> | |
36 | + <Select | |
37 | + style={{ marginRight: 20, minWidth: 200 }} | |
38 | + placeholder="搜索适用门店" | |
39 | + showSearch | |
40 | + optionFilterProp="children" | |
41 | + allowClear | |
42 | + onChange={(shopId) => { | |
43 | + _onChange({ shopId }); | |
44 | + }} | |
45 | + > | |
46 | + {shopsList && | |
47 | + shopsList.map((item: any) => ( | |
48 | + <Select.Option value={item.id} key={item.id}> | |
49 | + {item.name} | |
50 | + </Select.Option> | |
51 | + ))} | |
52 | + </Select> | |
53 | + <CascaderSpec | |
54 | + placeHolder="搜索适用车辆" | |
55 | + style={{ minWidth: 250 }} | |
56 | + value={value} | |
57 | + onChange={(v) => { | |
58 | + setValue([...v]); | |
59 | + const params = { brandId: v[0]?.id, seriesId: v[1]?.id, specId: v[2]?.id }; | |
60 | + _onChange({ ...params }); | |
61 | + }} | |
62 | + /> | |
63 | + </div> | |
64 | + ); | |
69 | 65 | } |
70 | 66 | |
71 | 67 | export default Filter; | ... | ... |
src/pages/carinsur/InsuranceTradingGift/components/List.tsx
1 | -import React from 'react'; | |
2 | -import { Table, Tag, Space, Popconfirm, Divider, message } from 'antd'; | |
3 | -import moment from 'moment'; | |
1 | +import React, { useRef } from 'react'; | |
2 | +import { Table, Space, Popconfirm, Divider, message } from 'antd'; | |
4 | 3 | import { useStore } from '../index'; |
5 | -import { TypeEnum, StatusTextEnum, StatusStyleList, StatusColorList } from '../entity'; | |
4 | +import { TypeEnum } from '../entity'; | |
6 | 5 | import * as API from '../api'; |
7 | 6 | import TextWithMore from '@/components/TextWithMore'; |
7 | +import type { ApprovalProgressModalRef } from '@/components/ApprovalProgressModal'; | |
8 | +import ApprovalProgressModal from '@/components/ApprovalProgressModal'; | |
9 | +import { BtnTypeEnum } from '../store'; | |
10 | +import _ from 'lodash'; | |
11 | +import type { ValueNameOption } from '../../entity'; | |
8 | 12 | |
9 | 13 | const { Column } = Table; |
10 | 14 | |
11 | -interface Props { | |
12 | - status: number; | |
13 | -} | |
14 | - | |
15 | -export default function List({ status: radioStatus }: Props) { | |
16 | - const { | |
17 | - tradingGiftList, | |
18 | - paginationConfig, | |
19 | - loading, | |
20 | - setLoading, | |
21 | - setApprovalProgressModalInfo, | |
22 | - setBuyInsuranceGiftConfigId, | |
23 | - setShopsModalData, | |
24 | - setCarModalData, | |
25 | - setAddVisible, | |
26 | - setReadOnly, | |
27 | - setTerminateModalData, | |
28 | - setCurrItem, | |
29 | - } = useStore(); | |
15 | +export default function List() { | |
16 | + const approvalProgressRef = useRef<ApprovalProgressModalRef | null>(null); | |
17 | + const { tradingGiftList, paginationConfig, loading, setLoading, setBuyInsuranceGiftConfigId, setCarModalData, setAddVisible, setBtnType } = | |
18 | + useStore(); | |
30 | 19 | |
31 | 20 | /** |
32 | - * @description: 查看 | |
21 | + * @description: 编辑 | |
33 | 22 | * @param {number} buyInsuranceGiftConfigId |
34 | 23 | * @return {*} |
35 | 24 | */ |
36 | - function handleReadOnly(buyInsuranceGiftConfigId: number) { | |
25 | + function handleEdit(buyInsuranceGiftConfigId: number) { | |
26 | + setBtnType(BtnTypeEnum.编辑); | |
37 | 27 | setBuyInsuranceGiftConfigId(buyInsuranceGiftConfigId); |
38 | - setReadOnly(true); | |
39 | 28 | setAddVisible(true); |
40 | 29 | } |
41 | - | |
42 | - /** | |
43 | - * @description: 编辑 | |
44 | - * @param {number} buyInsuranceGiftConfigId | |
45 | - * @return {*} | |
46 | - */ | |
47 | - function handleEdit(buyInsuranceGiftConfigId: number) { | |
30 | + // 复制 | |
31 | + function handleCopy(buyInsuranceGiftConfigId: number) { | |
32 | + setBtnType(BtnTypeEnum.复制); | |
48 | 33 | setBuyInsuranceGiftConfigId(buyInsuranceGiftConfigId); |
49 | 34 | setAddVisible(true); |
50 | 35 | } |
... | ... | @@ -63,140 +48,84 @@ export default function List({ status: radioStatus }: Props) { |
63 | 48 | message.error(error.message); |
64 | 49 | } |
65 | 50 | } |
66 | - /** | |
67 | - * @description: 撤销 | |
68 | - * @param {number} buyInsuranceGiftConfigId | |
69 | - * @return {*} | |
70 | - */ | |
71 | - async function handleRevoke(buyInsuranceGiftConfigId: number) { | |
72 | - try { | |
73 | - await API.revokeGiftConfig({ buyInsuranceGiftConfigId }); | |
74 | - message.success('撤销成功'); | |
75 | - setLoading(true); | |
76 | - } catch (error: any) { | |
77 | - message.error(error.message); | |
78 | - } | |
79 | - } | |
80 | - /** | |
81 | - * @description: 提审 | |
82 | - * @param {number} buyInsuranceGiftConfigId | |
83 | - * @return {*} | |
84 | - */ | |
85 | - async function handleApply(buyInsuranceGiftConfigId: number) { | |
86 | - try { | |
87 | - await API.applyGiftConfig({ buyInsuranceGiftConfigId }); | |
88 | - message.success('提交成功'); | |
89 | - setLoading(true); | |
90 | - } catch (error: any) { | |
91 | - message.error(error.message); | |
92 | - } | |
93 | - } | |
94 | 51 | |
95 | 52 | /** |
96 | 53 | * @description: 操作集合 |
97 | - * @param {number} status | |
98 | 54 | * @param {number} buyInsuranceGiftConfigId |
99 | 55 | * @return {*} |
100 | 56 | */ |
101 | - function operationDom(status: number = 0, buyInsuranceGiftConfigId: number, item: API.PageItem) { | |
57 | + function operationDom(buyInsuranceGiftConfigId: number) { | |
102 | 58 | return ( |
103 | 59 | <Space> |
104 | - <a onClick={() => handleReadOnly(buyInsuranceGiftConfigId)}>查看</a> | |
105 | - {[1, 3, 4].includes(status) && ( | |
106 | - <> | |
107 | - <Divider type="vertical" /> | |
108 | - <Popconfirm title="是否删除?" onConfirm={() => handleDelete(buyInsuranceGiftConfigId)} okText="确定" cancelText="取消"> | |
109 | - <a style={{ color: '#F8593E' }}>删除</a> | |
110 | - </Popconfirm> | |
111 | - </> | |
112 | - )} | |
113 | - {status === 2 && ( | |
114 | - <> | |
115 | - <Divider type="vertical" /> | |
116 | - <Popconfirm title="是否撤销?" onConfirm={() => handleRevoke(buyInsuranceGiftConfigId)} okText="确定" cancelText="取消"> | |
117 | - <a style={{ color: '#FF794C' }}>撤销</a> | |
118 | - </Popconfirm> | |
119 | - </> | |
120 | - )} | |
121 | - {[1, 3, 4, 5, 6].includes(status) && ( | |
122 | - <> | |
123 | - <Divider type="vertical" /> | |
124 | - <Popconfirm | |
125 | - title={`是否${![5, 6].includes(status) ? '编辑' : '变更'}?`} | |
126 | - onConfirm={() => handleEdit(buyInsuranceGiftConfigId)} | |
127 | - okText="确定" | |
128 | - cancelText="取消" | |
129 | - > | |
130 | - <a>{![5, 6].includes(status) ? '编辑' : '变更'}</a> | |
131 | - </Popconfirm> | |
132 | - </> | |
133 | - )} | |
134 | - {[1].includes(status) && ( | |
135 | - <> | |
136 | - <Divider type="vertical" /> | |
137 | - <Popconfirm title="是否提交审批?" onConfirm={() => handleApply(buyInsuranceGiftConfigId)} okText="确定" cancelText="取消"> | |
138 | - <a>提交审批</a> | |
139 | - </Popconfirm> | |
140 | - </> | |
141 | - )} | |
142 | - {[6].includes(status) && ( | |
143 | - <> | |
144 | - <Divider type="vertical" /> | |
145 | - <a | |
146 | - onClick={() => { | |
147 | - setCurrItem(item); | |
148 | - setTerminateModalData({ date: moment(), visible: true }); | |
149 | - }} | |
150 | - > | |
151 | - 提前结束 | |
152 | - </a> | |
153 | - </> | |
154 | - )} | |
60 | + <Popconfirm title="是否删除?" onConfirm={() => handleDelete(buyInsuranceGiftConfigId)} okText="确定" cancelText="取消"> | |
61 | + <a style={{ color: '#F8593E' }}>删除</a> | |
62 | + </Popconfirm> | |
63 | + <Divider type="vertical" /> | |
64 | + <a onClick={() => handleEdit(buyInsuranceGiftConfigId)}>编辑</a> | |
65 | + <Divider type="vertical" /> | |
66 | + <a style={{ color: '#F8593E' }} onClick={() => handleCopy(buyInsuranceGiftConfigId)}> | |
67 | + 复制 | |
68 | + </a> | |
155 | 69 | </Space> |
156 | 70 | ); |
157 | 71 | } |
158 | 72 | |
159 | 73 | return ( |
160 | - <Table dataSource={tradingGiftList || []} rowKey={(item) => item.buyInsuranceGiftConfigId} pagination={paginationConfig} loading={loading}> | |
161 | - <Column title="保险公司" dataIndex="insurers" render={(t) => <TextWithMore title="保险公司" dataIndex="insurerName" list={t ?? []} />} /> | |
162 | - <Column title="成交类型" dataIndex="type" render={(t: number) => TypeEnum[t || 0]} /> | |
163 | - <Column | |
164 | - title="适用门店" | |
165 | - dataIndex="shops" | |
166 | - render={(t) => { | |
167 | - return t.length ? <a onClick={() => setShopsModalData({ shops: t, visible: true })}>查看</a> : <div>全部门店</div>; | |
168 | - }} | |
169 | - /> | |
170 | - <Column | |
171 | - title="签单日期" | |
172 | - dataIndex="type" | |
173 | - render={(t, item: API.PageItem) => <div>{`${moment(item.startDate).format('YYYY.MM.DD')}~${moment(item.endDate).format('YYYY.MM.DD')}`}</div>} | |
174 | - /> | |
175 | - <Column title="品牌" dataIndex="brandName" render={(t) => t || '--'} /> | |
176 | - <Column | |
177 | - title="适用车辆" | |
178 | - dataIndex="applyCarList" | |
179 | - render={(t: API.ApplyCarList[]) => <a onClick={() => setCarModalData({ cars: t, visible: true })}>查看</a>} | |
180 | - /> | |
181 | - <Column | |
182 | - title="审批进度" | |
183 | - dataIndex="approvalOrderNo" | |
184 | - render={(t: string, item: API.PageItem) => | |
185 | - ![1].includes(item.status || 0) ? <a onClick={() => setApprovalProgressModalInfo({ approvalOrderNo: t, visible: true })}>查看</a> : <>--</> | |
186 | - } | |
187 | - /> | |
188 | - {radioStatus === 2 && ( | |
74 | + <> | |
75 | + <Table dataSource={tradingGiftList || []} rowKey={(item) => item.buyInsuranceGiftConfigId} pagination={paginationConfig} loading={loading}> | |
76 | + <Column title="编号" dataIndex="buyInsuranceGiftConfigId" /> | |
77 | + <Column title="保险公司" dataIndex="insurers" render={(t) => <TextWithMore title="保险公司" dataIndex="insurerName" list={t ?? []} />} /> | |
78 | + <Column title="成交类型" dataIndex="type" render={(t: number) => TypeEnum[t || 0]} /> | |
79 | + <Column | |
80 | + title="适用门店" | |
81 | + dataIndex="shops" | |
82 | + render={(t, record: API.PageItem) => | |
83 | + record.shopsType === 1 ? '全部门店' : <TextWithMore title="适用门店" dataIndex="shopName" list={t ?? []} unit="个门店" /> | |
84 | + } | |
85 | + /> | |
86 | + <Column title="适用品牌" dataIndex="brandName" render={(t) => t || '--'} /> | |
87 | + <Column | |
88 | + title="适用车辆" | |
89 | + dataIndex="applyCarList" | |
90 | + render={(t: API.ApplyCarList[]) => (t && t.length > 0 ? <a onClick={() => setCarModalData({ cars: t, visible: true })}>查看</a> : <>--</>)} | |
91 | + /> | |
92 | + <Column | |
93 | + title="不享受成交有礼情况" | |
94 | + dataIndex="giftOptionList" | |
95 | + render={(t) => { | |
96 | + if (!_.isArray(t) || t.length === 0) { | |
97 | + return '--'; | |
98 | + } | |
99 | + return t[0].conditions.map((i: ValueNameOption, index: number) => ( | |
100 | + <div key={i.value}> | |
101 | + {index + 1}.{i.name} | |
102 | + </div> | |
103 | + )); | |
104 | + }} | |
105 | + /> | |
106 | + <Column | |
107 | + title="返现比例" | |
108 | + dataIndex="giftOptionList" | |
109 | + render={(t) => { | |
110 | + if (!_.isArray(t) || t.length === 0) { | |
111 | + return '--'; | |
112 | + } | |
113 | + return `${(t[0].vciReturnMoneyRate * 100).toFixed(2)}%`; | |
114 | + }} | |
115 | + /> | |
189 | 116 | <Column |
190 | - title="状态" | |
191 | - dataIndex="status" | |
192 | - render={(t: number) => ( | |
193 | - <Tag style={StatusStyleList[t || 0]} color={StatusColorList[t || 0]}> | |
194 | - {StatusTextEnum[t || 0]} | |
195 | - </Tag> | |
196 | - )} | |
117 | + title="返现金券比例" | |
118 | + dataIndex="giftOptionList" | |
119 | + render={(t) => { | |
120 | + if (!_.isArray(t) || t.length === 0) { | |
121 | + return '--'; | |
122 | + } | |
123 | + return `${(t[0].cashCouponRate * 100).toFixed(2)}%`; | |
124 | + }} | |
197 | 125 | /> |
198 | - )} | |
199 | - <Column title="操作" render={(t: number, item: API.PageItem) => <>{operationDom(item.status || 0, item.buyInsuranceGiftConfigId, item)}</>} /> | |
200 | - </Table> | |
126 | + <Column title="操作" render={(t: number, item: API.PageItem) => <>{operationDom(item.buyInsuranceGiftConfigId)}</>} /> | |
127 | + </Table> | |
128 | + <ApprovalProgressModal ref={approvalProgressRef} /> | |
129 | + </> | |
201 | 130 | ); |
202 | 131 | } | ... | ... |
src/pages/carinsur/InsuranceTradingGift/components/ShopModal.tsx deleted
1 | -import React from "react"; | |
2 | -import { Button, Modal, Table } from "antd"; | |
3 | -import { useStore } from '../index'; | |
4 | -import * as API from '../api'; | |
5 | - | |
6 | -const { Column } = Table; | |
7 | - | |
8 | -export default function ShopModal() { | |
9 | - const { shopsModalData, setShopsModalData } = useStore(); | |
10 | - const { shops, visible } = shopsModalData; | |
11 | - return ( | |
12 | - <Modal | |
13 | - title="门店" | |
14 | - width={600} | |
15 | - open={visible} | |
16 | - maskClosable={false} | |
17 | - onCancel={() => setShopsModalData({shops: [], visible: false})} | |
18 | - footer={[ | |
19 | - <Button key="1" onClick={() => setShopsModalData({shops: [], visible: false})}>取消</Button>, | |
20 | - ]} | |
21 | - > | |
22 | - <Table | |
23 | - size="small" | |
24 | - dataSource={shops || []} | |
25 | - scroll={{ y: 500 }} | |
26 | - rowKey={(item: KtCanteenSpace.ServiceShop) => `${item.shopId}`} | |
27 | - > | |
28 | - <Column title="门店" dataIndex="shopName" width="100%" align="center" /> | |
29 | - </Table> | |
30 | - </Modal> | |
31 | - ); | |
32 | -} | |
33 | 0 | \ No newline at end of file |
src/pages/carinsur/InsuranceTradingGift/components/TerminateModal.tsx deleted
1 | -import React from 'react'; | |
2 | -import { Calendar, Modal, message } from 'antd'; | |
3 | -import { useStore } from '../index'; | |
4 | -import moment from 'moment'; | |
5 | -import { terminateGiftConfig } from '../api'; | |
6 | -import styles from './style.less'; | |
7 | - | |
8 | -export default function TerminateModal() { | |
9 | - const { terminateModalData, setTerminateModalData, setParams, innerParams, currItem } = useStore(); | |
10 | - | |
11 | - const handleTerminate = () => { | |
12 | - if (!terminateModalData.date) { | |
13 | - message.error('请选择签单结束日期'); | |
14 | - return; | |
15 | - } | |
16 | - Modal.confirm({ | |
17 | - title: '确认提交签单结束日期吗?', | |
18 | - zIndex: 1002, | |
19 | - onOk: async () => { | |
20 | - const hide = message.loading('提交中,请稍候', 0); | |
21 | - terminateGiftConfig({ buyInsuranceGiftConfigId: currItem?.buyInsuranceGiftConfigId, endDate: terminateModalData.date?.valueOf() }) | |
22 | - .then(() => { | |
23 | - message.success('提交成功'); | |
24 | - setParams({ ...innerParams }, true); | |
25 | - setTerminateModalData({ date: moment(), visible: false }); | |
26 | - }) | |
27 | - .catch((error: any) => { | |
28 | - message.error(error.message ?? '请求失败'); | |
29 | - }) | |
30 | - .finally(() => { | |
31 | - hide(); | |
32 | - }); | |
33 | - }, | |
34 | - }); | |
35 | - }; | |
36 | - | |
37 | - return ( | |
38 | - <Modal | |
39 | - title="选择签单结束日期" | |
40 | - width={600} | |
41 | - open={terminateModalData.visible} | |
42 | - maskClosable={false} | |
43 | - onCancel={() => | |
44 | - setTerminateModalData({ | |
45 | - date: moment(), | |
46 | - visible: false, | |
47 | - }) | |
48 | - } | |
49 | - onOk={handleTerminate} | |
50 | - destroyOnClose | |
51 | - > | |
52 | - <div className={styles.terminateCalendar}> | |
53 | - <Calendar | |
54 | - mode="month" | |
55 | - value={terminateModalData.date} | |
56 | - disabledDate={(currDate) => { | |
57 | - return currDate.valueOf() > moment(currItem?.endDate).endOf('day').valueOf() || currDate.valueOf() < moment().startOf('day').valueOf(); | |
58 | - }} | |
59 | - onChange={(value) => { | |
60 | - setTerminateModalData({ ...terminateModalData, date: value }); | |
61 | - }} | |
62 | - /> | |
63 | - </div> | |
64 | - </Modal> | |
65 | - ); | |
66 | -} |
src/pages/carinsur/InsuranceTradingGift/components/TradingGiftConfig.tsx
1 | -import React, { useState, useEffect, useRef } from 'react'; | |
2 | -import { Modal, Button, Form, Spin, Select, Radio, Table, Divider, Popconfirm } from 'antd'; | |
3 | -import { PlusOutlined } from '@ant-design/icons'; | |
4 | -import { typeList, carListFilter } from '../entity'; | |
5 | -import AddTradingGiftModal from './AddTradingGiftModal'; | |
1 | +import React, { useRef, useContext, useEffect, useImperativeHandle, Ref, forwardRef } from 'react'; | |
2 | +import { Form, Table, InputNumber } from 'antd'; | |
6 | 3 | import { useStore } from '../index'; |
7 | 4 | import * as API from '../api'; |
8 | 5 | import _ from 'lodash'; |
6 | +import type { InputRef } from 'antd'; | |
7 | +import type { FormInstance } from 'antd/es/form'; | |
9 | 8 | |
10 | -const { Column } = Table; | |
9 | +// 此交互暂不使用 | |
10 | +const EditableContext = React.createContext<FormInstance<any> | null>(null); | |
11 | + | |
12 | +interface EditableRowProps { | |
13 | + index: number; | |
14 | +} | |
15 | + | |
16 | +const EditableRow: React.FC<EditableRowProps> = ({ index, ...rest }) => { | |
17 | + return <tr {...rest} />; | |
18 | +}; | |
19 | + | |
20 | +interface EditableCellProps { | |
21 | + title: React.ReactNode; | |
22 | + editable: boolean; | |
23 | + children: React.ReactNode; | |
24 | + dataIndex: keyof API.TradingGiftConfig; | |
25 | + record: API.TradingGiftConfig; | |
26 | + handleSave: (record: API.TradingGiftConfig) => void; | |
27 | +} | |
28 | + | |
29 | +const EditableCell: React.FC<EditableCellProps> = ({ title, editable, children, dataIndex, record, handleSave, ...restProps }) => { | |
30 | + const inputRef = useRef<InputRef>(null); | |
31 | + const form = useContext(EditableContext)!; | |
32 | + | |
33 | + // 回车或者失去焦点时保存输入框值 | |
34 | + const save = async () => { | |
35 | + try { | |
36 | + const values = await form.validateFields(); | |
37 | + handleSave({ ...record, ...values }); | |
38 | + } catch (errInfo) { | |
39 | + console.log('Save failed:', errInfo); | |
40 | + } | |
41 | + }; | |
42 | + | |
43 | + useEffect(() => { | |
44 | + // 编辑时详情数据为异步,设置 initialValue 无效,需手动给表单赋值 | |
45 | + form.setFieldsValue({ | |
46 | + vciReturnMoneyRate: record?.vciReturnMoneyRate, | |
47 | + cashCouponRate: record?.cashCouponRate, | |
48 | + }); | |
49 | + }, [record]); | |
50 | + | |
51 | + const childNode = editable ? ( | |
52 | + <Form.Item | |
53 | + name={dataIndex} | |
54 | + style={{ margin: 0 }} | |
55 | + rules={[ | |
56 | + { | |
57 | + required: true, | |
58 | + message: `${title}值必须在 0.01-99.99 之间`, | |
59 | + }, | |
60 | + ]} | |
61 | + > | |
62 | + {/* @ts-ignore */} | |
63 | + <InputNumber ref={inputRef} min={0.01} max={99.99} placeholder="请输入" precision={2} addonAfter="%" onPressEnter={save} onBlur={save} /> | |
64 | + </Form.Item> | |
65 | + ) : ( | |
66 | + children | |
67 | + ); | |
68 | + | |
69 | + return <td {...restProps}>{childNode}</td>; | |
70 | +}; | |
11 | 71 | |
12 | 72 | interface Props { |
13 | - onChange?: (_: API.TradingGiftConfig[]) => any; | |
14 | 73 | value?: API.TradingGiftConfig[]; |
74 | + onChange?: (options: API.TradingGiftConfig[]) => void; | |
15 | 75 | } |
16 | 76 | |
17 | -export default function TradingGiftConfig({ onChange, value = [] }: Props) { | |
18 | - const { readOnly, setTradingGiftVisible, tradingGiftConfigList, setTradingGiftConfigList, setTradingGiftItem } = useStore(); | |
77 | +type EditableTableProps = Parameters<typeof Table>[0]; | |
78 | +type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>; | |
19 | 79 | |
20 | - const update = useRef(false); | |
80 | +export interface TradingGiftConfigRef { | |
81 | + validate: () => void; | |
82 | +} | |
21 | 83 | |
22 | - useEffect(() => { | |
23 | - if (!update.current) { | |
24 | - update.current = true; | |
25 | - } else { | |
26 | - onChange && onChange([...tradingGiftConfigList]); | |
84 | +function TradingGiftConfig({ onChange, value = [] }: Props, ref: Ref<TradingGiftConfigRef>) { | |
85 | + const { readOnly } = useStore(); | |
86 | + | |
87 | + const [form] = Form.useForm(); | |
88 | + | |
89 | + useImperativeHandle(ref, () => ({ | |
90 | + validate: () => { | |
91 | + return form.validateFields(); | |
92 | + }, | |
93 | + })); | |
94 | + | |
95 | + const handleSave = (row: API.TradingGiftConfig) => { | |
96 | + onChange && | |
97 | + onChange([ | |
98 | + { | |
99 | + ...row, | |
100 | + }, | |
101 | + ]); | |
102 | + }; | |
103 | + | |
104 | + const components = { | |
105 | + body: { | |
106 | + row: EditableRow, | |
107 | + cell: EditableCell, | |
108 | + }, | |
109 | + }; | |
110 | + | |
111 | + const defaultColumns: (ColumnTypes[number] & { editable?: boolean; dataIndex: string })[] = [ | |
112 | + { | |
113 | + title: '除以下场景外,都支持返现:', | |
114 | + dataIndex: 'conditions', | |
115 | + width: '40%', | |
116 | + render: (t: { name: string; value: string }[]) => ( | |
117 | + <>{t.length ? t.map((item, index) => <div key={item.value}>{`${index + 1}.${item.name}`}</div>) : '--'}</> | |
118 | + ), | |
119 | + }, | |
120 | + { | |
121 | + title: '返现比例', | |
122 | + dataIndex: 'vciReturnMoneyRate', | |
123 | + editable: !readOnly, | |
124 | + width: '30%', | |
125 | + render: (t) => (t ? `${t}%` : '--'), | |
126 | + }, | |
127 | + { | |
128 | + title: '返现金券比例', | |
129 | + dataIndex: 'cashCouponRate', | |
130 | + editable: !readOnly, | |
131 | + width: '30%', | |
132 | + render: (t) => (t ? `${t}%` : '--'), | |
133 | + }, | |
134 | + ]; | |
135 | + | |
136 | + const columns = defaultColumns.map((col) => { | |
137 | + if (!col.editable) { | |
138 | + return col; | |
27 | 139 | } |
28 | - }, [tradingGiftConfigList]); | |
29 | - | |
30 | - function edit(item: API.TradingGiftConfig) { | |
31 | - setTradingGiftItem({ ...item }); | |
32 | - setTradingGiftVisible(true); | |
33 | - } | |
34 | - | |
35 | - function _delete(item: API.TradingGiftConfig) { | |
36 | - const { key } = item; | |
37 | - const filterList = tradingGiftConfigList.filter((it) => it.key !== key); | |
38 | - const _tradingGiftConfigList = filterList.map((it, index) => ({ ...it, key: index + 1 })); | |
39 | - setTradingGiftConfigList([..._tradingGiftConfigList]); | |
40 | - } | |
41 | - | |
42 | - /** | |
43 | - * @description: 拼接优惠卷方式 | |
44 | - * @param {*} exchangeMethod | |
45 | - * @return {*} | |
46 | - */ | |
47 | - function giftExchangetoString(exchangeMethod: { label: string; value: string }[] = []) { | |
48 | - const str = exchangeMethod.reduce((str, item, index) => { | |
49 | - if (index + 1 !== exchangeMethod.length) { | |
50 | - str += item.label + ' + '; | |
51 | - } else { | |
52 | - str += item.label; | |
53 | - } | |
54 | - return str; | |
55 | - }, ''); | |
56 | - return str; | |
57 | - } | |
140 | + return { | |
141 | + ...col, | |
142 | + onCell: (record: API.TradingGiftConfig) => ({ | |
143 | + record, | |
144 | + editable: readOnly || col.editable, | |
145 | + dataIndex: col.dataIndex, | |
146 | + title: col.title, | |
147 | + handleSave, | |
148 | + }), | |
149 | + }; | |
150 | + }); | |
58 | 151 | |
59 | 152 | return ( |
60 | - <div> | |
61 | - <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 10 }}> | |
62 | - <Button | |
63 | - type="link" | |
64 | - icon={<PlusOutlined />} | |
65 | - onClick={() => { | |
66 | - setTradingGiftVisible(true); | |
67 | - }} | |
68 | - > | |
69 | - 新增 | |
70 | - </Button> | |
71 | - </div> | |
72 | - <Table dataSource={tradingGiftConfigList || []} rowKey={(item, index) => `${index}-item`}> | |
73 | - <Column | |
74 | - title="前置条件" | |
75 | - dataIndex="conditions" | |
76 | - render={(t: { label: string; value: string }[], record: API.TradingGiftConfig) => ( | |
77 | - <>{t.length ? t.map((item, index) => <div key={item.value}>{`(${index + 1})${item.label}`}</div>) : <div>--</div>}</> | |
78 | - )} | |
153 | + <Form form={form} component={false}> | |
154 | + <EditableContext.Provider value={form}> | |
155 | + <Table | |
156 | + // @ts-ignore | |
157 | + ref={ref} | |
158 | + components={components} | |
159 | + rowClassName={() => 'editable-row'} | |
160 | + bordered | |
161 | + dataSource={value} | |
162 | + pagination={false} | |
163 | + columns={columns as ColumnTypes} | |
79 | 164 | /> |
80 | - <Column | |
81 | - title="礼品兑换方式" | |
82 | - dataIndex="exchangeMethod" | |
83 | - render={(t: { label: string; value: string }[], record: API.TradingGiftConfig) => <div>{giftExchangetoString(t)}</div>} | |
84 | - /> | |
85 | - <Column | |
86 | - title="操作" | |
87 | - align="center" | |
88 | - width="35%" | |
89 | - render={(text, _item: API.TradingGiftConfig) => ( | |
90 | - <span> | |
91 | - <a | |
92 | - onClick={() => { | |
93 | - edit(_item); | |
94 | - }} | |
95 | - style={{ marginLeft: 5 }} | |
96 | - > | |
97 | - {' '} | |
98 | - {readOnly ? '查看' : '编辑'} | |
99 | - </a> | |
100 | - {!readOnly && ( | |
101 | - <> | |
102 | - <Divider type="vertical" /> | |
103 | - <Popconfirm title="是否删除?" onConfirm={() => _delete(_item)} okText="确定" cancelText="取消"> | |
104 | - <a | |
105 | - onClick={(e) => { | |
106 | - e.preventDefault(); | |
107 | - }} | |
108 | - style={{ color: 'red', marginLeft: 5 }} | |
109 | - > | |
110 | - 删除 | |
111 | - </a> | |
112 | - </Popconfirm> | |
113 | - </> | |
114 | - )} | |
115 | - </span> | |
116 | - )} | |
117 | - /> | |
118 | - </Table> | |
119 | - <AddTradingGiftModal /> | |
120 | - </div> | |
165 | + </EditableContext.Provider> | |
166 | + </Form> | |
121 | 167 | ); |
122 | 168 | } |
169 | + | |
170 | +export default forwardRef(TradingGiftConfig); | ... | ... |
src/pages/carinsur/InsuranceTradingGift/entity.tsx renamed to src/pages/carinsur/InsuranceTradingGift/entity.ts
... | ... | @@ -4,24 +4,26 @@ import _ from 'lodash'; |
4 | 4 | export const options = [ |
5 | 5 | { label: '生效中', value: 1 }, |
6 | 6 | { label: '未生效', value: 2 }, |
7 | - { label: '已过期', value: 3 }, | |
7 | + { label: '已失效', value: 3 }, | |
8 | 8 | ]; |
9 | 9 | |
10 | 10 | export const typeList = [ |
11 | 11 | { label: '新保', value: 1 }, |
12 | 12 | { label: '续保', value: 3 }, |
13 | + { label: '零售', value: 4 }, | |
13 | 14 | ]; |
14 | 15 | |
15 | 16 | export enum TypeEnum { |
16 | 17 | '--' = 0, |
17 | 18 | '新保' = 1, |
18 | 19 | '续保' = 3, |
20 | + '零售' = 4, | |
19 | 21 | } |
20 | 22 | |
21 | 23 | export enum StatusTextEnum { |
22 | 24 | '--' = 0, |
23 | 25 | '草稿' = 1, |
24 | - '审批中' = 2, | |
26 | + '审批中' = 2, // 审批状态废弃 | |
25 | 27 | '审批拒绝', |
26 | 28 | '审批超时', |
27 | 29 | '待生效', |
... | ... | @@ -111,49 +113,30 @@ export function businessCarListFilter(list: API.ApplyCarList[]) { |
111 | 113 | export function filterGiftOption(list: API.TradingGiftConfig[]) { |
112 | 114 | const _list = _.cloneDeep(list); |
113 | 115 | return _list.map((item) => { |
114 | - item.conditions = item.conditions?.map((i) => i.value); | |
115 | - item.exchangeMethod = item.exchangeMethod?.map((i) => i.value); | |
116 | - | |
117 | 116 | if (item.vciReturnMoneyRate) { |
118 | 117 | item.vciReturnMoneyRate = Number((item.vciReturnMoneyRate / 100).toFixed(4)); |
119 | 118 | } |
120 | - if (item.daiReturnMoneyRate) { | |
121 | - item.daiReturnMoneyRate = Number((item.daiReturnMoneyRate / 100).toFixed(4)); | |
122 | - } | |
123 | - if (item.couponConfigList?.length) { | |
124 | - item.couponConfigList = item.couponConfigList.map((it) => { | |
125 | - delete it.key; | |
126 | - delete it.disabled; | |
127 | - return it; | |
128 | - }); | |
119 | + if (item.cashCouponRate) { | |
120 | + item.cashCouponRate = Number((item.cashCouponRate / 100).toFixed(4)); | |
129 | 121 | } |
130 | - delete item.key; | |
122 | + delete item.conditions; | |
131 | 123 | return item; |
132 | 124 | }); |
133 | 125 | } |
134 | 126 | |
135 | -/** | |
136 | - * @description: 成交有礼条件配置过滤(后端-->业务) | |
137 | - * @param {any} lsit | |
138 | - * @return {*} | |
139 | - */ | |
140 | -export function businessFilterGiftOption(list: any[]) { | |
127 | +export function combineGiftOption(list: API.TradingGiftConfig[]) { | |
141 | 128 | const _list = _.cloneDeep(list); |
142 | - return _list.map((item, index) => { | |
143 | - item.conditions = item.conditions?.map((i) => ({ value: i.value, label: i.name })); | |
144 | - item.exchangeMethod = item.exchangeMethod?.map((i) => ({ value: i.value, label: i.name })); | |
129 | + return _list.map((item) => { | |
145 | 130 | if (item.vciReturnMoneyRate) { |
146 | - item.daiReturnMoneyRate = (item.daiReturnMoneyRate * 100).toFixed(2); | |
147 | - item.vciReturnMoneyRate = (item.vciReturnMoneyRate * 100).toFixed(2); | |
131 | + item.vciReturnMoneyRate = Number((item.vciReturnMoneyRate * 100).toFixed(4)); | |
148 | 132 | } |
149 | - if (item.couponConfigList?.length) { | |
150 | - item.couponConfigList = item.couponConfigList.map((it: any, index: number) => { | |
151 | - it.key = index + 1; | |
152 | - it.disabled = it.validityPeriodType === 1; | |
153 | - return it; | |
154 | - }); | |
133 | + if (item.cashCouponRate) { | |
134 | + item.cashCouponRate = Number((item.cashCouponRate * 100).toFixed(4)); | |
155 | 135 | } |
156 | - item.key = index + 1; | |
157 | - return item; | |
136 | + return { | |
137 | + conditions: item.conditions, | |
138 | + vciReturnMoneyRate: item.vciReturnMoneyRate, | |
139 | + cashCouponRate: item.cashCouponRate, | |
140 | + }; | |
158 | 141 | }); |
159 | 142 | } | ... | ... |
src/pages/carinsur/InsuranceTradingGift/index.tsx
1 | -import React, { useState } from 'react'; | |
2 | -import { Card, Radio, Row, Button } from 'antd'; | |
1 | +import React from 'react'; | |
2 | +import { Card, Row, Button } from 'antd'; | |
3 | 3 | import { PageHeaderWrapper } from '@ant-design/pro-layout'; |
4 | 4 | import { PlusOutlined } from '@ant-design/icons'; |
5 | 5 | import List from './components/List'; |
6 | 6 | import Filter from './components/Filter'; |
7 | 7 | import AddModal from './components/AddModal'; |
8 | -import ShopModal from './components/ShopModal'; | |
9 | 8 | import CarModal from './components/CarModal'; |
10 | -import ApprovalModal from './components/ApprovalModal'; | |
11 | 9 | import { createStore } from '@/hooks/moz'; |
12 | -import store from './store'; | |
13 | -import { options } from './entity'; | |
14 | -import TerminateModal from './components/TerminateModal'; | |
10 | +import store, { BtnTypeEnum } from './store'; | |
15 | 11 | |
16 | 12 | export const { Provider, useStore } = createStore(store); |
17 | 13 | |
18 | 14 | function TradingGift() { |
19 | - const { innerParams, setParams, setAddVisible, loading } = useStore(); | |
20 | - const [status, setStatus] = useState<number>(1); | |
21 | - | |
22 | - /** | |
23 | - * @description: 状态切换 | |
24 | - * @param {number} value | |
25 | - * @return {*} | |
26 | - */ | |
27 | - function handleSwitchCut(value: number) { | |
28 | - setStatus(value); | |
29 | - setParams({ ...innerParams, statusGroup: value }, true); | |
30 | - } | |
15 | + const { innerParams, setParams, setAddVisible, setBtnType } = useStore(); | |
31 | 16 | |
32 | 17 | function onSearch(params: any) { |
33 | 18 | setParams({ ...innerParams, ...params }, true); |
... | ... | @@ -38,35 +23,22 @@ function TradingGift() { |
38 | 23 | * @return {*} |
39 | 24 | */ |
40 | 25 | function handleAddTradingGift() { |
26 | + setBtnType(BtnTypeEnum.新增); | |
41 | 27 | setAddVisible(true); |
42 | 28 | } |
43 | 29 | |
44 | 30 | return ( |
45 | 31 | <PageHeaderWrapper title="成交有礼配置"> |
46 | 32 | <Card> |
47 | - <Row style={{ marginBottom: 20 }}> | |
48 | - <Radio.Group | |
49 | - optionType="button" | |
50 | - options={options} | |
51 | - value={status} | |
52 | - disabled={loading} | |
53 | - onChange={(value) => { | |
54 | - handleSwitchCut(value.target?.value); | |
55 | - }} | |
56 | - /> | |
57 | - </Row> | |
58 | 33 | <Row justify="space-between" style={{ marginBottom: 20 }}> |
59 | 34 | <Filter onChange={(params) => onSearch(params)} /> |
60 | 35 | <Button icon={<PlusOutlined />} type="primary" onClick={handleAddTradingGift}> |
61 | 36 | 新增 |
62 | 37 | </Button> |
63 | 38 | </Row> |
64 | - <List status={status} /> | |
39 | + <List /> | |
65 | 40 | <AddModal /> |
66 | - <ShopModal /> | |
67 | 41 | <CarModal /> |
68 | - <ApprovalModal /> | |
69 | - <TerminateModal /> | |
70 | 42 | </Card> |
71 | 43 | </PageHeaderWrapper> |
72 | 44 | ); | ... | ... |
src/pages/carinsur/InsuranceTradingGift/store.ts
... | ... | @@ -3,8 +3,12 @@ import usePagination from '@/hooks/usePagination'; |
3 | 3 | import useInitail from '@/hooks/useInitail'; |
4 | 4 | import { getShopApi } from '@/common/api'; |
5 | 5 | import * as API from './api'; |
6 | -import moment from 'moment'; | |
7 | -import type { Moment } from 'moment'; | |
6 | + | |
7 | +export enum BtnTypeEnum { | |
8 | + '新增' = 1, | |
9 | + '编辑', | |
10 | + '复制', | |
11 | +} | |
8 | 12 | |
9 | 13 | function useStore() { |
10 | 14 | const { |
... | ... | @@ -19,20 +23,14 @@ function useStore() { |
19 | 23 | const { data: shopsList } = useInitail(getShopApi, [], {}); |
20 | 24 | const [addVisible, setAddVisible] = useState<boolean>(false); |
21 | 25 | const [confNo, setConfNo] = useState<string>(''); |
22 | - const [type, setType] = useState<number | undefined>(); | |
23 | 26 | const [couponList, setCouponList] = useState<API.CouponResult[]>([]); |
24 | - const [tradingGiftConfigList, setTradingGiftConfigList] = useState<API.TradingGiftConfig[]>([]); | |
25 | 27 | const [tradingGiftVisible, setTradingGiftVisible] = useState<boolean>(false); |
26 | 28 | const [couponConfigVisible, setCouponConfigVisible] = useState<boolean>(false); |
27 | 29 | const [tradingGiftItem, setTradingGiftItem] = useState<API.TradingGiftConfig>({}); |
28 | - const [shopsModalData, setShopsModalData] = useState<{ shops?: API.Shops[]; visible?: boolean }>({ shops: [], visible: false }); | |
29 | 30 | const [carModalData, setCarModalData] = useState<{ cars?: API.ApplyCarList[]; visible?: boolean }>({ cars: [], visible: false }); |
30 | - const [approvalProgressModalInfo, setApprovalProgressModalInfo] = useState<API.ApprovalProgress>({ visible: false }); | |
31 | 31 | const [buyInsuranceGiftConfigId, setBuyInsuranceGiftConfigId] = useState<number>(); |
32 | - const [readOnly, setReadOnly] = useState<boolean>(false); | |
32 | + const [btnType, setBtnType] = useState<BtnTypeEnum>(); | |
33 | 33 | |
34 | - const [currItem, setCurrItem] = useState<API.PageItem>(); | |
35 | - const [terminateModalData, setTerminateModalData] = useState<{ date?: Moment; visible?: boolean }>({ date: moment(), visible: false }); | |
36 | 34 | return { |
37 | 35 | tradingGiftList, |
38 | 36 | paginationConfig, |
... | ... | @@ -40,12 +38,8 @@ function useStore() { |
40 | 38 | innerParams, |
41 | 39 | setLoading, |
42 | 40 | loading, |
43 | - readOnly, | |
44 | - setReadOnly, | |
45 | 41 | couponList, |
46 | 42 | setCouponList, |
47 | - tradingGiftConfigList, | |
48 | - setTradingGiftConfigList, | |
49 | 43 | tradingGiftItem, |
50 | 44 | setTradingGiftItem, |
51 | 45 | addVisible, |
... | ... | @@ -58,20 +52,12 @@ function useStore() { |
58 | 52 | shopsList, |
59 | 53 | confNo, |
60 | 54 | setConfNo, |
61 | - type, | |
62 | - setType, | |
63 | - shopsModalData, | |
64 | - setShopsModalData, | |
65 | 55 | carModalData, |
66 | 56 | setCarModalData, |
67 | - approvalProgressModalInfo, | |
68 | - setApprovalProgressModalInfo, | |
69 | 57 | buyInsuranceGiftConfigId, |
70 | 58 | setBuyInsuranceGiftConfigId, |
71 | - terminateModalData, | |
72 | - setTerminateModalData, | |
73 | - currItem, | |
74 | - setCurrItem, | |
59 | + btnType, | |
60 | + setBtnType | |
75 | 61 | }; |
76 | 62 | } |
77 | 63 | ... | ... |
src/pages/carinsur/Rebate/subpages/RebateConfirm/Second/index.tsx
... | ... | @@ -116,7 +116,8 @@ function Index({ form }: Props) { |
116 | 116 | <div> |
117 | 117 | <Divider orientation="left" orientationMargin="0" /> |
118 | 118 | <div style={{ fontWeight: 'bold', fontSize: 20, color: '#333', marginTop: 30, marginBottom: 20 }}> |
119 | - 应返利金额:<span style={{ color: '#FF921C' }}>{data?.totalRebateAmount ? rmb.p(data?.totalRebateAmount) : '--'}</span>元 | |
119 | + 应返利金额:<span style={{ color: '#FF921C' }}>{typeof data?.totalRebateAmount === 'number' ? rmb.p(data?.totalRebateAmount) : '--'}</span> | |
120 | + 元 | |
120 | 121 | </div> |
121 | 122 | <Form form={form} layout="vertical"> |
122 | 123 | <Form.Item | ... | ... |
src/pages/carinsur/companyConfig/index.tsx
... | ... | @@ -60,7 +60,7 @@ export default function WorkStationIndex() { |
60 | 60 | </Button> |
61 | 61 | </Row> |
62 | 62 | <Table dataSource={list} pagination={paginationConfig} rowKey="id" loading={loading} className={indexS.table}> |
63 | - <Column title="保险公司" dataIndex="name" /> | |
63 | + <Column title="保险公司" dataIndex="shortName" /> | |
64 | 64 | <Column |
65 | 65 | title="保单上保险公司名称" |
66 | 66 | dataIndex="orderInsurerNames" |
... | ... | @@ -69,13 +69,11 @@ export default function WorkStationIndex() { |
69 | 69 | )} |
70 | 70 | /> |
71 | 71 | <Column |
72 | - width="10%" | |
73 | 72 | title="送修差额是否包含驾意险" |
74 | 73 | dataIndex="repairMarginContainsDai" |
75 | 74 | render={(value) => (typeof value === 'boolean' ? (value ? '是' : '否') : '-')} |
76 | 75 | /> |
77 | 76 | <Column |
78 | - width="10%" | |
79 | 77 | title="多送修是否累计到下月" |
80 | 78 | dataIndex="extraRepairToNextMonth" |
81 | 79 | render={(value) => (typeof value === 'boolean' ? (value ? '是' : '否') : '-')} | ... | ... |
src/pages/carinsur/entity.ts
src/pages/cas/afterSaleConfiguration/maintainConfig/api.ts
1 | 1 | import { http } from '@/typing/http'; |
2 | 2 | import request from '@/utils/request'; |
3 | -import { CAS_HOST, OOP_HOST, PMS_HOST } from '@/utils/host'; | |
3 | +import { CAS_HOST, OOP_HOST, PMS_HOST } from '@/utils/host'; // 列表 | |
4 | 4 | |
5 | 5 | // 列表 |
6 | 6 | export function listApi(params: Maintain.ListParams): http.PromisePageResp<Maintain.ListVO> { |
... | ... | @@ -57,8 +57,10 @@ export interface PartItem { |
57 | 57 | partNo?: string; |
58 | 58 | /**配件数量 */ |
59 | 59 | partNumber?: number; |
60 | + | |
60 | 61 | [key: string]: any; |
61 | 62 | } |
63 | + | |
62 | 64 | export interface QueryParams { |
63 | 65 | current?: number; |
64 | 66 | pageSize?: number; |
... | ... | @@ -70,3 +72,17 @@ export interface QueryParams { |
70 | 72 | export function getPartItems(params: QueryParams): PromisePageResp<PartItem> { |
71 | 73 | return request.get(`${PMS_HOST}/erp/part/list`, { params }); |
72 | 74 | } |
75 | + | |
76 | +export interface OilItem { | |
77 | + oilBrandId: number; // 机油品牌id | |
78 | + oilBrandName: string; // 机油品牌名称 | |
79 | + oilModel: string; // 机油型号 | |
80 | + oilViscosity: string; // 机油粘稠度 | |
81 | + oilLevel: string; // 机油等级 | |
82 | + motorOilType: string; // 机油类型 | |
83 | +} | |
84 | + | |
85 | +/** 油料组合 */ | |
86 | +export function oilGroupListApi(): http.PromiseResp<Maintain.OilGroup[]> { | |
87 | + return request.get(`${CAS_HOST}/erp/basic/maintenance/config/oil/combination`); | |
88 | +} | ... | ... |
src/pages/cas/afterSaleConfiguration/maintainConfig/interface.d.ts
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/components/NewOilModal/index.tsx deleted
1 | -import React, { useEffect, useState } from 'react'; | |
2 | -import { Form, Modal, Select } from 'antd'; | |
3 | -import useInitail from '@/hooks/useInitail'; | |
4 | - | |
5 | -import { motorOilTypeData, oilViscosityData } from '@/pages/pms/entity'; | |
6 | -import { getBrandApi, getTypes } from '@/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/api'; | |
7 | - | |
8 | -interface Props { | |
9 | - selected: Maintain.OilGroup[]; | |
10 | - visible: boolean; | |
11 | - onCancel: () => void; | |
12 | - onOk: (data: Maintain.OilGroup[]) => any; | |
13 | - current: Maintain.OilGroup; | |
14 | - setCurrent: (value: any) => any; | |
15 | -} | |
16 | - | |
17 | -function NewOilModal(props: Props) { | |
18 | - const { visible, onCancel, onOk, selected, current, setCurrent } = props; | |
19 | - const [form] = Form.useForm(); | |
20 | - const [delay, setDelay] = useState(true); | |
21 | - const { data, setParams: setBrandParams } = useInitail<PmsPartOilSpace.Brand[], object>(getBrandApi, [], {}, delay); | |
22 | - const { data: oilLevelData, setParams: setOilLevelParams } = useInitail<PmsPartOilSpace.Type[], string>(getTypes, [], 'oil_level', delay); | |
23 | - const { data: oilModels, setParams } = useInitail<PmsPartOilSpace.Type[], string>(getTypes, [], 'oil_model', delay); | |
24 | - const { data: motorOilTypeData, setParams: oilType } = useInitail < PmsPartOilSpace.Type[], string> (getTypes, [], 'oil_type', delay); | |
25 | - const { data: oilViscosityData, setParams: oilViscosity } = useInitail < PmsPartOilSpace.Type[], string> (getTypes, [], 'oil_viscosity', delay); | |
26 | - useEffect(() => { | |
27 | - if (visible) { | |
28 | - setDelay(false); | |
29 | - setBrandParams({ oilType: 1 }, true); | |
30 | - oilType('oil_type', true); | |
31 | - oilViscosity('oil_viscosity', true); | |
32 | - setOilLevelParams('oil_level', true); | |
33 | - if (current.oilBrandId) { | |
34 | - form.setFieldsValue({ ...current }); | |
35 | - setParams(`oil_model_${current.oilBrandId}`, true); | |
36 | - } else { | |
37 | - form.resetFields(); | |
38 | - } | |
39 | - } | |
40 | - }, [visible]); | |
41 | - | |
42 | - function _onOk(value: any) { | |
43 | - const data: Maintain.OilGroup = { | |
44 | - ...value, | |
45 | - oilBrandName: value.oil.label, | |
46 | - oilBrandId: value.oil.value, | |
47 | - defaultUse: false, | |
48 | - }; | |
49 | - const index = selected.findIndex((e) => { | |
50 | - return ( | |
51 | - e.oilBrandId === value.oil.value && | |
52 | - e.motorOilType === value.motorOilType && | |
53 | - e.oilLevel === value.oilLevel && | |
54 | - e.oilModel === value.oilModel && | |
55 | - e.oilViscosity === value.oilViscosity | |
56 | - ); | |
57 | - }); | |
58 | - if (current.index || current.index == 0) { | |
59 | - selected[current.index] = data; | |
60 | - } else if (index > -1) { | |
61 | - selected[index] = data; | |
62 | - } else { | |
63 | - selected.push(data); | |
64 | - } | |
65 | - | |
66 | - setCurrent({}); | |
67 | - onOk && onOk(selected); | |
68 | - } | |
69 | - | |
70 | - const layout = { | |
71 | - labelCol: { span: 4 }, | |
72 | - wrapperCol: { span: 20 }, | |
73 | - }; | |
74 | - | |
75 | - return ( | |
76 | - <Modal width={650} forceRender title={`${current.oilBrandId ? '编辑' : '添加'}机油`} open={visible} onOk={form.submit} onCancel={onCancel}> | |
77 | - <Form {...layout} labelAlign="left" form={form} onFinish={_onOk} component={false}> | |
78 | - <Form.Item label="机油品牌" name="oil" rules={[{ required: true }]}> | |
79 | - <Select | |
80 | - labelInValue | |
81 | - placeholder="请选择机油品牌" | |
82 | - showSearch | |
83 | - optionFilterProp="children" | |
84 | - onChange={(id) => { | |
85 | - setParams(`oil_model_${id.value}`, true); | |
86 | - form.resetFields(['oilModel']); | |
87 | - }} | |
88 | - > | |
89 | - {data.map((i) => ( | |
90 | - <Select.Option value={i.brandId || 0} key={i.brandId || 0}> | |
91 | - {i.brandName || '--'} | |
92 | - </Select.Option> | |
93 | - ))} | |
94 | - </Select> | |
95 | - </Form.Item> | |
96 | - <Form.Item label="机油型号" name="oilModel" rules={[{ required: true }]}> | |
97 | - <Select placeholder="请选择机油型号" showSearch optionFilterProp="children"> | |
98 | - {oilModels.map((i) => ( | |
99 | - <Select.Option value={i.value || ''} key={i.value || ''}> | |
100 | - {i.value || '--'} | |
101 | - </Select.Option> | |
102 | - ))} | |
103 | - </Select> | |
104 | - </Form.Item> | |
105 | - <Form.Item label="机油类型" name="motorOilType" rules={[{ required: true }]}> | |
106 | - <Select placeholder="请选择机油类型" showSearch optionFilterProp="children"> | |
107 | - {motorOilTypeData.map((i) => ( | |
108 | - <Select.Option value={i.value || 0} key={i.value || 0}> | |
109 | - {i.value || '--'} | |
110 | - </Select.Option> | |
111 | - ))} | |
112 | - </Select> | |
113 | - </Form.Item> | |
114 | - <Form.Item label="机油等级" name="oilLevel" rules={[{ required: true }]}> | |
115 | - <Select placeholder="请选择机油等级" showSearch optionFilterProp="children"> | |
116 | - {oilLevelData.map((i) => ( | |
117 | - <Select.Option value={i.value || 0} key={i.value || 0}> | |
118 | - {i.value || '--'} | |
119 | - </Select.Option> | |
120 | - ))} | |
121 | - </Select> | |
122 | - </Form.Item> | |
123 | - <Form.Item label="粘稠度" name="oilViscosity" rules={[{ required: true }]}> | |
124 | - <Select placeholder="请选择粘稠度" showSearch optionFilterProp="children"> | |
125 | - {oilViscosityData.map((i) => ( | |
126 | - <Select.Option value={i.value || 0} key={i.value || 0}> | |
127 | - {i.value || '--'} | |
128 | - </Select.Option> | |
129 | - ))} | |
130 | - </Select> | |
131 | - </Form.Item> | |
132 | - </Form> | |
133 | - </Modal> | |
134 | - ); | |
135 | -} | |
136 | - | |
137 | -export default NewOilModal; |
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/components/OilSelector.tsx
0 → 100644
1 | +import React, { useEffect, useState } from 'react'; | |
2 | +import { Modal, Spin, Table } from 'antd'; | |
3 | + | |
4 | +import useInitail from '@/hooks/useInitail'; | |
5 | + | |
6 | +import { oilGroupListApi } from '@/pages/cas/afterSaleConfiguration/maintainConfig/api'; | |
7 | +import st from './style.less'; | |
8 | + | |
9 | +const Column = Table.Column; | |
10 | + | |
11 | +interface Props { | |
12 | + visible: boolean; | |
13 | + selected: Maintain.OilGroup[]; // 已选机油 | |
14 | + onCancel: () => void; | |
15 | + onConfirm: (selectItems: Maintain.OilGroup[]) => void; | |
16 | +} | |
17 | + | |
18 | +/** | |
19 | + * 油料选择器 | |
20 | + */ | |
21 | +export default function OilSelector({ visible, selected, onCancel, onConfirm }: Props) { | |
22 | + const [delay, setDelay] = useState(true); | |
23 | + const [selectItems, setSelectItems] = useState<Maintain.OilGroup[]>([]); | |
24 | + | |
25 | + const { data, loading, setParams } = useInitail(oilGroupListApi, [], undefined, delay); | |
26 | + | |
27 | + useEffect(() => { | |
28 | + if (visible) { | |
29 | + setDelay(false); | |
30 | + setParams(undefined, true); | |
31 | + | |
32 | + if (selected?.length > 0) { | |
33 | + setSelectItems(selected); | |
34 | + } | |
35 | + } | |
36 | + }, [visible, selected]); | |
37 | + | |
38 | + const handleConfirm = () => { | |
39 | + onConfirm(selectItems); | |
40 | + setSelectItems([]); | |
41 | + }; | |
42 | + | |
43 | + return ( | |
44 | + <Modal | |
45 | + title="选择作机油" | |
46 | + width={780} | |
47 | + open={visible} | |
48 | + okButtonProps={{ disabled: selectItems.length === 0 }} | |
49 | + onOk={handleConfirm} | |
50 | + onCancel={onCancel} | |
51 | + destroyOnClose | |
52 | + > | |
53 | + <Spin spinning={loading}> | |
54 | + <Table | |
55 | + loading={loading} | |
56 | + dataSource={data} | |
57 | + rowClassName={st.clickableRow} | |
58 | + rowKey="id" | |
59 | + rowSelection={{ | |
60 | + type: 'checkbox', | |
61 | + selectedRowKeys: selectItems.map((si) => si.id) || [], | |
62 | + onChange: (selectedRowKeys, selectedRows: Maintain.OilGroup[]) => { | |
63 | + setSelectItems(selectedRows); | |
64 | + }, | |
65 | + }} | |
66 | + onRow={(record) => ({ | |
67 | + onClick: () => { | |
68 | + if (selectItems.some((si) => si.id === record.id)) { | |
69 | + setSelectItems([...selectItems.filter((si) => si.id !== record.id)]); | |
70 | + } else { | |
71 | + setSelectItems([...selectItems, record]); | |
72 | + } | |
73 | + }, | |
74 | + })} | |
75 | + footer={() => ( | |
76 | + <span> | |
77 | + 已选:<span className={st.colorPrimary}>{`${selectItems.length} `}</span>项 | |
78 | + </span> | |
79 | + )} | |
80 | + > | |
81 | + <Column title="机油品牌" dataIndex="oilBrandName" /> | |
82 | + <Column title="型号" dataIndex="oilModel" /> | |
83 | + <Column title="类型" dataIndex="motorOilType" /> | |
84 | + <Column title="等级" dataIndex="oilLevel" /> | |
85 | + <Column title="粘稠度" dataIndex="oilViscosity" /> | |
86 | + </Table> | |
87 | + </Spin> | |
88 | + </Modal> | |
89 | + ); | |
90 | +} | ... | ... |
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/components/style.less
0 → 100644
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/index.tsx
1 | 1 | import React, { useEffect, useState } from 'react'; |
2 | -import { Button, Row, Table } from 'antd'; | |
2 | +import { Button, Row, Table, Tag } from 'antd'; | |
3 | 3 | import { MenuOutlined } from '@ant-design/icons'; |
4 | 4 | import type { SortableContainerProps, SortEnd } from 'react-sortable-hoc'; |
5 | 5 | import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'; |
6 | 6 | import { arrayMoveImmutable } from 'array-move'; |
7 | 7 | |
8 | -import NewOilModal from './components/NewOilModal'; | |
8 | +import OilSelector from './components/OilSelector'; | |
9 | 9 | import OilData from './components/OilData'; |
10 | 10 | |
11 | 11 | import './style.less'; |
... | ... | @@ -20,18 +20,36 @@ export interface Props { |
20 | 20 | oilGroups: Maintain.OilGroup[]; |
21 | 21 | capacity: number; |
22 | 22 | disabled?: boolean; |
23 | - onChange?: (data: any[]) => void; | |
23 | + onChange?: (data: Maintain.OilGroup[]) => void; | |
24 | 24 | } |
25 | 25 | |
26 | -export default function EngineOilSelector(props: Props) { | |
27 | - const { oilGroups, capacity, disabled, onChange } = props; | |
28 | - | |
26 | +export default function EngineOilSelector({ oilGroups, capacity, disabled, onChange }: Props) { | |
29 | 27 | const [visible, setVisible] = useState<boolean>(false); |
30 | - const [current, setCurrent] = useState({} as Maintain.OilGroup); | |
31 | 28 | const [oilData, setOilData] = useState<any>({ visible: false, data: {} }); |
32 | 29 | |
33 | 30 | const [dataSource, setDataSource] = useState<any[]>([]); |
34 | 31 | |
32 | + useEffect(() => { | |
33 | + const _list = oilGroups.map((e) => { | |
34 | + return { | |
35 | + ...e, | |
36 | + // 拼接 e 中属性为 id值 | |
37 | + id: `${e.oilBrandName}-${e.oilModel}-${e.motorOilType}-${e.oilLevel}-${e.oilViscosity}` | |
38 | + }; | |
39 | + }); | |
40 | + setDataSource([..._list]); | |
41 | + }, [oilGroups]); | |
42 | + | |
43 | + const handleOilSelect = (selectOils: Maintain.OilGroup[]) => { | |
44 | + onChange && onChange(selectOils); | |
45 | + setVisible(false); | |
46 | + }; | |
47 | + | |
48 | + const handleOilDelete = (index: number) => { | |
49 | + oilGroups.splice(index, 1); | |
50 | + onChange && onChange(oilGroups); | |
51 | + }; | |
52 | + | |
35 | 53 | const onSortEnd = ({ oldIndex, newIndex }: SortEnd) => { |
36 | 54 | if (oldIndex !== newIndex) { |
37 | 55 | const newData = arrayMoveImmutable(dataSource.slice(), oldIndex, newIndex).filter((el: any) => !!el); |
... | ... | @@ -50,41 +68,6 @@ export default function EngineOilSelector(props: Props) { |
50 | 68 | return <SortableItem index={index} {...restProps} />; |
51 | 69 | }; |
52 | 70 | |
53 | - useEffect(() => { | |
54 | - const _list = oilGroups.map((e, i) => { | |
55 | - return { | |
56 | - ...e, | |
57 | - id: i, | |
58 | - }; | |
59 | - }); | |
60 | - setDataSource([..._list]); | |
61 | - }, [oilGroups]); | |
62 | - | |
63 | - function _onOk(data: Maintain.OilGroup[]) { | |
64 | - onChange && onChange(data); | |
65 | - setVisible(false); | |
66 | - } | |
67 | - | |
68 | - function onDelete(record: Maintain.OilGroup) { | |
69 | - const _items = oilGroups; | |
70 | - const index = _items.findIndex((e) => { | |
71 | - return ( | |
72 | - e.oilBrandId === record.oilBrandId && | |
73 | - e.motorOilType === record.motorOilType && | |
74 | - e.oilLevel === record.oilLevel && | |
75 | - e.oilModel === record.oilModel && | |
76 | - e.oilViscosity === record.oilViscosity | |
77 | - ); | |
78 | - }); | |
79 | - _items.splice(index, 1); | |
80 | - _onOk(_items); | |
81 | - } | |
82 | - | |
83 | - function edit(record: Maintain.OilGroup, index: number) { | |
84 | - setCurrent({ ...record, oil: { value: record.oilBrandId, label: record.oilBrandName }, index }); | |
85 | - setVisible(true); | |
86 | - } | |
87 | - | |
88 | 71 | return ( |
89 | 72 | <div style={{ marginTop: 30 }}> |
90 | 73 | <Row justify="space-between" align="middle" style={{ marginBottom: 16 }}> |
... | ... | @@ -112,7 +95,22 @@ export default function EngineOilSelector(props: Props) { |
112 | 95 | }} |
113 | 96 | > |
114 | 97 | <Column align="center" className="drag-visible" title="拖拽排序" dataIndex="sort" width={100} render={() => <DragHandle />} /> |
115 | - <Column className="drag-visible" title="推荐顺序" dataIndex="oilIndex" width={100} render={(text, record, index) => <div>{index + 1}</div>} /> | |
98 | + <Column | |
99 | + className="drag-visible" | |
100 | + title="推荐顺序" | |
101 | + dataIndex="oilIndex" | |
102 | + width={160} | |
103 | + render={(text, record, index) => ( | |
104 | + <div> | |
105 | + {index + 1} | |
106 | + {index === 0 && ( | |
107 | + <Tag style={{ marginLeft: 5 }} color={'#FF9211'}> | |
108 | + 厂家首保机油 | |
109 | + </Tag> | |
110 | + )} | |
111 | + </div> | |
112 | + )} | |
113 | + /> | |
116 | 114 | <Column className="drag-visible" title="机油品牌" dataIndex="oilBrandName" /> |
117 | 115 | <Column className="drag-visible" title="机油型号" dataIndex="oilModel" /> |
118 | 116 | <Column className="drag-visible" title="机油类型" dataIndex="motorOilType" /> |
... | ... | @@ -134,32 +132,20 @@ export default function EngineOilSelector(props: Props) { |
134 | 132 | width={150} |
135 | 133 | align="center" |
136 | 134 | render={(text, record: Maintain.OilGroup, index) => ( |
137 | - <> | |
138 | - <Button onClick={() => edit(record, index)} type="link" size="small"> | |
139 | - 编辑 | |
140 | - </Button> | |
141 | - <Button onClick={() => onDelete(record)} type="link" danger size="small"> | |
142 | - 删除 | |
143 | - </Button> | |
144 | - </> | |
135 | + <Button onClick={() => handleOilDelete(index)} type="link" danger size="small"> | |
136 | + 删除 | |
137 | + </Button> | |
145 | 138 | )} |
146 | 139 | /> |
147 | 140 | </Table> |
148 | - <NewOilModal | |
149 | - selected={[...oilGroups]} | |
150 | - onOk={_onOk} | |
151 | - visible={visible} | |
152 | - onCancel={() => setVisible(false)} | |
153 | - current={current} | |
154 | - setCurrent={setCurrent} | |
155 | - /> | |
141 | + | |
142 | + <OilSelector visible={visible} selected={dataSource} onCancel={() => setVisible(false)} onConfirm={handleOilSelect} /> | |
156 | 143 | <OilData |
157 | 144 | visible={oilData.visible} |
145 | + data={oilData.data} | |
158 | 146 | onCancel={() => { |
159 | 147 | setOilData({ visible: false, data: {} }); |
160 | - setCurrent({} as Maintain.OilGroup); | |
161 | 148 | }} |
162 | - data={oilData.data} | |
163 | 149 | /> |
164 | 150 | </div> |
165 | 151 | ); | ... | ... |
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/MachineFilter/components/EngineFilterModal/index.tsx
... | ... | @@ -4,6 +4,7 @@ import debounce from 'lodash/debounce'; |
4 | 4 | import Search from 'antd/lib/input/Search'; |
5 | 5 | |
6 | 6 | import { getPartItems } from '../../../../../../api'; |
7 | +import st from '@/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/components/style.less'; | |
7 | 8 | |
8 | 9 | const { Column } = Table; |
9 | 10 | |
... | ... | @@ -86,6 +87,9 @@ function EngineOilModal(props: Props) { |
86 | 87 | <Table |
87 | 88 | dataSource={data} |
88 | 89 | loading={loading} |
90 | + pagination={{ total, defaultPageSize: 10, current, pageSize, onChange: onPageChange, onShowSizeChange: onPageChange }} | |
91 | + rowClassName={st.clickableRow} | |
92 | + rowKey="partCode" | |
89 | 93 | rowSelection={{ |
90 | 94 | selectedRowKeys: selectedRow.map((item) => item.partCode), |
91 | 95 | onSelect: (row: any, _selected: boolean) => { |
... | ... | @@ -111,8 +115,15 @@ function EngineOilModal(props: Props) { |
111 | 115 | setSelectedRow(newData); |
112 | 116 | }, |
113 | 117 | }} |
114 | - pagination={{ total, defaultPageSize: 10, current, pageSize, onChange: onPageChange, onShowSizeChange: onPageChange }} | |
115 | - rowKey="partCode" | |
118 | + onRow={(record) => ({ | |
119 | + onClick: () => { | |
120 | + if (selectedRow.some((si) => si.partCode === record.partCode)) { | |
121 | + setSelectedRow([...selectedRow.filter((si) => si.partCode !== record.partCode)]); | |
122 | + } else { | |
123 | + setSelectedRow([...selectedRow, record]); | |
124 | + } | |
125 | + }, | |
126 | + })} | |
116 | 127 | > |
117 | 128 | <Column title="名称" dataIndex="partName" width={250} /> |
118 | 129 | <Column title="编号" dataIndex="partCode" /> | ... | ... |
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/PartFilter/index.tsx
... | ... | @@ -105,7 +105,8 @@ export default function PartFilter({ partFilters, brandId, onChange }: Props) { |
105 | 105 | } |
106 | 106 | |
107 | 107 | const EditableCell: React.FC<EditableCellProps> = ({ editing, dataIndex, title, inputType, record, index, children, ...restProps }) => { |
108 | - const inputNode = <InputNumber />; | |
108 | + // todo 液态配件可以输入小数 | |
109 | + const inputNode = <InputNumber precision={0} />; | |
109 | 110 | |
110 | 111 | return ( |
111 | 112 | <td {...restProps}> |
... | ... | @@ -142,8 +143,8 @@ export default function PartFilter({ partFilters, brandId, onChange }: Props) { |
142 | 143 | <Table |
143 | 144 | dataSource={dataSource} |
144 | 145 | bordered |
145 | - rowClassName="editable-row" | |
146 | 146 | pagination={false} |
147 | + rowClassName="editable-row" | |
147 | 148 | rowKey={(row) => `${row.partCode}_${row.partName}`} |
148 | 149 | components={{ |
149 | 150 | body: { | ... | ... |
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/index.tsx
1 | 1 | import React, { useEffect, useState } from 'react'; |
2 | -import { Button, Card, Empty, Form, Input, message, Row, Select, Spin, Tabs } from 'antd'; | |
2 | +import { Button, Card, Empty, Form, Input, message, Modal, Row, Select, Spin, Tabs } from 'antd'; | |
3 | 3 | import { PageHeaderWrapper } from '@ant-design/pro-layout'; |
4 | 4 | import useInitial from '@/hooks/useInitail'; |
5 | 5 | import { ConnectProps } from '@/typing/common'; |
... | ... | @@ -411,8 +411,11 @@ export default function ConfigPage({ match }: Props) { |
411 | 411 | } |
412 | 412 | }) |
413 | 413 | .catch((e) => { |
414 | - message.error(e.message); | |
415 | 414 | setSubmitting(false); |
415 | + Modal.error({ | |
416 | + title: '提示', | |
417 | + content: e.message, | |
418 | + }); | |
416 | 419 | }); |
417 | 420 | } |
418 | 421 | ... | ... |
src/pages/ehr/RoleManagementGroup/api.ts
... | ... | @@ -4,18 +4,16 @@ |
4 | 4 | * @LastEditors: wangqiang@feewee.cn |
5 | 5 | * @LastEditTime: 2023-05-09 09:49:07 |
6 | 6 | */ |
7 | -import request from "@/utils/request"; | |
8 | -import { EHR_HOST } from "@/utils/host"; | |
9 | -import { http } from "@/typing/http"; | |
7 | +import request from '@/utils/request'; | |
8 | +import { EHR_HOST } from '@/utils/host'; | |
9 | +import { http } from '@/typing/http'; | |
10 | 10 | |
11 | 11 | /** |
12 | 12 | * @description: 获取角色管理组列表 |
13 | 13 | * @param {RoleManagementGrooup.QueryParams} params |
14 | 14 | * @return {http.PromisePageResp<RoleManagementGrooup.GroupItem>} |
15 | 15 | */ |
16 | -export function getListApi( | |
17 | - params: RoleManagementGrooup.QueryParams | |
18 | -): http.PromisePageResp<RoleManagementGrooup.GroupItem> { | |
16 | +export function getListApi(params: RoleManagementGrooup.QueryParams): http.PromisePageResp<RoleManagementGrooup.GroupItem> { | |
19 | 17 | return request.get(`${EHR_HOST}/roleStep/list`, { params }); |
20 | 18 | } |
21 | 19 | |
... | ... | @@ -24,9 +22,7 @@ export function getListApi( |
24 | 22 | * @param {RoleManagementGrooup.Detail} params |
25 | 23 | * @return {http.PromiseResp<string>} |
26 | 24 | */ |
27 | -export function saveGroupApi( | |
28 | - params: RoleManagementGrooup.Detail | |
29 | -): http.PromiseResp<string> { | |
25 | +export function saveGroupApi(params: RoleManagementGrooup.Detail): http.PromiseResp<string> { | |
30 | 26 | return request.post(`${EHR_HOST}/roleStep/save`, params); |
31 | 27 | } |
32 | 28 | |
... | ... | @@ -35,9 +31,7 @@ export function saveGroupApi( |
35 | 31 | * @param {number} id |
36 | 32 | * @return {http.PromiseResp<RoleManagementGrooup.GroupRoleStepItem[]>} |
37 | 33 | */ |
38 | -export function getGroupDetailApi( | |
39 | - id: number | |
40 | -): http.PromiseResp<RoleManagementGrooup.GroupRoleStepItem[]> { | |
34 | +export function getGroupDetailApi(id: number): http.PromiseResp<RoleManagementGrooup.GroupRoleStepItem[]> { | |
41 | 35 | return request.get(`${EHR_HOST}/roleStep/step/info`, { params: { id } }); |
42 | 36 | } |
43 | 37 | |
... | ... | @@ -49,3 +43,12 @@ export function getGroupDetailApi( |
49 | 43 | export function deleteGroupApi(id: number): http.PromiseResp<string> { |
50 | 44 | return request.get(`${EHR_HOST}/roleStep/remove`, { params: { id } }); |
51 | 45 | } |
46 | + | |
47 | +/** | |
48 | + * @description: 获取角色组对应组织架构 | |
49 | + * @param {number} stepId | |
50 | + * @return {http.PromiseResp<RoleManagementGrooup.RoleStaffTreeListVO>} | |
51 | + */ | |
52 | +export function getRoleStaffTreeApi(stepId: number): http.PromiseResp<RoleManagementGrooup.RoleStaffTreeListVO> { | |
53 | + return request.get(`${EHR_HOST}/hr/common/role/step/manage/tree`, { params: { stepId } }); | |
54 | +} | ... | ... |
src/pages/ehr/RoleManagementGroup/components/List.tsx
... | ... | @@ -2,28 +2,28 @@ |
2 | 2 | * @Author: wangqiang@feewee.cn |
3 | 3 | * @Date: 2022-06-29 10:35:41 |
4 | 4 | * @LastEditors: wangqiang@feewee.cn |
5 | - * @LastEditTime: 2022-07-01 15:20:41 | |
5 | + * @LastEditTime: 2024-04-19 17:15:41 | |
6 | 6 | */ |
7 | -import { Divider, message, Popconfirm, Table } from "antd"; | |
8 | -import moment from "moment"; | |
9 | -import React from "react"; | |
10 | -import { useStore } from "../index"; | |
11 | -import { deleteGroupApi } from "../api"; | |
7 | +import { Divider, message, Popconfirm, Table } from 'antd'; | |
8 | +import moment from 'moment'; | |
9 | +import React from 'react'; | |
10 | +import { useStore } from '../index'; | |
11 | +import { deleteGroupApi } from '../api'; | |
12 | 12 | // import SubmitModal from "@/pages/ehr/Insurance/components/SubmitModal"; |
13 | 13 | |
14 | 14 | export default function RoleManagementGroupList() { |
15 | - const { pagination, getDetail, current, setCurrent } = useStore(); | |
15 | + const { elements, pagination, getDetail, setType, setCurrent } = useStore(); | |
16 | 16 | // const [deleteVisible, setDeleteVisible] = useState(false); |
17 | 17 | |
18 | 18 | const deleteGroup = (id: number) => { |
19 | - const hide = message.loading("删除中...", 0); | |
19 | + const hide = message.loading('删除中...', 0); | |
20 | 20 | deleteGroupApi(id) |
21 | 21 | .then((res) => { |
22 | 22 | message.success(res.result); |
23 | 23 | pagination.setLoading(true); |
24 | 24 | }) |
25 | 25 | .catch((err) => { |
26 | - message.error(err.message || "删除失败"); | |
26 | + message.error(err.message || '删除失败'); | |
27 | 27 | }) |
28 | 28 | .finally(() => { |
29 | 29 | setCurrent(undefined); |
... | ... | @@ -32,59 +32,40 @@ export default function RoleManagementGroupList() { |
32 | 32 | }); |
33 | 33 | }; |
34 | 34 | |
35 | + function getRoleStaffTree(item: RoleManagementGrooup.GroupItem) { | |
36 | + setCurrent(item); | |
37 | + setType('tree'); | |
38 | + } | |
39 | + | |
35 | 40 | return ( |
36 | - <> | |
37 | - <Table | |
38 | - dataSource={pagination.list} | |
39 | - rowKey="id" | |
40 | - loading={pagination.loading} | |
41 | - pagination={pagination.paginationConfig} | |
42 | - > | |
43 | - <Table.Column title="角色管理组名" align="left" dataIndex="name" /> | |
44 | - <Table.Column | |
45 | - title="创建时间" | |
46 | - align="left" | |
47 | - render={(record: RoleManagementGrooup.GroupItem) => (record.createTime | |
48 | - ? moment(record.createTime).format("YYYY-MM-DD HH:mm") | |
49 | - : "-")} | |
50 | - /> | |
51 | - <Table.Column | |
52 | - title="操作" | |
53 | - align="left" | |
54 | - render={(record: RoleManagementGrooup.GroupItem) => ( | |
55 | - <> | |
56 | - <a onClick={() => getDetail(record, false)}>查看</a> | |
57 | - <Divider type="vertical" /> | |
58 | - <a onClick={() => getDetail(record, true)}>编辑</a> | |
59 | - <Divider type="vertical" /> | |
60 | - {/* <a | |
61 | - style={{ color: "red" }} | |
62 | - onClick={() => { | |
63 | - setCurrent(record); | |
64 | - setDeleteVisible(true); | |
65 | - }} | |
66 | - > | |
67 | - 删除 | |
68 | - </a> */} | |
69 | - <Popconfirm | |
70 | - title={`确定删除【${record.name}】角色管理组?`} | |
71 | - onConfirm={() => deleteGroup(record.id || -1)} | |
72 | - > | |
73 | - <a style={{ color: "red" }}>删除</a> | |
74 | - </Popconfirm> | |
75 | - </> | |
76 | - )} | |
77 | - /> | |
78 | - </Table> | |
79 | - {/* <SubmitModal | |
80 | - closable={false} | |
81 | - limit | |
82 | - style={{ minWidth: 400 }} | |
83 | - title={`确定删除【${current?.name}】角色管理组?`} | |
84 | - visible={deleteVisible} | |
85 | - onCancel={() => setDeleteVisible(false)} | |
86 | - onOk={deleteGroup} | |
87 | - /> */} | |
88 | - </> | |
41 | + <Table dataSource={pagination.list} rowKey="id" loading={pagination.loading} pagination={pagination.paginationConfig}> | |
42 | + <Table.Column title="角色管理组名" align="left" dataIndex="name" /> | |
43 | + <Table.Column | |
44 | + title="创建时间" | |
45 | + align="left" | |
46 | + render={(record: RoleManagementGrooup.GroupItem) => (record.createTime ? moment(record.createTime).format('YYYY-MM-DD HH:mm') : '-')} | |
47 | + /> | |
48 | + <Table.Column | |
49 | + title="操作" | |
50 | + align="left" | |
51 | + render={(record: RoleManagementGrooup.GroupItem) => ( | |
52 | + <> | |
53 | + {elements.includes('role:manage:edit') ? ( | |
54 | + <> | |
55 | + <a onClick={() => getDetail(record, false)}>查看</a> | |
56 | + <Divider type="vertical" /> | |
57 | + <a onClick={() => getDetail(record, true)}>编辑</a> | |
58 | + <Divider type="vertical" /> | |
59 | + <Popconfirm title={`确定删除【${record.name}】角色管理组?`} onConfirm={() => deleteGroup(record.id || -1)}> | |
60 | + <a style={{ color: 'red' }}>删除</a> | |
61 | + </Popconfirm> | |
62 | + <Divider type="vertical" /> | |
63 | + </> | |
64 | + ) : null} | |
65 | + <a onClick={() => getRoleStaffTree(record)}>查看组织架构</a> | |
66 | + </> | |
67 | + )} | |
68 | + /> | |
69 | + </Table> | |
89 | 70 | ); |
90 | 71 | } | ... | ... |
src/pages/ehr/RoleManagementGroup/components/ListIndex.tsx
0 → 100644
1 | +import React from 'react'; | |
2 | +import List from './List'; | |
3 | +import Modal from './Modal'; | |
4 | +import FeeweeFilterOption from '@/pages/notice/components/FeeweeFilterOption'; | |
5 | +import { useStore } from '../index'; | |
6 | +import { Button, Input, Row } from 'antd'; | |
7 | +import { PlusOutlined } from '@ant-design/icons'; | |
8 | + | |
9 | +export default function ListIndex() { | |
10 | + const { elements, pagination, setVisible } = useStore(); | |
11 | + | |
12 | + return ( | |
13 | + <> | |
14 | + <Row justify="space-between"> | |
15 | + <FeeweeFilterOption title="角色管理组名"> | |
16 | + <Input.Search | |
17 | + style={{ minWidth: 260, marginBottom: 10, marginRight: 10 }} | |
18 | + allowClear | |
19 | + placeholder="请输入角色管理组名查询" | |
20 | + value={pagination.innerParams.name} | |
21 | + onChange={(e) => pagination.setParams({ name: e.target.value })} | |
22 | + onSearch={() => pagination.setParams({ current: 1 }, true)} | |
23 | + /> | |
24 | + </FeeweeFilterOption> | |
25 | + | |
26 | + {elements.includes('role:manage:edit') ? ( | |
27 | + <Button | |
28 | + // @ts-ignore | |
29 | + icon={<PlusOutlined />} | |
30 | + type="primary" | |
31 | + onClick={() => { | |
32 | + setVisible(true); | |
33 | + }} | |
34 | + > | |
35 | + 新增 | |
36 | + </Button> | |
37 | + ) : null} | |
38 | + </Row> | |
39 | + <List /> | |
40 | + <Modal /> | |
41 | + </> | |
42 | + ); | |
43 | +} | ... | ... |
src/pages/ehr/RoleManagementGroup/components/RoleStaffTree.tsx
0 → 100644
1 | +import React, { useEffect, useRef, useState } from 'react'; | |
2 | +import { useStore } from '../index'; | |
3 | +import type { Point } from 'react-d3-tree'; | |
4 | +import Tree from 'react-d3-tree'; | |
5 | +import { getRoleStaffTreeApi } from '../api'; | |
6 | +import { Empty, Spin, Modal, Button, Row, Divider } from 'antd'; | |
7 | +import useInitial from '@/hooks/useInitail'; | |
8 | +import DetailItem from '@/pages/ehr/Authentication/Settings/components/DetailItem'; | |
9 | + | |
10 | +export default function RoleStaffTree() { | |
11 | + const { current } = useStore(); | |
12 | + const treeInitital = useInitial(getRoleStaffTreeApi, {}, current?.id ?? -1); | |
13 | + const treeContainer = useRef<HTMLDivElement | null>(null); | |
14 | + const [translate, setTranslate] = useState<Point>({ x: 200, y: 20 }); | |
15 | + const [dimensions, setDataimensions] = useState<{ width: number; height: number }>(); | |
16 | + | |
17 | + const [modalInfo, setModalInfo] = useState<{ open: boolean; data?: RoleManagementGrooup.RoleStaffTreeVO }>({ open: false }); | |
18 | + | |
19 | + useEffect(() => { | |
20 | + if (treeContainer.current) { | |
21 | + const rect = treeContainer.current.getBoundingClientRect(); | |
22 | + setTranslate({ x: rect.width / 2, y: 20 }); | |
23 | + setDataimensions({ width: rect.width, height: 20 }); | |
24 | + } | |
25 | + }, [treeContainer.current]); | |
26 | + | |
27 | + return ( | |
28 | + <div id="treeWrapper" style={{ height: 'calc(100vh - 288px)' }} ref={treeContainer}> | |
29 | + {treeInitital.loading ? ( | |
30 | + <div style={{ width: '100%' }}> | |
31 | + <Spin spinning style={{ width: '100%', margin: '40px auto' }} /> | |
32 | + </div> | |
33 | + ) : treeInitital.errMsg ? ( | |
34 | + <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={treeInitital.errMsg} /> | |
35 | + ) : treeInitital.data.treeList?.length ? ( | |
36 | + <Tree | |
37 | + data={treeInitital.data.treeList} | |
38 | + orientation="vertical" | |
39 | + separation={{ nonSiblings: 2, siblings: 2 }} | |
40 | + pathFunc="step" | |
41 | + onLinkClick={(...props) => console.log('onLinkClick', props)} | |
42 | + onNodeClick={(...props) => { | |
43 | + console.log('onNodeClick', props); | |
44 | + }} | |
45 | + scaleExtent={{ min: 0, max: 20 }} | |
46 | + enableLegacyTransitions | |
47 | + translate={translate} | |
48 | + initialDepth={treeInitital.data.levelCnt ?? 2} | |
49 | + dimensions={dimensions} | |
50 | + centeringTransitionDuration={500} | |
51 | + renderCustomNodeElement={({ nodeDatum, toggleNode }) => { | |
52 | + const data: RoleManagementGrooup.RoleStaffTreeVO = nodeDatum; | |
53 | + const level = data.level ?? '级别'; | |
54 | + const width = 15 * level.length; | |
55 | + const x = -(width / 2); | |
56 | + const textX = width / 2 + 10; | |
57 | + return ( | |
58 | + <g> | |
59 | + <rect | |
60 | + id="tree-item-toggle" | |
61 | + x={x} | |
62 | + width={width} | |
63 | + height="30" | |
64 | + fill={data.children?.length ? '#4189FD' : 'white'} | |
65 | + stroke={data.children?.length ? '#4189FD' : 'black'} | |
66 | + strokeWidth="0.5" | |
67 | + onClick={toggleNode} | |
68 | + /> | |
69 | + <text | |
70 | + id="tree-item-toggle" | |
71 | + x="0" | |
72 | + y="15" | |
73 | + fontSize="12" | |
74 | + textAnchor="middle" | |
75 | + alignmentBaseline="middle" | |
76 | + strokeWidth="0.5" | |
77 | + fill={data.children?.length ? 'white' : 'black'} | |
78 | + stroke={data.children?.length ? 'white' : 'black'} | |
79 | + onClick={toggleNode} | |
80 | + > | |
81 | + {level} | |
82 | + </text> | |
83 | + <text fill="black" strokeWidth="1" fontSize={15} x={textX} y={15}> | |
84 | + {nodeDatum.name} | |
85 | + <tspan | |
86 | + textDecoration="underline" | |
87 | + fontSize={12} | |
88 | + strokeWidth={0.5} | |
89 | + fill="#FF921C" | |
90 | + stroke="#FF921C" | |
91 | + onClick={() => setModalInfo({ open: true, data })} | |
92 | + > | |
93 | + 查看详情 | |
94 | + </tspan> | |
95 | + </text> | |
96 | + {Object.entries(nodeDatum.attributes ?? {}).map(([name, value], idx) => ( | |
97 | + <text key={name} fill="#666" stroke="#666" strokeWidth="0.5" fontSize={12} x={textX} y={15 * (idx + 2)}> | |
98 | + {name}:{value} | |
99 | + </text> | |
100 | + ))} | |
101 | + </g> | |
102 | + ); | |
103 | + }} | |
104 | + /> | |
105 | + ) : null} | |
106 | + <Modal | |
107 | + title="人员详情" | |
108 | + open={modalInfo.open} | |
109 | + footer={<Button onClick={() => setModalInfo({ open: false })}>关闭</Button>} | |
110 | + onCancel={() => setModalInfo({ open: false })} | |
111 | + > | |
112 | + <Row style={{ gap: '0 30px' }}> | |
113 | + <DetailItem title="级别" desp={modalInfo.data?.level ?? '-'} /> | |
114 | + <DetailItem title="员工" desp={modalInfo.data?.name ?? '-'} /> | |
115 | + {Object.entries(modalInfo.data?.attributes ?? {}).map(([name, value]) => ( | |
116 | + <DetailItem key={name} title={name} desp={value ?? '-'} /> | |
117 | + ))} | |
118 | + </Row> | |
119 | + <Divider orientation="left">角色授权门店({modalInfo.data?.roleShopList?.length ?? '-'} 个门店 )</Divider> | |
120 | + <Row style={{ flexDirection: 'column', flexWrap: 'nowrap', alignItems: 'start', maxHeight: '50vh', overflowY: 'auto' }}> | |
121 | + {modalInfo.data?.roleShopList?.map((shop, idx) => ( | |
122 | + <p key={shop} style={{ display: 'flex', alignItems: 'center', gap: 10 }}> | |
123 | + <div style={{ width: 6, height: 6, borderRadius: '50%', backgroundColor: '#4189FD' }} /> | |
124 | + <span style={{ flex: 1 }}> | |
125 | + {idx + 1}. {shop} | |
126 | + </span> | |
127 | + </p> | |
128 | + ))} | |
129 | + </Row> | |
130 | + </Modal> | |
131 | + </div> | |
132 | + ); | |
133 | +} | ... | ... |
src/pages/ehr/RoleManagementGroup/index.tsx
... | ... | @@ -2,51 +2,54 @@ |
2 | 2 | * @Author: wangqiang@feewee.cn |
3 | 3 | * @Date: 2022-06-29 10:09:59 |
4 | 4 | * @LastEditors: wangqiang@feewee.cn |
5 | - * @LastEditTime: 2023-09-02 16:12:33 | |
5 | + * @LastEditTime: 2024-04-19 17:07:55 | |
6 | 6 | */ |
7 | -import React from 'react'; | |
7 | +import React, { useEffect, useMemo } from 'react'; | |
8 | 8 | import { createStore } from '@/hooks/moz'; |
9 | 9 | import zhCN from 'antd/lib/locale-provider/zh_CN'; |
10 | 10 | import { PageHeaderWrapper } from '@ant-design/pro-layout'; |
11 | -import { Button, Card, ConfigProvider, Input, Row } from 'antd'; | |
12 | -import { PlusOutlined } from '@ant-design/icons'; | |
11 | +import { Button, Card, ConfigProvider } from 'antd'; | |
12 | +import { LeftCircleOutlined } from '@ant-design/icons'; | |
13 | 13 | import store from './store'; |
14 | -import List from './components/List'; | |
15 | -import Modal from './components/Modal'; | |
16 | -import FeeweeFilterOption from '@/pages/notice/components/FeeweeFilterOption'; | |
14 | +import List from './components/ListIndex'; | |
15 | +import Tree from './components/RoleStaffTree'; | |
17 | 16 | |
18 | 17 | export const { Provider, useStore } = createStore(store); |
19 | 18 | |
20 | 19 | function RoleManagementGroup() { |
21 | - const { pagination, setVisible } = useStore(); | |
20 | + const { type, current, setType, setCurrent } = useStore(); | |
21 | + | |
22 | + const DOM = useMemo(() => { | |
23 | + if (type === 'list') { | |
24 | + return List; | |
25 | + } else { | |
26 | + return Tree; | |
27 | + } | |
28 | + }, [type]); | |
22 | 29 | |
23 | 30 | return ( |
24 | - <PageHeaderWrapper title="角色管理组"> | |
31 | + <PageHeaderWrapper | |
32 | + title="角色管理组" | |
33 | + content={type === 'tree' ? current?.name ?? '-' : null} | |
34 | + extraContent={ | |
35 | + type === 'tree' ? ( | |
36 | + <Button | |
37 | + // @ts-ignore | |
38 | + icon={<LeftCircleOutlined />} | |
39 | + type="link" | |
40 | + onClick={() => { | |
41 | + setCurrent(undefined); | |
42 | + setType('list'); | |
43 | + }} | |
44 | + > | |
45 | + 返回 | |
46 | + </Button> | |
47 | + ) : null | |
48 | + } | |
49 | + > | |
25 | 50 | <ConfigProvider locale={zhCN}> |
26 | 51 | <Card bordered={false}> |
27 | - <Row justify="space-between"> | |
28 | - <FeeweeFilterOption title="角色管理组名"> | |
29 | - <Input.Search | |
30 | - style={{ minWidth: 260, marginBottom: 10, marginRight: 10 }} | |
31 | - allowClear | |
32 | - placeholder="请输入角色管理组名查询" | |
33 | - value={pagination.innerParams.name} | |
34 | - onChange={(e) => pagination.setParams({ name: e.target.value })} | |
35 | - onSearch={() => pagination.setParams({ current: 1 }, true)} | |
36 | - /> | |
37 | - </FeeweeFilterOption> | |
38 | - <Button | |
39 | - icon={<PlusOutlined />} | |
40 | - type="primary" | |
41 | - onClick={() => { | |
42 | - setVisible(true); | |
43 | - }} | |
44 | - > | |
45 | - 新增 | |
46 | - </Button> | |
47 | - </Row> | |
48 | - <List /> | |
49 | - <Modal /> | |
52 | + <DOM /> | |
50 | 53 | </Card> |
51 | 54 | </ConfigProvider> |
52 | 55 | </PageHeaderWrapper> | ... | ... |
src/pages/ehr/RoleManagementGroup/interface.d.ts
... | ... | @@ -27,4 +27,18 @@ declare namespace RoleManagementGrooup { |
27 | 27 | interface Role extends CommonApi.RoleCodeVO { |
28 | 28 | index?: number; // 所在级别,其他级别不能编辑 |
29 | 29 | } |
30 | + | |
31 | + interface RoleStaffTreeListVO { | |
32 | + treeList?: RoleStaffTreeVO[]; | |
33 | + levelCnt?: number; // | |
34 | + } | |
35 | + | |
36 | + interface RoleStaffTreeVO { | |
37 | + staffId?: number; // | |
38 | + name: string; // 员工名 | |
39 | + level?: string; // 级别 | |
40 | + attributes?: Record<string, string | number | boolean>; | |
41 | + roleShopList?: string[]; // 授权门店 | |
42 | + children?: RoleStaffTreeVO[]; | |
43 | + } | |
30 | 44 | } | ... | ... |
src/pages/ehr/RoleManagementGroup/store.ts
... | ... | @@ -4,25 +4,25 @@ |
4 | 4 | * @LastEditors: wangqiang@feewee.cn |
5 | 5 | * @LastEditTime: 2022-07-04 10:32:00 |
6 | 6 | */ |
7 | -import usePagination from "@/hooks/usePagination"; | |
8 | -import useInitial from "@/hooks/useInitail"; | |
9 | -import { getAllRoleCodeApi } from "@/common/api"; | |
10 | -import { useState } from "react"; | |
11 | -import { getListApi, getGroupDetailApi } from "./api"; | |
12 | -import { message } from "antd"; | |
7 | +import usePagination from '@/hooks/usePagination'; | |
8 | +import useInitial from '@/hooks/useInitail'; | |
9 | +import { getAllRoleCodeApi } from '@/common/api'; | |
10 | +import { useState } from 'react'; | |
11 | +import { getListApi, getGroupDetailApi } from './api'; | |
12 | +import { message } from 'antd'; | |
13 | +import useMenuElement from '@/hooks/useMenuElement'; | |
13 | 14 | |
14 | 15 | export default function useStore() { |
16 | + const { elements } = useMenuElement(); | |
15 | 17 | const pagination = usePagination(getListApi); |
16 | - const roleInitial = useInitial< | |
17 | - RoleManagementGrooup.Role[], | |
18 | - CommonApi.RoleParams | |
19 | - >(getAllRoleCodeApi, [], { roleType: 2 }); // 默认查询所有管理角色 | |
18 | + const roleInitial = useInitial<RoleManagementGrooup.Role[], CommonApi.RoleParams>(getAllRoleCodeApi, [], { roleType: 2 }); // 默认查询所有管理角色 | |
20 | 19 | const [visible, setVisible] = useState(false); |
21 | 20 | const [disabled, setDisabled] = useState(false); |
22 | 21 | const [current, setCurrent] = useState<RoleManagementGrooup.Detail>(); |
22 | + const [type, setType] = useState<'list' | 'tree'>('list'); | |
23 | 23 | |
24 | 24 | function getDetail(item: RoleManagementGrooup.GroupItem, edit: boolean) { |
25 | - const hide = message.loading("查询中...", 0); | |
25 | + const hide = message.loading('查询中...', 0); | |
26 | 26 | getGroupDetailApi(item.id || -1) |
27 | 27 | .then((res) => { |
28 | 28 | setCurrent({ |
... | ... | @@ -33,7 +33,7 @@ export default function useStore() { |
33 | 33 | setVisible(true); |
34 | 34 | }) |
35 | 35 | .catch((err) => { |
36 | - message.error(err.message || "查询失败"); | |
36 | + message.error(err.message || '查询失败'); | |
37 | 37 | }) |
38 | 38 | .finally(() => { |
39 | 39 | hide(); |
... | ... | @@ -45,6 +45,7 @@ export default function useStore() { |
45 | 45 | } |
46 | 46 | |
47 | 47 | return { |
48 | + elements, | |
48 | 49 | pagination, |
49 | 50 | roleInitial, |
50 | 51 | visible, |
... | ... | @@ -53,21 +54,20 @@ export default function useStore() { |
53 | 54 | setDisabled, |
54 | 55 | current, |
55 | 56 | setCurrent, |
57 | + type, | |
58 | + setType, | |
56 | 59 | getDetail, |
57 | 60 | formatRoleList, |
58 | 61 | }; |
59 | 62 | } |
60 | 63 | |
61 | -function handleRoleList( | |
62 | - roleList: RoleManagementGrooup.Role[], | |
63 | - codes?: (string | string[])[] | |
64 | -): RoleManagementGrooup.Role[] { | |
64 | +function handleRoleList(roleList: RoleManagementGrooup.Role[], codes?: (string | string[])[]): RoleManagementGrooup.Role[] { | |
65 | 65 | if (codes) { |
66 | 66 | roleList = roleList.map((role) => { |
67 | - let index = codes.findIndex((code) => { | |
67 | + const index = codes.findIndex((code) => { | |
68 | 68 | if (Array.isArray(code) && code.includes(role.roleCode)) { |
69 | 69 | return true; |
70 | - } else if (typeof code === "string" && code === role.roleCode) { | |
70 | + } else if (typeof code === 'string' && code === role.roleCode) { | |
71 | 71 | return true; |
72 | 72 | } else { |
73 | 73 | return false; | ... | ... |
src/pages/oop/Dealer/Shop/config.tsx
src/pages/order3/WeeklydataUpload/index.tsx
1 | +/* | |
2 | + * @Author: jiangwei jiangwei.feewee.cn | |
3 | + * @Date: 2024-04-19 10:49:37 | |
4 | + * @LastEditors: jiangwei jiangwei.feewee.cn | |
5 | + * @LastEditTime: 2024-04-19 11:03:43 | |
6 | + * @FilePath: /fw-cms/src/pages/order3/WeeklydataUpload/index.tsx | |
7 | + * @Description: | |
8 | + * | |
9 | + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. | |
10 | + */ | |
1 | 11 | import React, { useState } from 'react' |
2 | 12 | import { PageHeaderWrapper } from '@ant-design/pro-layout' |
3 | 13 | import { Button, Card, Table, Tag, Divider, Select } from 'antd' |
... | ... | @@ -80,7 +90,7 @@ export default function Index() { |
80 | 90 | <Column title="状态" dataIndex="status" render={t => <Tag color={t == 1 ? 'orange' : 'green'}>{t == 1 ? '处理中' : '已完成'}</Tag>} /> |
81 | 91 | </Table> |
82 | 92 | </Card> |
83 | - <UploadModal visible={visible} onCancel={() => setVisible(false)} onRefshing={setParams} /> | |
93 | + <UploadModal visible={visible} onCancel={() => setVisible(false)} onRefshing={() => setParams({}, true)} /> | |
84 | 94 | </PageHeaderWrapper> |
85 | 95 | ) |
86 | 96 | } |
87 | 97 | \ No newline at end of file | ... | ... |
src/pages/performance/KpiSetting/components/EditModal.tsx
... | ... | @@ -44,9 +44,10 @@ export default function EditModal({ onClose, setItem, item, roleList }: Props) { |
44 | 44 | useEffect(() => { |
45 | 45 | if (visible && currentItem) { |
46 | 46 | const result = transformFormData(currentItem, roleList, list); |
47 | - console.log(currentItem,'323') | |
48 | - console.log({...result},'1111dwewwwwwew') | |
49 | - form.setFieldsValue({ ...result}); | |
47 | + console.log(currentItem, '323'); | |
48 | + console.log({ ...result }, '1111dwewwwwwew'); | |
49 | + | |
50 | + form.setFieldsValue({ ...result }); | |
50 | 51 | } |
51 | 52 | }, [visible]); |
52 | 53 | function handleSave(values: any) { |
... | ... | @@ -203,6 +204,7 @@ export default function EditModal({ onClose, setItem, item, roleList }: Props) { |
203 | 204 | </Select> |
204 | 205 | </Form.Item> |
205 | 206 | )} |
207 | + | |
206 | 208 | <Form.Item |
207 | 209 | noStyle |
208 | 210 | shouldUpdate={(prevValues, currentValues) => { |
... | ... | @@ -211,7 +213,7 @@ export default function EditModal({ onClose, setItem, item, roleList }: Props) { |
211 | 213 | > |
212 | 214 | {({ getFieldValue }) => { |
213 | 215 | return getFieldValue('roleType') === 3 ? ( |
214 | - <Form.Item name="roles" label="适用角色1" rules={[{ required: true }]}> | |
216 | + <Form.Item name="roles" label="适用角色" rules={[{ required: true }]}> | |
215 | 217 | <Select |
216 | 218 | placeholder="请选择角色" |
217 | 219 | showSearch |
... | ... | @@ -231,18 +233,34 @@ export default function EditModal({ onClose, setItem, item, roleList }: Props) { |
231 | 233 | ) : null; |
232 | 234 | }} |
233 | 235 | </Form.Item> |
234 | - <Form.Item name="businessOriginName" label="原始指标名称" rules={[{ required: true, message: '请输入原始指标名称' }]}> | |
235 | - <Input placeholder="请输入指标名称" /> | |
236 | - </Form.Item> | |
237 | - <Form.Item name="businessOriginUnit" label="原始指标单位" rules={[{ required: true }]}> | |
238 | - <Select disabled={isOriginIndicatorCode} placeholder="请选择原始指标单位"> | |
239 | - {UnitType.map((item) => ( | |
240 | - <Option value={item.value} key={item.value}> | |
241 | - {item.label} | |
242 | - </Option> | |
243 | - ))} | |
244 | - </Select> | |
236 | + | |
237 | + <Form.Item | |
238 | + noStyle | |
239 | + shouldUpdate={(prevValues, currentValues) => { | |
240 | + return prevValues.hasTarget !== currentValues.hasTarget || prevValues.originIndicatorCode !== currentValues.originIndicatorCode; | |
241 | + }} | |
242 | + > | |
243 | + {({ getFieldValue }) => { | |
244 | + const ok = getFieldValue('hasTarget') === false && !getFieldValue('originIndicatorCode'); | |
245 | + return ok ? ( | |
246 | + <> | |
247 | + <Form.Item name="businessOriginName" label="原始指标名称" rules={[{ message: '请输入原始指标名称' }]}> | |
248 | + <Input placeholder="请输入指标名称" /> | |
249 | + </Form.Item> | |
250 | + <Form.Item name="businessOriginUnit" label="原始指标单位"> | |
251 | + <Select disabled={isOriginIndicatorCode} placeholder="请选择原始指标单位"> | |
252 | + {UnitType.map((item) => ( | |
253 | + <Option value={item.value} key={item.value}> | |
254 | + {item.label} | |
255 | + </Option> | |
256 | + ))} | |
257 | + </Select> | |
258 | + </Form.Item> | |
259 | + </> | |
260 | + ) : null; | |
261 | + }} | |
245 | 262 | </Form.Item> |
263 | + | |
246 | 264 | </Form> |
247 | 265 | </Modal> |
248 | 266 | ); | ... | ... |
src/pages/pms/partPlan/AppointPart/comonents/PartStorageModal.tsx
... | ... | @@ -55,8 +55,8 @@ export default function PartStorageModal({ onCancel, visible, onOk, itemData, se |
55 | 55 | |
56 | 56 | return ( |
57 | 57 | <Modal |
58 | - width={800} | |
59 | - visible={visible} | |
58 | + width={1000} | |
59 | + open={visible} | |
60 | 60 | onCancel={() => { |
61 | 61 | onCancel(); |
62 | 62 | setPartParams({}); |
... | ... | @@ -78,10 +78,10 @@ export default function PartStorageModal({ onCancel, visible, onOk, itemData, se |
78 | 78 | </Button>, |
79 | 79 | ]} |
80 | 80 | > |
81 | - <Form form={form} labelCol={{ span: 3 }} wrapperCol={{ span: 19 }}> | |
81 | + <Form form={form} labelCol={{ span: 2 }} wrapperCol={{ span: 19 }}> | |
82 | 82 | <Item label="库房" name="storageId" required rules={[{ required: true, message: '请选择库房' }]}> |
83 | 83 | <PmsSelect |
84 | - style={{ width: 250 }} | |
84 | + style={{ width: 400 }} | |
85 | 85 | placeholder="请选择库房" |
86 | 86 | value={storageid} |
87 | 87 | onChange={(v) => setStorageid(v)} |
... | ... | @@ -90,7 +90,7 @@ export default function PartStorageModal({ onCancel, visible, onOk, itemData, se |
90 | 90 | </Item> |
91 | 91 | <Item label="供应商" name="supplierId" required rules={[{ required: true, message: '请选择供应商' }]}> |
92 | 92 | <PmsSelect |
93 | - style={{ width: 250 }} | |
93 | + style={{ width: 400 }} | |
94 | 94 | placeholder="请选择供应商" |
95 | 95 | onChange={(v) => setPartParams({ stId: storageid, spId: v })} |
96 | 96 | options={suppliers | ... | ... |
src/pages/pms/storage/LocationManage/index.tsx
... | ... | @@ -36,6 +36,21 @@ export default function RepertoryIndex() { |
36 | 36 | allowClear |
37 | 37 | options={shops.map(i => ({ value: i.shopId, label: i.shopShortName }))} |
38 | 38 | /> |
39 | + <Select | |
40 | + style={{ width: 200, marginRight: 10, marginBottom: 10 }} | |
41 | + placeholder="是否有库存筛选" | |
42 | + onChange={v => { | |
43 | + if (typeof v != 'undefined') { | |
44 | + setParams({ hasStock: !!v }, true) | |
45 | + } else { | |
46 | + setParams({ hasStock: undefined }, true) | |
47 | + } | |
48 | + }} | |
49 | + showSearch | |
50 | + optionFilterProp="children" | |
51 | + allowClear | |
52 | + options={[{ value: 1, label: '是' }, { value: 0, label: '否' }]} | |
53 | + /> | |
39 | 54 | <Search |
40 | 55 | allowClear |
41 | 56 | placeholder="库位号搜索" | ... | ... |
src/pages/vms/OperationAdministration/components/PlayBackTable/index.tsx
... | ... | @@ -32,9 +32,9 @@ const columns: ColumnsType<DataType> = [ |
32 | 32 | width: 100, |
33 | 33 | }, |
34 | 34 | { |
35 | - title: '轨迹id', | |
36 | - dataIndex: 'trid', | |
37 | - key: 'trid', | |
35 | + title: '车牌号', | |
36 | + dataIndex: 'plateNumber', | |
37 | + key: 'plateNumber', | |
38 | 38 | width: 100, |
39 | 39 | }, |
40 | 40 | { |
... | ... | @@ -86,7 +86,6 @@ function PlayBackTable(props: any) { |
86 | 86 | }; |
87 | 87 | |
88 | 88 | const handlePageChange = (current: number, pageSize: number, keyword?: string) => { |
89 | - console.log(1); | |
90 | 89 | setTableData([]); |
91 | 90 | setData({ ...data, current, pageSize, keyword }); |
92 | 91 | }; |
... | ... | @@ -98,7 +97,7 @@ function PlayBackTable(props: any) { |
98 | 97 | enterButton="查询" |
99 | 98 | style={{ marginBottom: 10 }} |
100 | 99 | onSearch={(v) => handlePageChange(data.current || 1, data.pageSize || 10, v)} |
101 | - placeholder="搜索GPS号" | |
100 | + placeholder="搜索GPS号/车牌号" | |
102 | 101 | /> |
103 | 102 | <Table |
104 | 103 | dataSource={tableData} | ... | ... |