Эх сурвалжийг харах

Merge branch 'master' of http://git.qmth.com.cn/sop/web

刘洋 1 жил өмнө
parent
commit
095c7e0f17
82 өөрчлөгдсөн 1845 нэмэгдсэн , 621 устгасан
  1. 1 0
      package.json
  2. 12 0
      src/assets/icons/icon-add-circle.svg
  3. 14 0
      src/assets/icons/icon-analysis.svg
  4. 12 0
      src/assets/icons/icon-delete.svg
  5. 12 0
      src/assets/icons/icon-fill-customer.svg
  6. 12 0
      src/assets/icons/icon-fill-data.svg
  7. 12 0
      src/assets/icons/icon-fill-project.svg
  8. 12 0
      src/assets/icons/icon-fill-resource.svg
  9. 12 0
      src/assets/icons/icon-fill-service.svg
  10. 12 0
      src/assets/icons/icon-fill-sop.svg
  11. 12 0
      src/assets/icons/icon-fill-system.svg
  12. 12 0
      src/assets/icons/icon-fill-time.svg
  13. 12 0
      src/assets/icons/icon-fill-user.svg
  14. 12 0
      src/assets/icons/icon-fill-work.svg
  15. 14 0
      src/assets/icons/icon-message.svg
  16. 12 0
      src/assets/icons/icon-notice.svg
  17. 12 0
      src/assets/icons/icon-pull-down.svg
  18. 14 0
      src/assets/icons/icon-service-area.svg
  19. 14 0
      src/assets/icons/icon-service-crm.svg
  20. 14 0
      src/assets/icons/icon-service-range.svg
  21. 14 0
      src/assets/icons/icon-service-unit.svg
  22. 12 0
      src/assets/icons/icon-sop-wait.svg
  23. 14 0
      src/assets/icons/icon-user-circle.svg
  24. 14 0
      src/assets/icons/icon-warning-wait.svg
  25. BIN
      src/assets/imgs/menu-logo.png
  26. 27 0
      src/components/global/my-drawer/index.vue
  27. 4 2
      src/components/global/search-form/index.vue
  28. 36 0
      src/components/global/svg-icon/index.vue
  29. 6 4
      src/layout/children-menu.vue
  30. 236 0
      src/layout/index-old.vue
  31. 161 183
      src/layout/index.vue
  32. 5 57
      src/layout/left-menu.vue
  33. 1 0
      src/main.js
  34. 5 2
      src/router/modules/myWorkbenches.js
  35. 2 1
      src/router/modules/projectQuality.js
  36. 1 0
      src/router/modules/resourceGuard.js
  37. 7 4
      src/router/modules/serviceUnit.js
  38. 1 0
      src/router/modules/sop.js
  39. 10 4
      src/router/modules/system.js
  40. 2 1
      src/router/modules/user.js
  41. 2 1
      src/router/modules/workHours.js
  42. 17 3
      src/store/modules/user.js
  43. 59 8
      src/style/global.less
  44. 185 0
      src/style/td-var.less
  45. 32 4
      src/style/tdesign-reset.less
  46. 8 2
      src/utils/filter.js
  47. 2 2
      src/views/project-quality/project-quality-manage/issues-feedback/index.vue
  48. 1 1
      src/views/resource-guard/device-guard/registration-query/index.vue
  49. 1 1
      src/views/resource-guard/person-guard/person-allocate/index.vue
  50. 1 0
      src/views/resource-guard/person-guard/person-files/add-person-file-dialog.vue
  51. 3 3
      src/views/resource-guard/person-guard/person-files/index.vue
  52. 88 54
      src/views/service-unit/dispatch/dispatch-manage/add-dispatch-dialog.vue
  53. 70 58
      src/views/service-unit/dispatch/dispatch-manage/index.vue
  54. 7 8
      src/views/service-unit/dispatch/dispatch-manage/mult-delineation-dialog.vue
  55. 6 5
      src/views/service-unit/service-unit-manage/add-range/index.vue
  56. 251 0
      src/views/service-unit/service-unit-manage/range-manage/add-range-dialog.vue
  57. 39 24
      src/views/service-unit/service-unit-manage/range-manage/index.vue
  58. 15 7
      src/views/service-unit/service-unit-manage/regional-planning/add-region-dialog.vue
  59. 13 9
      src/views/service-unit/service-unit-manage/regional-planning/index.vue
  60. 14 12
      src/views/service-unit/service-unit-manage/unit-manage/add-unit-dialog.vue
  61. 42 24
      src/views/service-unit/service-unit-manage/unit-manage/index.vue
  62. 1 1
      src/views/sop/sop-manage/office-sop/index.vue
  63. 1 1
      src/views/sop/sop-manage/student-sop/index.vue
  64. 1 1
      src/views/sop/sop-monitor/delay-warning/index.vue
  65. 1 1
      src/views/sop/sop-monitor/violation-registration/index.vue
  66. 25 18
      src/views/system/config-manage/checkin-manage/index.vue
  67. 32 23
      src/views/system/config-manage/customer-manage/index.vue
  68. 43 39
      src/views/system/config-manage/device-manage/index.vue
  69. 19 12
      src/views/system/config-manage/service-level-manage/index.vue
  70. 11 10
      src/views/system/config-manage/supplier-manage/index.vue
  71. 2 2
      src/views/system/notice-log/log-manage/index.vue
  72. 20 14
      src/views/system/notice-log/notice-manage/index.vue
  73. 1 1
      src/views/system/notice-log/notice-manage/notice-message-dialog.vue
  74. 4 4
      src/views/system/task/task-manage/index.vue
  75. 1 1
      src/views/user/auth-manage/role-manage/index.vue
  76. 1 1
      src/views/user/auth-manage/user-manage/index.vue
  77. 1 1
      src/views/user/org-struct-manage/struct-manage/index.vue
  78. 1 1
      src/views/work-hours/work-hours-manage/abnormal-check/done-check.vue
  79. 1 1
      src/views/work-hours/work-hours-manage/abnormal-check/wait-check.vue
  80. 2 2
      src/views/work-hours/work-hours-manage/work-attendance/index.vue
  81. 3 3
      src/views/work-hours/work-hours-manage/work-statistics/index.vue
  82. 21 0
      vite.config.js

+ 1 - 0
package.json

@@ -75,6 +75,7 @@
     "vite-plugin-html": "^3.2.0",
     "vite-plugin-require-transform": "^1.0.12",
     "vite-plugin-style-import": "^2.0.0",
+    "vite-plugin-svg-icons": "^2.0.1",
     "vite-svg-loader": "^3.6.0",
     "vue-tsc": "^1.0.11"
   }

+ 12 - 0
src/assets/icons/icon-add-circle.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-新增-off</title>
+    <g id="服务单元管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="7.1-服务单元管理" transform="translate(-337, -25)">
+            <g id="icon-新增-off" transform="translate(336, 24)">
+                <rect id="add-circle-(Background)" opacity="0" x="0" y="0" width="16" height="16"></rect>
+                <path d="M4.5,8.5 L4.5,7.5 L7.5,7.5 L7.5,4.5 L8.5,4.5 L8.5,7.5 L11.5,7.5 L11.5,8.5 L8.5,8.5 L8.5,11.5 L7.5,11.5 L7.5,8.5 L4.5,8.5 Z M15,8 C15,4.13400674 11.8659935,1 8,1 C4.13400674,1 1,4.13400674 1,8 C1,11.8659935 4.13400674,15 8,15 C11.8659935,15 15,11.8659935 15,8 Z M14,8 C14,4.68629146 11.3137083,2 8,2 C4.68629146,2 2,4.68629146 2,8 C2,11.3137083 4.68629146,14 8,14 C11.3137083,14 14,11.3137083 14,8 Z" id="add-circle" fill="#FFFFFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/icons/icon-analysis.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="17.5px" height="17.5px" viewBox="0 0 17.5 17.5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-派单分析-off</title>
+    <g id="服务单元管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="6.1-派单管理" transform="translate(-97.25, -105.25)">
+            <g id="3.Navigation导航/4.Menu导航菜单/左侧导航选项/一级有图标/默认" transform="translate(80, 96)">
+                <g id="icon-派单分析-off" transform="translate(16, 8)">
+                    <rect id="chart-pie-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                    <path d="M10,18.75 C5.16750842,18.75 1.25,14.8324919 1.25,10 C1.25,5.16750842 5.16750842,1.25 10,1.25 C14.8324919,1.25 18.75,5.16750842 18.75,10 C18.75,14.8324919 14.8324919,18.75 10,18.75 Z M10,17.5 C5.85786432,17.5 2.5,14.1421354 2.5,10 C2.5,6.06833518 5.52529335,2.84326538 9.375,2.52567112 L9.375,10.625 L17.4743295,10.625 C17.1567357,14.4747066 13.9316642,17.5 10,17.5 Z M10.625,9.375 L10.625,2.52567112 C14.2686236,2.8262639 17.1737361,5.73137671 17.4743295,9.375 L10.625,9.375 Z" id="chart-pie" fill="#262626"></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-delete.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="12px" height="14px" viewBox="0 0 12 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-作废-off</title>
+    <g id="服务单元管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="7.1-服务单元管理" transform="translate(-494, -25)">
+            <g id="icon-作废-off" transform="translate(492, 24)">
+                <rect id="delete-(Background)" opacity="0" x="0" y="0" width="16" height="16"></rect>
+                <path d="M6,6 L7,6 L7,12 L6,12 L6,6 Z M9,12 L10,12 L10,6 L9,6 L9,12 Z M14,3 L14,4 L13,4 L13,14 C13,14.5522852 12.5522842,15 12,15 L4,15 C3.44771504,15 3,14.5522842 3,14 L3,4 L2,4 L2,3 L5.5,3 L5.5,1.80000073 C5.5,1.35817304 5.85817218,1 6.30000019,1 L9.69999981,1 C10.1418276,1 10.5,1.35817215 10.5,1.80000013 L10.5,3 L14,3 Z M6.5,2 L9.5,2 L9.5,3 L6.5,3 L6.5,2 Z M4,14 L12,14 L12,4 L4,4 L4,14 Z" id="delete" fill="#262626"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-customer.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="13.75px" height="16.7569733px" viewBox="0 0 13.75 16.7569733" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-智能客服-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-29.125, -305.6215)">
+            <g id="icon-智能客服-on" transform="translate(26, 304)">
+                <rect id="service-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M9.99993205,1.62147522 C13.6185849,1.62147522 16.5842521,4.4172442 16.8547535,7.96660423 C16.8679667,8.0171901 16.875,8.0702734 16.875,8.125 L16.875,13.125 C16.875,13.1882691 16.865598,13.2493412 16.8481171,13.3068979 C16.5700948,16.1537278 14.1698539,18.3784485 11.25,18.3784485 L10,18.3784485 L10,17.1284485 L11.25,17.1284485 C13.3234227,17.1284485 15.0599647,15.6860888 15.5109954,13.75 L13.125,13.75 C12.7798218,13.75 12.5,13.4701777 12.5,13.125 L12.5,8.125 C12.5,7.77982235 12.7798223,7.5 13.125,7.5 L15.5368841,7.5 C15.0665271,4.86872256 12.7664697,2.87147522 9.99993205,2.87147522 C7.23339438,2.87147522 4.93333757,4.86872256 4.46298048,7.5 L6.875,7.5 C7.22017795,7.5 7.5,7.77982235 7.5,8.125 L7.5,13.125 C7.5,13.4701777 7.22017795,13.75 6.875,13.75 L3.74999996,13.75 C3.40482201,13.75 3.125,13.4701777 3.125,13.125 L3.125,8.125 C3.125,8.07053924 3.13196566,8.01770568 3.14505465,7.96734095 C3.41520186,4.41763073 6.38102919,1.62147522 9.99993205,1.62147522 Z" id="service"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-data.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="15px" height="15px" viewBox="0 0 15 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-数据驾驶舱-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-28.5, -586.5)">
+            <g id="icon-数据驾驶舱-on" transform="translate(26, 584)">
+                <rect id="chart-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M5.62500149,9.37492192 L6.87500149,9.37492549 L6.87498897,15 L5.62498897,15 L5.62500149,9.37492192 Z M9.37500238,15 L10.6250024,15 L10.6250012,5.625 L9.37500119,5.625 L9.37500238,15 Z M13.1250012,11.2499976 L14.3750012,11.25 L14.3749952,15 L13.1249952,15 L13.1250012,11.2499976 Z M3.75000238,2.5 L16.2500024,2.5 C16.9403589,2.5 17.5,3.05964641 17.5,3.75000238 L17.5,16.2500024 C17.5,16.9403589 16.9403553,17.5 16.25,17.5 L3.74999948,17.5 C3.05964358,17.5 2.5,16.9403553 2.5,16.25 L2.5,3.7499994 C2.5,3.05964351 3.05964649,2.5 3.75000238,2.5 Z" id="chart" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-project.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="13.7500966px" height="15.7289302px" viewBox="0 0 13.7500966 15.7289302" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-项目质量-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-29.125, -418.5)">
+            <g id="icon-项目质量-on" transform="translate(26, 416)">
+                <rect id="secured-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M13.7054956,7.94224262 L12.8216034,7.05836773 L9.23674345,10.643295 L7.1783179,8.58487248 L6.29443526,9.46875691 L9.23675299,12.4110699 L13.7054956,7.94224262 Z M3.125,11.2500578 C3.125,13.0205953 4.05394033,14.6613109 5.57214528,15.572269 L9.99974072,18.2289302 L14.4278467,15.5721962 C15.9460855,14.6612966 16.8750966,13.0205917 16.8750966,11.2500626 L16.8750966,2.5 L3.125,2.5 L3.125,11.2500578 Z" id="secured" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-resource.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16.25px" height="16.2573326px" viewBox="0 0 16.25 16.2573326" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-资源保障-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-27.8738, -249.8736)">
+            <g id="icon-资源保障-on" transform="translate(26, 248)">
+                <rect id="layers-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M9.99969482,9.38551188 L2.40800705,6.22238815 C1.89497087,6.00862801 1.89496979,5.25050998 2.40800697,5.03674954 L9.99969482,1.87362671 L17.5913823,5.03674954 C18.1044185,5.25050938 18.1044197,6.00862741 17.5913835,6.22238785 L9.99969482,9.38551188 Z M1.8737793,10.3172386 L10.0000167,13.8899243 L18.1237793,10.3183258 L18.1237793,8.78439546 L10.0000167,12.355994 L1.8737793,8.78330767 L1.8737793,10.3172386 Z M1.8737793,14.5582211 L10.0001347,18.1309593 L18.1237793,14.5594132 L18.1237793,13.0254805 L10.0001347,16.5970278 L1.8737793,13.0242896 L1.8737793,14.5582211 Z" id="layers" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-service.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="15.3125px" height="15.3125px" viewBox="0 0 15.3125 15.3125" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-服务单元-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-28.5, -138.1875)">
+            <g id="icon-服务单元-on" transform="translate(26, 136)">
+                <rect id="app-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M10.3125,5.9375 C10.3125,8.00856769 11.9914323,9.6875 14.0625,9.6875 C16.1335683,9.6875 17.8125,8.00856769 17.8125,5.9375 C17.8125,3.86643231 16.1335683,2.1875 14.0625,2.1875 C11.9914323,2.1875 10.3125,3.86643231 10.3125,5.9375 Z M3.75,2.5 L8.125,2.5 C8.8153559,2.5 9.375,3.0596441 9.375,3.75 L9.375,8.125 C9.375,8.8153559 8.8153559,9.375 8.125,9.375 L3.75,9.375 C3.0596441,9.375 2.5,8.8153559 2.5,8.125 L2.5,3.75 C2.5,3.0596441 3.0596441,2.5 3.75,2.5 Z M3.75,10.625 L8.125,10.625 C8.8153559,10.625 9.375,11.1846441 9.375,11.875 L9.375,16.25 C9.375,16.9403553 8.8153559,17.5 8.125,17.5 L3.75,17.5 C3.0596441,17.5 2.5,16.9403553 2.5,16.25 L2.5,11.875 C2.5,11.1846441 3.0596441,10.625 3.75,10.625 Z M11.875,10.625 L16.25,10.625 C16.9403553,10.625 17.5,11.1846441 17.5,11.875 L17.5,16.25 C17.5,16.9403553 16.9403553,17.5 16.25,17.5 L11.875,17.5 C11.1846441,17.5 10.625,16.9403553 10.625,16.25 L10.625,11.875 C10.625,11.1846441 11.1846441,10.625 11.875,10.625 Z" id="app" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-sop.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="15px" height="15px" viewBox="0 0 15 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-SOP-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-28.5, -194.5)">
+            <g id="icon-SOP-on" transform="translate(26, 192)">
+                <rect id="fork-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M8.125,2.5 L11.875,2.5 C12.2201777,2.5 12.5,2.77982205 12.5,3.125 L12.5,6.875 C12.5,7.22017795 12.2201777,7.5 11.875,7.5 L10.625,7.5 L10.625,10 L14.375,10 C15.0653565,10 15.625,10.5596441 15.625,11.25 L15.625,12.5 L16.875,12.5 C17.2201777,12.5 17.5,12.7798223 17.5,13.125 L17.5,16.875 C17.5,17.2201777 17.2201777,17.5 16.875,17.5 L13.125,17.5 C12.7798223,17.5 12.5,17.2201777 12.5,16.875 L12.5,13.125 C12.5,12.7798223 12.7798223,12.5 13.125,12.5 L14.375,12.5 L14.375,11.25 L5.625,11.25 L5.625,12.5 L6.875,12.5 C7.22017795,12.5 7.5,12.7798223 7.5,13.125 L7.5,16.875 C7.5,17.2201777 7.22017795,17.5 6.875,17.5 L3.125,17.5 C2.77982205,17.5 2.5,17.2201777 2.5,16.875 L2.5,13.125 C2.5,12.7798223 2.77982205,12.5 3.125,12.5 L4.375,12.5 L4.375,11.25 C4.375,10.5596441 4.9346441,10 5.625,10 L9.375,10 L9.375,7.5 L8.125,7.5 C7.77982175,7.5 7.5,7.22017795 7.5,6.875 L7.5,3.125 C7.5,2.77982205 7.77982175,2.5 8.125,2.5 Z" id="fork" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-system.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="15.1554441px" height="16.875px" viewBox="0 0 15.1554441 16.875" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-系统-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-28.4225, -529.5625)">
+            <g id="icon-系统-on" transform="translate(26, 528)">
+                <rect id="setting-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M10.0002074,13.75 C7.92913973,13.75 6.25020742,12.0710683 6.25020742,10 C6.25020742,7.92893231 7.92913973,6.25 10.0002074,6.25 C12.0712751,6.25 13.7502074,7.92893231 13.7502074,10 C13.7502074,12.0710683 12.0712751,13.75 10.0002074,13.75 Z M10.0002074,12.5 C8.61949563,12.5 7.50020742,11.3807118 7.50020742,10 C7.50020742,8.61928821 8.61949563,7.5 10.0002074,7.5 C11.3809192,7.5 12.5002074,8.61928821 12.5002074,10 C12.5002074,11.3807118 11.3809192,12.5 10.0002074,12.5 Z M17.5779295,5.78125 L17.5779295,14.21875 L10.0002074,18.4375 L2.42248535,14.21875 L2.42248535,5.78125 L10.0002074,1.5625 L17.5779295,5.78125 Z" id="setting" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-time.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="17.5px" height="17.5px" viewBox="0 0 17.5 17.5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-工时-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-27.25, -361.25)">
+            <g id="icon-工时-on" transform="translate(26, 360)">
+                <rect id="time-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M9.375,10.4861557 L12.5003052,13.75 L13.3841896,12.8661156 L10.625,9.96838927 L10.625,5 L9.375,5 L9.375,10.4861557 Z M10,18.75 C5.16750842,18.75 1.25,14.8324919 1.25,10 C1.25,5.16750842 5.16750842,1.25 10,1.25 C14.8324919,1.25 18.75,5.16750842 18.75,10 C18.75,14.8324919 14.8324919,18.75 10,18.75 Z" id="time" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-user.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16.2500001px" height="16.2500001px" viewBox="0 0 16.2500001 16.2500001" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-用户-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-27.875, -473.875)">
+            <g id="icon-用户-on" transform="translate(26, 472)">
+                <polygon id="Rectangle-4117" opacity="0" transform="translate(10, 10) rotate(0) translate(-10, -10)" points="3.49690827e-06 3.4969103e-06 20.0000037 3.4969103e-06 20.0000037 20.0000037 3.49690827e-06 20.0000037"></polygon>
+                <path d="M10.0000071,10.6250001 C7.58376112,10.6250001 5.62500674,8.66624601 5.62500674,6.24999975 C5.62500674,3.8337538 7.58376112,1.87500001 10.0000071,1.87500001 C12.416253,1.87500001 14.375007,3.8337538 14.375007,6.24999975 C14.375007,8.66624601 12.416253,10.6250001 10.0000071,10.6250001 Z M18.1250071,14.6557857 L18.1250071,17.5000001 C18.1250071,17.8451778 17.8451848,18.1250001 17.5000071,18.1250001 L2.50000865,18.1250001 C2.15483066,18.1250001 1.87500701,17.8451778 1.87500701,17.5000001 L1.87500701,14.6557857 C1.87500701,14.1933204 2.12877692,13.7652827 2.54608729,13.5659684 C4.81176089,12.4838449 7.33314325,11.875 10.0000077,11.875 C12.6668715,11.875 15.1882541,12.4838449 17.453928,13.5659684 C17.871238,13.7652827 18.1250071,14.1933204 18.1250071,14.6557857 Z" id="Union" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-fill-work.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16.25px" height="15px" viewBox="0 0 16.25 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-工作台-off</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-27.875, -82.5)">
+            <g id="icon-工作台-off" transform="translate(26, 80)">
+                <rect id="desktop-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M9.375,13.75 L9.375,16.25 L3.75,16.25 L3.75,17.5 L16.25,17.5 L16.25,16.25 L10.625,16.25 L10.625,13.7499988 L16.875,13.7499988 C17.5653553,13.7499988 18.125,13.1903541 18.125,12.5 L18.125,3.75000045 C18.125,3.05964515 17.5653565,2.5 16.875,2.5 L3.12499948,2.5 C2.43464366,2.5 1.875,3.05964589 1.875,3.75000179 L1.875,12.5 C1.875,13.1903553 2.43464403,13.75 3.12499993,13.75 L9.375,13.75 Z" id="desktop" fill="#4E5969"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/icons/icon-message.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16.8745783px" height="14.0441929px" viewBox="0 0 16.8745783 14.0441929" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-通知公告-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-97.8753, -146.9779)">
+            <g id="3.Navigation导航/4.Menu导航菜单/左侧导航选项/一级有图标/默认备份-12" transform="translate(80, 136)">
+                <g id="icon-通知公告-on" transform="translate(16, 8)">
+                    <rect id="sound-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                    <path d="M10.3033233,16.9320655 C10.7199007,17.1820128 11.2498832,16.8819427 11.2498832,16.3961327 L11.2498832,3.60387027 C11.2498832,3.11806124 10.7199007,2.81799084 10.3033227,3.06793755 L4.99988317,6.25000119 L2.63091035,6.25000119 C2.21697122,6.25000119 1.88129723,6.58535987 1.88091055,6.99930072 L1.87530518,12.9992998 C1.87491827,13.4137869 2.21081741,13.7500012 2.62530521,13.7500012 L4.99988317,13.7500012 L10.3033233,16.9320655 Z M6.24988317,13.042264 L9.99988317,15.2922642 L9.99988317,4.7077392 L6.24988317,6.95773929 L6.24988317,13.042264 Z M4.99988317,7.50000119 L3.13044339,7.50000119 L3.12577248,12.5000012 L4.99988317,12.5000012 L4.99988317,7.50000119 Z M15.1511109,4.72663581 L16.0040092,3.81281674 C16.8745601,4.62533116 17.5651169,5.58992445 18.0362535,6.65152133 C18.5073924,7.71312118 18.7498832,8.85093629 18.7498832,10.0000012 C18.7498832,11.1490661 18.5073924,12.2868812 18.0362535,13.3484817 C17.5651169,14.4100785 16.8745601,15.3746712 16.0040092,16.1871862 L15.1511109,15.273366 C15.9019208,14.5726109 16.4925289,13.7454057 16.8937159,12.8414226 C17.294786,11.9377065 17.4998832,10.9724677 17.4998832,10.0000012 C17.4998832,9.02753472 17.294786,8.06229591 16.8937159,7.15857923 C16.4925289,6.25459671 15.9019208,5.42739183 15.1511109,4.72663581 Z M13.0342937,6.93297774 L13.9102805,6.04126781 C15.0287712,7.14003682 15.6261909,8.55799317 15.6249547,10.0014114 C15.6237185,11.4448643 15.0238407,12.862094 13.9033651,13.9593756 L13.0287743,13.0662954 C13.9215171,12.1920341 14.3740213,11.091547 14.3749547,10.0003409 C14.3758893,8.90918434 13.9253175,7.80829072 13.0342937,6.93297774 Z" id="sound" fill="#165DFF"></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-notice.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="13.7522696px" height="17.5px" viewBox="0 0 13.7522696 17.5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-消息提醒-off</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-99.1238, -25.25)">
+            <g id="icon-消息提醒-off" transform="translate(96, 24)">
+                <rect id="notification-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M10.6249142,1.25 L9.37491417,1.25 L9.37491417,2.53433049 C6.56244516,2.84523323 4.37491402,5.22965401 4.37491402,8.125 L4.37491402,13.75 L3.2499141,15.25 C2.94089709,15.6620228 3.23488548,16.25 3.7499138,16.25 L6.93742603,16.25 C7.2269696,17.6763999 8.4880662,18.75 9.99991417,18.75 C11.5117633,18.75 12.7728593,17.6763999 13.0624032,16.25 L16.2499142,16.25 C16.7649424,16.25 17.0589316,15.6620228 16.7499137,15.25 L15.6249142,13.75 L15.6249142,8.125 C15.6249142,5.22965431 13.4373832,2.84523323 10.6249142,2.53433049 L10.6249142,1.25 Z M4.99991432,15 L14.9999142,15 L14.3749142,14.1666663 L14.3749142,8.125 C14.3749142,5.70875436 12.4161601,3.75 9.99991417,3.75 C7.58366823,3.75 5.62491417,5.70875436 5.62491417,8.125 L5.62491417,14.1666663 L4.99991432,15 Z M8.23160529,16.25 L11.7682236,16.25 C11.5108258,16.978246 10.8163011,17.5000012 9.99991477,17.5000012 C9.18352783,17.5000012 8.48900259,16.978246 8.23160529,16.25 Z" id="notification" fill="#262626"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-pull-down.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="8.91923904px" height="5.37885809px" viewBox="0 0 8.91923904 5.37885809" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-下拉-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-543.5404, -93.5404)">
+            <g id="icon-下拉-on" transform="translate(540, 88)">
+                <polygon id="矩形" opacity="0" points="16 0 16 16 0 16 0 0"></polygon>
+                <polygon id="路径-4-(Stroke)" fill="#165DFF" points="4.45961356 5.54040527 7.99999428 9.08078575 11.5403748 5.54040527 12.4596138 6.45964408 7.99999428 10.9192634 3.54037476 6.45964408"></polygon>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/icons/icon-service-area.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="17.2500002px" height="17.5px" viewBox="0 0 17.2500002 17.5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-服务区域规划-off</title>
+    <g id="服务单元管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="6.1-派单管理" transform="translate(-97.3751, -265.25)">
+            <g id="3.Navigation导航/4.Menu导航菜单/左侧导航选项/一级有图标/默认备份-15" transform="translate(80, 256)">
+                <g id="icon-服务区域规划-off" transform="translate(16, 8)">
+                    <rect id="internet-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                    <path d="M10,1.25 C14.7634548,1.25 18.6251223,5.11154324 18.6251223,9.87499774 L18.6251223,10.1250017 C18.6251223,14.8884559 14.763577,18.75 10.0001222,18.75 C5.23672372,18.75 1.37512207,14.8884165 1.37512207,10.1250023 L1.37512207,9.87499833 C1.37512207,5.11158437 5.23660153,1.25 10,1.25 Z M13.6086655,10.625 C13.488102,13.0237281 12.6729906,15.3940582 11.1633313,17.4087882 C14.5228803,16.8764997 17.1274209,14.0757334 17.3584402,10.625 L13.6086655,10.625 Z M11.1633354,2.59121269 C14.5228839,3.12350243 17.1274221,5.92426807 17.3584402,9.375 L13.6086667,9.375 C13.4881055,6.97627187 12.6729953,4.60594267 11.1633354,2.59121269 Z M7.64309466,9.375 C7.76720166,7.15591431 8.55283678,4.96691883 10.0000006,3.12879264 C11.4471638,4.96691883 12.2327995,7.15591431 12.3569059,9.375 L7.64309466,9.375 Z M2.64180407,10.625 C2.87281618,14.0756381 5.47722012,16.8763459 8.83663595,17.4087441 C7.32699811,15.3940237 6.51189685,13.0237103 6.39133394,10.625 L2.64180407,10.625 Z M8.83663177,2.59125665 C5.47721803,3.12365666 2.87281632,5.92436314 2.64180407,9.375 L6.39133394,9.375 C6.51189446,6.97628975 7.32699335,4.60597724 8.83663177,2.59125665 Z M7.64309466,10.625 C7.76720107,12.8440857 8.55283678,15.0330818 10.0000006,16.871208 C11.4471638,15.0330818 12.2327995,12.8440857 12.3569059,10.625 L7.64309466,10.625 Z" id="internet" fill="#262626"></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/icons/icon-service-crm.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="15.053467px" height="15px" viewBox="0 0 15.053467 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-派单管理-on</title>
+    <g id="服务单元管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="6.1-派单管理" transform="translate(-98.5, -66.5)">
+            <g id="icon-派单管理-on" transform="translate(96, 64)">
+                <g id="编组" transform="translate(2.5, 2.5)" fill="#165DFF" fill-rule="nonzero">
+                    <rect id="矩形" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                    <path d="M13.2291667,0 C14.2071709,0 15,0.792829089 15,1.77083333 L15,7.51552582 C15,7.86070379 14.720178,8.14052582 14.375,8.14052582 C14.029822,8.14052582 13.75,7.86070379 13.75,7.51552582 L13.75,1.77083333 C13.75,1.48318503 13.516815,1.25 13.2291667,1.25 L1.77083333,1.25 C1.48318503,1.25 1.25,1.48318503 1.25,1.77083333 L1.25,13.2291667 C1.25,13.516815 1.48318503,13.75 1.77083333,13.75 L13.2291667,13.75 C13.5743446,13.75 13.8541667,14.029822 13.8541667,14.375 C13.8541667,14.720178 13.5743446,15 13.2291667,15 L1.77083333,15 C0.792829089,15 0,14.2071709 0,13.2291667 L0,1.77083333 C0,0.792829089 0.792829089,0 1.77083333,0 L13.2291667,0 Z M11.725,7.71611652 L14.6619275,10.6518028 C14.8181639,10.7052533 14.9395216,10.8339039 14.9828181,10.9945725 C15.0776638,11.1533733 15.077064,11.3534254 14.9807059,11.5115516 C14.9340664,11.6778864 14.8028864,11.8090664 14.6364003,11.8561685 C14.4889892,11.9456268 14.3049155,11.9521563 14.1520506,11.8752945 L5,11.875 L5,10.625 L12.866,10.6241165 L10.8411165,8.6 L11.725,7.71611652 Z M9.375,6 L9.375,7.25 L3.125,7.25 L3.125,6 L9.375,6 Z M11.875,3.125 L11.875,4.375 L3.125,4.375 L3.125,3.125 L11.875,3.125 Z" id="形状结合"></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/icons/icon-service-range.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="12.5343973px" height="16.9788819px" viewBox="0 0 12.5343973 16.9788819" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-服务范围管理-off</title>
+    <g id="服务单元管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="6.1-派单管理" transform="translate(-99.7329, -225.3459)">
+            <g id="3.Navigation导航/4.Menu导航菜单/左侧导航选项/一级有图标/默认备份-14" transform="translate(80, 216)">
+                <g id="icon-服务范围管理-off" transform="translate(16, 8)">
+                    <rect id="location-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                    <path d="M10.0001097,10.6249851 C8.27421963,10.6249851 6.87510967,9.22587454 6.87510967,7.4999851 C6.87510967,5.77409506 8.27421963,4.3749848 10.0001097,4.3749848 C11.7259991,4.3749848 13.1251097,5.77409506 13.1251097,7.4999851 C13.1251097,9.22587454 11.7259991,10.6249851 10.0001097,10.6249851 Z M10.0001097,9.3749851 C8.96457553,9.3749851 8.12510967,8.53551924 8.12510967,7.4999851 C8.12510967,6.46445096 8.96457553,5.6249848 10.0001097,5.6249848 C11.0356438,5.6249848 11.8751097,6.46445096 11.8751097,7.4999851 C11.8751097,8.53551924 11.0356438,9.3749851 10.0001097,9.3749851 Z M9.54777479,18.0855095 L4.81946178,11.1396742 C3.1255167,8.65128875 3.44004437,5.31005025 5.56860134,3.18149298 C8.01605567,0.734038353 11.9841635,0.734037161 14.4316185,3.18149179 C16.5601754,5.31004876 16.8746996,8.65129173 15.1807547,11.1396772 L10.452444,18.0855107 C10.2352667,18.404541 9.76495206,18.404541 9.54777479,18.0855095 Z M10.0001097,16.5286648 L5.8527641,10.4362637 C4.49668452,8.44419837 4.74847689,5.7693845 6.45248473,4.06537652 C8.41178417,2.10607678 11.5884358,2.10607648 13.5477352,4.06537533 C15.2517426,5.76938242 15.5035341,8.44419956 14.1474533,10.4362661 L10.0001097,16.5286648 Z" id="location" fill="#262626"></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/icons/icon-service-unit.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16.2513566px" height="15px" viewBox="0 0 16.2513566 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-服务单元管理-off</title>
+    <g id="服务单元管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="6.1-派单管理" transform="translate(-97.8753, -186.5)">
+            <g id="3.Navigation导航/4.Menu导航菜单/左侧导航选项/一级有图标/默认备份-13" transform="translate(80, 176)">
+                <g id="icon-服务单元管理-off" transform="translate(16, 8)">
+                    <rect id="server-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                    <path d="M5,6.5625 L5,5.3125 L8.75,5.3125 L8.75,6.5625 L5,6.5625 Z M2.50030518,2.5 L17.5003052,2.5 C17.8454173,2.5 18.1252122,2.77971875 18.1253052,3.1248305 L18.1264925,8.74985218 C18.1266618,9.09509659 17.8467369,9.37502205 17.5014925,9.37502205 L2.50149243,9.37502205 C2.15638068,9.37502205 1.87658564,9.09530342 1.87649202,8.75019133 L1.87530518,3.1251698 C1.87530518,2.77992561 2.15506099,2.5 2.50030518,2.5 Z M3.12547475,3.75 L16.8754745,3.75 L16.8763232,8.12502205 L3.12632248,8.12502205 L3.12547475,3.75 Z M8.7501353,14.6875 L8.7501353,13.4375 L5.0001356,13.4375 L5.0001356,14.6875 L8.7501353,14.6875 Z M2.50166148,10.6250173 L17.5016618,10.6250173 C17.8468394,10.6250173 18.1266618,10.9048396 18.1266618,11.2500173 L18.1266618,16.875 C18.1266618,17.2201777 17.8468394,17.5 17.5016618,17.5 L2.50166193,17.5 C2.15648398,17.5 1.87666151,17.2201777 1.87666151,16.875 L1.87666151,11.2500173 C1.87666151,10.904839 2.15648357,10.6250173 2.50166148,10.6250173 Z M3.12666148,11.8750173 L16.8766618,11.8750173 L16.8766618,16.25 L3.12666148,16.25 L3.12666148,11.8750173 Z" id="server" fill="#262626"></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-sop-wait.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="15px" height="15.625px" viewBox="0 0 15 15.625" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-SOP待办-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-98.5, -65.875)">
+            <g id="icon-SOP待办-on" transform="translate(96, 64)">
+                <rect id="calendar-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                <path d="M7.5,3.75 L7.5,1.875 L6.24999851,1.875 L6.24999911,3.75 L3.75,3.75 C3.0596441,3.75 2.5,4.30964366 2.5,4.9999997 L2.5,16.25 C2.5,16.9403553 3.05964381,17.5 3.7499997,17.5 L16.25,17.5 C16.9403553,17.5 17.5,16.9403565 17.5,16.25 L17.5,5 C17.5,4.3096441 16.9403565,3.75 16.25,3.75 L13.7499988,3.75 L13.7499988,1.875 L12.5,1.875 L12.5,3.75 L7.5,3.75 Z M6.2499994,5 L3.75,5 L3.75,7.5 L16.25,7.5 L16.25,5 L13.75,5 L13.75,6.2499997 L12.5,6.2500003 L12.5,5 L7.5,5 L7.5,6.2499997 L6.2499997,6.2500003 L6.2499994,5 Z M3.7499997,16.25 L16.25,16.25 L16.25,8.75 L3.75,8.75 L3.7499997,16.25 Z" id="calendar" fill="#165DFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/icons/icon-user-circle.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="17.5px" height="17.5px" viewBox="0 0 17.5 17.5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-用户头像</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-97.25, -777.25)">
+            <g id="编组-3" transform="translate(80, 768)">
+                <g id="user-circle" transform="translate(16, 8)">
+                    <rect id="user-circle-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                    <path d="M13.4749997,7.77500033 C13.4749997,5.85581064 11.9191897,4.30000007 10,4.30000007 C8.08081031,4.30000007 6.52500033,5.85581064 6.52500033,7.77500033 C6.52500033,9.69418943 8.08081031,11.25 10,11.25 C11.9191897,11.25 13.4749997,9.69418943 13.4749997,7.77500033 Z M12.2249997,7.77500033 C12.2249997,6.54616594 11.2288332,5.55000007 10,5.55000007 C8.77116621,5.55000007 7.77500033,6.54616654 7.77500033,7.77500033 C7.77500033,9.00383353 8.77116621,10 10,10 C11.2288332,10 12.2249997,9.00383353 12.2249997,7.77500033 Z M18.75,10 C18.75,5.16750842 14.8324919,1.25 10,1.25 C5.16750842,1.25 1.25,5.16750842 1.25,10 C1.25,14.8324919 5.16750842,18.75 10,18.75 C14.8324919,18.75 18.75,14.8324919 18.75,10 Z M17.5,10 C17.5,5.85786432 14.1421354,2.5 10,2.5 C5.85786432,2.5 2.5,5.85786432 2.5,10 C2.5,11.5370691 2.96238229,12.9661429 3.75564039,14.1557145 C5.65648943,13.0956304 7.76801586,12.5 9.9999696,12.5 C12.2319412,12.5 14.3434834,13.0956388 16.2443435,14.1557384 C17.037611,12.966162 17.5,11.5370798 17.5,10 Z M9.9999696,13.75 C8.06602955,13.75 6.22562021,14.2470145 4.5459339,15.1481509 C5.91332048,16.5962708 7.85112143,17.5 10,17.5 C12.1488678,17.5 14.0866601,16.5962803 15.4540455,15.1481724 C13.7743497,14.2470229 11.933924,13.75 9.9999696,13.75 Z" fill-opacity="0.81" fill="#000000"></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/icons/icon-warning-wait.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="17.5px" height="17.5px" viewBox="0 0 17.5 17.5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-预警待办-on</title>
+    <g id="我的工作台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="2.2-我的工作台-消息提醒-未读" transform="translate(-97.25, -105.25)">
+            <g id="3.Navigation导航/4.Menu导航菜单/左侧导航选项/一级有图标/默认" transform="translate(80, 96)">
+                <g id="icon-预警待办-on" transform="translate(16, 8)">
+                    <rect id="error-circle-(Background)" opacity="0" x="0" y="0" width="20" height="20"></rect>
+                    <path d="M10.625,11.875 L9.375,11.875 L9.375,5.00045776 L10.625,5.00045776 L10.625,11.875 Z M9.24285889,13.125 L9.24285889,14.624939 L10.7427979,14.624939 L10.7427979,13.125 L9.24285889,13.125 Z M10,1.25 C5.1675415,1.25 1.25,5.1675415 1.25,10 C1.25,14.8324585 5.1675415,18.75 10,18.75 C14.8324585,18.75 18.75,14.8324585 18.75,10 C18.75,5.1675415 14.8324585,1.25 10,1.25 Z M10,2.5 C5.85784912,2.5 2.5,5.85784912 2.5,10 C2.5,14.1421509 5.85784912,17.5 10,17.5 C14.1421509,17.5 17.5,14.1421509 17.5,10 C17.5,5.85784912 14.1421509,2.5 10,2.5 Z" id="Union" fill="#165DFF"></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

BIN
src/assets/imgs/menu-logo.png


+ 27 - 0
src/components/global/my-drawer/index.vue

@@ -0,0 +1,27 @@
+<template>
+  <t-drawer v-bind="attrs">
+    <template #body v-if="isFirstOpen">
+      <slot></slot>
+    </template>
+    <template #footer v-if="slots.foot">
+      <slot name="foot"></slot>
+    </template>
+  </t-drawer>
+</template>
+<script setup name="MyDrawer">
+import { useAttrs, useSlots, ref, watch } from 'vue';
+const attrs = useAttrs();
+const slots = useSlots();
+let isFirstOpen = ref(false);
+watch(
+  () => attrs.visible,
+  () => {
+    if (!isFirstOpen.value) {
+      isFirstOpen.value = true;
+      if (attrs.callBacks) {
+        attrs.callBacks.forEach((item) => item());
+      }
+    }
+  }
+);
+</script>

+ 4 - 2
src/components/global/search-form/index.vue

@@ -105,7 +105,7 @@ onUnmounted(() => {
 const props = defineProps({
   fields: Object, // 搜索配置列,见下方示例
   params: Object, // 搜索参数
-  showAll: Boolean, //是否要求直接展开,无需折叠换行按钮
+  showAll: { type: Boolean, default: true }, //是否要求直接展开,无需折叠换行按钮
   inPadding: Boolean,
 });
 //fields示例:(目前支持控件:input、select、dropdown按钮、treeSelect、date选择框、time选择框、timerange时间范围选择框、daterange日期范围选择框...后期可以按需求扩展)
@@ -246,8 +246,10 @@ const colToWidth = (colSpan) => {
 </script>
 <style lang="less" scoped>
 .table-search {
-  padding: 10px;
+  padding: 16px 16px 1px;
   background-color: #fff;
+  border-bottom: 1px solid #e5e5e5;
+
   :deep(.t-date-range-picker) {
     width: 100%;
   }

+ 36 - 0
src/components/global/svg-icon/index.vue

@@ -0,0 +1,36 @@
+<template>
+  <svg aria-hidden="true" class="svg-icon">
+    <use :xlink:href="symbolId" :fill="color" />
+  </svg>
+</template>
+
+<script setup name="SvgIcon">
+import { computed } from 'vue';
+
+const props = defineProps({
+  prefix: {
+    type: String,
+    default: 'icon-icon',
+  },
+  name: {
+    type: String,
+    required: true,
+  },
+  color: {
+    type: String,
+    default: '#4E5969',
+    // active:#165DFF
+  },
+});
+
+const symbolId = computed(() => `#${props.prefix}-${props.name}`);
+</script>
+
+<style lang="less">
+.svg-icon {
+  display: inline-block;
+  vertical-align: middle;
+  width: 16px;
+  height: 16px;
+}
+</style>

+ 6 - 4
src/layout/children-menu.vue

@@ -5,16 +5,17 @@
       <t-menu-item
         v-if="!menu.children || menu.children.length === 0"
         :value="menu.name"
+        :disabled="menu.disabled"
         @click="routerPush(menu)"
       >
         <template v-if="menu.meta.icon" #icon>
-          <t-icon :name="menu.meta.icon"></t-icon>
+          <svg-icon :name="menu.meta.icon"></svg-icon>
         </template>
-        {{ menu.meta.title }}</t-menu-item
-      >
+        {{ menu.meta.title }}
+      </t-menu-item>
       <t-submenu v-else :value="menu.name">
         <template v-if="menu.meta.icon" #icon>
-          <t-icon :name="menu.meta.icon"></t-icon>
+          <svg-icon :name="menu.meta.icon"></svg-icon>
         </template>
         <template #title>
           {{ menu.meta.title }}
@@ -31,6 +32,7 @@
 import { useRouter } from 'vue-router';
 
 defineProps({ modelValue: Array });
+
 const router = useRouter();
 const routerPush = (menu) => {
   if (menu.meta && menu.meta.type === 'L') {

+ 236 - 0
src/layout/index-old.vue

@@ -0,0 +1,236 @@
+<template>
+  <t-layout class="h-full app-layout">
+    <!-- <t-header class="layout-header">
+      <div class="header-wrap flex items-center">页头</div>
+    </t-header> -->
+    <t-aside
+      :width="
+        (appStore.menuCollapse ? appStore.collapseWidth : appStore.menuWidth) +
+        'px'
+      "
+    >
+      <!-- <div class="logo-box flex items-center justify-center">
+        <img src="../assets/logo.svg" />
+      </div> -->
+      <left-menu></left-menu>
+    </t-aside>
+    <t-layout class="right-view">
+      <t-header class="layout-header">
+        <div class="h-full header-wrap flex items-center justify-between">
+          <div class="flex-1">
+            <t-head-menu
+              style="height: 55px"
+              :value="userStore.curPageModule"
+              theme="light"
+              @change="moduleChange"
+            >
+              <t-menu-item
+                :value="item.name"
+                v-for="item in userStore.headerMenus"
+                :key="item.name"
+              >
+                {{ item.meta?.title }}
+              </t-menu-item>
+            </t-head-menu>
+          </div>
+          <div class="header-right flex items-center">
+            <t-dropdown
+              class="m-r-20px"
+              trigger="hover"
+              placement="bottom"
+              @click="colorChoose"
+            >
+              <t-button theme="default" variant="outline" shape="square">
+                <t-icon
+                  name="palette"
+                  size="26"
+                  color="#fff"
+                  :style="{ background: themeColor, borderRadius: '2px' }"
+              /></t-button>
+              <t-dropdown-menu>
+                <t-dropdown-item
+                  v-for="item in colorOptions"
+                  :key="item.value"
+                  :value="item.value"
+                >
+                  <div
+                    class="color-grid"
+                    :class="{ 'active-color-grid': themeColor === item.value }"
+                  >
+                    <div
+                      class="color-grid-center"
+                      :style="{
+                        backgroundColor: item.value,
+                        width: '100%',
+                        height: '100%',
+                        borderRadius: '2px',
+                      }"
+                    ></div>
+                  </div>
+                </t-dropdown-item>
+              </t-dropdown-menu>
+            </t-dropdown>
+            <t-dropdown
+              trigger="hover"
+              :options="userOptions"
+              @click="clickHandler"
+            >
+              <div class="flex items-center cursor-pointer">
+                <div class="head-img-box flex justify-center items-center">
+                  <img src="../assets/imgs/user_head.png" />
+                </div>
+                <span class="real-name">{{ userStore.user?.realName }}</span>
+                <ChevronDownIcon size="16px" />
+              </div>
+            </t-dropdown>
+          </div>
+        </div>
+      </t-header>
+      <t-content class="layout-content overflow-auto">
+        <router-view v-slot="{ Component }">
+          <transition name="fade-slide" mode="out-in" appear>
+            <component :is="Component" />
+          </transition>
+        </router-view>
+      </t-content>
+    </t-layout>
+  </t-layout>
+</template>
+
+<script setup name="Layout" lang="jsx">
+import { ref, onMounted } from 'vue';
+import { useAppStore, useUserStore } from '@/store';
+import { useRouter, useRoute } from 'vue-router';
+import LeftMenu from './left-menu.vue';
+import { Color } from 'tvision-color';
+import { generateColorMap, insertThemeStylesheet } from '@/config/color';
+import { moduleMap } from '@/router/asyncRoutes';
+import { ChevronDownIcon, UserIcon } from 'tdesign-icons-vue-next';
+import { clear, cookie } from '@/utils/tool';
+
+const router = useRouter();
+const route = useRoute();
+const appStore = useAppStore();
+const userStore = useUserStore();
+const moduleChange = (name) => {
+  userStore.setCurPageModule(name);
+  router.push({ name });
+};
+const setModuleByPath = () => {
+  let firstPath = route.path.split('/')[1];
+  let curModuleName = moduleMap[firstPath];
+  userStore.setCurPageModule(curModuleName);
+};
+const themeColor = ref(cookie.get('themeColor'));
+onMounted(() => {
+  setModuleByPath();
+  setTheme(themeColor.value || '#0052d9');
+});
+const colorOptions = ref([
+  {
+    value: '#0052d9',
+  },
+  {
+    value: '#0091ff',
+  },
+  {
+    value: '#35c1db',
+  },
+  {
+    value: '#5dbe8a',
+  },
+  {
+    value: '#f4b84a',
+  },
+  {
+    value: '#f29e55',
+  },
+  {
+    value: '#ac6ef6',
+  },
+  {
+    value: '#7969f3',
+  },
+  {
+    value: '#e65857',
+  },
+]);
+const userOptions = ref([
+  { content: '修改密码', value: '1' },
+  { content: '退出', value: '2' },
+]);
+const clickHandler = (data) => {
+  if (data.content === '修改密码') {
+    router.push({ name: 'PasswordModify' });
+  } else if (data.content === '退出') {
+    userStore.logout();
+  }
+};
+const setTheme = (hex) => {
+  const newPalette = Color.getPaletteByGradation({
+    colors: [hex],
+    step: 10,
+  })[0];
+  const colorMap = generateColorMap(hex, newPalette);
+  insertThemeStylesheet(hex, colorMap);
+  cookie.set('themeColor', hex);
+  themeColor.value = hex;
+};
+const colorChoose = (data) => {
+  const hex = data.value;
+  setTheme(hex);
+};
+</script>
+<style lang="less">
+.color-grid {
+  margin-left: auto;
+  margin-right: auto;
+  width: 54px;
+  height: 24px;
+  border-radius: 2px;
+  padding: 2px;
+  border: 1px solid transparent;
+  &.active-color-grid {
+    border-color: #ccc;
+  }
+}
+</style>
+<style lang="less" scoped>
+.app-layout {
+  .right-view {
+    overflow: auto;
+  }
+  .t-layout__sider {
+    //重写过渡时长,让其余menu的折叠动画保持同步
+    transition: all 0.28s cubic-bezier(0.645, 0.045, 0.355, 1);
+  }
+  .layout-header {
+    border-bottom: 1px solid #eee;
+    .header-wrap {
+      padding: 0 10px;
+      padding-right: 20px;
+      .t-head-menu .t-menu__item {
+        height: 44px;
+      }
+      .real-name {
+        color: @light-text-color;
+      }
+      .head-img-box {
+        width: 32px;
+        height: 32px;
+        border-radius: 16px;
+        overflow: hidden;
+        margin-right: 5px;
+
+        img {
+          width: 100%;
+          height: 100%;
+        }
+      }
+    }
+  }
+  .layout-content {
+    flex: 1;
+  }
+}
+</style>

+ 161 - 183
src/layout/index.vue

@@ -1,116 +1,67 @@
 <template>
-  <t-layout class="h-full app-layout">
-    <!-- <t-header class="layout-header">
-      <div class="header-wrap flex items-center">页头</div>
-    </t-header> -->
-    <t-aside
-      :width="
-        (appStore.menuCollapse ? appStore.collapseWidth : appStore.menuWidth) +
-        'px'
-      "
-    >
-      <!-- <div class="logo-box flex items-center justify-center">
-        <img src="../assets/logo.svg" />
-      </div> -->
-      <left-menu></left-menu>
+  <t-layout class="app-layout">
+    <t-aside class="app-menu" width="82px">
+      <div class="app-menu-list">
+        <div class="app-menu-logo">
+          <img src="@/assets/imgs/menu-logo.png" alt="logo" />
+        </div>
+        <div
+          v-for="item in userStore.headerMenus"
+          :key="item.name"
+          :class="[
+            'app-menu-item',
+            { 'is-active': userStore.curPageModule === item.name },
+          ]"
+          @click="moduleChange(item.name)"
+        >
+          <svg-icon prefix="icon-icon-fill" :name="item.meta.icon"></svg-icon>
+          <p>{{ item.meta.title }}</p>
+        </div>
+      </div>
+      <div class="app-menu-footer"></div>
     </t-aside>
-    <t-layout class="right-view">
-      <t-header class="layout-header">
-        <div class="h-full header-wrap flex items-center justify-between">
-          <div class="flex-1">
-            <t-head-menu
-              style="height: 55px"
-              :value="userStore.curPageModule"
-              theme="light"
-              @change="moduleChange"
-            >
-              <t-menu-item
-                :value="item.name"
-                v-for="item in userStore.headerMenus"
-                :key="item.name"
-              >
-                {{ item.meta?.title }}
-              </t-menu-item>
-            </t-head-menu>
-          </div>
-          <div class="header-right flex items-center">
-            <t-dropdown
-              class="m-r-20px"
-              trigger="hover"
-              placement="bottom"
-              @click="colorChoose"
-            >
-              <t-button theme="default" variant="outline" shape="square">
-                <t-icon
-                  name="palette"
-                  size="26"
-                  color="#fff"
-                  :style="{ background: themeColor, borderRadius: '2px' }"
-              /></t-button>
-              <t-dropdown-menu>
-                <t-dropdown-item
-                  v-for="item in colorOptions"
-                  :key="item.value"
-                  :value="item.value"
-                >
-                  <div
-                    class="color-grid"
-                    :class="{ 'active-color-grid': themeColor === item.value }"
-                  >
-                    <div
-                      class="color-grid-center"
-                      :style="{
-                        backgroundColor: item.value,
-                        width: '100%',
-                        height: '100%',
-                        borderRadius: '2px',
-                      }"
-                    ></div>
-                  </div>
-                </t-dropdown-item>
-              </t-dropdown-menu>
-            </t-dropdown>
-            <t-dropdown
-              trigger="hover"
-              :options="userOptions"
-              @click="clickHandler"
-            >
-              <div class="flex items-center cursor-pointer">
-                <div class="head-img-box flex justify-center items-center">
-                  <img src="../assets/imgs/user_head.png" />
-                </div>
-                <span class="real-name">{{ userStore.user?.realName }}</span>
-                <ChevronDownIcon size="16px" />
-              </div>
-            </t-dropdown>
+    <t-aside class="app-submenu" width="232px">
+      <left-menu class="app-submenu-body"></left-menu>
+      <div class="app-submenu-footer">
+        <t-dropdown
+          trigger="hover"
+          :options="userOptions"
+          :minColumnWidth="203"
+          @click="clickHandler"
+        >
+          <div class="app-submenu-user">
+            <div class="app-submenu-user-content">
+              <svg-icon name="user-circle"></svg-icon>
+              <span class="real-name">{{ userStore.user?.realName }}</span>
+              <span v-if="userStore.user?.mobileNumber" class="real-name">{{
+                userStore.user?.mobileNumber
+              }}</span>
+            </div>
+            <ChevronDownIcon size="16px" />
           </div>
-        </div>
-      </t-header>
-      <t-content class="layout-content overflow-auto">
-        <router-view v-slot="{ Component }">
-          <transition name="fade-slide" mode="out-in" appear>
-            <component :is="Component" />
-          </transition>
-        </router-view>
-      </t-content>
-    </t-layout>
+        </t-dropdown>
+      </div>
+    </t-aside>
+    <t-content class="layout-content">
+      <router-view v-slot="{ Component }">
+        <transition name="fade-slide" mode="out-in" appear>
+          <component :is="Component" />
+        </transition>
+      </router-view>
+    </t-content>
   </t-layout>
 </template>
 
 <script setup name="Layout" lang="jsx">
 import { ref, onMounted } from 'vue';
-import { useAppStore, useUserStore } from '@/store';
+import { useUserStore } from '@/store';
 import { useRouter, useRoute } from 'vue-router';
 import LeftMenu from './left-menu.vue';
-import { Color } from 'tvision-color';
-import { generateColorMap, insertThemeStylesheet } from '@/config/color';
 import { moduleMap } from '@/router/asyncRoutes';
-import { ChevronDownIcon, UserIcon } from 'tdesign-icons-vue-next';
-import { clear, cookie } from '@/utils/tool';
+import { ChevronDownIcon } from 'tdesign-icons-vue-next';
 
 const router = useRouter();
 const route = useRoute();
-const appStore = useAppStore();
 const userStore = useUserStore();
 const moduleChange = (name) => {
   userStore.setCurPageModule(name);
@@ -121,40 +72,9 @@ const setModuleByPath = () => {
   let curModuleName = moduleMap[firstPath];
   userStore.setCurPageModule(curModuleName);
 };
-const themeColor = ref(cookie.get('themeColor'));
 onMounted(() => {
   setModuleByPath();
-  setTheme(themeColor.value || '#0052d9');
 });
-const colorOptions = ref([
-  {
-    value: '#0052d9',
-  },
-  {
-    value: '#0091ff',
-  },
-  {
-    value: '#35c1db',
-  },
-  {
-    value: '#5dbe8a',
-  },
-  {
-    value: '#f4b84a',
-  },
-  {
-    value: '#f29e55',
-  },
-  {
-    value: '#ac6ef6',
-  },
-  {
-    value: '#7969f3',
-  },
-  {
-    value: '#e65857',
-  },
-]);
 const userOptions = ref([
   { content: '修改密码', value: '1' },
   { content: '退出', value: '2' },
@@ -166,71 +86,129 @@ const clickHandler = (data) => {
     userStore.logout();
   }
 };
-const setTheme = (hex) => {
-  const newPalette = Color.getPaletteByGradation({
-    colors: [hex],
-    step: 10,
-  })[0];
-  const colorMap = generateColorMap(hex, newPalette);
-  insertThemeStylesheet(hex, colorMap);
-  cookie.set('themeColor', hex);
-  themeColor.value = hex;
-};
-const colorChoose = (data) => {
-  const hex = data.value;
-  setTheme(hex);
-};
 </script>
-<style lang="less">
-.color-grid {
-  margin-left: auto;
-  margin-right: auto;
-  width: 54px;
-  height: 24px;
-  border-radius: 2px;
-  padding: 2px;
-  border: 1px solid transparent;
-  &.active-color-grid {
-    border-color: #ccc;
-  }
-}
-</style>
+
 <style lang="less" scoped>
 .app-layout {
-  .right-view {
+  background-color: #f2f3f5;
+  height: 100%;
+
+  .layout-content {
+    flex: 1;
     overflow: auto;
+    border-left: 1px solid #e5e5e5;
   }
-  .t-layout__sider {
-    //重写过渡时长,让其余menu的折叠动画保持同步
-    transition: all 0.28s cubic-bezier(0.645, 0.045, 0.355, 1);
-  }
-  .layout-header {
-    border-bottom: 1px solid #eee;
-    .header-wrap {
-      padding: 0 10px;
-      padding-right: 20px;
-      .t-head-menu .t-menu__item {
-        height: 44px;
+  .app-menu {
+    background-color: #f2f3f5;
+    height: 100%;
+
+    &-list {
+      padding: 16px 8px 40px;
+    }
+    &-logo {
+      height: 52px;
+      padding: 12px 8px;
+    }
+    &-item {
+      margin: 4px 0;
+      padding: 8px 0;
+      text-align: center;
+      border-radius: 4px;
+      color: #4e5969;
+
+      cursor: pointer;
+      &:hover {
+        background-color: #e5e6eb;
       }
-      .real-name {
-        color: @light-text-color;
+      &.is-active {
+        background-color: #e5e6eb;
+        color: #165dff;
+
+        :deep(.svg-icon use) {
+          fill: #165dff;
+        }
       }
-      .head-img-box {
-        width: 32px;
-        height: 32px;
-        border-radius: 16px;
+
+      > i {
+        display: inline-block;
+        vertical-align: middle;
+        width: 20px;
+        height: 20px;
+      }
+      > p {
+        margin: 0;
+        line-height: 18px;
+        font-size: 12px;
+      }
+
+      .svg-icon {
+        display: block;
+        margin: 0 auto 3px;
+        width: 18px;
+        height: 18px;
+      }
+    }
+
+    &-footer {
+      position: absolute;
+      height: 24px;
+      border-radius: 3px;
+      padding: 8px;
+      background-color: #f2f3f5;
+      z-index: 9;
+    }
+  }
+  .app-submenu {
+    background-color: #fff;
+    padding-bottom: 68px;
+    position: relative;
+    color: #262626;
+
+    &-footer {
+      position: absolute;
+      width: 100%;
+      bottom: 0;
+      left: 0;
+      padding: 16px 8px;
+      background-color: #fff;
+      z-index: 9;
+    }
+    &-user {
+      padding: 8px 16px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      border-radius: 4px;
+      cursor: pointer;
+
+      &:hover {
+        background-color: #f2f3f5;
+      }
+
+      &-content {
+        line-height: 20px;
         overflow: hidden;
-        margin-right: 5px;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        flex-grow: 2;
 
-        img {
-          width: 100%;
-          height: 100%;
+        span {
+          margin-left: 8px;
         }
       }
     }
-  }
-  .layout-content {
-    flex: 1;
+    :deep(.t-menu__item .svg-icon) {
+      margin-right: 8px;
+    }
+    :deep(.t-menu__item:not(.t-is-active)) {
+      color: #262626;
+    }
+    :deep(.t-menu__item.t-is-active .svg-icon use) {
+      fill: #165dff;
+    }
+    :deep(.t-menu__item.t-is-disabled) {
+      color: rgb(140, 140, 140);
+    }
   }
 }
 </style>

+ 5 - 57
src/layout/left-menu.vue

@@ -1,35 +1,7 @@
 <template>
   <div class="left-menu">
-    <t-menu
-      :key="key"
-      theme="dark"
-      v-model:expanded="openKeys"
-      v-model:value="activeKey"
-      :collapsed="appStore.menuCollapse"
-      :width="
-        (appStore.menuCollapse ? appStore.collapseWidth : appStore.menuWidth) +
-        'px'
-      "
-    >
-      <template #logo>
-        <div class="logo-box flex justify-center items-center">
-          LOGO!!!
-        </div>
-      </template>
+    <t-menu :key="key" v-model:expanded="openKeys" v-model:value="activeKey">
       <children-menu v-model="userStore.moduleMenus" />
-      <template #operations>
-        <div
-          class="flex justify-center items-center cursor-pointer h-full"
-          @click="onCollapse"
-        >
-          <t-icon
-            v-if="appStore.menuCollapse"
-            name="chevron-right-double"
-            color="#fff"
-          />
-          <t-icon v-else name="chevron-left-double" color="#fff" />
-        </div>
-      </template>
     </t-menu>
   </div>
 </template>
@@ -37,7 +9,7 @@
 <script setup name="LeftMenu">
 import { ref, watch, onBeforeMount } from 'vue';
 import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
-import { useAppStore, useUserStore } from '@/store';
+import { useUserStore } from '@/store';
 import childrenMenu from './children-menu.vue';
 import { moduleMap } from '@/router/asyncRoutes';
 const route = useRoute();
@@ -45,11 +17,11 @@ const router = useRouter();
 // const menus = ref([]);
 const activeKey = ref('');
 const openKeys = ref([]);
-const appStore = useAppStore();
 const userStore = useUserStore();
 const key = ref(new Date().getTime() + '');
 
 onBeforeMount(() => {
+  userStore.setCurPage(route.name);
   activeKey.value = route.name;
   setOpenMenu();
 });
@@ -57,6 +29,7 @@ onBeforeRouteUpdate((to) => {
   activeKey.value = to.name;
   let firstPath = to.path.split('/')[1];
   let curModuleName = moduleMap[firstPath];
+  userStore.setCurPage(to.name);
   userStore.setCurPageModule(curModuleName);
 });
 watch(
@@ -68,9 +41,7 @@ watch(
     }, 0);
   }
 );
-const onCollapse = () => {
-  appStore.toggleMenu();
-};
+
 const setOpenMenu = () => {
   openKeys.value = [];
   //如果初始化的时候左侧全部展开
@@ -89,26 +60,3 @@ const setOpenMenu = () => {
   // }
 };
 </script>
-
-<style lang="less" scoped>
-.left-menu {
-  height: 100%;
-  :deep(.t-menu__operations) {
-    padding: 0 !important;
-    height: 40px;
-  }
-  .logo-box {
-    padding: 10px;
-    height: 100%;
-    width: 100%;
-    span {
-      font-size: 22px;
-      color: #ccc;
-    }
-    img {
-      max-height: 100%;
-      max-width: 100%;
-    }
-  }
-}
-</style>

+ 1 - 0
src/main.js

@@ -7,6 +7,7 @@ import store from './store';
 import directives from './directives';
 import { capsule } from '@/utils/tool';
 import { Loading } from 'tdesign-vue-next';
+import 'virtual:svg-icons-register';
 import 'tdesign-vue-next/es/style/index.css';
 // import 'tdesign-vue-next/dist/reset.css';
 import './style/index.less';

+ 5 - 2
src/router/modules/myWorkbenches.js

@@ -3,10 +3,11 @@ export default {
   path: '/my-workbenches',
   redirect: '/my-workbenches/workbenches',
   meta: {
-    title: '我的工作台',
+    title: '工作台',
     sort: 0,
     isModule: true,
     alias: 'workManage',
+    icon: 'work',
   },
   children: [
     {
@@ -16,7 +17,6 @@ export default {
       meta: {
         title: '工作台',
         sort: 1,
-        icon: 'app',
         alias: 'workChildManage',
       },
       children: [
@@ -31,6 +31,7 @@ export default {
             title: '消息提醒',
             sort: 1,
             alias: 'message',
+            icon: 'notice',
           },
         },
         {
@@ -42,6 +43,7 @@ export default {
             title: '待办任务',
             sort: 2,
             alias: 'work',
+            icon: 'warning-wait',
           },
         },
         {
@@ -53,6 +55,7 @@ export default {
             title: '通知公告',
             sort: 3,
             alias: 'notice',
+            icon: 'message',
           },
         },
       ],

+ 2 - 1
src/router/modules/projectQuality.js

@@ -3,10 +3,11 @@ export default {
   path: '/project-quality',
   redirect: '/project-quality/project-quality-manage',
   meta: {
-    title: '项目质量管理',
+    title: '项目质量',
     sort: 6,
     isModule: true,
     alias: 'projectQualityManage',
+    icon: 'project',
   },
   children: [
     {

+ 1 - 0
src/router/modules/resourceGuard.js

@@ -7,6 +7,7 @@ export default {
     sort: 3,
     isModule: true,
     alias: 'resourceManage',
+    icon: 'resource',
   },
   children: [
     {

+ 7 - 4
src/router/modules/serviceUnit.js

@@ -3,10 +3,11 @@ export default {
   path: '/service-unit',
   redirect: '/service-unit/dispatch',
   meta: {
-    title: '服务单元管理',
+    title: '服务单元',
     sort: 1,
     isModule: true,
     alias: 'serviceManage',
+    icon: 'service',
   },
   children: [
     {
@@ -16,7 +17,6 @@ export default {
       meta: {
         title: '派单管理',
         sort: 1,
-        icon: 'user-talk',
         alias: 'crmManage',
       },
       children: [
@@ -29,6 +29,7 @@ export default {
             title: '派单管理',
             sort: 1,
             alias: 'crm',
+            icon: 'service-crm',
           },
         },
       ],
@@ -40,7 +41,6 @@ export default {
       meta: {
         title: '服务单元管理',
         sort: 2,
-        icon: 'server',
         alias: 'serviceChildManage',
       },
       children: [
@@ -55,6 +55,7 @@ export default {
             title: '服务单元管理',
             sort: 1,
             alias: 'service',
+            icon: 'service-unit',
           },
         },
         {
@@ -68,6 +69,7 @@ export default {
             title: '服务范围管理',
             sort: 2,
             alias: 'serviceScope',
+            icon: 'service-range',
           },
         },
         {
@@ -79,7 +81,7 @@ export default {
             ),
           meta: {
             title: '新增服务范围',
-            bind: '"serviceScope"',
+            bind: 'serviceScope',
             // bind: 'RangeManage', //注意,这种不是菜单,但是也属于路由,比如name为"RangeManage"的时候,该路由也要有权限。需要在addRoute的时候考虑进去
           },
         },
@@ -94,6 +96,7 @@ export default {
             title: '服务区域规划',
             sort: 3,
             alias: 'serviceRegion',
+            icon: 'service-area',
           },
         },
       ],

+ 1 - 0
src/router/modules/sop.js

@@ -7,6 +7,7 @@ export default {
     sort: 2,
     isModule: true,
     alias: 'sopManage',
+    icon: 'sop',
   },
   children: [
     {

+ 10 - 4
src/router/modules/system.js

@@ -3,10 +3,11 @@ export default {
   path: '/system',
   redirect: { name: 'CustomerManage' },
   meta: {
-    title: '系统管理',
+    title: '系统',
     sort: 2,
     isModule: true,
     alias: 'systemManage',
+    icon: 'system',
   },
   children: [
     {
@@ -16,7 +17,6 @@ export default {
       meta: {
         title: '配置管理',
         sort: 1,
-        icon: 'setting',
         alias: 'configureManage',
       },
       children: [
@@ -29,6 +29,7 @@ export default {
             title: '客户配置',
             sort: 1,
             alias: 'custom',
+            icon: 'service-crm',
           },
         },
         {
@@ -40,6 +41,7 @@ export default {
             title: '供应商配置',
             sort: 1,
             alias: 'supplier',
+            icon: 'service-crm',
           },
         },
         {
@@ -51,6 +53,7 @@ export default {
             title: '设备配置',
             sort: 1,
             alias: 'device',
+            icon: 'service-crm',
           },
         },
         {
@@ -64,6 +67,7 @@ export default {
             title: '服务档位配置',
             sort: 1,
             alias: 'level',
+            icon: 'service-crm',
           },
         },
         {
@@ -75,6 +79,7 @@ export default {
             title: '考勤配置',
             sort: 1,
             alias: 'dingConfigure',
+            icon: 'service-crm',
           },
         },
       ],
@@ -86,7 +91,6 @@ export default {
       meta: {
         title: '通知日志',
         sort: 1,
-        icon: 'root-list',
         alias: 'logManage',
       },
       children: [
@@ -99,6 +103,7 @@ export default {
             title: '通知公告管理',
             sort: 1,
             alias: 'noticeManage',
+            icon: 'service-crm',
           },
         },
         {
@@ -110,6 +115,7 @@ export default {
             title: '日志查询',
             sort: 2,
             alias: 'log',
+            icon: 'service-crm',
           },
         },
       ],
@@ -121,7 +127,6 @@ export default {
       meta: {
         title: '任务管理',
         sort: 1,
-        icon: 'root-list',
         alias: 'taskManage',
       },
       children: [
@@ -133,6 +138,7 @@ export default {
             title: '任务管理',
             sort: 1,
             alias: 'task',
+            icon: 'service-crm',
           },
         },
       ],

+ 2 - 1
src/router/modules/user.js

@@ -3,10 +3,11 @@ export default {
   path: '/user',
   redirect: '/user/org-struct-manage',
   meta: {
-    title: '用户管理',
+    title: '用户',
     sort: 2,
     isModule: true,
     alias: 'userManage',
+    icon: 'user',
   },
   children: [
     {

+ 2 - 1
src/router/modules/workHours.js

@@ -3,10 +3,11 @@ export default {
   path: '/work-hours',
   redirect: '/work-hours/work-hours-manage',
   meta: {
-    title: '工时管理',
+    title: '工时',
     sort: 5,
     isModule: true,
     alias: 'hoursManage',
+    icon: 'time',
   },
   children: [
     {

+ 17 - 3
src/store/modules/user.js

@@ -1,5 +1,5 @@
 import { defineStore } from 'pinia';
-import { cloneDeep } from 'lodash';
+import { cloneDeep, omit } from 'lodash';
 import { getMenus, logout, login } from '@/api/user';
 import router from '@/router/index';
 import asyncRoutes, { whiteMenuList } from '@/router/asyncRoutes';
@@ -83,6 +83,7 @@ const useUserStore = defineStore('user', {
     routers: undefined,
     user: undefined,
     menus: [],
+    curPage: '',
     curPageModule: '',
     headerMenus: [],
     moduleMenus: [],
@@ -96,14 +97,27 @@ const useUserStore = defineStore('user', {
     setInfo(data) {
       this.user = data;
     },
-
     resetUserInfo() {
       this.$reset();
     },
+    setCurPage(name) {
+      this.curPage = name;
+    },
     setCurPageModule(name) {
       this.curPageModule = name;
       let item = this.menus.find((item) => item.name === name);
-      this.moduleMenus = item?.children || [];
+      // this.moduleMenus = item?.children || [];
+      const data = item?.children || [];
+      let moduleMenus = [];
+      data.forEach((item) => {
+        moduleMenus.push({ ...omit(item, ['children']), disabled: true });
+        if (item.children && item.children.length) {
+          item.children.forEach((elem) => {
+            moduleMenus.push({ ...elem, disabled: false });
+          });
+        }
+      });
+      this.moduleMenus = moduleMenus;
     },
     setHeaderMenus(menus) {
       let newMenus = cloneDeep(menus);

+ 59 - 8
src/style/global.less

@@ -6,7 +6,7 @@ body {
   height: 100%;
   background-size: cover;
   font-size: 14px;
-  color: #333;
+  color: #262626;
 }
 #app {
   height: 100%;
@@ -18,9 +18,22 @@ body {
   // box-shadow: 1px 1px 2px var(--color-neutral-2);
 }
 
+.page-action {
+  padding: 16px 16px 1px;
+  background-color: #fff;
+  & > .t-button {
+    &:not(:first-child) {
+      margin-left: 16px;
+    }
+  }
+}
+.page-header {
+  padding: 16px;
+  border-bottom: 1px solid #e5e5e5;
+}
 .table-search {
   .t-form__item {
-    margin-bottom: 10px;
+    margin-bottom: 16px;
     .t-form__label {
       padding-right: var(--td-comp-paddingLR-m);
     }
@@ -33,12 +46,50 @@ body {
   }
 }
 .page-wrap {
-  margin: 10px;
-  border-radius: 6px;
-  background-color: #fff;
-  padding: 15px;
-  // min-height: 100%;
-  overflow: auto;
+  margin: 12px 16px;
+  &-tips {
+    color: #4e5969;
+    .t-icon {
+      margin-top: -3px;
+    }
+  }
+  > .t-table {
+    background-color: transparent;
+
+    th {
+      background-color: #fff;
+      color: #8c8c8c;
+      font-weight: 400;
+      padding: 12px 16px;
+    }
+    td {
+      padding: 12px 16px;
+      color: #262626;
+      font-weight: 400;
+    }
+
+    .t-table__pagination {
+      padding: 12px 0;
+    }
+    .t-input-adornment__append {
+      border: 1px solid #d9d9d9;
+      padding: 0 3px;
+      height: var(--td-comp-size-m);
+    }
+    .t-pagination .t-input {
+      height: var(--td-comp-size-m);
+    }
+  }
+  > .t-table--bordered {
+    td,
+    th,
+    .t-table__content {
+      border-color: #e5e5e5;
+    }
+    .t-table__content {
+      border-radius: 4px;
+    }
+  }
 }
 .btn-group {
   & > .t-button {

+ 185 - 0
src/style/td-var.less

@@ -0,0 +1,185 @@
+:root,
+:root[theme-mode='light'] {
+  --td-brand-color-1: #f2f3ff;
+  --td-brand-color-2: #d9e1ff;
+  --td-brand-color-3: #b5c7ff;
+  --td-brand-color-4: #8eabff;
+  --td-brand-color-5: #618dff;
+  --td-brand-color-6: #366ef4;
+  --td-brand-color-7: #0052d9;
+  --td-brand-color-8: #003cab;
+  --td-brand-color-9: #002a7c;
+  --td-brand-color-10: #001a57;
+  --td-warning-color-1: #fff1e9;
+  --td-warning-color-2: #ffd9c2;
+  --td-warning-color-3: #ffb98c;
+  --td-warning-color-4: #fa9550;
+  --td-warning-color-5: #e37318;
+  --td-warning-color-6: #be5a00;
+  --td-warning-color-7: #954500;
+  --td-warning-color-8: #713300;
+  --td-warning-color-9: #532300;
+  --td-warning-color-10: #3b1700;
+  --td-error-color-1: #fff0ed;
+  --td-error-color-2: #ffd8d2;
+  --td-error-color-3: #ffb9b0;
+  --td-error-color-4: #ff9285;
+  --td-error-color-5: #f6685d;
+  --td-error-color-6: #d54941;
+  --td-error-color-7: #ad352f;
+  --td-error-color-8: #881f1c;
+  --td-error-color-9: #68070a;
+  --td-error-color-10: #490002;
+  --td-success-color-1: #e3f9e9;
+  --td-success-color-2: #c6f3d7;
+  --td-success-color-3: #92dab2;
+  --td-success-color-4: #56c08d;
+  --td-success-color-5: #2ba471;
+  --td-success-color-6: #008858;
+  --td-success-color-7: #006c45;
+  --td-success-color-8: #005334;
+  --td-success-color-9: #003b23;
+  --td-success-color-10: #002515;
+  --td-gray-color-1: #f3f3f3;
+  --td-gray-color-2: #eee;
+  --td-gray-color-3: #e8e8e8;
+  --td-gray-color-4: #ddd;
+  --td-gray-color-5: #c6c6c6;
+  --td-gray-color-6: #a6a6a6;
+  --td-gray-color-7: #8b8b8b;
+  --td-gray-color-8: #777;
+  --td-gray-color-9: #5e5e5e;
+  --td-gray-color-10: #4b4b4b;
+  --td-gray-color-11: #393939;
+  --td-gray-color-12: #2c2c2c;
+  --td-gray-color-13: #242424;
+  --td-gray-color-14: #181818;
+
+  // 文字 & 图标 颜色
+  --td-font-white-1: rgba(255, 255, 255, 100%);
+  --td-font-white-2: rgba(255, 255, 255, 55%);
+  --td-font-white-3: rgba(255, 255, 255, 35%);
+  --td-font-white-4: rgba(255, 255, 255, 22%);
+  --td-font-gray-1: rgba(0, 0, 0, 90%);
+  --td-font-gray-2: rgba(0, 0, 0, 60%);
+  --td-font-gray-3: rgba(0, 0, 0, 40%);
+  --td-font-gray-4: rgba(0, 0, 0, 26%);
+
+  // 基础颜色
+  --td-brand-color: var(--td-brand-color-7); // 色彩-品牌-可操作
+  --td-warning-color: var(--td-warning-color-5); // 色彩-功能-警告
+  --td-error-color: var(--td-error-color-6); // 色彩-功能-失败
+  --td-success-color: var(--td-success-color-5); // 色彩-功能-成功
+
+  // 基础颜色的扩展 用于 hover / 聚焦 / 禁用 / 点击 等状态
+  --td-brand-color-hover: var(--td-brand-color-6); // hover态
+  --td-brand-color-focus: var(--td-brand-color-2); // focus态,包括鼠标和键盘
+  --td-brand-color-active: var(--td-brand-color-8); // 点击态
+  --td-brand-color-disabled: var(--td-brand-color-3); // 禁用态
+  --td-brand-color-light: var(--td-brand-color-1); // 浅色的选中态
+  --td-brand-color-light-hover: var(--td-brand-color-2);
+
+  // 警告色扩展
+  --td-warning-color-hover: var(--td-warning-color-4);
+  --td-warning-color-focus: var(--td-warning-color-2);
+  --td-warning-color-active: var(--td-warning-color-6);
+  --td-warning-color-disabled: var(--td-warning-color-3);
+  --td-warning-color-light: var(--td-warning-color-1);
+  --td-warning-color-light-hover: var(--td-warning-color-2);
+
+  // 失败/错误色扩展
+  --td-error-color-hover: var(--td-error-color-5);
+  --td-error-color-focus: var(--td-error-color-2);
+  --td-error-color-active: var(--td-error-color-7);
+  --td-error-color-disabled: var(--td-error-color-3);
+  --td-error-color-light: var(--td-error-color-1);
+  --td-error-color-light-hover: var(--td-error-color-2);
+
+  // 成功色扩展
+  --td-success-color-hover: var(--td-success-color-4);
+  --td-success-color-focus: var(--td-success-color-2);
+  --td-success-color-active: var(--td-success-color-6);
+  --td-success-color-disabled: var(--td-success-color-3);
+  --td-success-color-light: var(--td-success-color-1);
+  --td-success-color-light-hover: var(--td-success-color-2);
+
+  // 遮罩
+  --td-mask-active: rgba(0, 0, 0, 60%); // 遮罩-弹出
+  --td-mask-disabled: rgba(255, 255, 255, 60%); // 遮罩-禁用
+
+  // 背景色
+  --td-bg-color-page: var(--td-gray-color-2); // 色彩 - page
+  --td-bg-color-container: #fff; // 色彩 - 容器
+  --td-bg-color-container-hover: var(--td-gray-color-1); // 色彩 - 容器 - hover
+  --td-bg-color-container-active: var(
+    --td-gray-color-3
+  ); // 色彩 - 容器 - active
+  --td-bg-color-container-select: #fff; // 色彩 - 容器 - select
+  --td-bg-color-secondarycontainer: var(--td-gray-color-1); // 色彩 - 次级容器
+  --td-bg-color-secondarycontainer-hover: var(
+    --td-gray-color-2
+  ); // 色彩 - 次级容器 - hover
+  --td-bg-color-secondarycontainer-active: var(
+    --td-gray-color-4
+  ); // 色彩 - 次级容器 - active
+  --td-bg-color-component: var(--td-gray-color-3); // 色彩 - 组件
+  --td-bg-color-component-hover: var(--td-gray-color-4); // 色彩 - 组件 - hover
+  --td-bg-color-component-active: var(
+    --td-gray-color-6
+  ); // 色彩 - 组件 - active
+  --td-bg-color-secondarycomponent: var(--td-gray-color-4); // 色彩 - 次级组件
+  --td-bg-color-secondarycomponent-hover: var(
+    --td-gray-color-5
+  ); // 色彩 - 次级组件 - hover
+  --td-bg-color-secondarycomponent-active: var(
+    --td-gray-color-6
+  ); // 色彩 - 次级组件 - active
+  --td-bg-color-component-disabled: var(
+    --td-gray-color-2
+  ); // 色彩 - 组件 - disabled
+
+  // 特殊组件背景色,目前只用于 button、input 组件多主题场景,浅色主题下固定为白色,深色主题下为 transparent 适配背景颜色
+  --td-bg-color-specialcomponent: #fff;
+
+  // 文本颜色
+  --td-text-color-primary: var(--td-font-gray-1); // 色彩-文字-主要
+  --td-text-color-secondary: var(--td-font-gray-2); // 色彩-文字-次要
+  --td-text-color-placeholder: var(--td-font-gray-3); // 色彩-文字-占位符/说明
+  --td-text-color-disabled: var(--td-font-gray-4); // 色彩-文字-禁用
+  --td-text-color-anti: #fff; // 色彩-文字-反色
+  --td-text-color-brand: var(--td-brand-color-7); // 色彩-文字-品牌
+  --td-text-color-link: var(--td-brand-color-8); // 色彩-文字-链接
+
+  // 分割线
+  --td-border-level-1-color: var(--td-gray-color-3);
+  --td-component-stroke: var(--td-gray-color-3);
+  // 边框
+  --td-border-level-2-color: var(--td-gray-color-4);
+  --td-component-border: var(--td-gray-color-4);
+
+  // 基础/下层 投影 hover 使用的组件包括:表格 /
+  --td-shadow-1: 0 1px 10px rgba(0, 0, 0, 5%), 0 4px 5px rgba(0, 0, 0, 8%),
+    0 2px 4px -1px rgba(0, 0, 0, 12%);
+  // 中层投影 下拉 使用的组件包括:下拉菜单 / 气泡确认框 / 选择器 /
+  --td-shadow-2: 0 3px 14px 2px rgba(0, 0, 0, 5%),
+    0 8px 10px 1px rgba(0, 0, 0, 6%), 0 5px 5px -3px rgba(0, 0, 0, 10%);
+  // 上层投影(警示/弹窗)使用的组件包括:全局提示 / 消息通知
+  --td-shadow-3: 0 6px 30px 5px rgba(0, 0, 0, 5%),
+    0 16px 24px 2px rgba(0, 0, 0, 4%), 0 8px 10px -5px rgba(0, 0, 0, 8%);
+
+  // 内投影 用于弹窗类组件(气泡确认框 / 全局提示 / 消息通知)的内描边
+  --td-shadow-inset-top: inset 0 0.5px 0 #dcdcdc;
+  --td-shadow-inset-right: inset 0.5px 0 0 #dcdcdc;
+  --td-shadow-inset-bottom: inset 0 -0.5px 0 #dcdcdc;
+  --td-shadow-inset-left: inset -0.5px 0 0 #dcdcdc;
+
+  // table 特定阴影
+  --td-table-shadow-color: rgba(0, 0, 0, 8%);
+
+  // 滚动条颜色
+  --td-scrollbar-color: rgba(0, 0, 0, 10%);
+  // 滚动条悬浮颜色( hover )
+  --td-scrollbar-hover-color: rgba(0, 0, 0, 30%);
+  // 滚动条轨道颜色,不能是带透明度,否则纵向滚动时,横向滚动条会穿透
+  --td-scroll-track-color: #fff;
+}

+ 32 - 4
src/style/tdesign-reset.less

@@ -1,3 +1,11 @@
+:root,
+:root[theme-mode='light'] {
+  --td-brand-color: #165dff;
+  --td-warning-color: #ff7d00;
+  --td-error-color: #f53f3f;
+  --td-success-color: #00b42a;
+}
+
 .t-layout .t-table {
   margin-top: 10px;
   font-size: 14px !important;
@@ -8,20 +16,21 @@
     color: #515a6e;
   }
   .table-operations {
-    text-align: center;
     & > .t-link:not(:first-child) {
       margin-left: 15px;
     }
   }
 }
-.t-form__item {
-  // margin-bottom: 15px;
-}
 .t-dialog--default {
   padding-top: 20px;
 }
 .t-dialog__body {
   padding-top: 25px;
+  overflow: initial;
+}
+.t-dialog__body .t-form__label {
+  color: #595959;
+  padding-right: 8px;
 }
 
 .t-date-picker__panel .t-pagination-mini .t-pagination-mini__current {
@@ -45,6 +54,9 @@
   width: 100%;
   margin-right: 0;
 }
+.t-form__item .t-date-picker {
+  width: 100%;
+}
 // .t-tabs {
 //   border: 1px solid #dcdfe6;
 //   box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
@@ -63,3 +75,19 @@
     }
   }
 }
+.t-button {
+  .svg-icon {
+    margin-right: 8px;
+  }
+  &.t-is-disabled {
+    .svg-icon use {
+      fill: #00000042 !important;
+    }
+  }
+
+  &.t-button--theme-default:hover {
+    .svg-icon use {
+      fill: #165dff;
+    }
+  }
+}

+ 8 - 2
src/utils/filter.js

@@ -37,8 +37,14 @@ export function genderTypeFilter(val) {
 export function educationTypeFilter(val) {
   return EDUCATION_TYPE[val] || DEFAULT_FIELD;
 }
-export function timestampFilter(val) {
-  return val ? dateFormat(val) : DEFAULT_FIELD;
+export function timestampFilter(val, fmt = 'ss') {
+  // fmt: dd or yyyy-MM-dd
+  const formats = {
+    dd: 'yyyy-MM-dd',
+    mm: 'yyyy-MM-dd hh:mm',
+    ss: 'yyyy-MM-dd hh:mm:ss',
+  };
+  return val ? dateFormat(val, formats[fmt] || fmt) : DEFAULT_FIELD;
 }
 export function dayCountFilter(val) {
   return Math.ceil(val / (24 * 60 * 60 * 1000));

+ 2 - 2
src/views/project-quality/project-quality-manage/issues-feedback/index.vue

@@ -220,13 +220,13 @@ const columns = [
     colKey: 'submissionTime',
     title: '提交时间',
     cell: 'submit-time',
-    width: 170,
+    width: 180,
   },
   {
     colKey: 'updateDateTime',
     title: '更新时间',
     cell: 'update-time',
-    width: 170,
+    width: 180,
   },
   { colKey: 'status', title: '流程状态', cell: 'flow-status', width: 100 },
   { colKey: 'setup', title: '当前节点' },

+ 1 - 1
src/views/resource-guard/device-guard/registration-query/index.vue

@@ -138,7 +138,7 @@ const columns = [
     colKey: 'createTime',
     title: '出/入库时间',
     cell: 'create-time',
-    width: 170,
+    width: 180,
   },
   { colKey: 'creator', title: '登记人' },
   { colKey: 'custom', title: '客户名称' },

+ 1 - 1
src/views/resource-guard/person-guard/person-allocate/index.vue

@@ -215,7 +215,7 @@ const columns = [
   { colKey: 'distributed', title: '已分配(人)', width: 120 },
   { colKey: 'unDistributed', title: '分配差额(人)', width: 140 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 120,

+ 1 - 0
src/views/resource-guard/person-guard/person-files/add-person-file-dialog.vue

@@ -4,6 +4,7 @@
     :header="title"
     :width="1000"
     :closeOnOverlayClick="false"
+    attach="body"
     @close="emit('update:visible', false)"
     @opened="dialogOpened"
   >

+ 3 - 3
src/views/resource-guard/person-guard/person-files/index.vue

@@ -258,7 +258,7 @@ const columns = [
     colKey: 'archivesTime',
     title: '入档时间',
     cell: 'archives-time',
-    width: 170,
+    width: 180,
   },
   {
     colKey: 'roleInfoList',
@@ -271,13 +271,13 @@ const columns = [
     colKey: 'authenticationValidTime',
     title: '认证有效期',
     cell: 'valid-time',
-    width: 170,
+    width: 180,
   },
   { colKey: 'r', title: '剩余有效天数', cell: 'remain-day', width: 110 },
   { colKey: 'authenticationStatus', title: '认证状态', cell: 'status' },
   { colKey: 'remark', title: '备注' },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     cell: 'operate',
     fixed: 'right',

+ 88 - 54
src/views/service-unit/dispatch/dispatch-manage/add-dispatch-dialog.vue

@@ -1,64 +1,98 @@
 <template>
   <my-dialog
     :visible="visible"
-    @close="emit('update:visible', false)"
     :header="`${isEdit ? '修改' : '新增'}派单`"
-    :width="600"
+    :width="840"
     :closeOnOverlayClick="false"
+    attach="body"
+    @close="emit('update:visible', false)"
   >
     <t-form ref="formRef" :data="formData" :rules="rules" labelWidth="120px">
-      <t-form-item label="项目单号" name="crmNo">
-        <t-input v-model="formData.crmNo" clearable></t-input>
-      </t-form-item>
-      <t-form-item label="项目名称" name="name">
-        <t-input v-model="formData.name" clearable></t-input>
-      </t-form-item>
-      <t-form-item label="派单时间" name="beginTime">
-        <t-date-picker v-model="formData.beginTime" value-type="time-stamp" />
-      </t-form-item>
-      <t-form-item label="服务单元">
-        <select-service-unit v-model="formData.serviceId"></select-service-unit>
-      </t-form-item>
-      <t-form-item label="客户经理" name="crmUserId">
-        <select-type-user
-          v-model="formData.crmUserId"
-          type="ACCOUNT_MANAGER"
-        ></select-type-user>
-      </t-form-item>
-      <t-form-item label="客户类型" name="customType">
-        <t-select v-model="formData.customType">
-          <t-option
-            v-for="(val, key) in CUSTOMER_TYPE"
-            :key="key"
-            :label="val"
-            :value="key"
-          />
-        </t-select>
-      </t-form-item>
-      <t-form-item label="客户名称" name="customId">
-        <select-customer
-          v-model="formData.customId"
-          :type="formData.customType"
-          type-required
-        ></select-customer>
-      </t-form-item>
-      <t-form-item label="考试开始时间">
-        <t-date-picker
-          v-model="formData.examStartTime"
-          :disable-date="{ after: formData.examEndTime || undefined }"
-          value-type="time-stamp"
-        />
-      </t-form-item>
-      <t-form-item label="考试结束时间">
-        <t-date-picker
-          v-model="formData.examEndTime"
-          :disable-date="{ before: formData.examStartTime || undefined }"
-          value-type="time-stamp"
-        />
-      </t-form-item>
-      <t-form-item label="实施产品" name="productId">
-        <select-product v-model="formData.productId" clearable></select-product>
-      </t-form-item>
+      <t-row :gutter="[0, 20]">
+        <t-col :span="6">
+          <t-form-item label="项目单号" name="crmNo">
+            <t-input v-model="formData.crmNo" clearable></t-input>
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="项目名称" name="name">
+            <t-input v-model="formData.name" clearable></t-input>
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="派单时间" name="beginTime">
+            <t-date-picker
+              v-model="formData.beginTime"
+              value-type="time-stamp"
+              enable-time-picker
+              format="YYYY-MM-DD hh:mm"
+              :time-picker-props="{ format: 'HH:mm' }"
+            />
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="客户经理" name="crmUserId">
+            <select-type-user
+              v-model="formData.crmUserId"
+              type="ACCOUNT_MANAGER"
+            ></select-type-user>
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="客户类型" name="customType">
+            <t-select v-model="formData.customType">
+              <t-option
+                v-for="(val, key) in CUSTOMER_TYPE"
+                :key="key"
+                :label="val"
+                :value="key"
+              />
+            </t-select>
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="客户名称" name="customId">
+            <select-customer
+              v-model="formData.customId"
+              :type="formData.customType"
+              type-required
+            ></select-customer>
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="考试开始时间">
+            <t-date-picker
+              v-model="formData.examStartTime"
+              :disable-date="{ after: formData.examEndTime || undefined }"
+              value-type="time-stamp"
+            />
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="考试结束时间">
+            <t-date-picker
+              v-model="formData.examEndTime"
+              :disable-date="{ before: formData.examStartTime || undefined }"
+              value-type="time-stamp"
+            />
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="实施产品" name="productId">
+            <select-product
+              v-model="formData.productId"
+              clearable
+            ></select-product>
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="服务单元">
+            <select-service-unit
+              v-model="formData.serviceId"
+            ></select-service-unit>
+          </t-form-item>
+        </t-col>
+      </t-row>
     </t-form>
     <template #foot>
       <t-button theme="default" @click="emit('update:visible', false)"

+ 70 - 58
src/views/service-unit/dispatch/dispatch-manage/index.vue

@@ -1,5 +1,26 @@
 <template>
   <div class="dispatch-manage flex flex-col h-full">
+    <div class="page-action">
+      <t-button theme="primary" @click="handleAdd">
+        <template #icon><svg-icon name="add-circle" color="#fff" /></template>
+        新增</t-button
+      >
+      <t-button
+        variant="outline"
+        :disabled="!selectedRowKeys.length"
+        @click="handleBatchDisable"
+      >
+        <template #icon><svg-icon name="delete" color="#262626" /></template>
+        作废</t-button
+      >
+      <t-button
+        variant="outline"
+        :disabled="!selectedRowKeys.length"
+        @click="handleMultDelineation"
+      >
+        <template #icon><FactCheckIcon /></template>批量划定</t-button
+      >
+    </div>
     <SearchForm :fields="fields" :params="params">
       <template #service="{ item, params }">
         <select-service-unit v-model="params[item.prop]"></select-service-unit>
@@ -18,21 +39,6 @@
       </template>
     </SearchForm>
     <div class="flex-1 page-wrap">
-      <div class="btn-group">
-        <t-button theme="success" @click="handleAdd">新增</t-button>
-        <t-button
-          theme="success"
-          :disabled="!selectedRowKeys.length"
-          @click="handleBatchDisable"
-          >作废</t-button
-        >
-        <t-button
-          theme="success"
-          :disabled="!selectedRowKeys.length"
-          @click="handleMultDelineation"
-          >批量划定</t-button
-        >
-      </div>
       <t-table
         size="small"
         row-key="id"
@@ -56,13 +62,13 @@
           {{ customerTypeFilter(row[col.colKey]) }}
         </template>
         <template #begin-time="{ col, row }">
-          {{ timestampFilter(row[col.colKey]) }}
+          {{ timestampFilter(row[col.colKey], 'mm') }}
         </template>
         <template #start-time="{ col, row }">
-          {{ timestampFilter(row[col.colKey]) }}
+          {{ timestampFilter(row[col.colKey], 'dd') }}
         </template>
         <template #end-time="{ col, row }">
-          {{ timestampFilter(row[col.colKey]) }}
+          {{ timestampFilter(row[col.colKey], 'dd') }}
         </template>
         <template #create-time="{ col, row }">
           {{ timestampFilter(row[col.colKey]) }}
@@ -93,65 +99,60 @@
     <mult-delineation-dialog
       v-model:visible="showMultDelineationDialog"
       :crm-ids="curCrmIds"
-      :dialog-width="curRow ? 1100 : 600"
+      :dialog-title="curRow?.serviceId ? '重新划定服务单元' : undefined"
       @success="refresh"
     >
       <div v-if="curRow">
-        <t-divider align="left" dashed>
-          <span>派单信息</span>
-        </t-divider>
-        <t-form label-width="140px">
+        <h4>派单信息</h4>
+        <t-form class="crm-content" colon label-width="120px">
           <t-row :gutter="[0, 0]">
-            <t-col :span="4">
-              <t-form-item label="项目单号">
+            <t-col :span="6">
+              <t-form-item label="项目单号">
                 {{ curRow.crmNo }}
               </t-form-item>
             </t-col>
-            <t-col :span="4">
-              <t-form-item label="项目名称">
+            <t-col :span="6">
+              <t-form-item label="项目名称">
                 {{ curRow.name }}
               </t-form-item>
             </t-col>
-            <t-col :span="4">
-              <t-form-item label="派单时间">
-                {{ timestampFilter(curRow.beginTime) }}
+            <t-col :span="6">
+              <t-form-item label="派单时间">
+                {{ timestampFilter(curRow.beginTime, 'mm') }}
               </t-form-item>
             </t-col>
-            <t-col :span="4">
-              <t-form-item label="客户经理">
+            <t-col :span="6">
+              <t-form-item label="客户经理">
                 {{ curRow.crmUserName }}
               </t-form-item>
             </t-col>
-            <t-col :span="4">
-              <t-form-item label="客户类型">
+            <t-col :span="6">
+              <t-form-item label="客户类型">
                 {{ customerTypeFilter(curRow.customType) }}
               </t-form-item>
             </t-col>
-            <t-col :span="4">
-              <t-form-item label="客户名称">
+            <t-col :span="6">
+              <t-form-item label="客户名称">
                 {{ curRow.custom }}
               </t-form-item>
             </t-col>
-            <t-col :span="4">
-              <t-form-item label="考试开始时间">
-                {{ timestampFilter(curRow.examStartTime) }}
+            <t-col :span="6">
+              <t-form-item label="考试开始时间">
+                {{ timestampFilter(curRow.examStartTime, 'dd') }}
               </t-form-item>
             </t-col>
-            <t-col :span="4">
-              <t-form-item label="考试结束时间">
-                {{ timestampFilter(curRow.examEndTime) }}
+            <t-col :span="6">
+              <t-form-item label="考试结束时间">
+                {{ timestampFilter(curRow.examEndTime, 'dd') }}
               </t-form-item>
             </t-col>
-            <t-col :span="4">
-              <t-form-item label="实施产品">
+            <t-col :span="6">
+              <t-form-item label="实施产品">
                 {{ curRow.product }}
               </t-form-item>
             </t-col>
           </t-row>
         </t-form>
-        <t-divider align="left" dashed>
-          <span>划定派单</span>
-        </t-divider>
       </div>
     </mult-delineation-dialog>
   </div>
@@ -161,6 +162,7 @@
 import { reactive, ref, computed, onMounted } from 'vue';
 import { omit } from 'lodash';
 import { DialogPlugin, MessagePlugin } from 'tdesign-vue-next';
+import { FactCheckIcon } from 'tdesign-icons-vue-next';
 
 import {
   dispatchQueryApi,
@@ -289,31 +291,31 @@ const columns = [
     width: 50,
     fixed: 'left',
   },
-  { colKey: 'service', title: '服务单元' },
-  { colKey: 'crmNo', title: '项目单号' },
+  { colKey: 'service', title: '服务单元', minWidth: 160 },
+  { colKey: 'crmNo', title: '项目单号', minWidth: 160 },
   { colKey: 'beginTime', title: '派单时间', cell: 'begin-time', width: 170 },
-  { colKey: 'crmUserName', title: '客户经理' },
+  { colKey: 'crmUserName', title: '客户经理', minWidth: 120 },
   { colKey: 'customType', title: '客户类型', cell: 'type', width: 100 },
-  { colKey: 'custom', title: '客户名称' },
-  { colKey: 'name', title: '项目名称' },
-  { colKey: 'product', title: '实施产品' },
+  { colKey: 'custom', title: '客户名称', minWidth: 120 },
+  { colKey: 'name', title: '项目名称', minWidth: 120 },
+  { colKey: 'product', title: '实施产品', minWidth: 120 },
   {
     colKey: 'examStartTime',
     title: '考试开始时间',
     cell: 'start-time',
-    width: 170,
+    width: 180,
   },
   {
     colKey: 'examEndTime',
     title: '考试结束时间',
     cell: 'end-time',
-    width: 170,
+    width: 180,
   },
   { colKey: 'leadName', title: '大区经理' },
   { colKey: 'createName', title: '提交人' },
   { colKey: 'createTime', title: '提交时间', cell: 'create-time', width: 170 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 140,
@@ -389,10 +391,11 @@ const handleBatchDisable = () => {
     return;
   }
   const confirmDia = DialogPlugin({
-    header: '作废提示',
-    body: `您确定要将所选的派单作废吗?`,
+    header: '系统通知',
+    body: `是否作废所选服务单元?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await dispatchBatchDisableApi(selectedRowKeys.value).catch(
@@ -409,3 +412,12 @@ onMounted(() => {
   getWaitCount();
 });
 </script>
+
+<style lang="less" scoped>
+.crm-content {
+  padding: 16px 16px 16px 0;
+  border-radius: 3px;
+  border: 1px solid #e5e5e5;
+  margin: 8px 0 24px;
+}
+</style>

+ 7 - 8
src/views/service-unit/dispatch/dispatch-manage/mult-delineation-dialog.vue

@@ -1,20 +1,18 @@
 <template>
   <my-dialog
     :visible="visible"
-    header="确认提示"
+    :header="dialogTitle"
     :width="dialogWidth"
     attach="body"
     :closeOnOverlayClick="false"
     @close="emit('update:visible', false)"
     @opened="onOpened"
   >
-    <slot>
-      <p>请选择您要需要将这些派单划定的服务单元!</p>
-    </slot>
-    <t-form ref="formRef" :data="formData" :rules="rules" :labelWidth="140">
+    <slot></slot>
+    <t-form ref="formRef" :data="formData" :rules="rules" :labelWidth="100">
       <t-row :gutter="[0, 20]">
         <t-col :span="12">
-          <t-form-item label="服务单元名称" name="serviceUnitId">
+          <t-form-item label="服务单元" name="serviceUnitId">
             <select-service-unit v-model="formData.serviceUnitId">
             </select-service-unit>
           </t-form-item>
@@ -40,7 +38,8 @@ const formRef = ref(null);
 const props = defineProps({
   visible: Boolean,
   crmIds: Array,
-  dialogWidth: { type: Number, default: 600 },
+  dialogWidth: { type: Number, default: 640 },
+  dialogTitle: { type: String, default: '划定服务单元' },
 });
 
 const formData = reactive({ serviceUnitId: null, crmIdList: [] });
@@ -48,7 +47,7 @@ const rules = {
   serviceUnitId: [
     {
       required: true,
-      message: '服务单元必选',
+      message: '未选择服务单元',
       type: 'error',
       trigger: 'change',
     },

+ 6 - 5
src/views/service-unit/service-unit-manage/add-range/index.vue

@@ -64,7 +64,7 @@
 </template>
 
 <script setup name="AddRange">
-import { reactive, ref } from 'vue';
+import { reactive, ref, computed } from 'vue';
 import { omit } from 'lodash';
 import { MessagePlugin } from 'tdesign-vue-next';
 import { serviceScopeUnbindCrmQueryApi } from '@/api/service-unit';
@@ -72,6 +72,7 @@ import useFetchTable from '@/hooks/useFetchTable';
 import { CUSTOMER_TYPE } from '@/config/constants';
 import { customerTypeFilter, timestampFilter } from '@/utils/filter';
 import MultDelineationDialog from '../../dispatch/dispatch-manage/mult-delineation-dialog.vue';
+import { dictToOptionList } from '@/utils/tool';
 
 let showMultDelineationDialog = ref(false);
 
@@ -163,7 +164,7 @@ const columns = [
     fixed: 'left',
   },
   { colKey: 'crmNo', title: '项目单号', minWidth: 80 },
-  { colKey: 'beginTime', title: '派单时间', width: 170, cell: 'begin-time' },
+  { colKey: 'beginTime', title: '派单时间', width: 180, cell: 'begin-time' },
   { colKey: 'crmUserName', title: '客户经理', minWidth: 80 },
   { colKey: 'productType', title: '客户类型', width: 90, cell: 'type' },
   { colKey: 'customName', title: '客户名称', minWidth: 100 },
@@ -172,17 +173,17 @@ const columns = [
   {
     colKey: 'examStartTime',
     title: '考试开始时间',
-    width: 170,
+    width: 180,
     cell: 'exam-start-time',
   },
   {
     colKey: 'examEndTime',
     title: '考试结束时间',
-    width: 170,
+    width: 180,
     cell: 'exam-end-time',
   },
   { colKey: 'creatorName', title: '提交人', minWidth: 80 },
-  { colKey: 'createTime', title: '提交时间', width: 170, cell: 'create-time' },
+  { colKey: 'createTime', title: '提交时间', width: 180, cell: 'create-time' },
 ];
 const {
   loading: tableLoading,

+ 251 - 0
src/views/service-unit/service-unit-manage/range-manage/add-range-dialog.vue

@@ -0,0 +1,251 @@
+<template>
+  <my-drawer
+    :visible="visible"
+    size="80%"
+    :header="false"
+    :footer="false"
+    attach="body"
+    class="add-range-dialog"
+  >
+    <div class="add-range">
+      <div class="page-action">
+        <t-button
+          theme="primary"
+          :disabled="!selectedRowKeys.length"
+          @click="handlerBatchBind"
+        >
+          <template #icon><SaveIcon /></template>
+          批量划定
+        </t-button>
+        <t-button variant="text" @click="handleClose">
+          <template #icon><CloseIcon /></template>
+        </t-button>
+      </div>
+      <SearchForm :fields="fields" :params="params">
+        <template #user="{ item, params }">
+          <select-type-user
+            v-model="params[item.prop]"
+            type="ACCOUNT_MANAGER"
+          ></select-type-user>
+        </template>
+      </SearchForm>
+
+      <div class="flex-1 page-wrap">
+        <div class="btn-group"> </div>
+        <t-table
+          size="small"
+          row-key="id"
+          :columns="columns"
+          :data="tableData"
+          bordered
+          :pagination="{
+            defaultCurrent: 1,
+            defaultPageSize: 10,
+            onChange,
+            showJumper: true,
+            showPageSize: false,
+            current: pagination.pageNumber,
+          }"
+          v-loading="tableLoading"
+          :selected-row-keys="selectedRowKeys"
+          @select-change="selectChange"
+        >
+          <template #type="{ col, row }">
+            {{ customerTypeFilter(row[col.colKey]) }}
+          </template>
+          <template #begin-time="{ col, row }">
+            {{ timestampFilter(row[col.colKey]) }}
+          </template>
+          <template #exam-start-time="{ col, row }">
+            {{ timestampFilter(row[col.colKey]) }}
+          </template>
+          <template #exam-end-time="{ col, row }">
+            {{ timestampFilter(row[col.colKey]) }}
+          </template>
+          <template #create-time="{ col, row }">
+            {{ timestampFilter(row[col.colKey]) }}
+          </template>
+        </t-table>
+      </div>
+    </div>
+  </my-drawer>
+
+  <!-- MultDelineationDialog -->
+  <mult-delineation-dialog
+    v-model:visible="showMultDelineationDialog"
+    :crm-ids="selectedRowKeys"
+    dialog-title="保存划定"
+    @success="search"
+  >
+    <p style="color: #595959; margin-bottom: 28px"
+      >请选择您要需要将这些派单划定的服务单元!</p
+    >
+  </mult-delineation-dialog>
+</template>
+
+<script setup name="AddRangeDialog">
+import { reactive, ref, computed } from 'vue';
+import { omit } from 'lodash';
+import { MessagePlugin } from 'tdesign-vue-next';
+import { SaveIcon, CloseIcon } from 'tdesign-icons-vue-next';
+import { serviceScopeUnbindCrmQueryApi } from '@/api/service-unit';
+import useFetchTable from '@/hooks/useFetchTable';
+import { CUSTOMER_TYPE } from '@/config/constants';
+import { customerTypeFilter, timestampFilter } from '@/utils/filter';
+import MultDelineationDialog from '../../dispatch/dispatch-manage/mult-delineation-dialog.vue';
+import { dictToOptionList } from '@/utils/tool';
+
+const emit = defineEmits(['update:visible', 'success']);
+const props = defineProps({
+  visible: Boolean,
+});
+let showMultDelineationDialog = ref(false);
+
+const fields = ref([
+  {
+    prop: 'crmUserId',
+    label: '客户经理',
+    type: 'select',
+    labelWidth: 80,
+    colSpan: 5,
+    cell: 'user',
+  },
+  {
+    prop: 'productType',
+    label: '客户类型',
+    type: 'select',
+    labelWidth: 80,
+    colSpan: 5,
+    attrs: {
+      clearable: true,
+    },
+  },
+  {
+    prop: 'customName',
+    label: '客户名称',
+    labelWidth: 80,
+    colSpan: 5,
+    options: dictToOptionList(CUSTOMER_TYPE),
+    attrs: {
+      clearable: true,
+    },
+  },
+  {
+    prop: 'crmNo',
+    label: '项目单号',
+    labelWidth: 80,
+    colSpan: 5,
+    attrs: {
+      clearable: true,
+    },
+  },
+  {
+    type: 'buttons',
+    colSpan: 2,
+    children: [
+      {
+        type: 'button',
+        text: '查询',
+        onClick: () => {
+          search();
+        },
+      },
+    ],
+  },
+  {
+    prop: 'crmTime',
+    label: '派单时间',
+    type: 'daterange',
+    labelWidth: 80,
+    colSpan: 10,
+    attrs: {
+      clearable: true,
+    },
+  },
+]);
+const params = reactive({
+  crmUserId: '',
+  productType: '',
+  customName: '',
+  crmNo: '',
+  crmTime: [],
+});
+const computedParams = computed(() => {
+  let data = omit(params, ['crmTime']);
+  data.startTime = params.crmTime[0];
+  data.endTime = params.crmTime[1];
+  return data;
+});
+
+const selectedRowKeys = ref([]);
+const selectChange = (value) => {
+  selectedRowKeys.value = value;
+};
+const columns = [
+  {
+    colKey: 'row-select',
+    type: 'multiple',
+    width: 50,
+    fixed: 'left',
+  },
+  { colKey: 'crmNo', title: '项目单号', minWidth: 80 },
+  { colKey: 'beginTime', title: '派单时间', width: 180, cell: 'begin-time' },
+  { colKey: 'crmUserName', title: '客户经理', minWidth: 80 },
+  { colKey: 'productType', title: '客户类型', width: 90, cell: 'type' },
+  { colKey: 'customName', title: '客户名称', minWidth: 100 },
+  { colKey: 'productName', title: '项目名称', minWidth: 80 },
+  { colKey: 'productName', title: '实施产品', minWidth: 80 },
+  {
+    colKey: 'examStartTime',
+    title: '考试开始时间',
+    width: 180,
+    cell: 'exam-start-time',
+  },
+  {
+    colKey: 'examEndTime',
+    title: '考试结束时间',
+    width: 180,
+    cell: 'exam-end-time',
+  },
+  { colKey: 'creatorName', title: '提交人', minWidth: 80 },
+  { colKey: 'createTime', title: '提交时间', width: 180, cell: 'create-time' },
+];
+const {
+  loading: tableLoading,
+  pagination,
+  tableData,
+  search,
+  onChange,
+} = useFetchTable(serviceScopeUnbindCrmQueryApi, {
+  fetchDataHandle: () => {
+    selectedRowKeys.value = [];
+  },
+  params: computedParams,
+});
+
+const handlerBatchBind = () => {
+  if (!selectedRowKeys.value.length) {
+    MessagePlugin.error('您还没有选择任何派单!');
+    return;
+  }
+  showMultDelineationDialog.value = true;
+};
+
+const handleClose = () => {
+  emit('update:visible', false);
+};
+</script>
+
+<style lang="less">
+.add-range-dialog {
+  .t-drawer__body {
+    background-color: #f2f3f5;
+    padding: 0;
+  }
+  .page-action {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+}
+</style>

+ 39 - 24
src/views/service-unit/service-unit-manage/range-manage/index.vue

@@ -1,23 +1,27 @@
 <template>
   <div class="unit-manage flex flex-col h-full">
+    <div class="page-action">
+      <t-button theme="primary" @click="handleAddRange">
+        <template #icon><svg-icon name="add-circle" color="#fff" /></template>
+        新增服务范围
+      </t-button>
+    </div>
     <SearchForm :fields="fields" :params="params">
       <template #service-unit="{ item, params }">
         <select-service-unit v-model="params[item.prop]"></select-service-unit>
       </template>
+      <template #city="{ item, params }">
+        <select-area v-model="params[item.prop]" :level="2"></select-area>
+      </template>
     </SearchForm>
     <div class="flex-1 page-wrap">
-      <div class="flex justify-between items-center">
-        <t-space>
-          <span>共计服务派单:{{ totalData.totalCrmCount }}个</span>
-          <span>已划定派单:{{ totalData.bindCrmCount }}个</span>
-          <span>待划定派单:{{ totalData.unbindCrmCount }}个</span>
-        </t-space>
-        <div class="btn-group">
-          <t-button theme="success" @click="handleAddRange"
-            >新增服务范围</t-button
-          >
-        </div>
-      </div>
+      <p class="page-wrap-tips">
+        <ErrorCircleFilledIcon /> 共计服务派单:{{
+          totalData.totalCrmCount
+        }}个,已划定派单:{{ totalData.bindCrmCount }}个,待划定派单:{{
+          totalData.unbindCrmCount
+        }}个
+      </p>
 
       <t-table
         size="small"
@@ -48,6 +52,12 @@
         </template>
       </t-table>
     </div>
+
+    <!-- AddRangeDialog -->
+    <add-range-dialog
+      v-model:visible="showAddRangeDialog"
+      @success="fetchData"
+    ></add-range-dialog>
   </div>
 </template>
 
@@ -55,6 +65,7 @@
 import { ref, reactive, onMounted } from 'vue';
 import { useRouter } from 'vue-router';
 import { DialogPlugin, MessagePlugin } from 'tdesign-vue-next';
+import { ErrorCircleFilledIcon } from 'tdesign-icons-vue-next';
 import {
   serviceScopeQueryApi,
   serviceScopeUnbindApi,
@@ -64,8 +75,10 @@ import useFetchTable from '@/hooks/useFetchTable';
 import { CUSTOMER_TYPE } from '@/config/constants';
 import { dictToOptionList } from '@/utils/tool';
 import { customerTypeFilter } from '@/utils/filter';
+import AddRangeDialog from './add-range-dialog.vue';
 
 const router = useRouter();
+const showAddRangeDialog = ref(false);
 
 const fields = ref([
   {
@@ -129,19 +142,19 @@ const params = reactive({
 });
 
 const columns = [
-  { colKey: 'serviceUnitName', title: '服务单元', minWidth: 100 },
-  { colKey: 'crmNo', title: '项目单号', width: 120 },
-  { colKey: 'customName', title: '客户名称', minWidth: 100 },
-  { colKey: 'productType', title: '客户类型', width: 90, cell: 'type' },
-  { colKey: 'province', title: '省份', minWidth: 60 },
-  { colKey: 'city', title: '城市', minWidth: 60 },
-  { colKey: 'area', title: '区县', minWidth: 60 },
-  { colKey: 'level', title: '服务档位', width: 90 },
+  { colKey: 'serviceUnitName', title: '服务单元', minWidth: 120 },
+  { colKey: 'crmNo', title: '项目单号', width: 200 },
+  { colKey: 'customName', title: '客户名称', minWidth: 120 },
+  { colKey: 'productType', title: '客户类型', width: 120, cell: 'type' },
+  { colKey: 'province', title: '省份', minWidth: 100 },
+  { colKey: 'city', title: '城市', minWidth: 100 },
+  { colKey: 'area', title: '区县', minWidth: 100 },
+  { colKey: 'level', title: '服务档位', width: 100 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
-    width: 120,
+    width: 100,
     cell: 'operate',
   },
 ];
@@ -166,14 +179,16 @@ const getTotalData = async () => {
 };
 
 const handleAddRange = () => {
-  router.push({ name: 'AddRange' });
+  // router.push({ name: 'AddRange' });
+  showAddRangeDialog.value = true;
 };
 const handleDelete = (row) => {
   const confirmDia = DialogPlugin({
-    header: '移除提示',
+    header: '系统通知',
     body: `您确定要将当前派单从派单服务单元中移除吗?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await serviceScopeUnbindApi(row.crmId).catch(() => {});

+ 15 - 7
src/views/service-unit/service-unit-manage/regional-planning/add-region-dialog.vue

@@ -2,28 +2,28 @@
   <my-dialog
     :visible="visible"
     :header="title"
-    :width="600"
+    :width="670"
     attach="body"
     :closeOnOverlayClick="false"
     top="10vh"
     @close="emit('update:visible', false)"
   >
-    <t-form ref="formRef" :data="formData" :rules="rules" label-width="140px">
-      <t-form-item label="服务单元名称:" name="serviceUnitId">
+    <t-form ref="formRef" :data="formData" :rules="rules" label-width="80px">
+      <t-form-item label="服务单元" name="serviceUnitId">
         <select-service-unit v-model="formData.serviceUnitId">
         </select-service-unit>
       </t-form-item>
-      <t-form-item label="大区经理" name="leadId">
+      <t-form-item label="大区经理" name="leadId">
         <select-type-user v-model="formData.leadId" type="REGION_MANAGER">
         </select-type-user>
       </t-form-item>
-      <t-form-item label-width="0px" name="targetValue">
-        <div style="height: 400px; width: 100%">
+      <t-form-item label="区域" name="targetValue" requiredMark>
+        <div style="height: 400px">
           <t-transfer
             v-model="targetValue"
             v-model:checked="checkedRef"
             :data="areaData"
-            style="justify-content: center"
+            search
             @checked-change="handleCheckedChange"
           >
             <template #tree="slotProps">
@@ -147,3 +147,11 @@ const save = async () => {
   emit('success');
 };
 </script>
+
+<style lang="less" scoped>
+.t-transfer {
+  :deep(.t-transfer__list) {
+    width: 240px;
+  }
+}
+</style>

+ 13 - 9
src/views/service-unit/service-unit-manage/regional-planning/index.vue

@@ -1,5 +1,11 @@
 <template>
   <div class="unit-manage flex flex-col h-full">
+    <div class="page-action">
+      <t-button theme="primary" @click="handleAdd">
+        <template #icon><svg-icon name="add-circle" color="#fff" /></template
+        >新增大区
+      </t-button>
+    </div>
     <SearchForm :fields="fields" :params="params">
       <template #service="{ item, params }">
         <select-service-unit v-model="params[item.prop]"></select-service-unit>
@@ -15,9 +21,6 @@
       </template>
     </SearchForm>
     <div class="flex-1 page-wrap">
-      <div class="btn-group">
-        <t-button theme="success" @click="handleAdd">新增</t-button>
-      </div>
       <t-table
         size="small"
         row-key="id"
@@ -40,7 +43,7 @@
             <t-link theme="primary" hover="color" @click="handleEdit(row)">
               修改大区
             </t-link>
-            <t-link theme="danger" hover="color" @click="handleDelete(row)">
+            <t-link theme="primary" hover="color" @click="handleDelete(row)">
               删除
             </t-link>
           </div>
@@ -115,12 +118,12 @@ const params = reactive({
 });
 
 const columns = [
-  { colKey: 'serviceUnitName', title: '服务单元', minWidth: 150 },
-  { colKey: 'leadName', title: '大区经理', minWidth: 80 },
-  { colKey: 'regionInfo', title: '区域划分', minWidth: 150 },
-  { colKey: 'orderCount', title: '派单共计', minWidth: 80 },
+  { colKey: 'serviceUnitName', title: '服务单元', width: 160 },
+  { colKey: 'leadName', title: '大区经理', width: 120 },
+  { colKey: 'regionInfo', title: '区域划分', minWidth: 200 },
+  { colKey: 'orderCount', title: '派单共计', width: 100 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 150,
@@ -150,6 +153,7 @@ const handleDelete = (row) => {
     body: `您确定要删除当前规划的大区吗?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await serviceRegionRemoveApi(row.serviceRegionId).catch(

+ 14 - 12
src/views/service-unit/service-unit-manage/unit-manage/add-unit-dialog.vue

@@ -2,15 +2,16 @@
   <my-dialog
     :visible="visible"
     :header="`${isEdit ? '修改' : '新增'}服务单元`"
-    :width="650"
+    :width="460"
     :closeOnOverlayClick="false"
+    attach="body"
     @close="emit('update:visible', false)"
   >
-    <t-form ref="formRef" :data="formData" :rules="rules" labelWidth="140px">
-      <t-form-item label="服务单元名称" name="name">
+    <t-form ref="formRef" :data="formData" :rules="rules" labelWidth="120px">
+      <t-form-item label="服务单元名称" name="name">
         <t-input v-model="formData.name"></t-input>
       </t-form-item>
-      <t-form-item label="业务类型" name="type">
+      <t-form-item label="业务类型" name="type">
         <t-select v-model="formData.type">
           <t-option
             v-for="(val, key) in CUSTOMER_TYPE"
@@ -20,28 +21,29 @@
           />
         </t-select>
       </t-form-item>
-      <t-form-item label="服务开始时间" name="startTime">
+      <t-form-item label="服务开始时间" name="startTime">
         <t-date-picker
           v-model="formData.startTime"
           :disable-date="{ after: formData.endTime || undefined }"
           value-type="time-stamp"
         />
       </t-form-item>
-      <t-form-item label="服务截止时间" name="endTime">
+      <t-form-item label="服务截止时间" name="endTime">
         <t-date-picker
           v-model="formData.endTime"
           :disable-date="{ before: formData.startTime || undefined }"
           value-type="time-stamp"
         />
       </t-form-item>
-      <t-form-item label="区域配比" name="regionPeopleCount" required-mark>
+      <t-form-item label="区域配比" name="regionPeopleCount" required-mark>
         <t-input-number
           v-model="formData.regionPeopleCount"
           theme="column"
           :decimalPlaces="0"
           :max="1000"
           :min="0"
-          style="width: 100px"
+          style="width: 70px"
+          placeholder="00"
         ></t-input-number>
         <span style="padding: 0 10px">:</span>
         <t-input-number
@@ -50,11 +52,11 @@
           :decimalPlaces="0"
           :max="1000"
           :min="0"
-          style="width: 100px"
+          style="width: 70px"
+          placeholder="00"
         ></t-input-number>
-        <span style="padding: 0 10px"> (区域协调人数量/项目数量)</span>
       </t-form-item>
-      <t-form-item label="负责人" name="serviceLeadId">
+      <t-form-item label="负责人" name="serviceLeadId">
         <select-type-user
           v-model="formData.serviceLeadId"
           type="BUSSINESS"
@@ -76,7 +78,7 @@ import useClearDialog from '@/hooks/useClearDialog';
 import { serviceUnitEditApi } from '@/api/service-unit';
 import { CUSTOMER_TYPE } from '@/config/constants';
 
-const emit = defineEmits(['update:visible']);
+const emit = defineEmits(['update:visible', 'success']);
 const formRef = ref(null);
 
 const props = defineProps({

+ 42 - 24
src/views/service-unit/service-unit-manage/unit-manage/index.vue

@@ -1,5 +1,11 @@
 <template>
   <div class="unit-manage flex flex-col h-full">
+    <div class="page-action">
+      <t-button theme="primary" @click="handleAdd">
+        <template #icon><svg-icon name="add-circle" color="#fff" /></template>
+        新增服务单元</t-button
+      >
+    </div>
     <SearchForm :fields="fields" :params="params">
       <template #leader="{ item, params }">
         <select-type-user
@@ -9,9 +15,6 @@
       </template>
     </SearchForm>
     <div class="flex-1 page-wrap">
-      <div class="btn-group">
-        <t-button theme="success" @click="handleAdd">新增</t-button>
-      </div>
       <t-table
         size="small"
         row-key="id"
@@ -33,7 +36,11 @@
           {{ customerTypeFilter(row[col.colKey]) }}
         </template>
         <template #status="{ col, row }">
-          {{ serviceUnitStatusFilter(row[col.colKey]) }}
+          <t-tag
+            :theme="serviceUnitStatusTheme[row[col.colKey]]"
+            variant="light"
+            >{{ serviceUnitStatusFilter(row[col.colKey]) }}</t-tag
+          >
         </template>
         <template #start-time="{ col, row }">
           {{ timestampFilter(row[col.colKey]) }}
@@ -64,7 +71,7 @@
             </t-link>
             <t-link
               v-if="row.status === 'NEW'"
-              theme="danger"
+              theme="primary"
               hover="color"
               @click="handleDestroy(row)"
             >
@@ -80,7 +87,7 @@
             </t-link>
             <t-link
               v-if="row.status === 'PUBLISH'"
-              theme="danger"
+              theme="primary"
               hover="color"
               @click="handleCloze(row)"
             >
@@ -205,6 +212,13 @@ const params = reactive({
   serviceUnitName: '',
 });
 
+const serviceUnitStatusTheme = {
+  NEW: 'primary',
+  PUBLISH: 'success',
+  FINISH: 'danger',
+  CANCEL: 'danger',
+};
+
 const computedParams = computed(() => {
   let data = omit(params, ['createTime']);
   data.createStartTime = params.createTime[0];
@@ -213,22 +227,22 @@ const computedParams = computed(() => {
 });
 
 const columns = [
-  { colKey: 'name', title: '服务单元名称' },
+  { colKey: 'name', title: '服务单元名称', minWidth: 140 },
   {
     colKey: 'startTime',
     title: '服务开始时间',
     cell: 'start-time',
-    width: 170,
+    width: 180,
   },
-  { colKey: 'endTime', title: '服务截止时间', cell: 'end-time', width: 170 },
-  { colKey: 'type', title: '业务类型', cell: 'type', width: 100 },
-  { colKey: 'serviceLeadName', title: '负责人' },
-  { colKey: 'rate', title: '区域配比', width: 80 },
-  { colKey: 'status', title: '当前状态', cell: 'status', width: 80 },
-  { colKey: 'creatorName', title: '创建人' },
-  { colKey: 'createTime', title: '创建时间', cell: 'create-time', width: 170 },
+  { colKey: 'endTime', title: '服务截止时间', cell: 'end-time', width: 180 },
+  { colKey: 'type', title: '业务类型', cell: 'type', width: 120 },
+  { colKey: 'serviceLeadName', title: '负责人', minWidth: 120 },
+  { colKey: 'rate', title: '区域配比', width: 100 },
+  { colKey: 'status', title: '当前状态', cell: 'status', width: 100 },
+  { colKey: 'creatorName', title: '创建人', minWidth: 120 },
+  { colKey: 'createTime', title: '创建时间', cell: 'create-time', width: 180 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 240,
@@ -254,10 +268,11 @@ const handleEdit = (row) => {
 };
 const handleDestroy = (row) => {
   const confirmDia = DialogPlugin({
-    header: '作废提示',
-    body: `您确定要作废当前服务单元吗?`,
+    header: '系统通知',
+    body: `是否作废所选服务单元?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await serviceUnitCancelApi(row.id).catch(() => {});
@@ -269,10 +284,11 @@ const handleDestroy = (row) => {
 };
 const handlePublish = (row) => {
   const confirmDia = DialogPlugin({
-    header: '发布提示',
-    body: `您确定要发布当前服务单元吗?`,
+    header: '系统通知',
+    body: `是否发布所选服务单元?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'success',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await serviceUnitPublishApi(row.id).catch(() => {});
@@ -284,10 +300,11 @@ const handlePublish = (row) => {
 };
 const handleRestart = (row) => {
   const confirmDia = DialogPlugin({
-    header: '重启提示',
-    body: `您确定要重启当前服务单元吗?`,
+    header: '系统通知',
+    body: `是否重启所选服务单元?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'info',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await serviceUnitRestartApi(row.id).catch(() => {});
@@ -299,10 +316,11 @@ const handleRestart = (row) => {
 };
 const handleCloze = (row) => {
   const confirmDia = DialogPlugin({
-    header: '关闭提示',
-    body: `您确定要关闭当前服务单元吗?`,
+    header: '系统通知',
+    body: `是否关闭所选服务单元?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'danger',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await serviceUnitClozeApi(row.id).catch(() => {});

+ 1 - 1
src/views/sop/sop-manage/office-sop/index.vue

@@ -56,7 +56,7 @@ const columns = [
   },
   { colKey: 'a', title: '服务单元' },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 400,

+ 1 - 1
src/views/sop/sop-manage/student-sop/index.vue

@@ -47,7 +47,7 @@ const columns = [
   },
   { colKey: 'a', title: '服务单元' },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 240,

+ 1 - 1
src/views/sop/sop-monitor/delay-warning/index.vue

@@ -105,7 +105,7 @@ const columns = [
     },
   },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 200,

+ 1 - 1
src/views/sop/sop-monitor/violation-registration/index.vue

@@ -112,7 +112,7 @@ const columns = [
   { colKey: 'createTime', title: '登记时间' },
   { colKey: 'createName', title: '登记人' },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 200,

+ 25 - 18
src/views/system/config-manage/checkin-manage/index.vue

@@ -1,14 +1,17 @@
 <template>
-  <div class="registration-query flex flex-col h-full">
+  <div class="flex flex-col h-full">
+    <div class="page-action">
+      <t-button theme="primary" @click="handleAdd">
+        <template #icon><svg-icon name="add-circle" color="#fff" /></template
+        >新增考勤配置
+      </t-button>
+    </div>
     <SearchForm :fields="fields" :params="params">
       <template #service="{ item, params }">
         <select-service-unit v-model="params[item.prop]"></select-service-unit>
       </template>
     </SearchForm>
     <div class="flex-1 page-wrap">
-      <div class="btn-group">
-        <t-button theme="success" @click="handleAdd">新增</t-button>
-      </div>
       <t-table
         size="small"
         row-key="id"
@@ -56,7 +59,7 @@
             <t-link theme="primary" hover="color" @click="handleEdit(row)">
               修改
             </t-link>
-            <t-link theme="danger" hover="color" @click="handleDelete(row)">
+            <t-link theme="primary" hover="color" @click="handleDelete(row)">
               删除
             </t-link>
           </div>
@@ -114,25 +117,28 @@ const params = reactive({
 });
 
 const columns = [
-  { colKey: 'service', title: '服务单元' },
+  { colKey: 'service', title: '服务单元', minWidth: 120 },
   { colKey: 'status', title: '发布状态', cell: 'status', width: 100 },
-  { colKey: 'name', title: '考勤组名称' },
-  { colKey: 'dingObjs', title: '适用考勤对象', cell: 'ding-objs' },
-  { colKey: 'supplier', title: '适用供应商' },
-  { colKey: 'signInTime', title: '签到时段' },
-  { colKey: 'signOutTime', title: '签退时段' },
-  { colKey: 'auditRoles', title: '审核角色', cell: 'approve-objs' },
-  { colKey: 'faceOpen', title: '是否开启人脸', cell: 'face-open' },
-  { colKey: 'reissueCardCount', title: '允许补卡次数', width: 110 },
-  { colKey: 'createName', title: '创建人' },
-  { colKey: 'createTime', title: '创建时间', cell: 'create-time', width: 170 },
+  { colKey: 'name', title: '考勤组名称', minWidth: 140 },
+  {
+    colKey: 'dingObjs',
+    title: '适用考勤对象',
+    cell: 'ding-objs',
+    minWidth: 200,
+  },
+  { colKey: 'supplier', title: '适用供应商', minWidth: 140 },
+  { colKey: 'signInTime', title: '签到时段', width: 160 },
+  { colKey: 'signOutTime', title: '签退时段', width: 160 },
+  { colKey: 'auditRoles', title: '审核角色', cell: 'approve-objs', width: 120 },
+  { colKey: 'faceOpen', title: '是否开启人脸', cell: 'face-open', width: 120 },
+  { colKey: 'reissueCardCount', title: '允许补卡次数', width: 120 },
+  { colKey: 'createName', title: '创建人', with: 120 },
+  { colKey: 'createTime', title: '创建时间', cell: 'create-time', width: 180 },
   {
     title: '管理',
     colKey: 'operate',
-    cell: 'operate',
     fixed: 'right',
     width: 120,
-    align: 'center',
   },
 ];
 const {
@@ -158,6 +164,7 @@ const handleDelete = (row) => {
     body: `确定要删除当前记录吗`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await checkinDeleteApi(row.id).catch(() => {});

+ 32 - 23
src/views/system/config-manage/customer-manage/index.vue

@@ -1,5 +1,21 @@
 <template>
-  <div class="registration-query flex flex-col h-full">
+  <div class="flex flex-col h-full">
+    <div class="page-action">
+      <t-space size="small">
+        <t-button theme="primary" @click="handleAdd">
+          <template #icon><svg-icon name="add-circle" color="#fff" /></template
+          >新增客户
+        </t-button>
+        <upload-button
+          upload-url="/api/sys/custom/import"
+          :button-props="{
+            content: '批量导入',
+            variant: 'outline',
+            theme: 'default',
+          }"
+        ></upload-button>
+      </t-space>
+    </div>
     <SearchForm :fields="fields" :params="params">
       <template #manager="{ item, params }">
         <select-type-user v-model="params[item.prop]" type="ACCOUNT_MANAGER">
@@ -11,15 +27,6 @@
       </template>
     </SearchForm>
     <div class="flex-1 page-wrap">
-      <t-space size="small">
-        <t-button theme="success" @click="handleAdd">新增</t-button>
-        <upload-button
-          upload-url="/api/sys/custom/import"
-          :button-props="{
-            content: '批量导入',
-          }"
-        ></upload-button>
-      </t-space>
       <t-table
         size="small"
         row-key="id"
@@ -141,26 +148,29 @@ const params = reactive({
 });
 
 const columns = [
-  { colKey: 'id', title: '客户ID', width: 180 },
-  { colKey: 'name', title: '客户名称' },
+  { colKey: 'id', title: '客户ID', width: 200 },
+  { colKey: 'name', title: '客户名称', width: 120 },
   { colKey: 'type', title: '客户类型', cell: 'type', width: 100 },
   { colKey: 'province', title: '省份', width: 100 },
   { colKey: 'city', title: '城市', width: 100 },
   { colKey: 'area', title: '县区', width: 100 },
   { colKey: 'address', title: '地址', minWidth: 160 },
-  { colKey: 'managerName', title: '客户经理' },
-  { colKey: 'level', title: '服务档位名称' },
-  { colKey: 'roleList', title: '项目角色配置', cell: 'role-list', width: 170 },
-  { colKey: 'peoperDay', title: '标准人天', width: 80 },
-  { colKey: 'createName', title: '创建人' },
-  { colKey: 'createTime', title: '创建时间', width: 170, cell: 'create-time' },
+  { colKey: 'managerName', title: '客户经理', width: 120 },
+  { colKey: 'level', title: '服务档位名称', width: 120 },
+  {
+    colKey: 'roleList',
+    title: '项目角色配置',
+    cell: 'role-list',
+    minWidth: 200,
+  },
+  { colKey: 'peoperDay', title: '标准人天', width: 100 },
+  { colKey: 'createName', title: '创建人', width: 120 },
+  { colKey: 'createTime', title: '创建时间', width: 180, cell: 'create-time' },
   {
     title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 120,
-    align: 'center',
-    cell: 'operate',
   },
 ];
 const {
@@ -176,15 +186,14 @@ const handleAdd = () => {
   curRow.value = null;
   showEditCustomerDialog.value = true;
 };
-const handleImport = () => {
-  console.log('import');
-};
+
 const handleDelete = (row) => {
   const confirmDia = DialogPlugin({
     header: '操作提示',
     body: `确定要删除当前记录吗`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await customerDeleteApi(row.id).catch(() => {});

+ 43 - 39
src/views/system/config-manage/device-manage/index.vue

@@ -1,5 +1,39 @@
 <template>
-  <div class="registration-query flex flex-col h-full">
+  <div class="flex flex-col h-full">
+    <div class="page-action">
+      <t-space size="small">
+        <t-button theme="primary" @click="handleAdd">
+          <template #icon><svg-icon name="add-circle" color="#fff" /></template
+          >新增设备
+        </t-button>
+        <t-button
+          variant="outline"
+          :disabled="!selectedRowKeys.length"
+          @click="handleDestroy"
+          >批量作废</t-button
+        >
+        <t-button
+          variant="outline"
+          :disabled="!selectedRowKeys.length"
+          @click="handleEable(selectedRowKeys, true)"
+          >批量启用</t-button
+        >
+        <t-button
+          variant="outline"
+          :disabled="!selectedRowKeys.length"
+          @click="handleEable(selectedRowKeys, false)"
+          >批量禁用</t-button
+        >
+        <upload-button
+          upload-url="/api/sys/device/import"
+          :button-props="{
+            content: '批量导入',
+            variant: 'outline',
+            theme: 'default',
+          }"
+        ></upload-button>
+      </t-space>
+    </div>
     <SearchForm :fields="fields" :params="params">
       <template #supplier="{ item, params }">
         <select-supplier
@@ -24,34 +58,6 @@
       </template>
     </SearchForm>
     <div class="flex-1 page-wrap">
-      <t-space size="small">
-        <t-button theme="success" @click="handleAdd">新增设备</t-button>
-        <t-button
-          theme="danger"
-          :disabled="!selectedRowKeys.length"
-          @click="handleDestroy"
-          >批量作废</t-button
-        >
-        <t-button
-          theme="success"
-          :disabled="!selectedRowKeys.length"
-          @click="handleEable(selectedRowKeys, true)"
-          >批量启用</t-button
-        >
-        <t-button
-          theme="danger"
-          :disabled="!selectedRowKeys.length"
-          @click="handleEable(selectedRowKeys, false)"
-          >批量禁用</t-button
-        >
-        <upload-button
-          upload-url="/api/sys/device/import"
-          :button-props="{
-            content: '批量导入',
-            theme: 'success',
-          }"
-        ></upload-button>
-      </t-space>
       <t-table
         size="small"
         row-key="id"
@@ -261,20 +267,18 @@ const columns = [
   { colKey: 'serialNo', title: '序列号' },
   { colKey: 'brand', title: '品牌' },
   { colKey: 'model', title: '型号' },
-  { colKey: 'buyTime', title: '购买时间', cell: 'buy-time', width: 170 },
-  { colKey: 'supplier', title: '设备供应商' },
-  { colKey: 'status', title: '运行状态', cell: 'status', width: 80 },
-  { colKey: 'location', title: '当前所在地' },
-  { colKey: 'scanCount', title: '总扫描量', width: 80 },
-  { colKey: 'bound', title: '出库/入库', width: 100 },
-  { colKey: 'enable', title: '启用/禁用', width: 100 },
+  { colKey: 'buyTime', title: '购买时间', cell: 'buy-time', width: 180 },
+  { colKey: 'supplier', title: '设备供应商', width: 140 },
+  { colKey: 'status', title: '运行状态', cell: 'status', width: 100 },
+  { colKey: 'location', title: '当前所在地', width: 140 },
+  { colKey: 'scanCount', title: '总扫描量', width: 100 },
+  { colKey: 'bound', title: '出库/入库', width: 120 },
+  { colKey: 'enable', title: '启用/禁用', width: 120 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 120,
-    align: 'center',
-    cell: 'operate',
   },
 ];
 const {

+ 19 - 12
src/views/system/config-manage/service-level-manage/index.vue

@@ -1,9 +1,12 @@
 <template>
-  <div class="registration-query flex flex-col h-full">
+  <div class="flex flex-col h-full">
+    <div class="page-action page-header">
+      <t-button theme="primary" @click="handleAdd">
+        <template #icon><svg-icon name="add-circle" color="#fff" /></template
+        >新增服务档位
+      </t-button>
+    </div>
     <div class="flex-1 page-wrap">
-      <div class="btn-group">
-        <t-button theme="success" @click="handleAdd">新增</t-button>
-      </div>
       <t-table
         size="small"
         row-key="id"
@@ -66,19 +69,22 @@ const showEditServiceLevelDialog = ref(false);
 const curRow = ref(null);
 
 const columns = [
-  { colKey: 'level', title: '服务档位名称' },
+  { colKey: 'level', title: '服务档位名称', minWidth: 140 },
   { colKey: 'type', title: '业务类型', width: 100 },
-  { colKey: 'roleList', title: '项目角色配置', cell: 'role-list' },
-  { colKey: 'devices', title: '设备配置(台)', width: 120 },
-  { colKey: 'createName', title: '创建人' },
-  { colKey: 'createTime', title: '创建时间', width: 170, cell: 'create-time' },
   {
-    title: '操作',
+    colKey: 'roleList',
+    title: '项目角色配置',
+    cell: 'role-list',
+    minWidth: 200,
+  },
+  { colKey: 'devices', title: '设备配置(台)', width: 140 },
+  { colKey: 'createName', title: '创建人', width: 120 },
+  { colKey: 'createTime', title: '创建时间', width: 180, cell: 'create-time' },
+  {
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 120,
-    align: 'center',
-    cell: 'operate',
   },
 ];
 const {
@@ -103,6 +109,7 @@ const handleDelete = (row) => {
     body: `确定要删除当前记录吗`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await serviceLevelDeleteApi(row.id).catch(() => {});

+ 11 - 10
src/views/system/config-manage/supplier-manage/index.vue

@@ -1,9 +1,12 @@
 <template>
-  <div class="registration-query flex flex-col h-full">
+  <div class="flex flex-col h-full">
+    <div class="page-action page-header">
+      <t-button theme="primary" @click="handleAdd">
+        <template #icon><svg-icon name="add-circle" color="#fff" /></template
+        >新增供应商
+      </t-button>
+    </div>
     <div class="flex-1 page-wrap">
-      <div class="btn-group">
-        <t-button theme="success" @click="handleAdd">新增</t-button>
-      </div>
       <t-table
         size="small"
         row-key="id"
@@ -65,16 +68,14 @@ const curRow = ref(null);
 const columns = [
   { colKey: 'code', title: '供应商编号' },
   { colKey: 'name', title: '供应商名称' },
-  { colKey: 'type', title: '类型', cell: 'type' },
+  { colKey: 'type', title: '类型', cell: 'type', width: 120 },
   { colKey: 'remark', title: '备注' },
-  { colKey: 'enable', title: '启用/禁用', cell: 'enable', width: 80 },
+  { colKey: 'enable', title: '启用/禁用', cell: 'enable', width: 120 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
-    width: 100,
-    align: 'center',
-    cell: 'operate',
+    width: 120,
   },
 ];
 const {

+ 2 - 2
src/views/system/notice-log/log-manage/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <div class="registration-query flex flex-col h-full">
+    <div class="flex flex-col h-full">
       <SearchForm :fields="fields" :params="params"></SearchForm>
       <div class="flex-1 page-wrap">
         <t-table
@@ -81,7 +81,7 @@ const computedParams = computed(() => {
 });
 
 const columns = [
-  { colKey: 'createTime', title: '时间', cell: 'create-time', width: 170 },
+  { colKey: 'createTime', title: '时间', cell: 'create-time', width: 180 },
   { colKey: 'content', title: '内容' },
 ];
 const {

+ 20 - 14
src/views/system/notice-log/notice-manage/index.vue

@@ -1,16 +1,21 @@
 <template>
-  <div class="registration-query flex flex-col h-full">
+  <div class="flex flex-col h-full">
+    <div class="page-action">
+      <t-button theme="primary" @click="handleAdd">
+        <template #icon><svg-icon name="add-circle" color="#fff" /></template
+        >新增通知
+      </t-button>
+      <t-button
+        variant="outline"
+        :disabled="!selectedRowKeys.length"
+        @click="handleDestroy"
+      >
+        <template #icon><svg-icon name="delete" color="#262626" /></template>
+        作废</t-button
+      >
+    </div>
     <SearchForm :fields="fields" :params="params"></SearchForm>
     <div class="flex-1 page-wrap">
-      <div class="btn-group">
-        <t-button theme="success" @click="handleAdd">新增</t-button>
-        <t-button
-          theme="danger"
-          :disabled="!selectedRowKeys.length"
-          @click="handleDestroy"
-          >作废</t-button
-        >
-      </div>
       <t-table
         size="small"
         row-key="id"
@@ -194,14 +199,12 @@ const columns = [
   { colKey: 'row-select', type: 'multiple', width: 50 },
   { colKey: 'type', title: '类型', cell: 'type', width: 120 },
   { colKey: 'title', title: '消息名称', cell: 'name' },
-  { colKey: 'status', title: '发布状态', cell: 'status', width: 100 },
+  { colKey: 'status', title: '发布状态', cell: 'status', width: 120 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 160,
-    align: 'center',
-    cell: 'operate',
   },
 ];
 const {
@@ -237,6 +240,7 @@ const handleDestroy = () => {
     body: `确定要作废当前选择的所有记录吗`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await noticeDestroyApi(selectedRowKeys.value).catch(() => {});
@@ -252,6 +256,7 @@ const handleCancelPublish = (row) => {
     body: `您确定要撤销发布该通知公告吗?一旦撤销发布,该通知公告信息的回执将会被清空,重新发布后该通知公告将作为新消息发布。`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await noticeCancelPublishApi(row.id).catch(() => {});
@@ -275,6 +280,7 @@ const handlePublish = (row) => {
     body: `您确定要发布该通知公告吗?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
+    theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
       const res = await noticePublishApi(row.id).catch(() => {});

+ 1 - 1
src/views/system/notice-log/notice-manage/notice-message-dialog.vue

@@ -153,7 +153,7 @@ const columns = [
     colKey: 'receiveTime',
     title: '消息查阅时间',
     cell: 'receive-time',
-    width: 170,
+    width: 180,
   },
   { colKey: 'mobileNumber', title: '联系电话', width: 120 },
   { colKey: 'status', title: '回执状态', cell: 'status', width: 80 },

+ 4 - 4
src/views/system/task/task-manage/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="registration-query flex flex-col h-full">
+  <div class="flex flex-col h-full">
     <SearchForm :fields="fields" :params="params"></SearchForm>
     <div class="flex-1 page-wrap">
       <t-table
@@ -127,11 +127,11 @@ const params = reactive({
 const columns = [
   { colKey: 'type', title: '任务类型' },
   { colKey: 'status', title: '任务状态', width: 100 },
-  { colKey: 'result', title: '任务结果', width: 80 },
+  { colKey: 'result', title: '任务结果', width: 100 },
   { colKey: 'createName', title: '创建人' },
-  { colKey: 'createTime', title: '创建时间', cell: 'create-time', width: 170 },
+  { colKey: 'createTime', title: '创建时间', cell: 'create-time', width: 180 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 160,

+ 1 - 1
src/views/user/auth-manage/role-manage/index.vue

@@ -43,7 +43,7 @@ const toAddRole = (params) => {
 const columns = [
   { colKey: 'name', title: '角色名称' },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 200,

+ 1 - 1
src/views/user/auth-manage/user-manage/index.vue

@@ -75,7 +75,7 @@ const columns = [
   { colKey: 'roles', title: '角色', minWidth: 200 },
   { colKey: 'enable', title: '状态', width: 80 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     width: 230,

+ 1 - 1
src/views/user/org-struct-manage/struct-manage/index.vue

@@ -52,7 +52,7 @@ const columns = [
   { colKey: 'name', title: '管理节点' },
   { colKey: 'enable', title: '状态' },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     fixed: 'right',
     cell: (h, { row }) => {

+ 1 - 1
src/views/work-hours/work-hours-manage/abnormal-check/done-check.vue

@@ -179,7 +179,7 @@ const columns = [
     colKey: 'approveTime',
     title: '审核时间',
     cell: 'approve-time',
-    width: 170,
+    width: 180,
   },
 ];
 const { pagination, tableData, search, onChange } = useFetchTable(

+ 1 - 1
src/views/work-hours/work-hours-manage/abnormal-check/wait-check.vue

@@ -195,7 +195,7 @@ const columns = [
   { colKey: 'approveUserName', title: '当前审核人' },
   { colKey: 'createTime', title: '申请时间', cell: 'apply-time', width: 170 },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     cell: 'operate',
     fixed: 'right',

+ 2 - 2
src/views/work-hours/work-hours-manage/work-attendance/index.vue

@@ -293,10 +293,10 @@ const columns = [
     colKey: 'submissionTime',
     title: '提交时间',
     cell: 'submit-time',
-    width: 170,
+    width: 180,
   },
   {
-    title: '操作',
+    title: '管理',
     colKey: 'operate',
     cell: 'operate',
     fixed: 'right',

+ 3 - 3
src/views/work-hours/work-hours-manage/work-statistics/index.vue

@@ -200,13 +200,13 @@ const columns = [
   {
     colKey: 'examStartTime',
     title: '项目开始时间',
-    width: 170,
+    width: 180,
     cell: 'start-time',
   },
   {
     colKey: 'examEndTime',
     title: '项目结束时间',
-    width: 170,
+    width: 180,
     cell: 'end-time',
   },
   { colKey: 'userName', title: '姓名(人员档案号)', cell: 'user', width: 150 },
@@ -223,7 +223,7 @@ const columns = [
     colKey: 'submissionTime',
     title: '提交时间',
     cell: 'submit-time',
-    width: 170,
+    width: 180,
   },
   { colKey: 'status', title: '提交状态', cell: 'status', width: 100 },
   {

+ 21 - 0
vite.config.js

@@ -6,6 +6,7 @@ import {
   setupVitePlugins,
   createViteProxy,
 } from './build';
+import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
 import { getEnvConfig } from './.env-config.js';
 // yarn add --dev @esbuild-plugins/node-globals-polyfill
 import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';
@@ -15,6 +16,10 @@ import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfil
 import rollupNodePolyFill from 'rollup-plugin-node-polyfills';
 import { resolve } from 'path';
 
+const resolvePath = (...args) => {
+  return resolve(__dirname, ...args);
+};
+
 export default defineConfig((configEnv) => {
   const viteEnv = loadEnv(configEnv.mode, process.cwd());
   console.log('viteEnv:', viteEnv);
@@ -63,6 +68,22 @@ export default defineConfig((configEnv) => {
         process: true,
         buffer: true,
       }),
+      createSvgIconsPlugin({
+        iconDirs: [resolvePath('src/assets/icons')],
+        symbolId: 'icon-[dir]-[name]',
+        customDomId: '__svg__icons__dom__',
+        svgoOptions: {
+          full: true,
+          plugins: [
+            {
+              name: 'removeAttrs',
+              params: {
+                attrs: ['class', 'data-name', 'fill', 'stroke'],
+              },
+            },
+          ],
+        },
+      }),
     ],
     server: {
       host: '0.0.0.0',