Browse Source

审批列表

liushengqiang 2 years ago
parent
commit
55105548ba

+ 1 - 0
.eslintignore

@@ -1,3 +1,4 @@
 public
 dist
 *.d.ts
+*

+ 314 - 129
pnpm-lock.yaml

@@ -1,15 +1,30 @@
 lockfileVersion: '6.0'
 
 dependencies:
-  axios:
-    specifier: ^1.3.5
-    version: 1.3.5
+  '@amap/amap-jsapi-loader':
+    specifier: ^1.0.1
+    version: 1.0.1
+  '@vant/use':
+    specifier: ^1.5.1
+    version: 1.5.1(vue@3.2.47)
+  clean-deep:
+    specifier: ^3.4.0
+    version: 3.4.0
   dayjs:
     specifier: ^1.11.7
     version: 1.11.7
-  pinia:
-    specifier: ^2.0.34
-    version: 2.0.34(typescript@5.0.4)(vue@3.2.47)
+  numeral:
+    specifier: ^2.0.6
+    version: 2.0.6
+  plyr:
+    specifier: ^3.7.8
+    version: 3.7.8
+  query-string:
+    specifier: ^8.1.0
+    version: 8.1.0
+  umi-request:
+    specifier: ^1.4.0
+    version: 1.4.0
   vant:
     specifier: ^4.1.2
     version: 4.1.2(vue@3.2.47)
@@ -19,6 +34,9 @@ dependencies:
   vue-router:
     specifier: ^4.1.6
     version: 4.1.6(vue@3.2.47)
+  vue3-lottie:
+    specifier: ^2.7.0
+    version: 2.7.0(vue@3.2.47)
 
 devDependencies:
   '@babel/core':
@@ -69,9 +87,15 @@ devDependencies:
   eslint-plugin-vue:
     specifier: ^9.10.0
     version: 9.10.0(eslint@8.38.0)
+  husky:
+    specifier: ^8.0.0
+    version: 8.0.0
+  less:
+    specifier: ^4.1.3
+    version: 4.1.3
   lint-staged:
-    specifier: ^13.2.1
-    version: 13.2.1
+    specifier: ^13.2.2
+    version: 13.2.2
   plop:
     specifier: ^3.1.2
     version: 3.1.2
@@ -84,9 +108,6 @@ devDependencies:
   prettier:
     specifier: ^2.8.7
     version: 2.8.7
-  sass:
-    specifier: ^1.61.0
-    version: 1.61.0
   typescript:
     specifier: ^5.0.4
     version: 5.0.4
@@ -95,7 +116,7 @@ devDependencies:
     version: 0.24.1(vue@3.2.47)
   vite:
     specifier: ^4.2.1
-    version: 4.2.1(@types/node@16.18.23)(sass@1.61.0)
+    version: 4.2.1(@types/node@16.18.23)(less@4.1.3)
   vite-plugin-eslint:
     specifier: ^1.8.1
     version: 1.8.1(eslint@8.38.0)(vite@4.2.1)
@@ -111,6 +132,10 @@ devDependencies:
 
 packages:
 
+  /@amap/amap-jsapi-loader@1.0.1:
+    resolution: {integrity: sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==}
+    dev: false
+
   /@ampproject/remapping@2.2.1:
     resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
     engines: {node: '>=6.0.0'}
@@ -1831,7 +1856,7 @@ packages:
       '@babel/core': 7.21.4
       '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.21.4)
       '@vue/babel-plugin-jsx': 1.1.1(@babel/core@7.21.4)
-      vite: 4.2.1(@types/node@16.18.23)(sass@1.61.0)
+      vite: 4.2.1(@types/node@16.18.23)(less@4.1.3)
       vue: 3.2.47
     transitivePeerDependencies:
       - supports-color
@@ -1844,7 +1869,7 @@ packages:
       vite: ^4.0.0
       vue: ^3.2.25
     dependencies:
-      vite: 4.2.1(@types/node@16.18.23)(sass@1.61.0)
+      vite: 4.2.1(@types/node@16.18.23)(less@4.1.3)
       vue: 3.2.47
     dev: true
 
@@ -2117,10 +2142,6 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
-  /asynckit@0.4.0:
-    resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
-    dev: false
-
   /autoprefixer@10.4.14(postcss@8.4.21):
     resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==}
     engines: {node: ^10 || ^12 || >=14}
@@ -2137,16 +2158,6 @@ packages:
       postcss-value-parser: 4.2.0
     dev: true
 
-  /axios@1.3.5:
-    resolution: {integrity: sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==}
-    dependencies:
-      follow-redirects: 1.15.2
-      form-data: 4.0.0
-      proxy-from-env: 1.1.0
-    transitivePeerDependencies:
-      - debug
-    dev: false
-
   /babel-plugin-dynamic-import-node@2.3.3:
     resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==}
     dependencies:
@@ -2272,7 +2283,6 @@ packages:
     dependencies:
       function-bind: 1.1.1
       get-intrinsic: 1.2.0
-    dev: true
 
   /callsites@3.1.0:
     resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
@@ -2365,6 +2375,15 @@ packages:
     resolution: {integrity: sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==}
     dev: true
 
+  /clean-deep@3.4.0:
+    resolution: {integrity: sha512-Lo78NV5ItJL/jl+B5w0BycAisaieJGXK1qYi/9m4SjR8zbqmrUtO7Yhro40wEShGmmxs/aJLI/A+jNhdkXK8mw==}
+    engines: {node: '>=4'}
+    dependencies:
+      lodash.isempty: 4.4.0
+      lodash.isplainobject: 4.0.6
+      lodash.transform: 4.6.0
+    dev: false
+
   /clean-stack@2.2.0:
     resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
     engines: {node: '>=6'}
@@ -2440,13 +2459,6 @@ packages:
     resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==}
     dev: true
 
-  /combined-stream@1.0.8:
-    resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
-    engines: {node: '>= 0.8'}
-    dependencies:
-      delayed-stream: 1.0.0
-    dev: false
-
   /commander@10.0.0:
     resolution: {integrity: sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==}
     engines: {node: '>=14'}
@@ -2468,12 +2480,23 @@ packages:
     resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
     dev: true
 
+  /copy-anything@2.0.6:
+    resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==}
+    dependencies:
+      is-what: 3.14.1
+    dev: true
+
   /core-js-compat@3.30.0:
     resolution: {integrity: sha512-P5A2h/9mRYZFIAP+5Ab8ns6083IyVpSclU74UNvbGVQ8VM7n3n3/g2yF3AkKQ9NXz2O+ioxLbEWKnDtgsFamhg==}
     dependencies:
       browserslist: 4.21.5
     dev: true
 
+  /core-js@3.30.2:
+    resolution: {integrity: sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==}
+    requiresBuild: true
+    dev: false
+
   /cross-spawn@5.1.0:
     resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==}
     dependencies:
@@ -2500,6 +2523,10 @@ packages:
   /csstype@2.6.21:
     resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
 
+  /custom-event-polyfill@1.0.7:
+    resolution: {integrity: sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==}
+    dev: false
+
   /dayjs@1.11.7:
     resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==}
     dev: false
@@ -2508,6 +2535,18 @@ packages:
     resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
     dev: true
 
+  /debug@3.2.7:
+    resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+    dependencies:
+      ms: 2.1.2
+    dev: true
+    optional: true
+
   /debug@4.3.4:
     resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
     engines: {node: '>=6.0'}
@@ -2520,6 +2559,11 @@ packages:
       ms: 2.1.2
     dev: true
 
+  /decode-uri-component@0.4.1:
+    resolution: {integrity: sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==}
+    engines: {node: '>=14.16'}
+    dev: false
+
   /deep-is@0.1.4:
     resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
     dev: true
@@ -2552,11 +2596,6 @@ packages:
       slash: 3.0.0
     dev: true
 
-  /delayed-stream@1.0.0:
-    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
-    engines: {node: '>=0.4.0'}
-    dev: false
-
   /detect-file@1.0.0:
     resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==}
     engines: {node: '>=0.10.0'}
@@ -2599,6 +2638,21 @@ packages:
     resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
     dev: true
 
+  /encoding@0.1.13:
+    resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
+    dependencies:
+      iconv-lite: 0.6.3
+    dev: false
+
+  /errno@0.1.8:
+    resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==}
+    hasBin: true
+    requiresBuild: true
+    dependencies:
+      prr: 1.0.1
+    dev: true
+    optional: true
+
   /esbuild@0.17.15:
     resolution: {integrity: sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==}
     engines: {node: '>=12'}
@@ -2901,6 +2955,11 @@ packages:
       to-regex-range: 5.0.1
     dev: true
 
+  /filter-obj@5.1.0:
+    resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==}
+    engines: {node: '>=14.16'}
+    dev: false
+
   /find-up@5.0.0:
     resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
     engines: {node: '>=10'}
@@ -2947,16 +3006,6 @@ packages:
     resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
     dev: true
 
-  /follow-redirects@1.15.2:
-    resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
-    engines: {node: '>=4.0'}
-    peerDependencies:
-      debug: '*'
-    peerDependenciesMeta:
-      debug:
-        optional: true
-    dev: false
-
   /for-in@1.0.2:
     resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==}
     engines: {node: '>=0.10.0'}
@@ -2969,15 +3018,6 @@ packages:
       for-in: 1.0.2
     dev: true
 
-  /form-data@4.0.0:
-    resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
-    engines: {node: '>= 6'}
-    dependencies:
-      asynckit: 0.4.0
-      combined-stream: 1.0.8
-      mime-types: 2.1.35
-    dev: false
-
   /fraction.js@4.2.0:
     resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
     dev: true
@@ -2996,7 +3036,6 @@ packages:
 
   /function-bind@1.1.1:
     resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
-    dev: true
 
   /gensync@1.0.0-beta.2:
     resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
@@ -3009,7 +3048,6 @@ packages:
       function-bind: 1.1.1
       has: 1.0.3
       has-symbols: 1.0.3
-    dev: true
 
   /get-stream@3.0.0:
     resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
@@ -3141,14 +3179,12 @@ packages:
   /has-symbols@1.0.3:
     resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
     engines: {node: '>= 0.4'}
-    dev: true
 
   /has@1.0.3:
     resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
     engines: {node: '>= 0.4.0'}
     dependencies:
       function-bind: 1.1.1
-    dev: true
 
   /he@1.2.0:
     resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
@@ -3179,6 +3215,12 @@ packages:
     engines: {node: '>=14.18.0'}
     dev: true
 
+  /husky@8.0.0:
+    resolution: {integrity: sha512-4qbE/5dzNDNxFEkX9MNRPKl5+omTXQzdILCUWiqG/lWIAioiM5vln265/l6I2Zx8gpW8l1ukZwGQeCFbBZ6+6w==}
+    engines: {node: '>=14'}
+    hasBin: true
+    dev: true
+
   /iconv-lite@0.4.24:
     resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
     engines: {node: '>=0.10.0'}
@@ -3186,6 +3228,12 @@ packages:
       safer-buffer: 2.1.2
     dev: true
 
+  /iconv-lite@0.6.3:
+    resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      safer-buffer: 2.1.2
+
   /ieee754@1.2.1:
     resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
     dev: true
@@ -3195,9 +3243,13 @@ packages:
     engines: {node: '>= 4'}
     dev: true
 
-  /immutable@4.3.0:
-    resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==}
+  /image-size@0.5.5:
+    resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==}
+    engines: {node: '>=0.10.0'}
+    hasBin: true
+    requiresBuild: true
     dev: true
+    optional: true
 
   /import-fresh@3.3.0:
     resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
@@ -3348,7 +3400,6 @@ packages:
   /is-stream@1.1.0:
     resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
     engines: {node: '>=0.10.0'}
-    dev: true
 
   /is-stream@3.0.0:
     resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
@@ -3372,6 +3423,10 @@ packages:
     engines: {node: '>=12'}
     dev: true
 
+  /is-what@3.14.1:
+    resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==}
+    dev: true
+
   /is-windows@1.0.2:
     resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
     engines: {node: '>=0.10.0'}
@@ -3391,6 +3446,13 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
+  /isomorphic-fetch@2.2.1:
+    resolution: {integrity: sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==}
+    dependencies:
+      node-fetch: 1.7.3
+      whatwg-fetch: 3.6.2
+    dev: false
+
   /js-sdsl@4.4.0:
     resolution: {integrity: sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==}
     dev: true
@@ -3436,6 +3498,26 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
+  /less@4.1.3:
+    resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==}
+    engines: {node: '>=6'}
+    hasBin: true
+    dependencies:
+      copy-anything: 2.0.6
+      parse-node-version: 1.0.1
+      tslib: 2.5.0
+    optionalDependencies:
+      errno: 0.1.8
+      graceful-fs: 4.2.11
+      image-size: 0.5.5
+      make-dir: 2.1.0
+      mime: 1.6.0
+      needle: 3.2.0
+      source-map: 0.6.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /levn@0.4.1:
     resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
     engines: {node: '>= 0.8.0'}
@@ -3463,8 +3545,8 @@ packages:
     engines: {node: '>=10'}
     dev: true
 
-  /lint-staged@13.2.1:
-    resolution: {integrity: sha512-8gfzinVXoPfga5Dz/ZOn8I2GOhf81Wvs+KwbEXQn/oWZAvCVS2PivrXfVbFJc93zD16uC0neS47RXHIjXKYZQw==}
+  /lint-staged@13.2.2:
+    resolution: {integrity: sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA==}
     engines: {node: ^14.13.1 || >=16.0.0}
     hasBin: true
     dependencies:
@@ -3480,7 +3562,7 @@ packages:
       object-inspect: 1.12.3
       pidtree: 0.6.0
       string-argv: 0.3.1
-      yaml: 2.2.1
+      yaml: 2.2.2
     transitivePeerDependencies:
       - enquirer
       - supports-color
@@ -3505,6 +3587,10 @@ packages:
       wrap-ansi: 7.0.0
     dev: true
 
+  /loadjs@4.2.0:
+    resolution: {integrity: sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==}
+    dev: false
+
   /local-pkg@0.4.3:
     resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
     engines: {node: '>=14'}
@@ -3517,6 +3603,10 @@ packages:
       p-locate: 5.0.0
     dev: true
 
+  /lodash-es@4.17.21:
+    resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+    dev: false
+
   /lodash.debounce@4.0.8:
     resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
     dev: true
@@ -3525,10 +3615,22 @@ packages:
     resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
     dev: true
 
+  /lodash.isempty@4.4.0:
+    resolution: {integrity: sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==}
+    dev: false
+
+  /lodash.isplainobject@4.0.6:
+    resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+    dev: false
+
   /lodash.merge@4.6.2:
     resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
     dev: true
 
+  /lodash.transform@4.6.0:
+    resolution: {integrity: sha512-LO37ZnhmBVx0GvOU/caQuipEh4GN82TcWv3yHlebGDgOxbxiwwzW5Pcx2AcvpIv2WmvmSMoC492yQFNhy/l/UQ==}
+    dev: false
+
   /lodash@4.17.21:
     resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
     dev: true
@@ -3559,6 +3661,10 @@ packages:
       wrap-ansi: 6.2.0
     dev: true
 
+  /lottie-web@5.11.0:
+    resolution: {integrity: sha512-9vSt0AtdOH98GKDXwD5LPfFg9Pcmxt5+1BllAbudKM5iqPxpJnJUfuGaP45OyudDrESCOBgsjnntVUTygBNlzw==}
+    dev: false
+
   /lower-case@2.0.2:
     resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
     dependencies:
@@ -3597,6 +3703,16 @@ packages:
       '@jridgewell/sourcemap-codec': 1.4.15
     dev: true
 
+  /make-dir@2.1.0:
+    resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
+    engines: {node: '>=6'}
+    requiresBuild: true
+    dependencies:
+      pify: 4.0.1
+      semver: 5.7.1
+    dev: true
+    optional: true
+
   /make-iterator@1.0.1:
     resolution: {integrity: sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==}
     engines: {node: '>=0.10.0'}
@@ -3626,17 +3742,13 @@ packages:
       picomatch: 2.3.1
     dev: true
 
-  /mime-db@1.52.0:
-    resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
-    engines: {node: '>= 0.6'}
-    dev: false
-
-  /mime-types@2.1.35:
-    resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
-    engines: {node: '>= 0.6'}
-    dependencies:
-      mime-db: 1.52.0
-    dev: false
+  /mime@1.6.0:
+    resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
+    engines: {node: '>=4'}
+    hasBin: true
+    requiresBuild: true
+    dev: true
+    optional: true
 
   /mimic-fn@2.1.0:
     resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
@@ -3703,6 +3815,20 @@ packages:
     resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
     dev: true
 
+  /needle@3.2.0:
+    resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==}
+    engines: {node: '>= 4.4.x'}
+    hasBin: true
+    requiresBuild: true
+    dependencies:
+      debug: 3.2.7
+      iconv-lite: 0.6.3
+      sax: 1.2.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+    optional: true
+
   /neo-async@2.6.2:
     resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
     dev: true
@@ -3714,6 +3840,13 @@ packages:
       tslib: 2.5.0
     dev: true
 
+  /node-fetch@1.7.3:
+    resolution: {integrity: sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==}
+    dependencies:
+      encoding: 0.1.13
+      is-stream: 1.1.0
+    dev: false
+
   /node-plop@0.31.1:
     resolution: {integrity: sha512-qmXJJt3YETFt/e0dtMADVpvck6EvN01Jig086o+J3M6G++mWA7iJ3Pqz4m4kvlynh73Iz2/rcZzxq7xTiF+aIQ==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -3772,9 +3905,12 @@ packages:
       boolbase: 1.0.0
     dev: true
 
+  /numeral@2.0.6:
+    resolution: {integrity: sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==}
+    dev: false
+
   /object-inspect@1.12.3:
     resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
-    dev: true
 
   /object-keys@1.1.1:
     resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
@@ -3932,6 +4068,11 @@ packages:
       path-root: 0.1.1
     dev: true
 
+  /parse-node-version@1.0.1:
+    resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==}
+    engines: {node: '>= 0.10'}
+    dev: true
+
   /parse-passwd@1.0.0:
     resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==}
     engines: {node: '>=0.10.0'}
@@ -4011,23 +4152,11 @@ packages:
     hasBin: true
     dev: true
 
-  /pinia@2.0.34(typescript@5.0.4)(vue@3.2.47):
-    resolution: {integrity: sha512-cgOoGUiyqX0SSgX8XelK9+Ri4XA2/YyNtgjogwfzIx1g7iZTaZPxm7/bZYMCLU2qHRiHhxG7SuQO0eBacFNc2Q==}
-    peerDependencies:
-      '@vue/composition-api': ^1.4.0
-      typescript: '>=4.4.4'
-      vue: ^2.6.14 || ^3.2.0
-    peerDependenciesMeta:
-      '@vue/composition-api':
-        optional: true
-      typescript:
-        optional: true
-    dependencies:
-      '@vue/devtools-api': 6.5.0
-      typescript: 5.0.4
-      vue: 3.2.47
-      vue-demi: 0.13.11(vue@3.2.47)
-    dev: false
+  /pify@4.0.1:
+    resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
+    engines: {node: '>=6'}
+    dev: true
+    optional: true
 
   /plop@3.1.2:
     resolution: {integrity: sha512-39SOtQ3WlePXSNqKqAh/QlUSHXHO25iCnyCO3Qs/9UzPVmwVledRTDGvPd2csh+JnHVXz4c63F6fBwdqZHgbUg==}
@@ -4044,6 +4173,16 @@ packages:
       v8flags: 4.0.0
     dev: true
 
+  /plyr@3.7.8:
+    resolution: {integrity: sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==}
+    dependencies:
+      core-js: 3.30.2
+      custom-event-polyfill: 1.0.7
+      loadjs: 4.2.0
+      rangetouch: 2.0.1
+      url-polyfill: 1.1.12
+    dev: false
+
   /postcss-pxtorem@6.0.0(postcss@8.4.21):
     resolution: {integrity: sha512-ZRXrD7MLLjLk2RNGV6UA4f5Y7gy+a/j1EqjAfp9NdcNYVjUMvg5HTYduTjSkKBkRkfqbg/iKrjMO70V4g1LZeg==}
     peerDependencies:
@@ -4090,9 +4229,10 @@ packages:
     hasBin: true
     dev: true
 
-  /proxy-from-env@1.1.0:
-    resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
-    dev: false
+  /prr@1.0.1:
+    resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
+    dev: true
+    optional: true
 
   /pseudomap@1.0.2:
     resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
@@ -4103,10 +4243,30 @@ packages:
     engines: {node: '>=6'}
     dev: true
 
+  /qs@6.11.1:
+    resolution: {integrity: sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==}
+    engines: {node: '>=0.6'}
+    dependencies:
+      side-channel: 1.0.4
+    dev: false
+
+  /query-string@8.1.0:
+    resolution: {integrity: sha512-BFQeWxJOZxZGix7y+SByG3F36dA0AbTy9o6pSmKFcFz7DAj0re9Frkty3saBn3nHo3D0oZJ/+rx3r8H8r8Jbpw==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      decode-uri-component: 0.4.1
+      filter-obj: 5.1.0
+      split-on-first: 3.0.0
+    dev: false
+
   /queue-microtask@1.2.3:
     resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
     dev: true
 
+  /rangetouch@2.0.1:
+    resolution: {integrity: sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==}
+    dev: false
+
   /readable-stream@3.6.2:
     resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
     engines: {node: '>= 6'}
@@ -4263,17 +4423,17 @@ packages:
 
   /safer-buffer@2.1.2:
     resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+  /sax@1.2.4:
+    resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
     dev: true
+    optional: true
 
-  /sass@1.61.0:
-    resolution: {integrity: sha512-PDsN7BrVkNZK2+dj/dpKQAWZavbAQ87IXqVvw2+oEYI+GwlTWkvbQtL7F2cCNbMqJEYKPh1EcjSxsnqIb/kyaQ==}
-    engines: {node: '>=14.0.0'}
+  /semver@5.7.1:
+    resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
     hasBin: true
-    dependencies:
-      chokidar: 3.5.3
-      immutable: 4.3.0
-      source-map-js: 1.0.2
     dev: true
+    optional: true
 
   /semver@6.3.0:
     resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
@@ -4320,6 +4480,14 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
+  /side-channel@1.0.4:
+    resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+    dependencies:
+      call-bind: 1.0.2
+      get-intrinsic: 1.2.0
+      object-inspect: 1.12.3
+    dev: false
+
   /signal-exit@3.0.7:
     resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
     dev: true
@@ -4379,6 +4547,11 @@ packages:
     resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
     deprecated: Please use @jridgewell/sourcemap-codec instead
 
+  /split-on-first@3.0.0:
+    resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==}
+    engines: {node: '>=12'}
+    dev: false
+
   /stdin-discarder@0.1.0:
     resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -4543,6 +4716,7 @@ packages:
     resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==}
     engines: {node: '>=12.20'}
     hasBin: true
+    dev: true
 
   /uglify-js@3.17.4:
     resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
@@ -4552,6 +4726,13 @@ packages:
     dev: true
     optional: true
 
+  /umi-request@1.4.0:
+    resolution: {integrity: sha512-OknwtQZddZHi0Ggi+Vr/olJ7HNMx4AzlywyK0W3NZBT7B0stjeZ9lcztA85dBgdAj3KVk8uPJPZSnGaDjELhrA==}
+    dependencies:
+      isomorphic-fetch: 2.2.1
+      qs: 6.11.1
+    dev: false
+
   /unc-path-regex@0.1.2:
     resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==}
     engines: {node: '>=0.10.0'}
@@ -4647,6 +4828,10 @@ packages:
       punycode: 2.3.0
     dev: true
 
+  /url-polyfill@1.1.12:
+    resolution: {integrity: sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==}
+    dev: false
+
   /util-deprecate@1.0.2:
     resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
     dev: true
@@ -4676,10 +4861,10 @@ packages:
       '@types/eslint': 8.37.0
       eslint: 8.38.0
       rollup: 2.79.1
-      vite: 4.2.1(@types/node@16.18.23)(sass@1.61.0)
+      vite: 4.2.1(@types/node@16.18.23)(less@4.1.3)
     dev: true
 
-  /vite@4.2.1(@types/node@16.18.23)(sass@1.61.0):
+  /vite@4.2.1(@types/node@16.18.23)(less@4.1.3):
     resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
@@ -4706,29 +4891,14 @@ packages:
     dependencies:
       '@types/node': 16.18.23
       esbuild: 0.17.15
+      less: 4.1.3
       postcss: 8.4.21
       resolve: 1.22.2
       rollup: 3.20.2
-      sass: 1.61.0
     optionalDependencies:
       fsevents: 2.3.2
     dev: true
 
-  /vue-demi@0.13.11(vue@3.2.47):
-    resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==}
-    engines: {node: '>=12'}
-    hasBin: true
-    requiresBuild: true
-    peerDependencies:
-      '@vue/composition-api': ^1.0.0-rc.1
-      vue: ^3.0.0-0 || ^2.6.0
-    peerDependenciesMeta:
-      '@vue/composition-api':
-        optional: true
-    dependencies:
-      vue: 3.2.47
-    dev: false
-
   /vue-eslint-parser@9.1.1(eslint@8.38.0):
     resolution: {integrity: sha512-C2aI/r85Q6tYcz4dpgvrs4wH/MqVrRAVIdpYedrxnATDHHkb+TroeRcDpKWGZCx/OcECMWfz7tVwQ8e+Opy6rA==}
     engines: {node: ^14.17.0 || >=16.0.0}
@@ -4774,6 +4944,17 @@ packages:
       typescript: 5.0.4
     dev: true
 
+  /vue3-lottie@2.7.0(vue@3.2.47):
+    resolution: {integrity: sha512-6vblrGFQxRP1bqd5Lfg+/g/kDH7OL5dQMxU9xYORSsTC7NfHXOjebhYrIYOlRodtA5/zfWMkG+3+sIR7wjaIXw==}
+    engines: {node: '>=12'}
+    peerDependencies:
+      vue: ^3.2
+    dependencies:
+      lodash-es: 4.17.21
+      lottie-web: 5.11.0
+      vue: 3.2.47
+    dev: false
+
   /vue@3.2.47:
     resolution: {integrity: sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==}
     dependencies:
@@ -4798,6 +4979,10 @@ packages:
     resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==}
     dev: true
 
+  /whatwg-fetch@3.6.2:
+    resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==}
+    dev: false
+
   /which@1.3.1:
     resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
     hasBin: true
@@ -4861,8 +5046,8 @@ packages:
     resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
     dev: true
 
-  /yaml@2.2.1:
-    resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==}
+  /yaml@2.2.2:
+    resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==}
     engines: {node: '>= 14'}
     dev: true
 

BIN
src/common/images/icon-im.png


+ 1 - 1
src/components/m-empty/index.tsx

@@ -10,7 +10,7 @@ export default defineComponent({
   props: {
     description: {
       type: String as PropType<string | undefined>,
-      default: null
+      default: ''
     },
     image: {
       type: String as PropType<'empty' | 'network' | '404'>,

+ 9 - 1
src/router/routes-common.ts

@@ -121,7 +121,15 @@ export default [
         meta: {
           title: '新增活动'
         }
-      }
+      },
+      {
+        path: '/schedule-manage-detail',
+        name: 'schedule-manage-detail',
+        component: () => import('@/views/schedule-manage/detial'),
+        meta: {
+          title: '退团审批'
+        }
+      },
     ]
   },
   ...rootRouter

+ 5 - 0
src/themes.css

@@ -0,0 +1,5 @@
+:root {
+    --text-white: #fff;
+    --text-color: #333;
+    --text-color-2: #777;
+}

+ 57 - 0
src/views/schedule-manage/api.ts

@@ -0,0 +1,57 @@
+import request from '@/helpers/request';
+
+export interface IMusicGroupQuitQueryPage {
+  /** 审核状态 */
+  status?: 'ING' | 'PASS' | 'REJECT';
+  /** 页码 */
+  page: number;
+  /** 页容量 */
+  rows: number;
+  /** 搜索关键字 */
+  search?: string;
+}
+/** 学校学员退团 分页查询 */
+export const musicGroupQuitQueryPage = (data: IMusicGroupQuitQueryPage) => {
+  return request.post('/api-web/musicGroupQuit/queryPage', { data });
+};
+
+/**
+ * 获取退团详情
+ * @param musicGroupQuitId 退团编号
+ * @returns
+ */
+export const api_musicGroupQuitGetDetail = (musicGroupQuitId: string) => {
+  return request.get('/api-web/musicGroupQuit/getDetail', {
+    params: { musicGroupQuitId }
+  });
+};
+
+/**
+ * 退团审批通过
+ * @param musicGroupQuitId
+ * @param reason
+ * @returns
+ */
+export const api_musicGroupQuitAuditPass = (
+  musicGroupQuitId: number,
+  reason: string
+) => {
+  return request.get(`/api-web/musicGroupQuit/auditPass`, {
+    params: { musicGroupQuitId, reason }
+  });
+};
+
+/**
+ * 退团审批拒绝
+ * @param musicGroupQuitId
+ * @param reason
+ * @returns
+ */
+export const api_musicGroupQuitAuditReject = (
+  musicGroupQuitId: number,
+  reason: string
+) => {
+  return request.get('musicGroupQuit/auditReject', {
+    params: { musicGroupQuitId, reason }
+  });
+};

BIN
src/views/schedule-manage/detial/icons/icon-cancel.png


BIN
src/views/schedule-manage/detial/icons/icon-comfirm.png


+ 143 - 0
src/views/schedule-manage/detial/index.module.less

@@ -0,0 +1,143 @@
+.detail {
+    padding: 12px;
+}
+
+.listItem {
+    border-radius: 10px;
+    background-color: #fff;
+    overflow: hidden;
+    margin-bottom: 12px;
+
+    .itemTop {
+        display: flex;
+        align-items: center;
+        padding: 13px 12px;
+        border-bottom: 1px solid #F2F2F2;
+        font-size: 14px;
+
+        .icon {
+            display: block;
+            width: 17px;
+            height: 17px;
+        }
+
+        .timeTitle {
+            margin-left: 4px;
+            color: var(--text-color);
+        }
+
+        .time {
+            color: var(--text-color-2);
+        }
+
+        .timeBtn {
+            margin-left: auto;
+            font-weight: 600;
+
+            &.success {
+                color: var(--van-primary-color);
+            }
+        }
+    }
+
+    .iconIm {
+        width: 20px;
+        height: 20px;
+        margin-left: 5px;
+    }
+
+    .cellTitle {
+        display: flex;
+        align-items: center;
+        font-weight: bold;
+    }
+
+    .iconTeacher {
+        width: 48px;
+        height: 48px;
+        margin-right: 8px;
+    }
+
+    :global {
+        .van-cell {
+            padding: 14px 12px;
+        }
+
+        .van-cell__value {
+            color: var(--text-color);
+        }
+    }
+}
+
+.item_box {
+    position: relative;
+
+    .iconResult {
+        position: absolute;
+        right: 0;
+        bottom: -40px;
+        width: 105px;
+        height: 105px;
+    }
+}
+
+.item {
+    padding: 16px 12px;
+    border-radius: 10px;
+    background-color: #fff;
+    margin-bottom: 12px;
+}
+
+.info {
+    font-size: 14px;
+    color: #777;
+    line-height: 20px;
+    min-height: 40px;
+    padding: 0.32rem;
+    margin-bottom: 15px;
+}
+
+.itemTitleDes {
+    display: flex;
+    align-items: center;
+    color: var(--text-color);
+    font-size: 15px;
+
+    .line {
+        height: 12px;
+        width: 4px;
+        background-color: var(--van-primary-color);
+        border-radius: 2px;
+        margin-right: 6px;
+    }
+}
+
+.btns {
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 20px;
+    display: flex;
+    justify-content: space-evenly;
+    padding: 0 13px;
+
+    .cancelBtn {
+        background-color: #ccc;
+        margin-right: 15px;
+        color: #fff;
+    }
+
+    :global {
+        .van-button {
+            height: 44px;
+            font-size: 16px;
+            font-weight: 600;
+        }
+    }
+}
+
+.skeleton {
+    &>div {
+        width: 100%;
+    }
+}

+ 180 - 0
src/views/schedule-manage/detial/index.tsx

@@ -0,0 +1,180 @@
+import { defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import Item from './item';
+import { Button, Cell, Field, Skeleton, SkeletonParagraph, showToast } from 'vant';
+import MSticky from '@/components/m-sticky';
+import MHeader from '@/components/m-header';
+import SkeletionDetailItem from './skeletion-detail-item';
+import { useRoute } from 'vue-router';
+import { MusicGroupQuitDetailDto } from '../schedule';
+import {
+  api_musicGroupQuitAuditPass,
+  api_musicGroupQuitAuditReject,
+  api_musicGroupQuitGetDetail
+} from '../api';
+
+export default defineComponent({
+  name: 'schedule-manage-detail',
+  setup() {
+    const route = useRoute();
+    const detailData = reactive({
+      student: {} as MusicGroupQuitDetailDto,
+      skeleton: true
+    });
+
+    /** 获取退团详情 */
+    const getDetail = async () => {
+      const musicGroupQuitId: string = route.query.musicGroupQuitId as any;
+      api_musicGroupQuitGetDetail(musicGroupQuitId)
+        .then(res => {
+          const data: MusicGroupQuitDetailDto = res?.data || {};
+          detailData.student = data;
+        })
+        .finally(() => {
+          detailData.skeleton = false;
+        });
+    };
+
+    /** 通过 */
+    const musicGroupQuitAuditPass = async () => {
+      await api_musicGroupQuitAuditPass(
+        detailData.student.musicGroupQuitId,
+        detailData.student.reasonEnum
+      );
+      showToast('操作成功')
+    };
+    /** 拒绝 */
+    const musicGroupQuitAuditReject = async () => {
+      await api_musicGroupQuitAuditReject(
+        detailData.student.musicGroupQuitId,
+        detailData.student.reasonEnum
+      );
+      showToast('操作成功')
+    };
+    onMounted(() => {
+      getDetail();
+    });
+    return () => (
+      <div class={styles.detail}>
+        <MSticky position="top">
+          <MHeader></MHeader>
+        </MSticky>
+
+        <Skeleton loading={detailData.skeleton}>
+          {{
+            template: () => (
+              <div style={{ width: '100%' }}>
+                <SkeletionDetailItem />
+              </div>
+            ),
+            default: () => <Item />
+          }}
+        </Skeleton>
+
+        <div class={styles.item}>
+          <div class={styles.itemTitleDes}>
+            <div class={styles.line}></div>
+            <div>退团原因</div>
+          </div>
+          <Skeleton class={styles.skeleton} loading={detailData.skeleton}>
+            {{
+              template: () => (
+                <div class={styles.info}>
+                  <SkeletonParagraph />
+                  <SkeletonParagraph />
+                </div>
+              ),
+              default: () => <div class={styles.info}>毕业</div>
+            }}
+          </Skeleton>
+
+          <div class={styles.itemTitleDes}>
+            <div class={styles.line}></div>
+            <div>具体原因</div>
+          </div>
+
+          <Skeleton class={styles.skeleton} loading={detailData.skeleton}>
+            {{
+              template: () => (
+                <div class={styles.info}>
+                  <SkeletonParagraph />
+                  <SkeletonParagraph />
+                </div>
+              ),
+              default: () => (
+                <div class={styles.info}>
+                  孩子快升学了,需要专心学习文化课。
+                </div>
+              )
+            }}
+          </Skeleton>
+        </div>
+        <div class={styles.item}>
+          <div class={styles.itemTitleDes}>
+            <div class={styles.line}></div>
+            <div>
+              审批意见 <span style={{ color: 'red' }}>*</span>
+            </div>
+          </div>
+
+          <Skeleton class={styles.skeleton} loading={detailData.skeleton}>
+            {{
+              template: () => (
+                <div class={styles.info}>
+                  <SkeletonParagraph />
+                  <SkeletonParagraph />
+                </div>
+              ),
+              default: () => (
+                <>
+                  {detailData.student.status === 'ING' ? (
+                    <Field
+                      required
+                      rows={2}
+                      type="textarea"
+                      placeholder="请输入审批意见"
+                      border={false}
+                    />
+                  ) : (
+                    <div class={styles.info}>
+                      这次比赛很有希望,不要留下遗憾,乐团需要你!
+                    </div>
+                  )}
+                </>
+              )
+            }}
+          </Skeleton>
+        </div>
+
+        {!detailData.skeleton && detailData.student.status !== 'ING' && (
+          <div class={styles.item}>
+            <div class={styles.itemTitleDes}>
+              <div class={styles.line}></div>
+              <div>审批时间</div>
+            </div>
+            <div class={styles.info}>2023-03-24 14:20:32</div>
+          </div>
+        )}
+
+        {detailData.skeleton && detailData.student.status === 'ING' && (
+          <div class={[styles.btns, 'van-safe-area-bottom']}>
+            <Button
+              class={styles.cancelBtn}
+              round
+              block
+              onClick={musicGroupQuitAuditReject}>
+              拒绝
+            </Button>
+            <Button
+              type="primary"
+              round
+              block
+              onClick={musicGroupQuitAuditPass}>
+              通过
+            </Button>
+          </div>
+        )}
+      </div>
+    );
+  }
+});

+ 75 - 0
src/views/schedule-manage/detial/item.tsx

@@ -0,0 +1,75 @@
+import { PropType, defineComponent } from 'vue';
+import styles from './index.module.less';
+import icontimer from '@/common/images/icon-timer.png';
+import iconTeacher from '@/common/images/icon-teacher-default.png';
+import iconIm from '@/common/images/icon-im.png';
+import { Cell, Image } from 'vant';
+import icon_cancel from './icons/icon-cancel.png';
+import icon_comfirm from './icons/icon-comfirm.png';
+import { MusicGroupQuitDetailDto } from '../schedule';
+import { postMessage } from '@/helpers/native-message';
+
+export default defineComponent({
+  name: 'schedule-manage-list-item',
+  props: {
+    status: {
+      type: String as PropType<'success' | 'error'>,
+      default: ''
+    },
+    item: {
+      type: Object as PropType<MusicGroupQuitDetailDto>,
+      default: () => ({})
+    }
+  },
+  emits: ['goto'],
+  setup(props, { emit }) {
+    const item = props.item;
+    
+    /** 去聊天 */
+    const openIm = () => {
+      postMessage({
+        api: 'joinChatGroup',
+        content: {
+          type: 'single', // single 单人 multi 多人
+          id: item.imGroupId
+        }
+      })
+    }
+    return () => (
+      <div class={styles.item_box}>
+        <div class={styles.listItem}>
+          <div class={styles.itemTop}>
+            <img class={styles.icon} src={icontimer} />
+            <span class={styles.timeTitle}>审批时间:</span>
+            <span class={styles.time}>
+              {item.createTime || '2023-03-24 14:00:32'}
+            </span>
+          </div>
+          <Cell center label={item.subjectName || '长笛'}>
+            {{
+              icon: () => (
+                <Image
+                  src={item.studentAvatar || iconTeacher}
+                  class={styles.iconTeacher}
+                  fit="contain"
+                />
+              ),
+              title: () => (
+                <div class={styles.cellTitle}>
+                  <span>{item.studentName || '李天泽'}</span>
+                  <img class={styles.iconIm} src={iconIm} onClick={() => openIm()} />
+                </div>
+              )
+            }}
+          </Cell>
+        </div>
+        {item.status !== 'ING' && (
+          <img
+            class={styles.iconResult}
+            src={item.status === 'PASS' ? icon_comfirm : icon_cancel}
+          />
+        )}
+      </div>
+    );
+  }
+});

+ 38 - 0
src/views/schedule-manage/detial/skeletion-detail-item.tsx

@@ -0,0 +1,38 @@
+import { PropType, defineComponent } from 'vue';
+import styles from './index.module.less';
+import icontimer from '@/common/images/icon-timer.png';
+import iconTeacher from '@/common/images/icon-teacher-default.png';
+import iconIm from '@/common/images/icon-im.png';
+import { Cell, Image, SkeletonAvatar, SkeletonParagraph } from 'vant';
+
+export default defineComponent({
+  name: 'schedule-manage-list-item',
+  props: {
+    status: {
+      type: String as PropType<'success' | 'error'>,
+      default: ''
+    },
+    item: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  emits: ['goto'],
+  setup(props, { emit }) {
+    const item = props.item;
+    return () => (
+      <div class={styles.listItem}>
+        <div class={styles.itemTop}>
+          <SkeletonParagraph />
+        </div>
+        <Cell center label={item.subjectName || '长笛'}>
+          {{
+            icon: () => <SkeletonAvatar avatarSize={'1.28rem'} />,
+            title: () => <SkeletonParagraph rowWidth="50%" />,
+            label: () => <SkeletonParagraph rowWidth="30%" />,
+          }}
+        </Cell>
+      </div>
+    );
+  }
+});

+ 149 - 0
src/views/schedule-manage/index.module.less

@@ -0,0 +1,149 @@
+.schedule-manage {
+    :global {
+        .van-tabs {
+            position: fixed;
+            left: 0;
+            right: 0;
+            top: var(--header-height);
+        }
+
+        .van-tabs__content {
+            height: calc(100vh - var(--header-height) - var(--van-tabs-line-height));
+        }
+
+        .van-tab__panel {
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+        }
+
+        .van-pull-refresh {
+            height: 100%;
+        }
+
+        .van-empty {
+            // height: 100% !important;
+        }
+
+        .van-tabs__line {
+            bottom: 26px;
+            width: 45px;
+            height: 6px;
+            background: linear-gradient(250deg, rgba(45, 199, 170, 0.22) 0%, #2DC7AA 100%);
+            z-index: 0;
+        }
+    }
+}
+
+.list {
+    padding: 12px;
+    flex: 1;
+    overflow-y: auto;
+
+    &::-webkit-scrollbar {
+        display: none;
+    }
+}
+
+.listHide {
+    padding: 0;
+    overflow: hidden;
+}
+
+.listItem {
+    border-radius: 10px;
+    background-color: #fff;
+    overflow: hidden;
+    margin-bottom: 12px;
+
+    .itemTop {
+        display: flex;
+        align-items: center;
+        padding: 13px 12px;
+        border-bottom: 1px solid #F2F2F2;
+        font-size: 14px;
+
+        .icon {
+            display: block;
+            width: 17px;
+            height: 17px;
+        }
+
+        .timeTitle {
+            margin-left: 4px;
+            color: var(--text-color);
+        }
+
+        .time {
+            color: var(--text-color-2);
+        }
+
+        .timeBtn {
+            margin-left: auto;
+            font-weight: 600;
+
+            &.success {
+                color: var(--van-primary-color);
+            }
+        }
+    }
+
+    .iconTeacher {
+        width: 48px;
+        height: 48px;
+        margin-right: 8px;
+    }
+
+    :global {
+        .van-cell {
+            padding: 14px 12px;
+        }
+
+        .van-cell__title {
+            font-weight: bold;
+        }
+
+        .van-cell__value {
+            color: var(--text-color);
+        }
+    }
+}
+
+.menubox {
+    display: flex;
+    align-items: center;
+    background-color: #fff;
+
+    :global {
+        .van-search {
+            flex: 1
+        }
+
+        .van-dropdown-menu {
+            min-width: 100px;
+        }
+
+        .van-dropdown-menu__title {
+            font-size: 14px;
+            padding: 0 25px 0 12px;
+
+            &::after {
+                right: 10px;
+            }
+        }
+    }
+}
+
+:global {
+    .van-dropdown-item {
+        .van-dropdown-item__content .van-dropdown-item__option .van-cell__title {
+            font-size: 16px;
+            color: var(--text-color);
+        }
+
+        .van-dropdown-item__content .van-dropdown-item__option--active {
+            color: var(--van-primary-color);
+        }
+
+    }
+}

+ 256 - 3
src/views/schedule-manage/index.tsx

@@ -1,8 +1,261 @@
-import { defineComponent } from 'vue';
+import MHeader from '@/components/m-header';
+import MSticky from '@/components/m-sticky';
+import {
+  CellGroup,
+  DropdownItem,
+  DropdownMenu,
+  List,
+  Skeleton,
+  Tab,
+  Tabs
+} from 'vant';
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import MFullRefresh from '@/components/m-full-refresh';
+import ListItem from './list-item';
+import SkeletionItem from './skeletion-item';
+import MEmpty from '@/components/m-empty';
+import MSearch from '@/components/m-search';
+import DropDownModal from '../site-management/drop-down-modal';
+import { musicGroupQuitQueryPage } from './api';
+import { MusicGroupQuitPageDto } from './schedule';
+import { useRouter } from 'vue-router';
 
 export default defineComponent({
   name: 'schedule-manage',
-  set() {
-    return () => <>待办事项</>;
+  setup() {
+    const router = useRouter();
+    const todoData = reactive({
+      examineLoading: true,
+      refreshLoading: false,
+      examineFinish: false,
+      /** 待审批列表 */
+      examineList: [] as MusicGroupQuitPageDto[],
+      examinePage: {
+        page: 1,
+        rows: 20
+      },
+      examineSkelet: true,
+      /** 完成列表 */
+      completeList: [] as MusicGroupQuitPageDto[],
+      completePage: {
+        page: 1,
+        rows: 20
+      },
+      completeResh: false,
+      completeLoading: false,
+      completeSkelet: true,
+      completeFinish: false,
+      completeActive: '',
+      completeColumns: [{ text: '全部活动', value: '' }],
+
+      options: [
+        { text: '全部状态', value: '' },
+        { text: '已通过', value: 'PASS' },
+        { text: '未通过', value: 'REJECT' }
+      ],
+      optionTitle: '全部状态',
+      activeOption: '' as any,
+      search: ''
+    });
+    const getExamine = async () => {
+      console.log('请求');
+      todoData.examineLoading = true;
+      if (todoData.refreshLoading) {
+        todoData.examineList = [];
+      }
+      musicGroupQuitQueryPage({
+        page: todoData.examinePage.page,
+        rows: todoData.examinePage.rows
+      })
+        .then(res => {
+          const rows: MusicGroupQuitPageDto[] = Array.isArray(res?.data?.rows)
+            ? res.data.rows
+            : [];
+          todoData.examineList = todoData.examineList.concat(rows);
+          if (!rows.length) {
+            todoData.examineFinish = true;
+          }
+        })
+        .catch(() => {
+          todoData.examineFinish = true;
+        })
+        .finally(() => {
+          todoData.examineLoading = false;
+          setTimeout(() => {
+            todoData.refreshLoading = false;
+            todoData.examineSkelet = false;
+          }, 500);
+        });
+    };
+    const getComplete = () => {
+      console.log('请求');
+      todoData.completeLoading = true;
+      musicGroupQuitQueryPage({
+        page: todoData.examinePage.page,
+        rows: todoData.examinePage.rows,
+        search: todoData.search,
+        status: todoData.activeOption
+      })
+        .then(res => {
+          const rows: MusicGroupQuitPageDto[] = Array.isArray(res?.data?.rows)
+            ? res.data.rows
+            : [];
+          todoData.completeList = todoData.completeList.concat(rows);
+          if (!rows.length) {
+            todoData.completeFinish = true;
+          }
+        })
+        .catch(() => {
+          todoData.completeFinish = true;
+        })
+        .finally(() => {
+          todoData.completeLoading = false;
+          setTimeout(() => {
+            todoData.completeResh = false;
+            todoData.completeSkelet = false;
+          }, 500);
+        });
+    };
+
+    onMounted(() => {
+      getExamine();
+      getComplete();
+    });
+
+    /** 下载菜单改变 */
+    const changeDropTitle = (option: any) => {
+      // console.log(option, todoData.activeOption);
+      todoData.optionTitle =
+        todoData.activeOption === 'PASS'
+          ? '已通过'
+          : todoData.activeOption === 'REJECT'
+          ? '未通过'
+          : '全部状态';
+    };
+
+    /** 去详情页 */
+    const handleGoto = (item: MusicGroupQuitPageDto) => {
+      router.push({
+        path: 'schedule-manage-detail',
+        query: {
+          musicGroupQuitId: item.musicGroupQuitId
+        }
+      });
+    };
+
+    return () => (
+      <div class={styles['schedule-manage']}>
+        <MSticky position="top">
+          <MHeader></MHeader>
+        </MSticky>
+        <Tabs swipeable animated>
+          <Tab name="待审批" title="待审批">
+            <List
+              loading={todoData.examineLoading}
+              finished={todoData.examineFinish}
+              class={styles.list}
+              onLoad={getExamine}>
+              <MFullRefresh
+                v-model:modelValue={todoData.refreshLoading}
+                onRefresh={() => {
+                  todoData.examinePage.page = 1;
+                  todoData.examineFinish = false;
+                  getExamine();
+                }}>
+                {todoData.examineSkelet && (
+                  <div class={[styles.list, styles.listHide]}>
+                    <Skeleton loading={true}>
+                      {{
+                        template: () => (
+                          <div style={{ width: '100%' }}>
+                            {new Array(10).fill(1).map((item: any) => (
+                              <SkeletionItem />
+                            ))}
+                          </div>
+                        )
+                      }}
+                    </Skeleton>
+                  </div>
+                )}
+                {todoData.examineList.map((item: MusicGroupQuitPageDto) => (
+                  <ListItem status="success" onGoto={() => handleGoto(item)} />
+                ))}
+                {!todoData.examineList.length && (
+                  <MEmpty
+                    description="暂无数据"
+                    style={{
+                      minHeight: '100%'
+                    }}
+                  />
+                )}
+              </MFullRefresh>
+            </List>
+          </Tab>
+          <Tab name="已完成" title="已完成">
+            <div class={styles.menubox}>
+              <DropdownMenu>
+                <DropdownItem
+                  teleport="body"
+                  title={todoData.optionTitle}
+                  v-model={todoData.activeOption}
+                  options={todoData.options}
+                  onChange={changeDropTitle}
+                />
+              </DropdownMenu>
+              <MSearch
+                placeholder="请输入学员名称"
+                v-model:modelValue={todoData.search}
+                onSearch={() => {
+                  todoData.examinePage.page = 1;
+                  todoData.completeFinish = false;
+                  getComplete();
+                }}
+              />
+            </div>
+            <List
+              loading={todoData.completeLoading}
+              finished={todoData.completeFinish}
+              class={styles.list}
+              onLoad={getComplete}>
+              <MFullRefresh
+                v-model:modelValue={todoData.completeResh}
+                onRefresh={() => {
+                  todoData.examinePage.page = 1;
+                  todoData.completeFinish = false;
+                  getComplete();
+                }}>
+                {todoData.completeSkelet && (
+                  <div class={[styles.list, styles.listHide]}>
+                    <Skeleton loading={true}>
+                      {{
+                        template: () => (
+                          <div style={{ width: '100%' }}>
+                            {new Array(10).fill(1).map((item: any) => (
+                              <SkeletionItem />
+                            ))}
+                          </div>
+                        )
+                      }}
+                    </Skeleton>
+                  </div>
+                )}
+                {todoData.completeList.map((item: any) => (
+                  <ListItem status="success" />
+                ))}
+                {!todoData.examineList.length && (
+                  <MEmpty
+                    description="暂无数据"
+                    style={{
+                      minHeight: '100%'
+                    }}
+                  />
+                )}
+              </MFullRefresh>
+            </List>
+          </Tab>
+        </Tabs>
+      </div>
+    );
   }
 });

+ 56 - 0
src/views/schedule-manage/list-item.tsx

@@ -0,0 +1,56 @@
+import { PropType, defineComponent } from 'vue';
+import styles from './index.module.less';
+import icontimer from '@/common/images/icon-timer.png';
+import iconTeacher from '@/common/images/icon-teacher-default.png';
+import { Cell, Image } from 'vant';
+import { MusicGroupQuitPageDto } from './schedule';
+
+export default defineComponent({
+  name: 'schedule-manage-list-item',
+  props: {
+    status: {
+      type: String as PropType<'success' | 'error'>,
+      default: ''
+    },
+    item: {
+      type: Object as PropType<MusicGroupQuitPageDto>,
+      default: () => ({})
+    }
+  },
+  emits: ['goto'],
+  setup(props, { emit }) {
+    const item = props.item
+    return () => (
+      <div class={styles.listItem}>
+        <div class={styles.itemTop}>
+          <img class={styles.icon} src={icontimer} />
+          <span class={styles.timeTitle}>审批时间:</span>
+          <span class={styles.time}>{item.createTime}</span>
+          {props.status === 'success' && (
+            <div class={[styles.timeBtn, styles.success]}>已通过</div>
+          )}
+          {props.status === 'error' && (
+            <div class={[styles.timeBtn, styles.error]}>未通过</div>
+          )}
+        </div>
+        <Cell
+          center
+          title={item.studentName}
+          label={item.subjectName}
+          value={'退团申请'}
+          isLink
+          onClick={() => emit('goto')}>
+          {{
+            icon: () => (
+              <Image
+                src={item.studentAvatar || iconTeacher}
+                class={styles.iconTeacher}
+                fit="contain"
+              />
+            )
+          }}
+        </Cell>
+      </div>
+    );
+  }
+});

+ 51 - 0
src/views/schedule-manage/schedule.d.ts

@@ -0,0 +1,51 @@
+/** 审核状态 */
+type IStatus = 'ING' | 'PASS' | 'REJECT';
+/** 学员编号 */
+type IReasonEnum =
+  | 'GRADUATE'
+  | 'NOT_INTERESTED'
+  | 'TIME_CONFLICT'
+  | 'FEELING_UNWELL'
+  | 'OTHER';
+
+/** 学员信息 */
+interface IStudentInfo {
+  /** 学员头像 */
+  studentAvatar: string;
+  /** 学员编号 */
+  studentId: number;
+  /** 学员名称 */
+  studentName: string;
+  /** 声部id */
+  subjectId: number;
+  /** 声部名称 */
+  subjectName: string;
+  /** im id */
+  imGroupId?: string
+}
+
+/** 审核列表分页 */
+export interface MusicGroupQuitPageDto extends IStudentInfo {
+  /** 提交时间 */
+  createTime?: string;
+  /**  */
+  musicGroupQuitId: number;
+  /** 审核状态 */
+  status: IStatus;
+}
+
+/** 退团详情 */
+export interface MusicGroupQuitDetailDto extends IStudentInfo {
+  /**提交时间 */
+  createTime: string;
+  /**退团id */
+  musicGroupQuitId: number;
+  /**学员编号 */
+  reasonEnum: IReasonEnum;
+  /** 审核原因 */
+  schoolStaffAuditReason: string;
+  /** 审核状态 */
+  status: IStatus;
+  /** 学员退团原因 */
+  userComment: string;
+}

+ 40 - 0
src/views/schedule-manage/skeletion-item.tsx

@@ -0,0 +1,40 @@
+import { PropType, defineComponent } from 'vue';
+import styles from './index.module.less';
+import {
+  Cell,
+  Image,
+  SkeletonAvatar,
+  SkeletonImage,
+  SkeletonParagraph
+} from 'vant';
+
+export default defineComponent({
+  name: 'schedule-manage-list-item',
+  props: {
+    status: {
+      type: String as PropType<'success' | 'error'>,
+      default: ''
+    }
+  },
+  emits: ['goto'],
+  setup(props, { emit }) {
+    return () => (
+      <div class={styles.listItem}>
+        <div class={styles.itemTop}>
+          <SkeletonParagraph />
+        </div>
+        <Cell
+          center
+          isLink
+          onClick={() => emit('goto')}>
+          {{
+            icon: () => <SkeletonAvatar avatarSize={'1.28rem'} />,
+            title: () => <SkeletonParagraph rowWidth="50%" />,
+            label: () => <SkeletonParagraph rowWidth="30%" />,
+            value: () => <SkeletonParagraph />,
+          }}
+        </Cell>
+      </div>
+    );
+  }
+});