瀏覽代碼

Merge branch 'dev' of United_Software/k_online_ui into master

Jack Zhou 9 月之前
父節點
當前提交
eb88a87f2f
共有 100 個文件被更改,包括 4180 次插入727 次删除
  1. 2 0
      .env
  2. 2 0
      .env.development
  3. 2 0
      .env.product
  4. 2 0
      .env.test
  5. 1 0
      .gitignore
  6. 1 1
      .prettierrc.json
  7. 4 1
      index.html
  8. 18 5
      package.json
  9. 二進制
      public/favicon.ico
  10. 1 2
      src/App.vue
  11. 5 1
      src/api/index.ts
  12. 18 4
      src/api/module/booking.ts
  13. 247 1
      src/api/module/common.ts
  14. 122 0
      src/api/module/login.ts
  15. 15 0
      src/api/module/other.ts
  16. 121 1
      src/api/module/tracking.ts
  17. 1 1
      src/assets/main.css
  18. 6 1
      src/auto-imports.d.ts
  19. 0 5
      src/components/AutoComplete/src/AutoComplete.vue
  20. 22 2
      src/components/AutoSelect/src/AutoSelect.vue
  21. 148 83
      src/components/ContainerStatus/src/ContainerStatus.vue
  22. 二進制
      src/components/ContainerStatus/src/image/no_data.png
  23. 二進制
      src/components/ContainerStatus/src/image/no_data_dark.png
  24. 74 36
      src/components/CustomizeColumns/src/CustomizeColumns.vue
  25. 234 20
      src/components/DateRange/src/DateRange.vue
  26. 69 19
      src/components/DateRange/src/components/CalendarDate.vue
  27. 184 0
      src/components/DateRange/src/components/QuickCalendarDate.vue
  28. 81 0
      src/components/DateRange/src/components/QuickMonth.vue
  29. 25 8
      src/components/FliterTags/src/FilterTags.vue
  30. 1 1
      src/components/IconDropDown/src/IconDropDown.vue
  31. 662 131
      src/components/MoreFilters/src/MoreFilters.vue
  32. 94 32
      src/components/MoreFilters/src/components/SelectValue.vue
  33. 14 4
      src/components/ScoringGrade/components/DialogColorful.vue
  34. 51 19
      src/components/ScoringGrade/components/DialogUe.vue
  35. 二進制
      src/components/ScoringGrade/image/Vector.png
  36. 二進制
      src/components/ScoringGrade/image/angry_2.png
  37. 二進制
      src/components/ScoringGrade/image/bubble_corner.png
  38. 二進制
      src/components/ScoringGrade/image/bubble_corner@2x.png
  39. 二進制
      src/components/ScoringGrade/image/bubble_corner_colorful.png
  40. 二進制
      src/components/ScoringGrade/image/bubble_corner_colorful@2x.png
  41. 二進制
      src/components/ScoringGrade/image/bubble_corner_colorful_darkmode.png
  42. 二進制
      src/components/ScoringGrade/image/bubble_corner_darkmode.png
  43. 二進制
      src/components/ScoringGrade/image/dashboard_scoring.png
  44. 二進制
      src/components/ScoringGrade/image/happy_2.png
  45. 二進制
      src/components/ScoringGrade/image/hhh_2.png
  46. 二進制
      src/components/ScoringGrade/image/sad_2.png
  47. 二進制
      src/components/ScoringGrade/image/score_angry.png
  48. 二進制
      src/components/ScoringGrade/image/score_happy.png
  49. 二進制
      src/components/ScoringGrade/image/score_hhh.png
  50. 二進制
      src/components/ScoringGrade/image/score_normal.png
  51. 二進制
      src/components/ScoringGrade/image/score_sad.png
  52. 二進制
      src/components/ScoringGrade/image/score_smile.png
  53. 二進制
      src/components/ScoringGrade/image/smile_2.png
  54. 二進制
      src/components/ScoringGrade/image/submit_successful.png
  55. 231 61
      src/components/ScoringGrade/src/ScoringGrade.vue
  56. 34 12
      src/components/SelectTable/src/SelectTable.vue
  57. 30 13
      src/components/SelectTableSelect/src/SelectTableSelect.vue
  58. 32 12
      src/components/ShipmentStatus/src/ShipmentStatus.vue
  59. 120 22
      src/components/TransportMode/src/TransportMode.vue
  60. 3 1
      src/components/VBox/src/VBox.vue
  61. 23 28
      src/components/VBox_Dashboard/src/VBox_Dashboard.vue
  62. 1 0
      src/components/VBreadcrumb/index.ts
  63. 75 0
      src/components/VBreadcrumb/src/VBreadcrumb.vue
  64. 0 1
      src/components/VBreadcrumd/index.ts
  65. 0 38
      src/components/VBreadcrumd/src/VBreadcrumd.vue
  66. 20 6
      src/components/VEmpty/src/VEmpty.vue
  67. 二進制
      src/components/VEmpty/src/images/default_dark_image.png
  68. 9 6
      src/components/VLoading/src/VLoading.vue
  69. 1 0
      src/components/VSliderVerification/index.ts
  70. 238 0
      src/components/VSliderVerification/src/VSliderVerification.vue
  71. 二進制
      src/components/VSliderVerification/src/image/icon_refresh_bold_b.png
  72. 二進制
      src/components/VSliderVerification/src/image/verification-img-1.png
  73. 二進制
      src/components/VSliderVerification/src/image/verification-img-2.png
  74. 二進制
      src/components/VSliderVerification/src/image/verification-img-3.png
  75. 二進制
      src/components/VSliderVerification/src/image/verification-img-4.png
  76. 11 2
      src/components/VTag/src/VTag.vue
  77. 48 23
      src/components/selectAutoSelect/src/selectAutoSelect.vue
  78. 6 0
      src/components/transportationMode.ts
  79. 1 1
      src/hooks/rowClickStyle.ts
  80. 49 0
      src/hooks/useOverflow.ts
  81. 47 1
      src/main.ts
  82. 62 13
      src/router/index.ts
  83. 58 0
      src/stores/modules/breadCrumb.ts
  84. 30 0
      src/stores/modules/headerSearch.ts
  85. 18 0
      src/stores/modules/loadingState.ts
  86. 0 28
      src/stores/modules/parentPath.ts
  87. 44 0
      src/stores/modules/theme.ts
  88. 38 0
      src/stores/modules/user.ts
  89. 30 0
      src/stores/modules/visitedRow.ts
  90. 58 21
      src/styles/Antdui.scss
  91. 306 48
      src/styles/elementui.scss
  92. 244 12
      src/styles/icons/iconfont.css
  93. 0 0
      src/styles/icons/iconfont.js
  94. 10 0
      src/styles/icons/iconfont.svg
  95. 二進制
      src/styles/icons/iconfont.ttf
  96. 二進制
      src/styles/icons/iconfont.woff
  97. 二進制
      src/styles/icons/iconfont.woff2
  98. 二進制
      src/styles/images/dashboard_scoring.png
  99. 4 0
      src/styles/index.scss
  100. 72 0
      src/styles/theme-g.scss

+ 2 - 0
.env

@@ -0,0 +1,2 @@
+VITE_API_HOST = 'http://localhost/api'
+VITE_BASE_URL = '/k_new_online/'

+ 2 - 0
.env.development

@@ -0,0 +1,2 @@
+VITE_API_HOST = 'http://192.168.0.161/Customer_Service_Online'
+VITE_BASE_URL = '/k_new_online/'

+ 2 - 0
.env.product

@@ -0,0 +1,2 @@
+VITE_API_HOST = '/online_backend'
+VITE_BASE_URL = '/'

+ 2 - 0
.env.test

@@ -0,0 +1,2 @@
+VITE_API_HOST = 'https://ra.kerryapex.com/new/online_backend'
+VITE_BASE_URL = '/new/'

+ 1 - 0
.gitignore

@@ -16,6 +16,7 @@ coverage
 components.d.ts
 package-lock.json
 pnpm-lock.yaml
+auto-imports.d.ts
 
 /cypress/videos/
 /cypress/screenshots/

+ 1 - 1
.prettierrc.json

@@ -5,4 +5,4 @@
   "singleQuote": true,
   "printWidth": 100,
   "trailingComma": "none"
-}
+}

+ 4 - 1
index.html

@@ -4,7 +4,10 @@
     <meta charset="UTF-8" />
     <link rel="icon" href="/favicon.ico" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>online</title>
+    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
+    <meta http-equiv="Pragma" content="no-cache" />
+    <meta http-equiv="Expires" content="0" />
+    <title>KLN Online Tracking</title>
   </head>
   <body>
     <div id="app"></div>

+ 18 - 5
package.json

@@ -5,43 +5,56 @@
   "type": "module",
   "scripts": {
     "dev": "vite",
+    "dev:test": "vite --host --mode test",
+    "dev:dev": "vite --host --mode development",
     "build": "run-p type-check \"build-only {@}\" --",
     "preview": "vite preview",
     "build-only": "vite build",
+    "build:dev": "vite build --mode development",
+    "build:test": "vite build --mode test",
+    "build:pro": "vite build --mode product",
     "type-check": "vue-tsc --build --force",
     "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
     "format": "prettier --write src/"
   },
   "dependencies": {
     "@element-plus/icons-vue": "^2.3.1",
+    "@turf/turf": "^7.1.0",
     "@wangeditor/editor": "^5.1.23",
     "@wangeditor/editor-for-vue": "^5.1.12",
     "ant-design-vue": "^4.2.3",
     "axios": "^1.7.5",
+    "crypto-js": "^4.2.0",
     "dayjs": "^1.11.13",
+    "decimal.js": "^10.4.3",
     "echarts": "^5.5.1",
     "element-plus": "^2.8.1",
     "exceljs": "^4.4.0",
-    "js-md5": "^0.8.3",
+    "leaflet": "^1.9.4",
     "lodash": "^4.17.21",
     "mitt": "^3.0.1",
     "moment": "^2.30.1",
+    "moment-timezone": "^0.5.46",
     "pinia": "^2.2.2",
+    "sass-loader": "^16.0.2",
     "vue": "^3.4.29",
     "vue-draggable-plus": "^0.5.3",
     "vue-router": "^4.3.3",
+    "vue3-puzzle-vcode": "^1.1.7",
     "vuedraggable": "^2.24.3",
     "vxe-pc-ui": "^4.1.7",
     "vxe-table": "^4.7.70",
     "vxe-table-plugin-export-xlsx": "^4.0.5",
-    "xe-clipboard": "^1.10.2"
+    "xe-clipboard": "^1.10.2",
+    "xlsx": "^0.18.5"
   },
   "devDependencies": {
     "@rushstack/eslint-patch": "^1.8.0",
     "@tsconfig/node20": "^20.1.4",
+    "@types/leaflet": "^1.9.12",
     "@types/lodash": "^4.17.7",
     "@types/node": "^20.14.5",
-    "@vitejs/plugin-vue": "^5.0.5",
+    "@vitejs/plugin-vue": "^5.1.4",
     "@vue/eslint-config-prettier": "^9.0.0",
     "@vue/eslint-config-typescript": "^13.0.0",
     "@vue/tsconfig": "^0.5.1",
@@ -52,10 +65,10 @@
     "postcss": "^8.4.41",
     "postcss-loader": "^8.1.1",
     "prettier": "^3.2.5",
-    "sass": "^1.77.8",
+    "sass": "^1.79.4",
     "typescript": "~5.4.0",
     "unplugin-auto-import": "^0.18.2",
-    "unplugin-icons": "^0.19.2",
+    "unplugin-icons": "^0.19.3",
     "unplugin-vue-components": "^0.27.4",
     "vite": "^5.3.1",
     "vue-tsc": "^2.0.21"

二進制
public/favicon.ico


+ 1 - 2
src/App.vue

@@ -1,6 +1,5 @@
 <script setup lang="ts">
-import { RouterLink, RouterView } from 'vue-router'
-import HelloWorld from './components/HelloWorld.vue'
+import { RouterView } from 'vue-router'
 </script>
 
 <template>

+ 5 - 1
src/api/index.ts

@@ -1,6 +1,8 @@
 import * as booking from './module/booking'
 import * as tracking from './module/tracking'
 import * as common from './module/common'
+import * as login from './module/login'
+import * as other from './module/other'
 /**
  * api 对象接口定义
  */
@@ -15,7 +17,9 @@ function generateApiMap(maps: any) {
 const apis = generateApiMap({
   ...booking,
   ...tracking,
-  ...common
+  ...common,
+  ...login,
+  ...other
 })
 export default {
   ...apis // 取出所有可遍历属性赋值在新的对象上

+ 18 - 4
src/api/module/booking.ts

@@ -1,6 +1,7 @@
 import HttpAxios from '@/utils/axios'
 
-const baseUrl = 'http://localhost/api/Customer_Service_Online/main_new_version.php'
+const base = import.meta.env.VITE_API_HOST
+const baseUrl = `${base}/main_new_version.php`
 
 /**
  * Booking首页表格列数据
@@ -41,7 +42,6 @@ export const getBookingDetail = (params: any, config: any) => {
     {
       action: 'ocean_booking',
       operate: 'detail',
-      _schemas: 'public',
       ...params
     },
     config
@@ -51,11 +51,10 @@ export const getBookingDetail = (params: any, config: any) => {
 /**
  * 获取Booking详情页发送邮件
  */
-export const bookingSendEmail = (params: any, config: any) => {
+export const sendEmailApi = (params: any, config: any) => {
   return HttpAxios.post(
     `${baseUrl}`,
     {
-      action: 'ocean_booking',
       operate: 'save_communication',
       ...params
     },
@@ -90,3 +89,18 @@ export const getMoreFiltersTableData = (params: any, config: any) => {
     config
   )
 }
+
+/**
+ * 用户下载表格时获取所有数据
+ */
+export const getAllBookingTableData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'ocean_booking',
+      operate: 'excel',
+      ...params
+    },
+    config
+  )
+}

+ 247 - 1
src/api/module/common.ts

@@ -1,6 +1,7 @@
 import HttpAxios from '@/utils/axios'
 
-const baseUrl = 'http://localhost/api/Customer_Service_Online/main_new_version.php'
+const base = import.meta.env.VITE_API_HOST
+const baseUrl = `${base}/main_new_version.php`
 
 /**
  * 获取表格定制列功能数据
@@ -24,3 +25,248 @@ export const saveTableSettingColumns = (params: any, config: any) => {
     config
   )
 }
+
+/**
+ * 修改密码
+ */
+export const changePwdByLogin = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'password',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取菜单列表
+ */
+export const getMenuList = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取日志列
+ */
+export const getOperationTableColumns = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'opreation_log'
+    },
+    config
+  )
+}
+/**
+ * 查询日志
+ */
+export const SearchOperationLog = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'opreation_log',
+      operate: 'search',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 日志表格下载
+ */
+export const OperationLogDownload = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'opreation_log',
+      operate: 'excel',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 获取首页数据
+ */
+export const GetDashboardData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'main_welcome',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 获取ETD to ETA (Days)
+ */
+export const GetETDEcharts = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_report_etd',
+      r_type: 'r1',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 获取KPI Echarts
+ */
+export const GetKPIEcharts = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_report_kpi',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 获取Pending Echarts
+ */
+export const GetPendingEcharts = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_report',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 获取ContainerCount Echarts
+ */
+export const GetContainerCountEcharts = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_report_container_bar',
+      r_type: 'r2',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 获取CO2 Emission
+ */
+export const GetCo2EmissionEcharts = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_report_co2e_bar',
+      r_type: 'co2e_orgin',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 获取CO2 Destination
+ */
+export const GetCo2DestinationEcharts = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_report_co2e_bar',
+      r_type: 'co2e_destination',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * Top10 Origin/Destination
+ */
+export const GetTop10ODEcharts = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_report_top10_bar',
+      r_type: 'top',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * Revenue Spent
+ */
+export const GetRevenueEcharts = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_report_revenue',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * Save Layout
+ */
+export const SaveLayout = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'save_layout',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 评分提交
+ */
+export const scoringgrade = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'tools',
+      operate: 'mark_save',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 获取首页筛选条件
+ */
+export const getDashboardFilters = (config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_filter',
+    },
+    config
+  )
+}
+
+/**
+ * 获取首页筛选条件
+ */
+export const RevenueDownload = (params:any,config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'ocean_order',
+      operate: 'revenue',
+      ...params
+    },
+    config
+  )
+}

+ 122 - 0
src/api/module/login.ts

@@ -0,0 +1,122 @@
+import HttpAxios from '@/utils/axios'
+
+const base = import.meta.env.VITE_API_HOST
+const baseUrl = `${base}/login.php`
+
+/**
+ * 获取验证码
+ */
+export const getVerifcationCode = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'login',
+      operate: 'verifcation_code',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 验证用户名是否存在
+ */
+export const isUserNameExit = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'login',
+      operate: 'check_uname',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 登录
+ */
+export const login = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'login',
+      operate: 'do_login',
+      ...params
+    },
+    config
+  )
+}
+
+// 退出登录
+export const logout = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'login',
+      operate: 'logout',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 忘记密码
+ */
+export const forgotPassword = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'login',
+      operate: 'forgot_password',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 更新密码
+ */
+export const changePassword = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'login',
+      operate: 'update_pwd_expires',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取public tracking detail详情数据
+ */
+export const getPublicTrackingDetail = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'login',
+      operate: 'tracking_checked',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * reset password
+ */
+export const resetPwd = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'login',
+      operate: 'update_pwd_expires',
+      ...params
+    },
+    config
+  )
+}

+ 15 - 0
src/api/module/other.ts

@@ -0,0 +1,15 @@
+import axios from 'axios'
+
+const base = import.meta.env.VITE_API_HOST
+const baseUrl = `${base}/main_new_version.php`
+/**
+ * user guide
+ */
+export const getUserGuide = () => {
+  return axios.get(baseUrl, {
+    params: {
+      action: 'user_guide'
+    },
+    responseType: 'blob'
+  })
+}

+ 121 - 1
src/api/module/tracking.ts

@@ -1,6 +1,7 @@
 import HttpAxios from '@/utils/axios'
 
-const baseUrl = 'http://localhost/api/Customer_Service_Online/main_new_version.php'
+const base = import.meta.env.VITE_API_HOST
+const baseUrl = `${base}/main_new_version.php`
 
 /**
  * Tracking首页表格列数据
@@ -47,3 +48,122 @@ export const getTrackingDetail = (params: any, config: any) => {
     config
   )
 }
+
+/**
+ * 获取Tracking详情页中地图数据
+ */
+export const getTrackingDetailMapData = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'main_map_new',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取Tracking详情页中AMS/ISF表格数据
+ */
+export const getTrackingAmsIsf = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'ocean_order',
+      operate: 'ams_isf_log',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取add vgm页面数据
+ */
+export const getVGMData = (params: any, config: any) => {
+  return HttpAxios.get(
+    `${baseUrl}`,
+    {
+      action: 'ocean_order',
+      operate: 'ocean_vgm',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 保存 vgm页面数据
+ */
+export const saveVGMData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'ocean_order',
+      operate: 'save_ocean_vgm',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 用户下载表格时获取所有数据
+ */
+export const getAllTrackingTableData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'ocean_order',
+      operate: 'excel',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 用户点击分享链接后请求接口留下记录
+ */
+export const recordShareLinkClicked = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'ocean_order',
+      operate: 'share_shipment',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取文件上传的类型
+ */
+export const getUploadType = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'ocean_order',
+      operate: 'document_upload',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 上传文件
+ */
+export const uploadFile = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'ocean_order',
+      operate: 'document_upload_do',
+      ...params
+    },
+    config
+  )
+}

+ 1 - 1
src/assets/main.css

@@ -13,7 +13,7 @@
   /* background-color: white; */
 }
 ::-webkit-scrollbar-thumb {
-  background-color: #dddee0;
+  background-color: var(--color-scrollbar-thumb);
   border-radius: 20px;
   box-shadow: inset 0 0 0 white;
 }

+ 6 - 1
src/auto-imports.d.ts

@@ -3,6 +3,7 @@
 // @ts-nocheck
 // noinspection JSUnusedGlobalSymbols
 // Generated by unplugin-auto-import
+// biome-ignore lint: disable
 export {}
 declare global {
   const $api: typeof import('@/api/index')['default']
@@ -38,6 +39,7 @@ declare global {
   const onServerPrefetch: typeof import('vue')['onServerPrefetch']
   const onUnmounted: typeof import('vue')['onUnmounted']
   const onUpdated: typeof import('vue')['onUpdated']
+  const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
   const provide: typeof import('vue')['provide']
   const reactive: typeof import('vue')['reactive']
   const readonly: typeof import('vue')['readonly']
@@ -55,7 +57,10 @@ declare global {
   const useAttrs: typeof import('vue')['useAttrs']
   const useCssModule: typeof import('vue')['useCssModule']
   const useCssVars: typeof import('vue')['useCssVars']
+  const useId: typeof import('vue')['useId']
+  const useModel: typeof import('vue')['useModel']
   const useSlots: typeof import('vue')['useSlots']
+  const useTemplateRef: typeof import('vue')['useTemplateRef']
   const watch: typeof import('vue')['watch']
   const watchEffect: typeof import('vue')['watchEffect']
   const watchPostEffect: typeof import('vue')['watchPostEffect']
@@ -64,6 +69,6 @@ declare global {
 // for type re-export
 declare global {
   // @ts-ignore
-  export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
+  export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
   import('vue')
 }

+ 0 - 5
src/components/AutoComplete/src/AutoComplete.vue

@@ -233,9 +233,4 @@ const handleCurrentChange = (val: number) => {
 :deep(.el-popper) {
   border-radius: 12px !important;
 }
-:deep(.el-pagination) {
-  .is-active {
-    color: #b57b32 !important;
-  }
-}
 </style>

+ 22 - 2
src/components/AutoSelect/src/AutoSelect.vue

@@ -13,6 +13,15 @@ const props = defineProps({
   },
   ASType: {
     type: String
+  },
+  ASSearchFiled: {
+    type: String
+  },
+  ASSearchMode: {
+    type: String
+  },
+  ASSearchObj: {
+    type: Object
   }
 })
 
@@ -25,6 +34,9 @@ const list = ref<ListItem[]>([])
 const options = ref<ListItem[]>([])
 const value = ref(props.ASValue)
 const type = ref(props.ASType)
+const search_field = ref(props.ASSearchFiled)
+const search_mode = ref(props.ASSearchMode)
+const MoreFiltersObj = ref(props.ASSearchObj)
 const loading = ref(false)
 watch(
   () => props.ASValue,
@@ -32,6 +44,12 @@ watch(
     value.value = current
   }
 )
+watch(
+  () => props.ASSearchObj,
+  (current) => {
+    MoreFiltersObj.value = current
+  }
+)
 const remoteMethod = (query: string) => {
   if (query) {
     loading.value = true
@@ -39,10 +57,12 @@ const remoteMethod = (query: string) => {
       $api
         .getMoreFiltersData({
           term: query,
-          type: type.value
+          type: type.value,
+          search_field: search_field.value,
+          search_mode: search_mode.value,
+          ...MoreFiltersObj.value
         })
         .then((res: any) => {
-          console.log(res)
           loading.value = false
           if (res.code == 200) {
             list.value = res.data.map((item: any) => {

+ 148 - 83
src/components/ContainerStatus/src/ContainerStatus.vue

@@ -1,42 +1,29 @@
 <script setup lang="ts">
-import dayjs from 'dayjs'
+import { formatTimezone } from '@/utils/tools'
+import { useThemeStore } from '@/stores/modules/theme'
+import lightPng from './image/no_data.png'
+import darkPng from './image/no_data_dark.png'
 
+const themeStore = useThemeStore()
+
+const emptyImg = computed(() => {
+  return themeStore.theme === 'dark' ? darkPng : lightPng
+})
 const props = defineProps({
   data: Object
 })
 
-const containerStatusData: any = ref([
-  {
-    title: 'Empty Equipment Dispatched',
-    date: 'May-31-2024 10:03(GMT+02)',
-    country: 'CN,SHK'
-  },
-  {
-    title: 'In-Gate',
-    date: 'May-31-2024 10:03(GMT+02)',
-    country: 'CN,SHK'
-  },
-  {
-    title: 'Loaded On Vessel',
-    date: 'Jun-05-2024 10:03(GMT+02)',
-    country: 'CN,SHK'
-  },
-  {
-    title: 'Vessel Departure',
-    date: 'Jun-06-2024 10:03(GMT+02)',
-    country: 'CN,SHK'
-  },
-  {
-    title: 'Vessel Arrival',
-    date: 'Jun-07-2024 14:00(GMT+02)',
-    country: 'ES,BCN'
-  }
-])
+const activeNames = ref<number[]>([])
+
+const containerStatusData: any = ref([])
 watch(
   () => props.data,
   (newVal) => {
     if (newVal) {
-      containerStatusData.value = newVal[0].content
+      containerStatusData.value = newVal
+      if (containerStatusData.value.length === 1) {
+        activeNames.value = [0]
+      }
     } else {
       containerStatusData.value = []
     }
@@ -46,80 +33,158 @@ watch(
     deep: true
   }
 )
-
-const formatDate = (date: string) => {
-  return date ? dayjs(date).format('MMM-DD-YYYY HH:mm [(GMT]Z[)]') : '--'
-}
 </script>
 
 <template>
   <div class="container-status">
-    <div class="step-item" v-for="(item, index) in containerStatusData" :key="item.title">
-      <div class="step-data">
-        <div class="step-dot-icon"></div>
-        <div class="info">
-          <div class="left-info">
-            <div class="title">{{ item.title }}</div>
-            <div class="date">{{ formatDate(item.date) }}</div>
+    <el-collapse class="container" v-if="containerStatusData.length !== 0" v-model="activeNames">
+      <el-collapse-item
+        :title="containers.label"
+        v-for="(containers, name) in containerStatusData"
+        :key="name"
+        :name="name"
+      >
+        <template #title>
+          <div class="title">
+            Container <span>{{ containers.label }}</span>
           </div>
-          <div class="right-country">{{ item.country }}</div>
+        </template>
+        <div class="step-item" v-for="(item, index) in containers.content" :key="item.title">
+          <div class="step-data">
+            <div class="step-dot-icon"></div>
+            <div class="info">
+              <div class="left-info">
+                <div class="title">{{ item.title }}</div>
+                <div class="date">{{ formatTimezone(item.date, item.timezone) }}</div>
+              </div>
+              <div class="right-country">{{ item.country }}</div>
+            </div>
+          </div>
+          <div class="line" v-if="index + 1 !== containers.content.length"></div>
         </div>
-      </div>
-      <div class="line" v-if="index + 1 !== containerStatusData.length"></div>
+      </el-collapse-item>
+    </el-collapse>
+    <div v-else class="empty-content" style="">
+      <img :src="emptyImg" :class="{ 'is-dark': themeStore.theme === 'dark' }" alt="empty" />
+      <div class="empty-text" style="">No data</div>
+    </div>
+    <div class="footer">
+      Tracking on carrier website:
+      <a href="http://www.rcjgroup.com/" target="_blank" class="link">http://www.rcjgroup.com/</a>
     </div>
   </div>
 </template>
 
 <style lang="scss" scoped>
 .container-status {
+  position: relative;
   width: 100%;
-  padding: 22px 0 22px;
-}
+  height: 100%;
+  overflow: auto;
+  .container {
+    height: 358px;
+    padding-bottom: 8px;
+    overflow: auto;
+  }
+  .empty-content {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    height: 358px;
+    padding-top: 140px;
 
-.step-data {
-  display: flex;
-  gap: 8px;
-  height: 8px;
-  width: 100%;
-  .step-dot-icon {
-    height: 8px;
-    width: 8px;
-    background-color: var(--color-neutral-1);
-    border-radius: 50%;
+    .empty-text {
+      margin-top: 8px;
+      color: #b5b9bf;
+    }
   }
-  .info {
-    flex: 1;
+  .footer {
+    line-height: 38px;
+    color: #999;
+    font-size: 12px;
+    text-align: center;
+    border-top: 1px solid var(--color-border);
+    overflow: hidden;
+    .link {
+      text-decoration: none;
+      color: var(--color-theme);
+    }
+  }
+}
+</style>
+<style lang="scss">
+.container-status {
+  .el-collapse {
+    height: auto;
+    border-bottom: 0;
+  }
+  .el-collapse-item__content {
+    padding: 30px 16px 38px;
+    border-top: 1px solid var(--color-border);
+  }
+  .el-collapse-item__header {
+    height: 40px;
+    padding-left: 16px;
+    padding-right: 8px;
+    line-height: 50px;
+    & > .title {
+      font-size: 16px;
+      color: var(--color-neutral-2);
+      span {
+        margin-left: 4px;
+        font-weight: 700;
+        color: var(--color-neutral-1);
+      }
+    }
+  }
+  .step-data {
     display: flex;
-    height: 52px;
-    margin-top: -22px;
-    background-color: var(--color-table-header-bg);
-    border: 1px solid var(--color-border);
-    border-radius: 6px;
-    color: var(--color-neutral-1);
-    .left-info {
+    gap: 8px;
+    height: 8px;
+    width: 100%;
+    .step-dot-icon {
+      height: 8px;
+      width: 8px;
+      background-color: var(--color-neutral-1);
+      border-radius: 50%;
+    }
+    .info {
       flex: 1;
-      padding: 8px 10px;
-      border-right: 1px solid var(--color-border);
-      .title {
-        font-size: 14px;
-        font-weight: 700;
+      display: flex;
+      height: 52px;
+      margin-top: -22px;
+      background-color: var(--color-container-status-node-bg);
+      border: 1px solid var(--color-border);
+      border-radius: 6px;
+      color: var(--color-neutral-1);
+      .left-info {
+        flex: 1;
+        display: flex;
+        flex-direction: column;
+        padding: 8px 10px;
+        border-right: 1px solid var(--color-border);
+        .title {
+          font-size: 14px;
+          line-height: 18px;
+          font-weight: 700;
+        }
+        .date {
+          font-size: 12px;
+        }
       }
-      .date {
-        margin-top: 4px;
-        font-size: 12px;
+      .right-country {
+        width: 94px;
+        padding: 0 24px;
+        line-height: 52px;
+        font-weight: 700;
       }
     }
-    .right-country {
-      padding: 0 24px;
-      line-height: 52px;
-      font-weight: 700;
-    }
   }
-}
-.line {
-  height: 60px;
-  width: 0;
-  margin-left: 3px;
-  border-left: 1px solid var(--color-neutral-1);
+  .line {
+    height: 60px;
+    width: 0;
+    margin-left: 3px;
+    border-left: 1px solid var(--color-neutral-1);
+  }
 }
 </style>

二進制
src/components/ContainerStatus/src/image/no_data.png


二進制
src/components/ContainerStatus/src/image/no_data_dark.png


+ 74 - 36
src/components/CustomizeColumns/src/CustomizeColumns.vue

@@ -1,6 +1,8 @@
 <script setup lang="ts">
 import { VueDraggable } from 'vue-draggable-plus'
+import { useRoute } from 'vue-router'
 
+const route = useRoute()
 const dialogVisible = ref(false)
 // search筛选的字段
 const searchColumn = ref('')
@@ -105,13 +107,21 @@ const scrollToItem = (itemId: string) => {
 }
 
 // 系统首次加载时,会有引导操作
-let firstLoad = localStorage.getItem('firstLoadCustomizeColumns')
+let firstLoad = ref()
 const step1 = ref()
 const open1 = ref(false)
+const isShowStep1 = ref(false)
 const step2 = ref()
 const open2 = ref(false)
+const isShowStep2 = ref(false)
 const handleCloseTour = (stepStr: string) => {
-  stepStr === 'step1' ? (open1.value = false) : (open2.value = false)
+  if (stepStr === 'step1') {
+    isShowStep1.value = false
+    open1.value = false
+  } else {
+    isShowStep2.value = false
+    open2.value = false
+  }
   localStorage.setItem('firstLoadCustomizeColumns', 'true')
   // firstLoad = 'true'
 }
@@ -142,6 +152,13 @@ const getData = async (reset?: string) => {
       selectColumns.value = res.data.GroupColumnsRight
       nextTick(() => {
         handleTabArrow()
+        // 八秒后关闭引导
+        if (!firstLoad.value) {
+          setTimeout(() => {
+            handleCloseTour('step1')
+            handleCloseTour('step2')
+          }, 8000)
+        }
       })
     }
   })
@@ -151,14 +168,17 @@ const getData = async (reset?: string) => {
 const params = ref()
 // rightDistance是右侧箭头消失所需要translateX的值
 const openDialog = async (paramsData: Object, rightDistance: number) => {
+  firstLoad.value = localStorage.getItem('firstLoadCustomizeColumns')
   params.value = paramsData
   dialogVisible.value = true
   await getData()
   rightArrowHideDistance.value = rightDistance
   nextTick(() => {
-    if (!firstLoad) {
+    if (!firstLoad.value) {
       open1.value = true
+      isShowStep1.value = true
       open2.value = true
+      isShowStep2.value = true
     }
   })
 }
@@ -329,11 +349,7 @@ defineExpose({
           placeholder="Search columns you preffered"
         >
           <template #prefix>
-            <span class="iconfont_icon">
-              <svg class="iconfont" aria-hidden="true">
-                <use xlink:href="#icon-icon_search_b"></use>
-              </svg>
-            </span>
+            <span class="font_family icon-icon_search_b"></span>
           </template>
           <el-option
             v-for="item in searchOptions"
@@ -346,8 +362,8 @@ defineExpose({
       <div class="tips">
         <span style="font-size: 16px">* </span>
         <span
-          >Drag item over to this selection or click "add" icon to show the column on your booking
-          list</span
+          >Drag item over to this selection or click "add" icon to show the column on your
+          {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list</span
         >
       </div>
     </div>
@@ -364,7 +380,6 @@ defineExpose({
               <VueDraggable
                 v-model="groupItem.children"
                 class="column-list"
-                :sort="false"
                 ghost-class="ghost-column"
                 :forceFallback="true"
                 fallbackClass="fallback-class"
@@ -383,7 +398,7 @@ defineExpose({
                     <span class="title">{{ item.label }}</span>
                     <span
                       ref="step1"
-                      v-if="hoverAllIcon === item.field || (index === 0 && !firstLoad)"
+                      v-if="hoverAllIcon === item.field || (index === 0 && isShowStep1)"
                       class="font_family icon-icon_add_b move-icon"
                       @click="handleAddSelect(item)"
                     ></span>
@@ -395,7 +410,10 @@ defineExpose({
         </div>
       </div>
       <div class="right-select-columns">
-        <div class="title">Selected columns on your booking list</div>
+        <div class="title">
+          Selected columns on your
+          {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list
+        </div>
         <VueDraggable
           v-vloading="loading"
           v-model="selectColumns"
@@ -419,18 +437,18 @@ defineExpose({
               ></span>
               <span class="title">{{ item.label }}</span>
               <span
-                v-if="hoverSelectIcon === item.field || (index === 0 && !firstLoad)"
+                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
                 class="font_family icon-icon_moveup_b move-icon"
                 @click="handleMoveUpSelect(item)"
               ></span>
               <span
-                v-if="hoverSelectIcon === item.field || (index === 0 && !firstLoad)"
+                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
                 class="font_family icon-icon_movedown_b move-icon"
                 @click="handleMoveDownSelect(item)"
               ></span>
               <span
                 ref="step2"
-                v-if="hoverSelectIcon === item.field || (index === 0 && !firstLoad)"
+                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
                 class="font_family icon-icon_reduce_b move-icon"
                 @click="handleDeleteSelect(item)"
               ></span>
@@ -440,23 +458,36 @@ defineExpose({
       </div>
     </div>
     <template #footer>
-      <el-button type="default" @click="dialogVisible = false">Cancel</el-button>
-      <el-button type="default" @click="handleReset">Reset to default</el-button>
-      <el-button class="el-button--dark" @click="handleApply"> Apply </el-button>
+      <el-button
+        type="default"
+        style="height: 40px; padding: 8px 40px"
+        @click="dialogVisible = false"
+        >Cancel</el-button
+      >
+      <el-button type="default" style="height: 40px; padding: 8px 20px" @click="handleReset"
+        >Reset to default</el-button
+      >
+      <el-button
+        class="el-button--dark"
+        style="height: 40px; padding: 8px 40px"
+        @click="handleApply"
+      >
+        Apply
+      </el-button>
     </template>
     <el-tour
       :target-area-clickable="false"
       class="step1-tour"
       v-model="open1"
-      type="primary"
       :mask="false"
+      type="primary"
       v-if="step1?.[0]"
     >
       <el-tour-step :show-close="false" :target="step1?.[0]">
         <template #default>
           <div class="description">
             <span>Drag</span> items to the right group or click the "<span>Add</span>" icon to add
-            columns to the shipment list.
+            columns to the {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list.
           </div>
           <div class="got-it-text" @click="handleCloseTour('step1')">Got it</div>
         </template>
@@ -474,10 +505,12 @@ defineExpose({
         <template #default>
           <div class="description">
             <span>Drag</span> items to the left group or click the "<span>Remove</span>" icon to
-            delete columns from the shipment list.
+            delete columns from the
+            {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list.
           </div>
           <div class="description">
-            <span>Drag</span> items up or down to reorder the shipment list, or use the "<span
+            <span>Drag</span> items up or down to reorder the
+            {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list, or use the "<span
               >Move up</span
             >" and "<span>Move down</span>" icons.
           </div>
@@ -540,9 +573,10 @@ defineExpose({
       padding-left: 12px;
       border: 1px solid var(--color-border);
       border-radius: 6px;
+      background-color: var(--color-customize-column-item-bg);
 
       &:hover {
-        background-color: #fff1e5;
+        background-color: var(--color-customize-column-item-hover-bg);
         box-shadow: 4px 4px 32px 0px rgba(0, 0, 0, 0.1);
       }
 
@@ -552,7 +586,7 @@ defineExpose({
 
       span.draggable-icon {
         margin-right: 12px;
-        color: var(--color-neutral-3);
+        color: var(--color-customize-column-item-drag-icon);
       }
 
       .font_family {
@@ -570,13 +604,18 @@ defineExpose({
   }
 
   .ghost-column {
-    opacity: 0;
     cursor: move !important;
+    span {
+      opacity: 0;
+    }
+    border: 1px dashed var(--color-customize-column-item-drag-border) !important;
+    background-color: var(--color-customize-column-item-drag-bg) !important;
+    box-shadow: none !important;
   }
 
   .fallback-class {
     opacity: 1 !important;
-    background-color: #fff1e5 !important;
+    background-color: var(--color-customize-column-item-hover-bg) !important;
     cursor: move !important;
   }
 }
@@ -592,7 +631,7 @@ defineExpose({
     .el-tabs {
       .el-tabs__header {
         margin-bottom: 0px;
-        border-bottom: 1px solid #ebeef5;
+        border-bottom: 1px solid var(--color-customize-column-tabs-header-border);
       }
 
       .el-tabs__item {
@@ -617,9 +656,9 @@ defineExpose({
 }
 
 .right-select-columns {
-  background-color: #fffbf7;
+  background-color: var(--color-customize-column-right-section-bg);
   padding-top: 0;
-  border: 1px dashed var(--color-border);
+  border: 1px dashed var(--color-customize-column-right-section-border);
   border-radius: 12px;
 
   & > .title {
@@ -634,10 +673,6 @@ defineExpose({
     padding: 8px;
     padding-bottom: 0px;
   }
-
-  .column-item {
-    background-color: #fff;
-  }
 }
 </style>
 <style lang="scss">
@@ -663,13 +698,16 @@ defineExpose({
 
   .el-tabs__nav-prev {
     border-right: 1px solid var(--color-border);
-    box-shadow: 1px 0px 10px rgba(0, 0, 0, 0.2);
+    box-shadow: 2px 0px 12px rgba(0, 0, 0, 0.3);
+    // .el-icon {
+    //   color: white;
+    // }
     /* 左侧阴影 */
   }
 
   .el-tabs__nav-next {
     border-left: 1px solid var(--color-border);
-    box-shadow: -1px 0px 10px rgba(0, 0, 0, 0.2);
+    box-shadow: -2px 0px 12px rgba(0, 0, 0, 0.2);
     /* 左侧阴影 */
   }
 

+ 234 - 20
src/components/DateRange/src/DateRange.vue

@@ -1,10 +1,13 @@
 <script setup lang="ts">
 import emitter from '@/utils/bus'
-import { ref, computed, onMounted, onBeforeMount } from 'vue'
+import { ref, watch, onMounted, onBeforeMount } from 'vue'
 import IconDropDown from '@/components/IconDropDown'
 import CalendarDate from './components/CalendarDate.vue'
+import moment from 'moment'
+import dayjs from 'dayjs'
 
 onMounted(() => {
+  defaultDate()
   emitter.on('clearTag', (tag: any) => {
     if (tag.includes('ETD')) {
       clearDateStart()
@@ -43,71 +46,265 @@ const AddType = () => {
 const deleteType = (i: any) => {
   AddDateType.value.splice(i, 1)
   DateType.value = ''
+  clearDateCreation()
 }
+const props = defineProps({
+  isShipment: Boolean
+})
 let daterangeObj: any = {}
 const DateStart = ref()
+DateStart.value = []
 const DateEnd = ref()
+DateEnd.value = []
 const DateCreation = ref()
+DateCreation.value = []
+const searchTableQeury = ref()
+const searchTableQeuryTracking = ref()
+// 查询默认日期
+const defaultDate = () => {
+  if (props.isShipment) {
+    if (
+      sessionStorage.getItem('clickParams') == null ||
+      sessionStorage.getItem('clickParams') == '{}'
+    ) {
+      if (sessionStorage.getItem('searchTableQeuryTracking') == null) {
+        DateStart.value = [dayjs().subtract(2, 'month').startOf('month'), dayjs().add(1, 'month')]
+        daterangeObj.ETD =
+          DateStart.value[0].format('MMM/DD/YYYY') +
+          ' To ' +
+          DateStart.value[1].format('MMM/DD/YYYY')
+        const obj = {
+          title: 'ETD',
+          data: [DateStart.value[0].format('MM/DD/YYYY'), DateStart.value[1].format('MM/DD/YYYY')]
+        }
+        daterangeObj2.ETD = obj
+      } else {
+        searchTableQeuryTracking.value =
+          JSON.parse(sessionStorage.getItem('searchTableQeuryTracking') as string) || {}
+        if (searchTableQeuryTracking.value.etd_start) {
+          DateStart.value = [
+            dayjs(searchTableQeuryTracking.value.etd_start),
+            dayjs(searchTableQeuryTracking.value.etd_end)
+          ]
+          daterangeObj.ETD =
+            DateStart.value[0].format('MMM/DD/YYYY') +
+            ' To ' +
+            DateStart.value[1].format('MMM/DD/YYYY')
+          const obj = {
+            title: 'ETD',
+            data: [DateStart.value[0].format('MM/DD/YYYY'), DateStart.value[1].format('MM/DD/YYYY')]
+          }
+          daterangeObj2.ETD = obj
+        }
+        if (searchTableQeuryTracking.value.eta_start) {
+          DateEnd.value = [
+            dayjs(searchTableQeuryTracking.value.eta_start),
+            dayjs(searchTableQeuryTracking.value.eta_end)
+          ]
+          daterangeObj.ETA =
+            DateEnd.value[0].format('MMM/DD/YYYY') + ' To ' + DateEnd.value[1].format('MMM/DD/YYYY')
+          const obj = {
+            title: 'ETA',
+            data: [DateEnd.value[0].format('MM/DD/YYYY'), DateEnd.value[1].format('MM/DD/YYYY')]
+          }
+          daterangeObj2.ETA = obj
+        }
+        if (searchTableQeuryTracking.value.created_time_start) {
+          DateCreation.value = [
+            dayjs(searchTableQeuryTracking.value.created_time_start),
+            dayjs(searchTableQeuryTracking.value.created_time_end)
+          ]
+          daterangeObj['Creation Time'] =
+            DateCreation.value[0].format('MMM/DD/YYYY') +
+            ' To ' +
+            DateCreation.value[1].format('MMM/DD/YYYY')
+          const obj = {
+            title: 'Creation Time',
+            data: [
+              DateCreation.value[0].format('MM/DD/YYYY'),
+              DateCreation.value[1].format('MM/DD/YYYY')
+            ]
+          }
+          daterangeObj2['Creation Time'] = obj
+        }
+      }
+      emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeuryTracking.value)
+    } else {
+      const data = JSON.parse(sessionStorage.getItem('reportList') as string) || {}
+      searchTableQeuryTracking.value =
+        JSON.parse(sessionStorage.getItem('searchTableQeuryTracking') as string) || {}
+      if (data.eta_start) {
+        DateEnd.value = [dayjs(data.eta_start), dayjs(data.eta_end)]
+        daterangeObj.ETA =
+          DateEnd.value[0].format('MMM/DD/YYYY') + ' To ' + DateEnd.value[1].format('MMM/DD/YYYY')
+        const obj = {
+          title: 'ETA',
+          data: [DateEnd.value[0].format('MM/DD/YYYY'), DateEnd.value[1].format('MM/DD/YYYY')]
+        }
+        daterangeObj2.ETA = obj
+        emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeuryTracking.value)
+      }
+      if (data.etd_start) {
+        DateStart.value = [dayjs(data.etd_start), dayjs(data.etd_end)]
+        daterangeObj.ETD =
+          DateStart.value[0].format('MMM/DD/YYYY') +
+          ' To ' +
+          DateStart.value[1].format('MMM/DD/YYYY')
+        const obj = {
+          title: 'ETD',
+          data: [DateStart.value[0].format('MM/DD/YYYY'), DateStart.value[1].format('MM/DD/YYYY')]
+        }
+        daterangeObj2.ETD = obj
+        emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeuryTracking.value)
+      }
+    }
+  } else {
+    if (sessionStorage.getItem('searchTableQeury') == null) {
+      DateStart.value = [dayjs().subtract(2, 'month').startOf('month'), dayjs().add(1, 'month')]
+      daterangeObj.ETD =
+        DateStart.value[0].format('MMM/DD/YYYY') + ' To ' + DateStart.value[1].format('MMM/DD/YYYY')
+      const obj = {
+        title: 'ETD',
+        data: [DateStart.value[0].format('MM/DD/YYYY'), DateStart.value[1].format('MM/DD/YYYY')]
+      }
+      daterangeObj2.ETD = obj
+    } else {
+      searchTableQeury.value =
+        JSON.parse(sessionStorage.getItem('searchTableQeury') as string) || {}
+      if (searchTableQeury.value.f_etd_start) {
+        DateStart.value = [
+          dayjs(searchTableQeury.value.f_etd_start),
+          dayjs(searchTableQeury.value.f_etd_end)
+        ]
+        daterangeObj.ETD =
+          DateStart.value[0].format('MMM/DD/YYYY') +
+          ' To ' +
+          DateStart.value[1].format('MMM/DD/YYYY')
+        const obj = {
+          title: 'ETD',
+          data: [DateStart.value[0].format('MM/DD/YYYY'), DateStart.value[1].format('MM/DD/YYYY')]
+        }
+        daterangeObj2.ETD = obj
+      }
+      if (searchTableQeury.value.m_eta_start) {
+        DateEnd.value = [
+          dayjs(searchTableQeury.value.m_eta_start),
+          dayjs(searchTableQeury.value.m_eta_end)
+        ]
+        daterangeObj.ETA =
+          DateEnd.value[0].format('MMM/DD/YYYY') + ' To ' + DateEnd.value[1].format('MMM/DD/YYYY')
+        const obj = {
+          title: 'ETA',
+          data: [DateEnd.value[0].format('MM/DD/YYYY'), DateEnd.value[1].format('MM/DD/YYYY')]
+        }
+        daterangeObj2.ETA = obj
+      }
+      if (searchTableQeury.value.created_time_start) {
+        DateCreation.value = [
+          dayjs(searchTableQeury.value.created_time_start),
+          dayjs(searchTableQeury.value.created_time_end)
+        ]
+        daterangeObj['Creation Time'] =
+          DateCreation.value[0].format('MMM/DD/YYYY') +
+          ' To ' +
+          DateCreation.value[1].format('MMM/DD/YYYY')
+        const obj = {
+          title: 'Creation Time',
+          data: [
+            DateCreation.value[0].format('MM/DD/YYYY'),
+            DateCreation.value[1].format('MM/DD/YYYY')
+          ]
+        }
+        daterangeObj2['Creation Time'] = obj
+      }
+    }
+    emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeury.value)
+  }
+}
 const daterangedata = ref()
 daterangedata.value = []
+let daterangeObj2: any = {}
 const DateRangeChange = (val: any) => {
-  daterangeObj[val.title] = val.data[0] + ' To ' + val.data[1]
+  if (val.data != null) {
+    const date1 = moment(String(val.data[0])).format('MMM-DD-YYYY')
+    const date2 = moment(String(val.data[1])).format('MMM-DD-YYYY')
+    daterangeObj[val.title] = date1 + ' To ' + date2
+    daterangeObj2[val.title] = val
+  } else {
+    delete daterangeObj[val.title]
+    delete daterangeObj2[val.title]
+    if (val.title == 'ETD') {
+      DateStart.value = []
+    } else if (val.title == 'ETA') {
+      DateEnd.value = []
+    } else {
+      DateCreation.value = []
+      AddDateType.value = []
+      DateType.value = ''
+    }
+  }
 }
-const emit = defineEmits(['DateRangeSearch', 'clearDaterangeTags'])
+const emit = defineEmits(['DateRangeSearch', 'clearDaterangeTags', 'defaultDate'])
 const DateRangeSearch = () => {
-  emit('DateRangeSearch', daterangeObj)
+  emit('DateRangeSearch', daterangeObj, daterangeObj2)
   Date_visible.value = false
 }
-const CalendarTitle = computed(() => {
-  if (DateType.value == 'undefined') {
-    return 'Date Range'
-  } else {
-    return DateType.value
+const CalendarTitle = ref('Date Range')
+watch(
+  () => DateType.value,
+  (current) => {
+    CalendarTitle.value = current
   }
-})
+)
 // 清除
 const clearrest = () => {
   emit('clearDaterangeTags')
   clearDateStart()
   clearDateEnd()
   clearDateCreation()
+  clearDaterangeObj()
 }
 // 清除EDT
 const clearDateStart = () => {
   DateStart.value = []
   delete daterangeObj['ETD']
+  delete daterangeObj2['ETD']
 }
 // 清除EDA
 const clearDateEnd = () => {
   DateEnd.value = []
   delete daterangeObj['ETA']
+  delete daterangeObj2['ETA']
 }
 // 清除Creation Time
 const clearDateCreation = () => {
   DateCreation.value = []
   AddDateType.value = []
   DateType.value = ''
+  CalendarTitle.value = 'Date Range'
   delete daterangeObj['Creation Time']
+  delete daterangeObj2['Creation Time']
 }
 // 清除 daterangeObj
 const clearDaterangeObj = () => {
   daterangeObj = {}
+  daterangeObj2 = {}
 }
 </script>
 <template>
   <div class="select">
-    <el-popover trigger="click" :width="400" :visible="Date_visible">
+    <el-popover trigger="click" :width="400" :visible="Date_visible" popper-class="DaterangeClass">
       <template #reference>
-        <div class="Date_Range" @click="Date_visible = !Date_visible">
+        <div class="Date_Range" @blur="Date_visible = false" @click="Date_visible = !Date_visible">
           <div class="select_title">Date Range</div>
           <span class="iconfont_icon">
-            <svg class="iconfont" aria-hidden="true">
+            <svg class="iconfont icon_dark" aria-hidden="true">
               <use xlink:href="#icon-icon_dropdown_b"></use>
             </svg>
           </span>
         </div>
       </template>
-      <div>
+      <div class="date_header">
         <div class="title">Date Range</div>
         <div class="ETD">
           <CalendarDate
@@ -126,7 +323,7 @@ const clearDaterangeObj = () => {
         <div class="AddType" v-for="(item, index) in AddDateType" :key="item">
           <div>
             <div class="ETD_title Date_Title">
-              <div>Date Type</div>
+              <div class="Date_type">Date Type</div>
               <span class="iconfont_icon" @click="deleteType(index)">
                 <svg class="iconfont icon_delete" aria-hidden="true">
                   <use xlink:href="#icon-icon_delete_b"></use>
@@ -153,11 +350,12 @@ const clearDaterangeObj = () => {
               CalendarWidth="352px"
               :Date="DateCreation"
               @DateRangeChange="DateRangeChange"
+              :isType="true"
             ></CalendarDate>
           </div>
         </div>
         <div class="MoreType" @click="AddType" v-if="AddDateType.length != DateTypeoptions.length">
-          + More Date Type
+          <el-button class="el-button--noborder moretype">+ More Date Type</el-button>
         </div>
         <div class="daterange_bottom">
           <div><el-button type="default" @click="clearrest" class="Clear">Reset</el-button></div>
@@ -182,7 +380,7 @@ const clearDaterangeObj = () => {
   cursor: pointer;
   display: flex;
   align-items: center;
-  border: 1px solid var(--color-border);
+  border: 1px solid var(--color-select-border);
   border-radius: var(--border-radius-6);
 }
 .Date_Range {
@@ -208,11 +406,12 @@ const clearDaterangeObj = () => {
 .title {
   font-weight: 700;
   font-size: var(--font-size-5);
-  background-color: #f6f8fa;
+  background-color: var(--color-header-bg);
   height: 48px;
   display: flex;
   align-items: center;
   padding-left: 16px;
+  border-radius: 12px 12px 0 0;
 }
 .ETD {
   margin: 8px 16px;
@@ -251,7 +450,7 @@ const clearDaterangeObj = () => {
   height: 40px;
 }
 .AddType {
-  background-color: var(--color-neutral-4);
+  background-color: var(--color-header-bg);
   margin: 0 16px 8px 16px;
   padding: 8px;
   border-radius: var(--border-radius-6);
@@ -261,7 +460,7 @@ const clearDaterangeObj = () => {
   justify-content: flex-end;
   align-items: center;
   height: 48px;
-  border-top: 1px solid var(--color-border);
+  border-top: 1px solid var(--border-color-2);
   margin-top: 5px;
   font-weight: 400;
   font-size: var(--font-size-3);
@@ -292,4 +491,19 @@ const clearDaterangeObj = () => {
     width: 336px;
   }
 }
+.moretype {
+  background-color: transparent;
+  padding: 0 4px;
+  height: 24px;
+}
+.icon_dark {
+  fill: var(--color-neutral-1);
+}
+.date_header {
+  background-color: var(--management-bg-color);
+  border-radius: 12px;
+}
+.Date_type {
+  color: var(--color-neutral-2);
+}
 </style>

+ 69 - 19
src/components/DateRange/src/components/CalendarDate.vue

@@ -1,6 +1,7 @@
 <script lang="ts" setup>
 import dayjs, { Dayjs } from 'dayjs'
 import { ref, watch } from 'vue'
+import moment from 'moment'
 
 // type RangeValue = [Dayjs, Dayjs]
 // const ETDDate = ref<RangeValue>()
@@ -14,6 +15,10 @@ const props = defineProps({
   },
   Date: {
     type: Array
+  },
+  isType: {
+    type: Boolean,
+    default: false
   }
 })
 const ETDDate = ref(props.Date)
@@ -23,41 +28,66 @@ watch(
     ETDDate.value = current
   }
 )
-const emit = defineEmits(['DateRangeChange'])
+const emit = defineEmits(['DateRangeChange', 'DateChange'])
 const open = ref(false)
 const Disabled = ref([false, false])
 const isShowExtra = ref(true)
 
+const DateList = ref()
+DateList.value = []
+const daterange = (val: any) => {
+  if (DateList.value.length == 2 && val != undefined) {
+    const rangedata = {
+      title: props.CalendarTitle,
+      data: DateList.value
+    }
+    emit('DateRangeChange', rangedata)
+  }
+}
 const ChangeToday = (val: any) => {
-  console.log(ETDDate.value)
   if (val == 'Earliest') {
     // ETDDate.value = [dayjs(), dayjs()]
     ETDDate.value[0] = dayjs()
-    open.value = false
-    console.log(ETDDate.value)
+    const date1 = moment(String(ETDDate.value[0])).format('MM/DD/YYYY')
+    DateList.value[0] = date1
+    daterange(DateList.value[1])
   } else {
     ETDDate.value[1] = dayjs()
-    open.value = false
-    // ETDDate.value = [dayjs(), dayjs()]
+    const date1 = moment(String(ETDDate.value[1])).format('MM/DD/YYYY')
+    DateList.value[1] = date1
+    daterange(DateList.value[0])
   }
 }
-const handleCalendarOpen = () => {
+const handleCalendarOpen = (date: any) => {
   open.value = !open.value
+  if (open.value == false) {
+    if (date.length != 2) {
+      DateList.value = []
+      ETDDate.value = []
+    }
+  }
 }
 const Earliest = () => {
-  Disabled.value = [true, false]
-  ETDDate.value = [dayjs('Oct-05-2009'), dayjs()]
+  ETDDate.value[0] = dayjs('Oct-05-2009')
+  const date1 = moment(String(ETDDate.value[0])).format('MM/DD/YYYY')
+  DateList.value[0] = date1
+  daterange(DateList.value[1])
 }
 const Latest = () => {
-  Disabled.value = [false, true]
+  ETDDate.value[1] = dayjs()
+  const date1 = moment(String(ETDDate.value[1])).format('MM/DD/YYYY')
+  DateList.value[1] = date1
+  daterange(DateList.value[0])
 }
 const changeRangeData = (value: any) => {
+  DateList.value = value
   if (value != '') {
     const rangedata = {
       title: props.CalendarTitle,
       data: value
     }
     emit('DateRangeChange', rangedata)
+    emit('DateChange', value)
   }
 }
 const handlePanelChange = (value: any, mode: any) => {
@@ -67,6 +97,10 @@ const handlePanelChange = (value: any, mode: any) => {
     isShowExtra.value = true
   }
 }
+// 判断失焦时是否两个都有值
+const isTwoDate = (date: any) => {
+  console.log(date)
+}
 </script>
 <template>
   <div>
@@ -74,27 +108,29 @@ const handlePanelChange = (value: any, mode: any) => {
     <a-range-picker
       separator="To"
       :showToday="false"
-      :allowClear="false"
-      :style="{ width: props.CalendarWidth }"
+      :style="{
+        width: props.CalendarWidth,
+        backgroundColor: props.isType ? 'var(--more-type-bg-color)' : 'var(--management-bg-color)'
+      }"
       :open="open"
       :disabled="Disabled"
       @change="changeRangeData"
       :placeholder="['Start Time', 'End Time']"
       format="MMM-DD-YYYY"
-      valueFormat="MMM-DD-YYYY"
-      @openChange="handleCalendarOpen"
+      valueFormat="MM/DD/YYYY"
+      @openChange="handleCalendarOpen(ETDDate)"
       @panelChange="handlePanelChange"
       v-model:value="ETDDate"
     >
       <template #suffixIcon>
         <span class="iconfont_icon">
-          <svg class="iconfont" aria-hidden="true">
+          <svg class="iconfont icon_suffix" aria-hidden="true">
             <use xlink:href="#icon-icon_date_b"></use>
           </svg>
         </span>
       </template>
       <template #renderExtraFooter v-if="isShowExtra">
-        <div class="flex">
+        <div class="calender_flex">
           <div class="footer_left">
             <el-button class="el-button--noborder" @click="Earliest">Earliest Time</el-button>
             <el-button class="el-button--noborder" @click="ChangeToday('Earliest')"
@@ -112,17 +148,21 @@ const handlePanelChange = (value: any, mode: any) => {
 </template>
 
 <style lang="scss" scoped>
-.flex {
+.calender_flex {
   display: flex;
   justify-content: space-between;
 }
 .footer_left {
   display: flex;
   flex: 50%;
-  padding: 4px 0 4px 8px;
+  padding: 0 0 0 5px;
+  height: 48px;
+  display: flex;
+  align-items: center;
 }
 .footer_right {
-  border-left: 1px solid var(--color-border);
+  border-left: 1px solid var(--border-color-2);
+  padding-left: 8px;
 }
 .el-button--noborder {
   color: var(--color-theme);
@@ -132,4 +172,14 @@ const handlePanelChange = (value: any, mode: any) => {
   margin-bottom: 4px;
   color: var(--color-neutral-2);
 }
+.iconfont_icon {
+  margin-right: 0;
+}
+.iconfont {
+  width: 14px;
+  height: 14px;
+}
+.icon_suffix {
+  fill: var(--color-neutral-1);
+}
 </style>

+ 184 - 0
src/components/DateRange/src/components/QuickCalendarDate.vue

@@ -0,0 +1,184 @@
+<script lang="ts" setup>
+import dayjs from 'dayjs'
+import { ref, watch, computed } from 'vue'
+import moment from 'moment'
+
+const props = defineProps({
+  CalendarWidth: {
+    type: String,
+    default: '250px'
+  },
+  CalendarTitle: {
+    type: String
+  },
+  Date: {
+    type: Array
+  },
+  isDisabled: {
+    type: Boolean,
+    default: false
+  }
+})
+const ETDDate = ref(props.Date)
+watch(
+  () => props.Date,
+  (current) => {
+    ETDDate.value = current
+  }
+)
+const emit = defineEmits(['DateRangeChange', 'DateChange'])
+const open = ref(false)
+const isShowExtra = ref(true)
+
+const DateList = ref()
+const daterange = (val: any) => {
+  if (DateList.value.length == 2 && val != undefined) {
+    emit('DateChange', DateList.value)
+  }
+}
+const ChangeToday = (val: any) => {
+  if (val == 'Earliest') {
+    // ETDDate.value = [dayjs(), dayjs()]
+    ETDDate.value[0] = dayjs()
+    const date1 = moment(String(ETDDate.value[0])).format('MM/DD/YYYY')
+    DateList.value[0] = date1
+    daterange(DateList.value[1])
+  } else {
+    ETDDate.value[1] = dayjs()
+    const date1 = moment(String(ETDDate.value[1])).format('MM/DD/YYYY')
+    DateList.value[1] = date1
+    daterange(DateList.value[0])
+  }
+}
+const handleCalendarOpen = (date: any) => {
+  open.value = !open.value
+  if (open.value == false) {
+    if (date.length != 2) {
+      DateList.value = []
+      ETDDate.value = []
+    }
+  }
+}
+const Earliest = () => {
+  ETDDate.value[0] = dayjs('Oct-05-2009')
+  const date1 = moment(String(ETDDate.value[0])).format('MM/DD/YYYY')
+  DateList.value[0] = date1
+  daterange(DateList.value[1])
+}
+const Latest = () => {
+  ETDDate.value[1] = dayjs()
+  const date1 = moment(String(ETDDate.value[1])).format('MM/DD/YYYY')
+  DateList.value[1] = date1
+  daterange(DateList.value[0])
+}
+const changeRangeData = (value: any) => {
+  if (value != '') {
+    const rangedata = {
+      title: props.CalendarTitle,
+      data: value
+    }
+    emit('DateRangeChange', rangedata)
+    emit('DateChange', value)
+  }
+}
+const handlePanelChange = (value: any, mode: any) => {
+  if (mode[0] == 'year' || mode[0] == 'month') {
+    isShowExtra.value = false
+  } else {
+    isShowExtra.value = true
+  }
+}
+//预设范围
+const rangePresets = ref([
+  { label: 'Current Month', value: [dayjs().startOf('month'), dayjs().endOf('month')] },
+  {
+    label: 'Last Month',
+    value: [
+      dayjs().startOf('month').subtract(1, 'month'),
+      dayjs().endOf('month').subtract(1, 'month')
+    ]
+  },
+  { label: 'This Year', value: [dayjs().startOf('year'), dayjs().endOf('year')] }
+])
+const placeholder = computed(() => {
+  if (props.isDisabled) {
+    return ['No Start Limit', 'No End Limit']
+  } else {
+    return ['Start Time', 'End Time']
+  }
+})
+</script>
+<template>
+  <div>
+    <a-range-picker
+      separator="To"
+      :showToday="false"
+      :allowClear="false"
+      :style="{ width: props.CalendarWidth }"
+      :open="open"
+      style="height: 40px"
+      :presets="rangePresets"
+      :disabled="props.isDisabled"
+      @change="changeRangeData"
+      :placeholder="placeholder"
+      format="MMM-DD-YYYY"
+      valueFormat="MM/DD/YYYY"
+      @openChange="handleCalendarOpen(ETDDate)"
+      @panelChange="handlePanelChange"
+      v-model:value="ETDDate"
+    >
+      <template #suffixIcon>
+        <span class="iconfont_icon">
+          <svg class="iconfont icon_dark" aria-hidden="true">
+            <use xlink:href="#icon-icon_date_b"></use>
+          </svg>
+        </span>
+      </template>
+      <template #renderExtraFooter v-if="isShowExtra">
+        <div class="calender_flex">
+          <div class="footer_left">
+            <el-button class="el-button--noborder" @click="Earliest">Earliest Time</el-button>
+            <el-button class="el-button--noborder" @click="ChangeToday('Earliest')"
+              >Today</el-button
+            >
+          </div>
+          <div class="footer_left footer_right">
+            <el-button @click="Latest" class="el-button--noborder">Latest Time</el-button>
+            <el-button class="el-button--noborder" @click="ChangeToday('Latest')">Today</el-button>
+          </div>
+        </div>
+      </template>
+    </a-range-picker>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.calender_flex {
+  display: flex;
+  justify-content: space-between;
+}
+.footer_left {
+  display: flex;
+  flex: 50%;
+  padding: 0 0 0 5px;
+  height: 48px;
+  display: flex;
+  align-items: center;
+  border-left: 1px solid var(--border-color-2);
+}
+.footer_right {
+  border-left: 1px solid var(--border-color-2);
+  padding-left: 8px;
+}
+.el-button--noborder {
+  color: var(--color-theme);
+}
+.ETD_title {
+  font-size: var(--font-size-2);
+  margin-bottom: 4px;
+  color: var(--color-neutral-2);
+}
+:deep(.ant-picker-range) {
+  padding: 4px 8px;
+}
+</style>

+ 81 - 0
src/components/DateRange/src/components/QuickMonth.vue

@@ -0,0 +1,81 @@
+<script lang="ts" setup>
+import { ref, watch } from 'vue'
+import moment from 'moment'
+
+const props = defineProps({
+  MonthStartDate: {
+    type: String
+  },
+  MonthEndDate: {
+    type: String
+  },
+  isETDToETA: {
+    type: Boolean,
+    default: false
+  }
+})
+const startDate = ref(props.MonthStartDate)
+const EndDate = ref(props.MonthEndDate)
+watch(
+  () => props.MonthStartDate,
+  (current) => {
+    startDate.value = current
+  }
+)
+watch(
+  () => props.MonthEndDate,
+  (current) => {
+    EndDate.value = current
+  }
+)
+const emit = defineEmits(['DateChange'])
+const StartChange = (val: any) => {
+  if (!props.isETDToETA) {
+    const nextMonth = new Date(val)
+    let currentYear = nextMonth.getFullYear() + 1
+    let currentMonth = nextMonth.getMonth() + 2
+    let current = currentYear + '-' + currentMonth
+    EndDate.value = current
+  }
+  const date1 = moment(String(val)).format('MM/YYYY')
+  const date2 = moment(EndDate.value).format('MM/YYYY')
+  emit('DateChange', date1, date2)
+}
+const EndChange = (val: any) => {
+  if (!props.isETDToETA) {
+    const nextMonth = new Date(val)
+    let currentYear = nextMonth.getFullYear() - 1
+    let currentMonth = nextMonth.getMonth()
+    let current = currentYear + '-' + currentMonth
+    startDate.value = current
+  }
+  const date1 = moment(startDate.value).format('MM/YYYY')
+  const date2 = moment(String(val)).format('MM/YYYY')
+  emit('DateChange', date1, date2)
+}
+</script>
+
+<template>
+  <div>
+    <el-date-picker
+      style="width: 120px"
+      v-model="startDate"
+      format="MMM-YYYY"
+      type="month"
+      @change="StartChange"
+      :clearable="false"
+      placeholder="Start month"
+      placement="bottom"
+    />
+    <el-date-picker
+      style="width: 120px; margin-left: 8px"
+      v-model="EndDate"
+      format="MMM-YYYY"
+      type="month"
+      @change="EndChange"
+      :clearable="false"
+      placeholder="End month"
+      placement="bottom"
+    />
+  </div>
+</template>

+ 25 - 8
src/components/FliterTags/src/FilterTags.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
-import { ref, watch } from 'vue'
+import { ref, onMounted, onBeforeMount, watch, computed } from 'vue'
+import emitter from '@/utils/bus'
 interface ListItem {
   name: string
   number: number
@@ -20,6 +21,23 @@ watch(
     TagsList.value = current
   }
 )
+onMounted(() => {
+  emitter.on('clearTag', (tag: any) => {
+    if (tag.includes('Shipment status')) {
+      checkedCount = []
+      // TagsList.value.forEach((item: any) => {
+      //   item.checked = false
+      // })
+      // TagsList.value[0].checked = true
+      NewTagsList.value = ['All']
+      emits('changeTag', NewTagsList.value, false)
+    }
+  })
+})
+
+onBeforeMount(() => {
+  emitter.off('clearTag')
+})
 
 NewTagsList.value = []
 
@@ -40,7 +58,7 @@ const checkedBox = (i: any, name: any, checked: any) => {
     checkedCount.forEach((item) => map.set(item, true))
     checkedCount = [...map.keys()]
   } else {
-    checkedCount.pop()
+    checkedCount.splice(checkedCount.indexOf(name), 1)
     TagsList.value[0].checked = false
     TagsList.value[i].checked = !TagsList.value[i].checked
   }
@@ -56,7 +74,7 @@ const checkedBox = (i: any, name: any, checked: any) => {
   } else {
     NewTagsList.value = checkedCount
   }
-  emits('changeTag', NewTagsList.value)
+  emits('changeTag', NewTagsList.value, true)
 }
 </script>
 
@@ -94,7 +112,6 @@ const checkedBox = (i: any, name: any, checked: any) => {
   flex-wrap: wrap;
 }
 .list {
-  margin-right: 16px;
   min-width: 93px;
   padding: 5.42px 16px;
   color: var(--color-neutral-2);
@@ -106,17 +123,17 @@ const checkedBox = (i: any, name: any, checked: any) => {
   border-radius: var(--border-radius-12);
 }
 .v-tag {
-  min-width: 36px;
+  min-width: 18px;
   font-size: var(--font-size-2);
   margin-left: 6px;
   border-radius: 6px;
-  padding: 3px;
+  padding: 3px 4px;
   text-align: center;
 }
 .v-tag__all {
   font-weight: 400;
-  background-color: var(--color-tag-all-bg);
-  color: var(--color-tag-all);
+  background-color: var(--color-tag-all-bg-color);
+  color: #e26394;
 }
 .v-tag__created {
   font-weight: 400;

+ 1 - 1
src/components/IconDropDown/src/IconDropDown.vue

@@ -13,6 +13,6 @@
 .iconfont_select {
   width: 17px;
   height: 17px;
-  fill: var(--color-btn-default-dark-bg);
+  fill: var(--color-neutral-1);
 }
 </style>

File diff suppressed because it is too large
+ 662 - 131
src/components/MoreFilters/src/MoreFilters.vue


+ 94 - 32
src/components/MoreFilters/src/components/SelectValue.vue

@@ -4,7 +4,6 @@ import type { DropdownInstance } from 'element-plus'
 
 interface ListItem {
   name: string
-  number: number
   checked: boolean
 }
 interface Props {
@@ -41,15 +40,6 @@ watch(
 
 const dropdown1 = ref<DropdownInstance>()
 let checkedCount: any[] = []
-const TotalAll = computed(() => {
-  var total_sum = 0
-  if (TransportList.value != undefined) {
-    TransportList.value.map((item) => {
-      total_sum += item.number
-    })
-  }
-  return total_sum
-})
 
 const handleCheckAllChange = (val: any) => {
   checkedCount = []
@@ -90,65 +80,99 @@ const clearList = () => {
 }
 const emit = defineEmits(['generalSearch'])
 const changedata = ref()
+const changedata2 = ref()
 //点击搜索
 const TransportSearch = (visible: any) => {
   if (checkedCount.length == TransportList.value.length) {
     changedata.value = 'All'
+    changedata2.value = 'All'
   } else {
     changedata.value = checkedCount.join(', ')
+    changedata2.value = checkedCount
   }
   const TransportData = {
     title: Title.value,
     data: changedata.value
   }
   Serval.value = changedata.value
-  emit('generalSearch', TransportData)
+  emit('generalSearch', TransportData, changedata2.value)
   if (!dropdown1.value) return
   if (visible) {
     dropdown1.value.handleClose()
   } else {
     dropdown1.value.handleOpen()
   }
+  checkedCount = []
+}
+const seeall = ref(false)
+const clickSeeAll = () => {
+  seeall.value = !seeall.value
 }
 </script>
 <template>
-  <div class="select">
-    <el-dropdown ref="dropdown1" trigger="click" :hide-on-click="false">
+  <div class="select" :class="{ isDisabled: TransportList.length == 0 }">
+    <el-dropdown
+      ref="dropdown1"
+      trigger="click"
+      :hide-on-click="false"
+      :disabled="TransportList.length == 0"
+    >
       <div class="el-dropdown-link">
-        <div v-if="Serval == 'Please Select Date Range' || Serval == ''" class="select_title">
+        <div
+          v-if="
+            props.title == 'Incoterms' && (Serval == 'Please Select Date Range' || Serval == '')
+          "
+          class="select_title"
+        >
           Please Select Date Range
         </div>
+        <div
+          v-else-if="
+            props.title == 'Service' && (Serval == 'Please Select Service' || Serval == '')
+          "
+          class="select_title"
+        >
+          Please Select Service
+        </div>
         <div v-else class="select_title_2">{{ Serval }}</div>
         <span class="iconfont_icon">
-          <svg class="iconfont" aria-hidden="true">
+          <svg class="iconfont icon_dark" aria-hidden="true">
             <use xlink:href="#icon-icon_dropdown_b"></use>
           </svg>
         </span>
       </div>
       <template #dropdown>
         <div class="dropdownwidth">
-          <div class="title">{{ Title }} {{ checkAll }}</div>
+          <div class="title">{{ Title }}</div>
           <el-dropdown-menu>
             <el-dropdown-item>
               <el-checkbox v-model="checkAll" class="checkbox" @change="handleCheckAllChange">
                 <div class="checkbox_title">Select All</div>
-                <div class="checkbox_number">({{ TotalAll }})</div>
               </el-checkbox>
             </el-dropdown-item>
             <el-divider></el-divider>
-            <el-dropdown-item v-for="(item, index) in TransportList" :key="index">
-              <el-checkbox
-                :value="item.name"
-                v-model="item.checked"
-                class="checkbox"
-                @change="handleCheckedTransportChange(item.name, item.checked, index)"
-              >
-                <div class="checkbox_title">
-                  {{ item.name }}
-                </div>
-                <div class="checkbox_number">({{ item.number }})</div>
-              </el-checkbox>
-            </el-dropdown-item>
+            <div class="inval" :class="{ seeall: seeall }">
+              <el-dropdown-item v-for="(item, index) in TransportList" :key="index">
+                <el-checkbox
+                  :value="item.name"
+                  v-model="item.checked"
+                  class="checkbox"
+                  @change="handleCheckedTransportChange(item.name, item.checked, index)"
+                >
+                  <div class="checkbox_title">
+                    {{ item.name }}
+                  </div>
+                </el-checkbox>
+              </el-dropdown-item>
+            </div>
+            <div class="See_all" @click="clickSeeAll">
+              <span class="iconfont_icon iconfont_icon_text" :class="{ transformTotal: seeall }">
+                <svg class="iconfont" aria-hidden="true">
+                  <use xlink:href="#icon-icon_dropdown__line_b"></use>
+                </svg>
+              </span>
+              See All
+            </div>
             <div class="transport_bottom">
               <div>
                 <el-button class="clear" type="default" @click="clearList">Reset</el-button>
@@ -174,13 +198,14 @@ const TransportSearch = (visible: any) => {
 .select {
   cursor: pointer;
   width: 368px;
-  height: 40px;
+  height: 32px;
   display: flex;
   align-items: center;
   justify-content: space-between;
   background-color: white;
-  border: 1px solid var(--color-border);
+  border: 1px solid var(--color-select-border);
   border-radius: var(--border-radius-6);
+  background-color: transparent;
 }
 .select:hover {
   border: 1px solid var(--color-theme);
@@ -280,4 +305,41 @@ const TransportSearch = (visible: any) => {
   margin: 8px 0;
   border-top-color: var(--color-border);
 }
+.See_all {
+  width: 60px;
+  height: 24px;
+  border-radius: 3px;
+  color: var(--color-theme);
+  margin: 0 16px;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+}
+.See_all:hover {
+  background-color: var(--color-btn-default-bg-hover);
+}
+.iconfont_icon_text {
+  margin-right: 2px;
+  fill: var(--color-theme);
+}
+.transformTotal {
+  transform: rotate(-180deg);
+}
+.inval {
+  max-height: 100px;
+  overflow-y: clip;
+}
+.seeall {
+  max-height: 426px;
+  overflow: scroll;
+}
+.isDisabled {
+  background-color: var(--input-disabled-bg-color);
+  color: #a8abb2;
+  cursor: not-allowed;
+  box-shadow: none !important;
+}
+.isDisabled:hover {
+  border-color: var(--color-border);
+}
 </style>

+ 14 - 4
src/components/ScoringGrade/components/DialogColorful.vue

@@ -1,5 +1,8 @@
 <script setup lang="ts">
 import { ref } from 'vue'
+import { useThemeStore } from '@/stores/modules/theme'
+import BubbleLight from '../image/bubble_corner_colorful.png'
+import BubbleDark from '../image/bubble_corner_colorful_darkmode.png'
 const props = defineProps({
   colorfulSrc: String,
   isshowexpression: Boolean,
@@ -10,6 +13,7 @@ const emits = defineEmits(['submitDetails'])
 const submitDetails = (val: any) => {
   emits('submitDetails', val)
 }
+const themeStore = useThemeStore()
 </script>
 <template>
   <div class="colorfulflex">
@@ -18,7 +22,7 @@ const submitDetails = (val: any) => {
         <img :src="props.colorfulSrc" />
       </div>
       <div class="vector">
-        <img class="vector_img" src="/src/styles/images/bubble_corner_colorful.png" />
+        <img class="vector_img" :src="themeStore.theme == 'light' ? BubbleLight : BubbleDark" />
       </div>
     </div>
     <div v-if="props.isshowDetails" class="dialogcolorful submit">
@@ -29,7 +33,7 @@ const submitDetails = (val: any) => {
           style="width: 554px"
           :rows="4"
           type="textarea"
-          placeholder="We look forward to hearing from you.  thank you for helping to build a better customer system"
+          placeholder="We look forward to hearing from you. Thank you for helping to build a better customer system."
         />
         <div class="button_submit">
           <el-button class="submit_button el-button--dark" @click="submitDetails(inputdetails)"
@@ -38,7 +42,7 @@ const submitDetails = (val: any) => {
         </div>
       </div>
       <div class="vector vector_submit">
-        <img class="vector_img" src="/src/styles/images/bubble_corner_colorful.png" />
+        <img class="vector_img" :src="themeStore.theme == 'light' ? BubbleLight : BubbleDark" />
       </div>
     </div>
   </div>
@@ -62,7 +66,7 @@ const submitDetails = (val: any) => {
   color: var(--tag-info-text-color);
   font-size: var(--font-size-4);
   border-radius: var(--border-radius-12) var(--border-radius-12) 0 var(--border-radius-12);
-  background: linear-gradient(251deg, rgba(242, 244, 247) 0%, rgba(255, 237, 230) 100%);
+  background: var(--scoring-colurful-color);
   padding: 8px;
   width: 56px;
   height: 56px;
@@ -91,6 +95,7 @@ const submitDetails = (val: any) => {
   .el-textarea__inner {
     resize: none; // 去除右下角图标
     padding: 5px 7px 5px 10px;
+    box-shadow: 0 0 0 1px var(--color-select-border) inset;
   }
 }
 .submit_button {
@@ -108,4 +113,9 @@ const submitDetails = (val: any) => {
   font-weight: 400;
   font-size: var(--font-size-3);
 }
+.inputdetails {
+  background-color: var(--management-bg-color);
+  border-radius: 6px;
+  border-color: var(--color-select-border);
+}
 </style>

+ 51 - 19
src/components/ScoringGrade/components/DialogUe.vue

@@ -1,23 +1,38 @@
 <script setup lang="ts">
 import { ref } from 'vue'
+import { useThemeStore } from '@/stores/modules/theme'
+import BubbleLight from '../image/bubble_corner.png'
+import BubbleDark from '../image/bubble_corner_darkmode.png'
 
 const props = defineProps({
   content: String,
   dialogWidth: String,
   isShowAngry: Boolean,
-  isShowSmile: Boolean
+  isShowSmile: Boolean,
+  isShowHappy: Boolean
 })
 const checkboxGroup1 = ref([])
+const checkboxGroup2 = ref([])
 const evaluate = [
-  'Complete funtionality',
-  'Accurate information',
-  'Visualization of shipments',
-  'Easy to use',
-  'Performance'
+  'Functionality',
+  'Data accuracy',
+  'Look and feel',
+  'Ease of use',
+  'Website performance'
 ]
-const emits = defineEmits(['changeAngryDetails', 'changeSmileRadio'])
+const happyevaluate = [
+  'Functionality',
+  'Data accuracy',
+  'Look and feel',
+  'Ease of use',
+  'Website performance'
+]
+const emits = defineEmits(['changeAngryDetails', 'changeSmileRadio', 'changeHappybuttonbox'])
 const changebuttonbox = () => {
-  emits('changeAngryDetails')
+  emits('changeAngryDetails', checkboxGroup1.value)
+}
+const changeHappybuttonbox = () => {
+  emits('changeHappybuttonbox', checkboxGroup2.value)
 }
 const Aspects = ref([
   'Highly Dissatisfied',
@@ -35,27 +50,27 @@ interface smileAspectsItem {
 const smileAspects = ref<smileAspectsItem[]>([])
 smileAspects.value = [
   {
-    title: 'Complete funtionality',
+    title: 'Functionality',
     proposal: ['Highly Dissatisfied', 'Dissatisfied', 'Neutral', 'Satisfied', 'Highly Satisfied'],
     radio: ''
   },
   {
-    title: 'Accurate information',
+    title: 'Data accuracy',
     proposal: ['Highly Dissatisfied', 'Dissatisfied', 'Neutral', 'Satisfied', 'Highly Satisfied'],
     radio: ''
   },
   {
-    title: 'Visualization of shipments',
+    title: 'Look and feel',
     proposal: ['Highly Dissatisfied', 'Dissatisfied', 'Neutral', 'Satisfied', 'Highly Satisfied'],
     radio: ''
   },
   {
-    title: 'Easy to use',
+    title: 'Ease of use',
     proposal: ['Highly Dissatisfied', 'Dissatisfied', 'Neutral', 'Satisfied', 'Highly Satisfied'],
     radio: ''
   },
   {
-    title: 'Performance',
+    title: 'Website performance',
     proposal: ['Highly Dissatisfied', 'Dissatisfied', 'Neutral', 'Satisfied', 'Highly Satisfied'],
     radio: ''
   }
@@ -65,6 +80,7 @@ const changeSmileRadio = (title: any, value: any) => {
   SmileObj[title] = value
   emits('changeSmileRadio', SmileObj)
 }
+const themeStore = useThemeStore()
 </script>
 <template>
   <div style="margin-bottom: 8px">
@@ -82,6 +98,18 @@ const changeSmileRadio = (title: any, value: any) => {
           </el-checkbox-button>
         </el-checkbox-group>
       </div>
+      <div v-if="props.isShowHappy" class="dialogflex">
+        <el-checkbox-group v-model="checkboxGroup2" size="large">
+          <el-checkbox-button
+            @change="changeHappybuttonbox"
+            v-for="item in happyevaluate"
+            :key="item"
+            :value="item"
+          >
+            {{ item }}
+          </el-checkbox-button>
+        </el-checkbox-group>
+      </div>
       <div v-if="props.isShowSmile">
         <div class="smile_flex">
           <div class="smile_title_left"></div>
@@ -106,7 +134,9 @@ const changeSmileRadio = (title: any, value: any) => {
         </div>
       </div>
     </div>
-    <div class="vector"><img class="vector_img" src="/src/styles/images/bubble_corner.png" /></div>
+    <div class="vector">
+      <img class="vector_img" :src="themeStore.theme == 'light' ? BubbleLight : BubbleDark" />
+    </div>
   </div>
 </template>
 <style lang="scss" scoped>
@@ -118,7 +148,7 @@ const changeSmileRadio = (title: any, value: any) => {
   color: var(--tag-info-text-color);
   font-size: var(--font-size-4);
   border-radius: var(--border-radius-12) var(--border-radius-12) var(--border-radius-12) 0;
-  background-color: #f2f4f7;
+  background-color: var(--scoring-bg-color);
   padding: 8px;
 }
 .vector {
@@ -130,6 +160,7 @@ const changeSmileRadio = (title: any, value: any) => {
 :deep(.el-checkbox-button__inner) {
   color: var(--tag-info-text-color);
   font-size: var(--font-size-3);
+  background-color: var(--management-bg-color);
   font-weight: 400;
   padding: 0;
   width: 180px;
@@ -137,7 +168,7 @@ const changeSmileRadio = (title: any, value: any) => {
   display: flex;
   align-items: center;
   justify-content: center;
-  border: 1px solid var(--color-border);
+  border: 1px solid var(--color-select-border);
   border-radius: var(--border-radius-6);
   margin-bottom: 8px;
 }
@@ -150,7 +181,7 @@ const changeSmileRadio = (title: any, value: any) => {
   border-color: transparent;
 }
 :deep(.el-checkbox-button:first-child .el-checkbox-button__inner) {
-  border-left: 1px solid var(--color-border);
+  border-left: 1px solid var(--color-select-border);
   border-top-left-radius: var(--border-radius-6);
   border-bottom-left-radius: var(--border-radius-6);
 }
@@ -195,8 +226,9 @@ const changeSmileRadio = (title: any, value: any) => {
 }
 .content_left {
   height: 41px;
-  background-color: #fff;
+  background-color: var(--management-bg-color);
   font-weight: 400;
+  border: 1px solid var(--color-select-border);
   font-size: var(--font-size-3);
   border-radius: 6px 0 0 6px;
   display: flex;
@@ -209,7 +241,7 @@ const changeSmileRadio = (title: any, value: any) => {
   justify-content: center;
 }
 .content_right {
-  background-color: #e0e2e6;
+  background-color: var(--scoring-smile-radio-color);
   border-radius: 0 6px 6px 0;
 }
 .el-radio {

二進制
src/components/ScoringGrade/image/Vector.png


二進制
src/components/ScoringGrade/image/angry_2.png


二進制
src/components/ScoringGrade/image/bubble_corner.png


二進制
src/components/ScoringGrade/image/bubble_corner@2x.png


二進制
src/components/ScoringGrade/image/bubble_corner_colorful.png


二進制
src/components/ScoringGrade/image/bubble_corner_colorful@2x.png


二進制
src/components/ScoringGrade/image/bubble_corner_colorful_darkmode.png


二進制
src/components/ScoringGrade/image/bubble_corner_darkmode.png


二進制
src/components/ScoringGrade/image/dashboard_scoring.png


二進制
src/components/ScoringGrade/image/happy_2.png


二進制
src/components/ScoringGrade/image/hhh_2.png


二進制
src/components/ScoringGrade/image/sad_2.png


二進制
src/components/ScoringGrade/image/score_angry.png


二進制
src/components/ScoringGrade/image/score_happy.png


二進制
src/components/ScoringGrade/image/score_hhh.png


二進制
src/components/ScoringGrade/image/score_normal.png


二進制
src/components/ScoringGrade/image/score_sad.png


二進制
src/components/ScoringGrade/image/score_smile.png


二進制
src/components/ScoringGrade/image/smile_2.png


二進制
src/components/ScoringGrade/image/submit_successful.png


+ 231 - 61
src/components/ScoringGrade/src/ScoringGrade.vue

@@ -2,11 +2,24 @@
 import { ref } from 'vue'
 import DialogUe from '../components/DialogUe.vue'
 import DialogColorful from '../components/DialogColorful.vue'
+import angryPng from '../image/score_angry.png'
+import angryPng2 from '../image/angry_2.png'
+import sadPng from '../image/score_sad.png'
+import sadPng2 from '../image/sad_2.png'
+import smilePng from '../image/score_smile.png'
+import smilePng2 from '../image/smile_2.png'
+import hhhPng from '../image/score_hhh.png'
+import hhhPng2 from '../image/hhh_2.png'
+import happyPng from '../image/score_happy.png'
+import happyPng2 from '../image/happy_2.png'
+import normalPng from '../image/score_normal.png'
+import submitsucessful from '../image/submit_successful.png'
 
-const isShow = ref(true)
+// const isShow = ref(true)
 const visible = ref(false)
 const isLoaded = ref(false)
 const isShowAngry = ref(false)
+const isShowHappy = ref(false)
 const isShowSmile = ref(false)
 const isLoaded_share = ref(false)
 const isshowexpression = ref(true)
@@ -15,6 +28,7 @@ const isshowDetails_submit = ref(false)
 const isshowDetails = ref(true)
 interface AvaterItem {
   src: string
+  src1: string
   itemsrc: string
   itemtext: string
   expression: string
@@ -25,39 +39,44 @@ const colorfulSrc = ref()
 const dialogcontent = ref()
 const angryproposal = ref()
 const smileproposal = ref()
-const clickSrc = ref('/src/styles/images/score_normal.png')
+const clickSrc = ref(normalPng)
 avater.value = [
   {
-    src: '/src/styles/images/score_angry.png',
-    itemsrc: '/src/styles/images/angry_2.png',
+    src: angryPng,
+    src1: angryPng,
+    itemsrc: angryPng2,
     itemtext: 'We are so sorry for the inconveniences. We value your experience immensely. ',
     expression: 'angry',
     proposal: 'Could you please tell us which aspects of the system you are dissatisfied with?'
   },
   {
-    src: '/src/styles/images/score_sad.png',
-    itemsrc: '/src/styles/images/sad_2.png',
+    src: sadPng,
+    src1: sadPng,
+    itemsrc: sadPng2,
     itemtext: 'We are so sorry for the inconveniences. We value your experience immensely. ',
-    expression: 'angry',
+    expression: 'sad',
     proposal: 'Could you please tell us which aspects of the system you are dissatisfied with?'
   },
   {
-    src: '/src/styles/images/score_smile.png',
-    itemsrc: '/src/styles/images/smile_2.png',
+    src: smilePng,
+    src1: smilePng,
+    itemsrc: smilePng2,
     itemtext: 'Thank you for sharing your thoughts with us. We value your experience greatly.',
     expression: 'smile',
     proposal: 'Could you share what aspects you liked and what could be improved ?'
   },
   {
-    src: '/src/styles/images/score_hhh.png',
-    itemsrc: '/src/styles/images/hhh_2.png',
+    src: hhhPng,
+    src1: hhhPng,
+    itemsrc: hhhPng2,
     itemtext: 'Thank you very much for giving us a satisfied rating on our service or system.',
-    expression: 'happy',
+    expression: 'hhh',
     proposal: 'We are curious to learn more about what specifically made you feel satisfied. '
   },
   {
-    src: '/src/styles/images/score_happy.png',
-    itemsrc: '/src/styles/images/happy_2.png',
+    src: happyPng,
+    src1: happyPng,
+    itemsrc: happyPng2,
     itemtext: 'Thank you very much for giving us a satisfied rating on our service or system.',
     expression: 'happy',
     proposal: 'We are curious to learn more about what specifically made you feel satisfied. '
@@ -66,76 +85,195 @@ avater.value = [
 const dialogVisible = ref(false)
 
 // 控制表情normal的显隐
-const showPopver = () => {
-  isShow.value = false
-}
+// const showPopver = () => {
+//   isShow.value = false
+// }
 // 控制popover的显隐
+const checkexpression = ref()
 const showScore = (item: any) => {
   visible.value = false
   dialogVisible.value = true
   clickSrc.value = item.itemsrc
-  isShow.value = true
+  // isShow.value = true
   colorfulSrc.value = item.itemsrc
   setTimeout(() => {
     isLoaded.value = true
     dialogcontent.value = item.itemtext
     if (item.expression == 'angry') {
+      SubmitText.value = 'Apologize once again for your experience.'
+      checkexpression.value = 'angry'
       setTimeout(() => {
         isShowAngry.value = true
         angryproposal.value = item.proposal
-      }, 1500)
+      }, 1000)
+    } else if (item.expression == 'sad') {
+      SubmitText.value = 'Apologize once again for your experience.'
+      checkexpression.value = 'sad'
+      setTimeout(() => {
+        isShowAngry.value = true
+        angryproposal.value = item.proposal
+      }, 1000)
     } else if (item.expression == 'smile') {
+      SubmitText.value = 'We greatly appreciate your valuable time and feedback.'
+      checkexpression.value = 'smile'
       setTimeout(() => {
         isShowSmile.value = true
         smileproposal.value = item.proposal
-      }, 1500)
-    } else {
+      }, 1000)
+    } else if (item.expression == 'hhh') {
+      SubmitText.value = 'Once again, thank you for your positive evaluation.'
+      checkexpression.value = 'hhh'
       setTimeout(() => {
-        isShowAngry.value = true
+        isShowHappy.value = true
+        angryproposal.value = item.proposal
+      }, 1000)
+    } else if (item.expression == 'happy') {
+      SubmitText.value = 'Once again, thank you for your positive evaluation.'
+      checkexpression.value = 'happy'
+      setTimeout(() => {
+        isShowHappy.value = true
         angryproposal.value = item.proposal
-      }, 1500)
+      }, 1000)
     }
   }, 1000)
 }
 const avatarClick = () => {
-  visible.value = true
+  visible.value = !visible.value
   isshowDetails.value = true
 }
 //关闭对话框后,隐藏有动画的对话框
 const closeDialog = () => {
-  isLoaded.value = false
-  isLoaded.value = false
-  isLoaded_share.value = false
-  isShowAngry.value = false
-  isshowDetails.value = false
-  isShowSmile.value = false
-  isshowexpression_details.value = false
+  setTimeout(() => {
+    isLoaded.value = false
+    isLoaded_share.value = false
+    isShowAngry.value = false
+    isShowHappy.value = false
+    isShowSmile.value = false
+    isshowexpression_details.value = false
+    isshowDetails_submit.value = false
+    smileCheckbox.value = {}
+    angryCheckbox.value = []
+    happyCheckbox.value = []
+  }, 1500)
 }
 //生气表情,选择建议后显示对话
-const changeAngryDetails = () => {
+const angryCheckbox = ref([])
+const happyCheckbox = ref([])
+const smileCheckbox = ref()
+const changeAngryDetails = (val: any) => {
+  angryCheckbox.value = val
   setTimeout(() => {
     isLoaded_share.value = true
     setTimeout(() => {
       isshowexpression_details.value = true
-    }, 1500)
-  }, 1500)
+      setTimeout(() => {
+        document.getElementById('moreMerchant').scrollIntoView()
+      }, 200)
+    }, 1000)
+  }, 500)
+}
+//开心表情,选择建议后显示对话
+const changeHappybuttonbox = (val: any) => {
+  happyCheckbox.value = val
+  setTimeout(() => {
+    isLoaded_share.value = true
+    setTimeout(() => {
+      isshowexpression_details.value = true
+      setTimeout(() => {
+        document.getElementById('moreMerchant').scrollIntoView()
+      }, 200)
+    }, 1000)
+  }, 500)
 }
 // smile提交后显示对话
 const changeSmileRadio = (val: any) => {
+  smileCheckbox.value = val
   if (Object.keys(val).length == 5) {
-    changeAngryDetails()
+    setTimeout(() => {
+      isLoaded_share.value = true
+      setTimeout(() => {
+        isshowexpression_details.value = true
+        setTimeout(() => {
+          document.getElementById('moreMerchant').scrollIntoView()
+        }, 200)
+      }, 1000)
+    }, 500)
   }
 }
 // 提交details
 const submitDetails = (val: any) => {
-  console.log(val)
-  isshowDetails_submit.value = true
+  const username = localStorage.getItem('account') ? localStorage.getItem('account') : ''
+  if (angryCheckbox.value.length) {
+    $api
+      .scoringgrade({
+        suggestion: angryCheckbox.value,
+        proposal: val,
+        expression: checkexpression.value,
+        username: username
+      })
+      .then((res: any) => {
+        if (res.code == 200) {
+          isshowDetails.value = false
+          isshowDetails_submit.value = true
+          setTimeout(() => {
+            isshowDetails_submit.value = false
+            dialogVisible.value = false
+          }, 3000)
+        }
+      })
+  } else if (happyCheckbox.value.length) {
+    $api
+      .scoringgrade({
+        suggestion: happyCheckbox.value,
+        proposal: val,
+        expression: checkexpression.value
+      })
+      .then((res: any) => {
+        if (res.code == 200) {
+          isshowDetails.value = false
+          isshowDetails_submit.value = true
+          setTimeout(() => {
+            isshowDetails_submit.value = false
+            dialogVisible.value = false
+          }, 3000)
+        }
+      })
+  } else {
+    let obj: any = {}
+    obj.Complete_funtionality = smileCheckbox.value['Complete funtionality']
+    obj.Accurate_data = smileCheckbox.value['Accurate data']
+    obj.Clear_information = smileCheckbox.value['Clear information']
+    obj.Easy_to_use = smileCheckbox.value['Easy to use']
+    obj.System_Performance = smileCheckbox.value['System Performance']
+    $api
+      .scoringgrade({
+        proposal: val,
+        expression: checkexpression.value,
+        ...obj
+      })
+      .then((res: any) => {
+        if (res.code == 200) {
+          isshowDetails.value = false
+          isshowDetails_submit.value = true
+          setTimeout(() => {
+            isshowDetails_submit.value = false
+            dialogVisible.value = false
+          }, 3000)
+        }
+      })
+  }
+}
+const mouseenter = (item: any) => {
+  item.src = item.itemsrc
 }
+const mouseout = (item: any) => {
+  item.src = item.src1
+}
+const SubmitText = ref()
 </script>
 <template>
-  <div class="scoring" :style="[{ display: isShow ? 'flex' : 'none' }]">
+  <div class="scoring">
     <el-popover
-      @show="showPopver"
       :visible="visible"
       placement="left"
       trigger="click"
@@ -143,26 +281,28 @@ const submitDetails = (val: any) => {
       popper-class="popver_class"
     >
       <template #reference>
-        <el-avatar
-          @click="avatarClick"
-          :style="[{ display: isShow ? 'block' : 'none' }]"
-          :size="46"
-          shape="square"
-          :src="clickSrc"
-        />
+        <el-avatar @click="avatarClick" :size="46" shape="square" :src="clickSrc" />
       </template>
-      <div class="flex">
+      <div class="score_flex">
         <el-popover
           placement="top"
-          :width="260"
+          :width="276"
           trigger="hover"
           v-for="(item, index) in avater"
           :key="index"
+          popper-class="avater_popver"
           content="How satisfied are you with this system?"
         >
           <template #reference>
             <div class="score">
-              <el-avatar @click="showScore(item)" :size="40" shape="square" :src="item.src" />
+              <el-avatar
+                @mouseenter="mouseenter(item)"
+                @mouseout="mouseout(item)"
+                @click="showScore(item)"
+                :size="40"
+                shape="square"
+                :src="item.src"
+              />
             </div>
           </template>
         </el-popover>
@@ -170,7 +310,7 @@ const submitDetails = (val: any) => {
     </el-popover>
     <el-dialog
       v-model="dialogVisible"
-      title="Hi,Caroline!"
+      title="Hi!"
       :destroy-on-close="true"
       @close="closeDialog"
       width="640"
@@ -197,6 +337,14 @@ const submitDetails = (val: any) => {
             dialogWidth="573px"
           ></DialogUe>
         </transition>
+        <transition name="fade" v-if="isShowHappy">
+          <DialogUe
+            :content="angryproposal"
+            :isShowHappy="isShowHappy"
+            @changeHappybuttonbox="changeHappybuttonbox"
+            dialogWidth="573px"
+          ></DialogUe>
+        </transition>
         <transition name="fade" v-if="isShowSmile">
           <DialogUe
             :isShowSmile="isShowSmile"
@@ -211,7 +359,7 @@ const submitDetails = (val: any) => {
             dialogWidth="334px"
           ></DialogUe>
         </transition>
-        <transition name="fade" v-if="isshowexpression_details">
+        <transition name="fade" id="moreMerchant" v-if="isshowexpression_details">
           <DialogColorful
             :isshowDetails="isshowexpression_details"
             @submitDetails="submitDetails"
@@ -225,10 +373,10 @@ const submitDetails = (val: any) => {
         title="Submit Successful"
       >
         <template #icon>
-          <el-image src="/src/styles/images/submit_successful.png" />
+          <el-image :src="submitsucessful" />
         </template>
         <template #sub-title>
-          <div class="sub_title_text">Apologize once again for your experience.</div>
+          <div class="sub_title_text">{{ SubmitText }}</div>
           <div class="sub_title_text">
             We are committed to working hard to provide better services.
           </div>
@@ -243,23 +391,29 @@ const submitDetails = (val: any) => {
   width: 64px;
   height: 64px;
   border-radius: 12px 0 0 12px;
-  background-color: #fff;
+  background-color: var(--management-bg-color);
   position: absolute;
+  box-shadow: -2px 2px 12px rgba(0, 0, 0, 15%);
   z-index: 2013;
   right: 0;
-  bottom: 168px;
+  bottom: 80px;
   display: flex;
   align-items: center;
   justify-content: center;
 }
 .el-avatar {
-  background-color: #fff;
+  background-color: var(--management-bg-color);
   cursor: pointer;
 }
-.flex {
+.score_flex {
   display: flex;
   height: 64px;
   align-items: center;
+  position: absolute;
+  right: 64px;
+  top: -30px;
+  background-color: var(--management-bg-color);
+  border-radius: 12px 0 0 12px;
 }
 .score {
   margin: 0 16px;
@@ -269,16 +423,25 @@ const submitDetails = (val: any) => {
   box-shadow: none;
   filter: drop-shadow(-2px 2px 12px rgba(0, 0, 0, 0.15));
   right: 0 !important;
+  height: 0;
+  background: transparent;
+  z-index: 2013 !important;
+  border: none;
+}
+:deep(.scoreDialog) {
+  background-color: var(--management-bg-color);
 }
 .el-dialog.scoreDialog {
   position: absolute;
   margin-bottom: 0;
   right: 0;
-  bottom: 168px;
+  bottom: 60px;
+  max-height: 640px;
+  overflow-y: scroll;
 }
 .fade-enter-active,
 .fade-leave-active {
-  transition: opacity 3s;
+  transition: opacity 1s;
 }
 .fade-enter-from,
 .fade-leave-to {
@@ -286,8 +449,15 @@ const submitDetails = (val: any) => {
 }
 .sub_title_text {
   color: var(--color-neutral-3);
+  font-size: 14px;
+  line-height: 21px;
 }
 .result {
-  height: 578px;
+  height: 560px;
+  padding: 0;
+}
+.avater_popver {
+  padding-left: 8px !important;
+  color: var(--color-neutral-1) !important;
 }
-</style>
+</style>

+ 34 - 12
src/components/SelectTable/src/SelectTable.vue

@@ -20,6 +20,21 @@ const props = defineProps({
   keyVal: {
     type: String,
     default: 'city'
+  },
+  isError: {
+    type: Boolean,
+    default: false
+  },
+  ASSearchMode: {
+    type: String,
+    default: ''
+  },
+  ASSearchFiled: {
+    type: String,
+    default: ''
+  },
+  ASSearchObj: {
+    type: Object
   }
 })
 
@@ -74,7 +89,10 @@ const handleSearch = _.debounce((val?) => {
         term: searchVal.value ? searchVal.value : '',
         cp: state.currentPage,
         ps: state.pageSize,
-        rc: '-1'
+        rc: '-1',
+        search_field: props.ASSearchFiled,
+        search_mode: props.ASSearchMode,
+        ...props.ASSearchObj
       })
       .then((res: any) => {
         if (res.code == 200) {
@@ -104,7 +122,10 @@ const handleCurrentChange = () => {
         term: searchVal.value ? searchVal.value : '',
         cp: state.currentPage,
         ps: state.pageSize,
-        rc: state.total
+        rc: state.total,
+        search_field: props.ASSearchFiled,
+        search_mode: props.ASSearchMode,
+        ...props.ASSearchObj
       })
       .then((res: any) => {
         if (res.code == 200) {
@@ -148,6 +169,7 @@ const onInput = () => {
         <div
           class="el-input el-input--suffix el-tooltip__trigger"
           @click="disabled ? null : onInput"
+          :class="{ is_error: props.isError }"
         >
           <div class="el-input__wrapper" :class="{ 'is-disabled': disabled }">
             <el-space :class="[innerTags.length ? 'custom-el-spaceno' : 'custom-el-space']">
@@ -275,7 +297,7 @@ const onInput = () => {
 
 :deep(.el-table__row:not(.current-row):hover) {
   td {
-    background-color: #fff1e6 !important;
+    background-color: var(--color-btn-default-bg-hover) !important;
   }
 }
 
@@ -291,7 +313,7 @@ const onInput = () => {
   height: 40px;
   justify-content: space-between;
   padding: 0 12px 0 8px;
-
+  background-color: var(--color-mode);
   > span {
     font-size: 13px;
   }
@@ -301,12 +323,6 @@ const onInput = () => {
   border-radius: 12px !important;
 }
 
-:deep(.el-pagination) {
-  .is-active {
-    color: #b57b32 !important;
-  }
-}
-
 :deep(.el-table--fit) {
   border-top-left-radius: 12px;
   border-top-right-radius: 12px;
@@ -317,8 +333,8 @@ const onInput = () => {
 }
 
 .is-disabled {
-  background-color: #f5f7fa;
-  color: #a8abb2;
+  background-color: var(--input-disabled-bg-color);
+  color: var(--input-disabled-text-color);
   cursor: not-allowed;
   box-shadow: none !important;
 }
@@ -338,4 +354,10 @@ const onInput = () => {
 :deep(.custom-el-space .el-space__item) {
   width: 100%;
 }
+
+.is_error {
+  :deep(.el-input__wrapper) {
+    box-shadow: 0 0 0 0.5px var(--color-danger) !important;
+  }
+}
 </style>

+ 30 - 13
src/components/SelectTableSelect/src/SelectTableSelect.vue

@@ -1,13 +1,11 @@
 <script setup lang="ts">
 import { ref, watch } from 'vue'
 import IconDropDown from '@/components/IconDropDown'
-import VerrifyInformation from '@/components/VerrifyInformation'
 import SelectTable from '@/components/SelectTable'
 
 interface TypeItem {
   placesType: ''
   placesname: []
-  isshowVerfication: boolean
 }
 interface dateoptions {
   value: string
@@ -17,8 +15,9 @@ interface Props {
   AddDateType: TypeItem[]
   ASPlaceholder: string
   DateTypeoptions: dateoptions[]
-  Verification: string
   selectedPartyTypeoptions: Array<string>
+  TablesearchTableQeury: Object
+  TablesearchMode: String
 }
 interface optionsItem {
   value: string
@@ -74,10 +73,16 @@ const changeSelect = (val: any) => {
 }
 // 选中name改变
 const emit = defineEmits(['changeAutoSelectAddType', 'delSelect', 'changeAutoSelect'])
+const errorBoolean = ref(false)
 let AutoSelectObj: any = {}
 const changeAutoSelect = (val: any, value: any) => {
-  AutoSelectObj[val] = value.join()
-  emit('changeAutoSelect', AutoSelectObj)
+  if (value.length) {
+    errorBoolean.value = true
+  } else {
+    errorBoolean.value = false
+  }
+  AutoSelectObj[val] = value
+  emit('changeAutoSelect', AutoSelectObj, errorBoolean.value)
 }
 const typeSelectFocus = (index: any, e: any) => {
   typeSelectIndex.value = index
@@ -168,20 +173,30 @@ const checkdestination = (row: any, index: any) => {
     <div style="margin-top: 16px">
       <div class="ETD_title">Places Details</div>
       <SelectTable
+        :ASSearchFiled="AddType[index].placesType"
+        :ASSearchObj="props.TablesearchTableQeury"
+        :ASSearchMode="props.TablesearchMode"
         :key-val="
-          AddType[index].placesType && AddType[index].placesType === 'Port of Loading'
+          AddType[index].placesType &&
+          (AddType[index].placesType === 'Port of Loading' ||
+            AddType[index].placesType === 'Port of Discharge')
             ? 'uncode'
             : 'city'
         "
+        :is-error="
+          AddType[index].placesType != '' && AddType[index].placesname.length == 0 ? true : false
+        "
         :disabled="AddType[index].placesType ? false : true"
         :searchInput="AddType[index].placesname"
         @check="(row) => checkdestination(row, index)"
       />
-      <VerrifyInformation
-        :isshowVerfication="AddDateType[index]?.isshowVerfication"
-        :verification="props.Verification"
+
+      <div
+        class="error"
+        v-if="AddType[index].placesType != '' && AddType[index].placesname.length == 0"
       >
-      </VerrifyInformation>
+        Please Input Places Details
+      </div>
     </div>
   </div>
 </template>
@@ -233,8 +248,10 @@ const checkdestination = (row: any, index: any) => {
     color: var(--badge__content--warning);
   }
 }
-
-.AlertInput :deep(.el-select__wrapper) {
-  box-shadow: 0 0 0 0.5px var(--color-danger);
+.error {
+  font-size: 12px;
+  color: var(--color-danger);
+  line-height: 14px;
+  margin-top: 5px;
 }
 </style>

+ 32 - 12
src/components/ShipmentStatus/src/ShipmentStatus.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
 import dayjs from 'dayjs'
+import { useOverflow } from '@/hooks/useOverflow'
 
 const props = defineProps({
   data: Object
@@ -36,6 +37,10 @@ const getDateHeight = (index: number) => {
 const formatDate = (date: string) => {
   return date ? dayjs(date).format('MMM-DD-YYYY') : '--'
 }
+
+const pathRef = ref()
+
+const { isOverflow: isPathOverflow } = useOverflow(pathRef, props)
 </script>
 
 <template>
@@ -45,7 +50,7 @@ const formatDate = (date: string) => {
       :class="{
         last: !stepItem.isArrival
       }"
-      v-for="stepItem in simplexData"
+      v-for="(stepItem, index) in simplexData"
       :key="stepItem.index"
     >
       <div class="data">
@@ -53,7 +58,14 @@ const formatDate = (date: string) => {
         <div class="right-info">
           <div class="path">
             <div class="label">{{ stepItem.label }}</div>
-            <div class="detail-path">{{ stepItem.path }}</div>
+            <el-tooltip v-if="isPathOverflow?.[index]" placement="top">
+              <template #content>{{ stepItem.path }}</template>
+
+              <div ref="pathRef" class="detail-path single-line-ellipsis">{{ stepItem.path }}</div>
+            </el-tooltip>
+            <div v-else ref="pathRef" class="detail-path single-line-ellipsis">
+              {{ stepItem.path }}
+            </div>
           </div>
           <div
             class="transport-info"
@@ -81,7 +93,7 @@ const formatDate = (date: string) => {
 // 单式样式
 .simplex-content {
   width: 100%;
-  padding: 8px 0 9px;
+  padding: 24px 8px 9px 16px;
 }
 .detail-step-item {
   & > .data {
@@ -99,7 +111,7 @@ const formatDate = (date: string) => {
       font-weight: 700;
       text-align: center;
       line-height: 16px;
-      color: #fff;
+      color: var(--color-mode);
     }
     .right-info {
       flex: 1;
@@ -131,7 +143,7 @@ const formatDate = (date: string) => {
         .label {
           // width: 96px;
           background-color: var(--color-neutral-1);
-          color: #fff;
+          color: var(--color-mode);
           font-weight: 500;
           font-size: 12px;
           border-radius: 3px 0 0 3px;
@@ -139,7 +151,7 @@ const formatDate = (date: string) => {
         .detail-path {
           flex: 1;
           width: 252px;
-          background-color: #fff;
+          background-color: transparent;
           font-weight: 700;
           color: var(--color-neutral-1);
           border: 1px solid #bfc1c3;
@@ -178,21 +190,22 @@ const formatDate = (date: string) => {
   &.last {
     & > .data {
       .left-step-icon {
-        background-color: #ccd1db;
+        background-color: var(--color-shipment-status-label-bg);
       }
       .right-info {
         .step-dot {
-          background-color: #ccd1db;
+          background-color: var(--color-shipment-status-label-bg);
         }
         .path {
           .label {
-            background-color: #ccd1db;
+            background-color: var(--color-shipment-status-label-bg);
 
-            font-weight: 600;
-            color: var(--color-neutral-1);
+            font-weight: 500;
+            color: var(--color-shipment-status-label-font-color);
           }
           .detail-path {
-            border-color: #ccd1db;
+            color: var(--color-shipment-status-detail-path-font-color);
+            border-color: var(--color-shipment-status-label-bg);
           }
         }
       }
@@ -202,4 +215,11 @@ const formatDate = (date: string) => {
     }
   }
 }
+.single-line-ellipsis {
+  height: 18px;
+  display: inline-block; /* 或者根据需要使用 inline-block */
+  white-space: nowrap; /* 不换行 */
+  overflow: hidden; /* 隐藏超出部分 */
+  text-overflow: ellipsis; /* 超出部分显示省略号 */
+}
 </style>

+ 120 - 22
src/components/TransportMode/src/TransportMode.vue

@@ -5,19 +5,33 @@ import emitter from '@/utils/bus'
 
 interface ListItem {
   name: string
+  sname: string
   number: number
   icon: string
   checked: boolean
 }
 interface Props {
   TransportListItem: ListItem[]
+  isShipment: Boolean
 }
 const props = withDefaults(defineProps<Props>(), {})
 const TransportList = ref(props.TransportListItem)
 watch(
   () => props.TransportListItem,
   (current) => {
+    console.log(current)
     TransportList.value = current
+    TransportList.value.forEach((item: any) => {
+      if (item.checked) {
+        checkedCount.push(item.sname)
+        const map = new Map()
+        checkedCount.forEach((item) => map.set(item, true))
+        checkedCount = [...map.keys()]
+      }
+      if (checkedCount.length == TransportList.value.length) {
+        checkAll.value = true
+      }
+    })
   }
 )
 
@@ -27,6 +41,7 @@ onMounted(() => {
       clearList()
     }
   })
+  defaultTransport()
 })
 
 onBeforeMount(() => {
@@ -51,25 +66,21 @@ const handleCheckAllChange = (val: any) => {
   TransportList.value.forEach((item: any) => {
     if (val) {
       item.checked = true
-      checkedCount.push(item.name)
+      checkedCount.push(item.sname)
     } else {
       item.checked = false
       checkedCount = []
     }
   })
 }
-const handleCheckedTransportChange = (value: any, checked: any, index: any) => {
+const handleCheckedTransportChange = (value: any, checked: any) => {
   if (checked) {
     checkedCount.push(value)
     const map = new Map()
     checkedCount.forEach((item) => map.set(item, true))
     checkedCount = [...map.keys()]
   } else {
-    if (checkedCount.length == 1) {
-      checkedCount.splice(0, 1)
-    } else {
-      checkedCount.splice(index, 1)
-    }
+    checkedCount.splice(checkedCount.indexOf(value), 1)
   }
   checkAll.value = checkedCount.length === TransportList.value.length
 }
@@ -77,26 +88,37 @@ const handleCheckedTransportChange = (value: any, checked: any, index: any) => {
 // 清除选中
 const clearList = () => {
   checkAll.value = false
-  TransportList.value.forEach((item: any) => {
-    item.checked = false
-  })
+  if (TransportList.value != undefined) {
+    TransportList.value.forEach((item: any) => {
+      item.checked = false
+    })
+  }
   changedata.value = ''
   checkedCount = []
   emit('clearTransportTags')
 }
-const emit = defineEmits(['TransportSearch', 'clearTransportTags'])
+const emit = defineEmits(['TransportSearch', 'clearTransportTags', 'defaultTransport'])
 const changedata = ref()
 //点击搜索
+const TransportData = {
+  title: 'Transport Mode',
+  data: ['']
+}
 const TransportSearch = (visible: any) => {
+  TransportList.value.forEach((item: any) => {
+    if (item.checked) {
+      checkedCount.push(item.sname)
+      const map = new Map()
+      checkedCount.forEach((item) => map.set(item, true))
+      checkedCount = [...map.keys()]
+    }
+  })
   if (checkedCount.length == TransportList.value.length) {
-    changedata.value = 'All'
+    changedata.value = ['All']
   } else {
-    changedata.value = checkedCount.join(', ')
-  }
-  const TransportData = {
-    title: 'Transport Mode',
-    data: changedata.value
+    changedata.value = checkedCount
   }
+  TransportData.data = changedata.value
   emit('TransportSearch', TransportData)
   if (!dropdown1.value) return
   if (visible) {
@@ -105,6 +127,76 @@ const TransportSearch = (visible: any) => {
     dropdown1.value.handleOpen()
   }
 }
+const searchTableQeury = ref()
+const searchTableQeuryTracking = ref()
+const defaultTransport = () => {
+  if (props.isShipment) {
+    if (
+      sessionStorage.getItem('clickParams') == null ||
+      sessionStorage.getItem('clickParams') == '{}'
+    ) {
+      if (sessionStorage.getItem('searchTableQeuryTracking') == null) {
+        checkAll.value = true
+        TransportData.data = ['All']
+      } else {
+        searchTableQeuryTracking.value =
+          JSON.parse(sessionStorage.getItem('searchTableQeuryTracking') as string) || {}
+        if (searchTableQeuryTracking.value.transport_mode.length !== 0) {
+          TransportData.data = searchTableQeuryTracking.value.transport_mode
+          searchTableQeuryTracking.value.transport_mode.forEach((item: any) => {
+            if (item == 'All') {
+              checkAll.value = true
+            } else {
+              checkAll.value = false
+            }
+          })
+        } else {
+          TransportData.data = []
+          checkAll.value = false
+        }
+      }
+      emit('defaultTransport', TransportData, searchTableQeuryTracking.value)
+    } else {
+      const data = JSON.parse(sessionStorage.getItem('reportList') as string) || {}
+      searchTableQeuryTracking.value =
+        JSON.parse(sessionStorage.getItem('searchTableQeuryTracking') as string) || {}
+      if (data.transport_mode) {
+        const obj = {
+          title: 'Transport Mode',
+          data: data.transport_mode
+        }
+        data.transport_mode.forEach((item: any) => {
+          if (item == 'All') {
+            checkAll.value = true
+          }
+        })
+        emit('defaultTransport', obj, searchTableQeuryTracking.value)
+      }
+    }
+  } else {
+    if (sessionStorage.getItem('searchTableQeury') == null) {
+      checkAll.value = true
+      TransportData.data = ['All']
+    } else {
+      searchTableQeury.value =
+        JSON.parse(sessionStorage.getItem('searchTableQeury') as string) || {}
+      if (searchTableQeury.value.transport_mode.length !== 0) {
+        TransportData.data = searchTableQeury.value.transport_mode
+        searchTableQeury.value.transport_mode.forEach((item: any) => {
+          if (item == 'All') {
+            checkAll.value = true
+          } else {
+            checkAll.value = false
+          }
+        })
+      } else {
+        TransportData.data = []
+        checkAll.value = false
+      }
+    }
+    emit('defaultTransport', TransportData, searchTableQeury.value)
+  }
+}
 </script>
 <template>
   <div class="select">
@@ -112,7 +204,7 @@ const TransportSearch = (visible: any) => {
       <div class="el-dropdown-link">
         <div class="select_title">Transport Mode</div>
         <span class="iconfont_icon">
-          <svg class="iconfont" aria-hidden="true">
+          <svg class="iconfont icon_dark" aria-hidden="true">
             <use xlink:href="#icon-icon_dropdown_b"></use>
           </svg>
         </span>
@@ -140,7 +232,7 @@ const TransportSearch = (visible: any) => {
                 :value="item.name"
                 v-model="item.checked"
                 class="checkbox"
-                @change="handleCheckedTransportChange(item.name, item.checked, index)"
+                @change="handleCheckedTransportChange(item.sname, item.checked)"
               >
                 <div class="checkbox_title">
                   <span class="iconfont_icon">
@@ -176,6 +268,7 @@ const TransportSearch = (visible: any) => {
 .iconfont_select {
   width: 17px;
   height: 17px;
+  fill: var(--color-neutral-1);
 }
 .select {
   width: 186px;
@@ -183,7 +276,7 @@ const TransportSearch = (visible: any) => {
   cursor: pointer;
   display: flex;
   align-items: center;
-  border: 1px solid var(--color-border);
+  border: 1px solid var(--color-select-border);
   border-radius: var(--border-radius-6);
 }
 .select:hover {
@@ -239,7 +332,7 @@ const TransportSearch = (visible: any) => {
   justify-content: flex-end;
   align-items: center;
   height: 48px;
-  border-top: 1px solid var(--color-border);
+  border-top: 1px solid var(--border-color-2);
   margin-top: 5px;
   font-weight: 400;
   font-size: var(--font-size-3);
@@ -271,8 +364,13 @@ const TransportSearch = (visible: any) => {
   border-radius: var(--border-radius-6);
   border-color: var(--border-hover-color);
 }
+:deep(.el-dropdown-menu) {
+  background-color: var(--management-bg-color);
+}
 .dropdownwidth {
   width: 248px;
+  background-color: var(--management-bg-color);
+  border-color: var(--management-bg-color);
 }
 @media only screen and (min-width: 1280px) {
   .el-dropdown-link,
@@ -294,6 +392,6 @@ const TransportSearch = (visible: any) => {
 }
 .el-divider--horizontal {
   margin: 8px 0;
-  border-top-color: var(--color-border);
+  border-top-color: var(--border-color-2);
 }
 </style>

+ 3 - 1
src/components/VBox/src/VBox.vue

@@ -74,7 +74,7 @@ const vBoxPopoverRef = ref()
             </div>
           </div>
           <template #reference v-if="props.isDraggable">
-            <el-button type="text" class="sort handle-draggable">
+            <el-button class="sort handle-draggable el-button--text">
               <span class="font_family icon-icon_dragsort__b" style="font-size: 16px"></span>
             </el-button>
           </template>
@@ -116,6 +116,8 @@ const vBoxPopoverRef = ref()
       display: flex;
       align-items: center;
       justify-content: center;
+      height: 32px;
+      width: 32px;
       span.icon-icon_dragsort__b {
         color: var(--color-neutral-1);
       }

+ 23 - 28
src/components/VBox_Dashboard/src/VBox_Dashboard.vue

@@ -45,25 +45,6 @@ const vBoxPopoverRef = ref()
     <div class="header">
       <slot name="header">Title</slot>
       <div class="option">
-        <!-- <el-popover
-          ref="vBoxPopoverRef"
-          popper-class="v-box-options"
-          :width="172"
-          placement="bottom"
-          trigger="click"
-        >
-          <div class="options">
-            <div
-              class="move-item"
-              @click="handleDraggable(item.name)"
-              v-for="item in optionList"
-              :key="item.name"
-            >
-              <span class="font_family" :class="[`icon-${item.icon}`]"></span>
-              <span>{{ item.name }}</span>
-            </div>
-          </div>
-          <template #reference> -->
         <el-button type="text" class="sort handle-draggable">
           <span class="iconfont_icon">
             <svg class="iconfont" aria-hidden="true">
@@ -71,11 +52,9 @@ const vBoxPopoverRef = ref()
             </svg>
           </span>
         </el-button>
-        <!-- </template>
-        </el-popover> -->
       </div>
       <div class="cancel" @click="changeCancel">
-        <span class="iconfont_icon">
+        <span class="iconfont_icon iconfont_cancel">
           <svg class="iconfont" aria-hidden="true">
             <use xlink:href="#icon-icon_reject_b"></use>
           </svg>
@@ -92,6 +71,21 @@ const vBoxPopoverRef = ref()
 </template>
 
 <style lang="scss" scoped>
+.iconfont_icon {
+  margin-right: 0;
+}
+.cancel {
+  fill: var(--color-neutral-1);
+  position: absolute;
+  right: 12px;
+  top: 12px;
+  height: 24px;
+  width: 24px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+}
 .v-box {
   border: 1px solid var(--color-border);
   overflow: hidden;
@@ -101,6 +95,7 @@ const vBoxPopoverRef = ref()
     padding: 0 16px 0 48px;
     height: 48px;
     line-height: 48px;
+    fill: var(--color-neutral-1);
     font-size: 18px;
     border-bottom: 1px solid var(--color-border);
     font-weight: 700;
@@ -112,16 +107,16 @@ const vBoxPopoverRef = ref()
       display: flex;
       align-items: center;
     }
-    .cancel {
-      position: absolute;
-      right: 26px;
-      cursor: pointer;
-      top: 0;
+    .cancel:hover {
+      background-color: var(--color-btn-default-bg-hover);
+      border-radius: 6px;
     }
     .sort {
       position: absolute;
       top: 50%;
-      right: -40px;
+      width: 24px;
+      height: 24px;
+      left: 12px;
       transform: translateY(-50%);
       display: flex;
       align-items: center;

+ 1 - 0
src/components/VBreadcrumb/index.ts

@@ -0,0 +1 @@
+export { default } from './src/VBreadcrumb.vue'

+ 75 - 0
src/components/VBreadcrumb/src/VBreadcrumb.vue

@@ -0,0 +1,75 @@
+<script setup lang="ts">
+import { useRouter } from 'vue-router'
+import { useBreadCrumb } from '@/stores/modules/breadCrumb'
+import { useThemeStore } from '@/stores/modules/theme'
+
+const router = useRouter()
+const breadCrumb = useBreadCrumb()
+const themeStore = useThemeStore()
+
+const handleGoBack = () => {
+  const routeData = breadCrumb.getUpperRoute()
+  router.push({
+    name: routeData.label,
+    query: routeData.query
+  })
+}
+const jumpLink = (label: string, query: any) => {
+  label &&
+    router.push({
+      name: label,
+      query: query
+    })
+}
+</script>
+
+<template>
+  <div
+    class="v-breadcrumd"
+    :class="{ 'is-dark': themeStore.theme === 'dark' }"
+    v-if="breadCrumb.routeList.length > 1"
+  >
+    <span class="font_family icon-icon_back_b" @click="handleGoBack"></span>
+    <template v-for="(routeItem, index) in breadCrumb.routeList" :key="routeItem.label">
+      <template v-if="index + 1 !== breadCrumb.routeList.length">
+        <span @click="jumpLink(routeItem.label, routeItem.query)" class="previous-route">{{
+          routeItem.label
+        }}</span>
+        <span class="interval">|</span>
+      </template>
+      <span v-else>{{ routeItem.label }}</span>
+    </template>
+  </div>
+  <div v-else></div>
+</template>
+
+<style lang="scss" scoped>
+.v-breadcrumd {
+  display: flex;
+  align-items: center;
+  font-weight: 700;
+  gap: 4px;
+  .icon-icon_back_b {
+    font-size: 18px;
+    cursor: pointer;
+  }
+  .interval {
+    margin: 0 2px;
+    color: var(--color-neutral-3);
+    transform: rotate(20deg);
+  }
+  .previous-route {
+    color: var(--color-neutral-3);
+    cursor: pointer;
+    &:hover {
+      color: var(--color-theme);
+    }
+  }
+  &.is-dark {
+    .interval,
+    .previous-route {
+      color: var(--color-neutral-2);
+    }
+  }
+}
+</style>

+ 0 - 1
src/components/VBreadcrumd/index.ts

@@ -1 +0,0 @@
-export { default } from './src/VBreadcrumd.vue'

+ 0 - 38
src/components/VBreadcrumd/src/VBreadcrumd.vue

@@ -1,38 +0,0 @@
-<script setup lang="ts">
-import { useParentPathStore } from '@/stores/modules/parentPath'
-import { useRouter } from 'vue-router'
-
-const router = useRouter()
-const parentPathStore = useParentPathStore()
-
-const handleGoBack = () => {
-  router.push({ path: parentPathStore.parentPathInfo?.fullPath })
-}
-</script>
-
-<template>
-  <div class="v-breadcrumd" v-if="parentPathStore.parentPathInfo?.name">
-    <span class="font_family icon-icon_back_b" @click="handleGoBack"></span>
-    <span style="color: var(--color-neutral-3)">{{ parentPathStore.parentPathInfo?.name }}</span>
-    <span class="interval">|</span>
-    <span style="font-weight: 700">Detail</span>
-  </div>
-  <div v-else></div>
-</template>
-
-<style lang="scss" scoped>
-.v-breadcrumd {
-  display: flex;
-  align-items: center;
-  gap: 4px;
-  .icon-icon_back_b {
-    font-size: 18px;
-    cursor: pointer;
-  }
-  .interval {
-    margin: 0 2px;
-    color: var(--color-neutral-3);
-    transform: rotate(20deg);
-  }
-}
-</style>

+ 20 - 6
src/components/VEmpty/src/VEmpty.vue

@@ -1,15 +1,29 @@
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import lightPng from './images/default_image.png'
+import darkPng from './images/default_dark_image.png'
+import { useThemeStore } from '@/stores/modules/theme'
+
+const themeStore = useThemeStore()
+// 判断当前系统主题模式
+const emptyImg = computed(() => {
+  return themeStore.theme === 'dark' ? darkPng : lightPng
+})
+</script>
 
 <template>
   <div class="v-empty">
     <div class="empty-img">
-      <img src="./images/default_image.png" alt="" />
+      <img :src="emptyImg" alt="" />
     </div>
-    <p class="title">Whoops, No matches</p>
-    <p class="light">We didn't find any search results,</p>
-    <p class="light">please try to adjust your search keywords.</p>
+    <p class="title">
+      <slot name="title">No Results Found</slot>
+    </p>
+    <slot name="result">
+      <p class="light">We didn't find any search results,</p>
+      <p class="light">please try to adjust your search keywords.</p>
+    </slot>
     <div class="suggestion">
-      <slot></slot>
+      <slot name="suggestion"></slot>
     </div>
   </div>
 </template>

二進制
src/components/VEmpty/src/images/default_dark_image.png


+ 9 - 6
src/components/VLoading/src/VLoading.vue

@@ -8,7 +8,7 @@
 interface internalProps {
   target?: string
   loading: boolean
-  isLoadingBackground: boolean
+  isLoadingBackground?: boolean
 }
 
 const props = withDefaults(defineProps<internalProps>(), {
@@ -18,8 +18,11 @@ const props = withDefaults(defineProps<internalProps>(), {
 </script>
 <template>
   <Teleport :to="props.target">
-    <div v-if="props.loading" class="v-loading-mask"
-      :style="{ background: props.isLoadingBackground ? 'none' : '#2B2F36' }">
+    <div
+      v-if="props.loading"
+      class="v-loading-mask"
+      :style="{ background: props.isLoadingBackground ? 'none' : '#2B2F36' }"
+    >
       <div class="v-loading-spinner">
         <div>
           <img class="circular" src="./images/icon_loading.png" alt="" />
@@ -43,11 +46,11 @@ const props = withDefaults(defineProps<internalProps>(), {
 }
 
 .v-loading-spinner {
+  position: sticky;
   top: 50%;
-  margin-top: -24px;
+  transform: translateY(-50%);
   width: 100%;
   text-align: center;
-  position: absolute;
 }
 
 .circular {
@@ -59,7 +62,7 @@ const props = withDefaults(defineProps<internalProps>(), {
 }
 
 .loading-text {
-  color: var(--color-neutral-3);
+  color: #b5b9bf;
 }
 
 @keyframes loading-rotate {

+ 1 - 0
src/components/VSliderVerification/index.ts

@@ -0,0 +1 @@
+export { default } from './src/VSliderVerification.vue'

+ 238 - 0
src/components/VSliderVerification/src/VSliderVerification.vue

@@ -0,0 +1,238 @@
+<script lang="ts" setup>
+//滑动图片验证码部分
+import Img01 from './image/verification-img-1.png'
+import Img02 from './image/verification-img-2.png'
+import Img03 from './image/verification-img-3.png'
+import Img04 from './image/verification-img-4.png'
+import { ref } from 'vue'
+//引入'vue3-puzzle-vcode'插件
+import Vcode from 'vue3-puzzle-vcode'
+
+const openDialog = () => {
+  isShow.value = true
+  nextTick(() => {
+    addElement()
+    onSuccess()
+    updateSliderBackground('success')
+  })
+}
+// 添加自定义元素
+const addElement = () => {
+  addTipsNode()
+  addSliderBtnNode('start')
+  updateRefreshImg()
+}
+
+const updateRefreshImg = () => {
+  const targetNode: any = document.querySelector('img.reset_')
+  if (targetNode) {
+    // 使用 import.meta.url 结合 new URL 获取图片的正确路径
+    targetNode.src = new URL('./image/icon_refresh_bold_b.png', import.meta.url).href
+  }
+}
+const addTipsNode = () => {
+  const childNode = document.createElement('div')
+  childNode.className = 'tips'
+  childNode.innerHTML = `
+    <p>Please drag the slider below to complete the</p>
+    <p>verification to ensure normal access</p>
+  `
+  const parentNode = document.querySelector('.vue-auth-box_')
+  if (parentNode.firstChild) {
+    parentNode.insertBefore(childNode, parentNode.firstChild)
+  } else {
+    parentNode.appendChild(childNode)
+  }
+}
+
+const styleMap = {
+  start: {
+    thumbColor: 'var(--color-slider-thumb-start)',
+    thumbIcon: 'icon-icon_drag__line_b',
+    trackBackground: 'var(--color-success)'
+  },
+  success: {
+    thumbColor: '#fff',
+    thumbIcon: 'icon-icon_confirm_b',
+    trackBackground: 'var(--color-success)'
+  },
+  error: {
+    thumbColor: '#fff',
+    thumbIcon: 'icon-icon_reject_b',
+    trackBackground: '#c7353f'
+  }
+}
+
+const addSliderBtnNode = (state: string) => {
+  const parentNode = document.querySelector('.range-btn')
+  if (state === 'start') {
+    parentNode.innerHTML = `
+      <span style="color: ${styleMap[state].thumbColor}" class="font_family ${styleMap[state].thumbIcon}"></span>
+  `
+  } else {
+    parentNode.innerHTML = `
+    <div class="icon-border" style="background: ${styleMap[state].trackBackground}">
+      <span style="color: ${styleMap[state].thumbColor}" class="font_family ${styleMap[state].thumbIcon}"></span>
+    </div>
+  `
+  }
+}
+
+const isShow = ref(false)
+
+// 根据不同的状态,设置已滑动区域的背景颜色
+const updateSliderBackground = (state: string) => {
+  const targetNode: any = document.querySelector('.range-slider')
+  targetNode.style.background = styleMap[state].trackBackground
+}
+
+const emit = defineEmits<{
+  close: []
+}>()
+// 监听验证成功事件,因为这里库中的成功事件有0.8秒的延迟,所以这里手动监听验证成功事件
+const onSuccess = () => {
+  // 选择要监听的目标元素
+  const targetNode = document.querySelector('.info-box_') // 将此选择器替换为你的实际目标
+  if (targetNode) {
+    const observer = new MutationObserver((mutationsList) => {
+      mutationsList.forEach((mutation) => {
+        if (mutation.type === 'childList') {
+          if ((mutation.target as any).innerHTML === 'Verification successful') {
+            updateSliderBackground('success')
+            addSliderBtnNode('success')
+            setTimeout(() => {
+              emit('close')
+              isShow.value = false
+            }, 500)
+          }
+        }
+      })
+    })
+
+    // 配置 MutationObserver,监听子节点的变化
+    const config = { childList: true, subtree: true }
+
+    // 启动监听
+    observer.observe(targetNode, config)
+  }
+}
+const close = () => {
+  isShow.value = true
+}
+const fail = () => {
+  updateSliderBackground('error')
+  addSliderBtnNode('error')
+  setTimeout(() => {
+    updateSliderBackground('start')
+    addSliderBtnNode('start')
+  }, 800)
+}
+
+defineExpose({
+  openDialog
+})
+</script>
+<template>
+  <Vcode
+    :show="isShow"
+    @close="close"
+    @fail="fail"
+    :canvasWidth="320"
+    :canvasHeight="180"
+    sliderText="Swipe to verify"
+    :sliderSize="38"
+    successText="Verification successful"
+    failText="Verification failed"
+    :range="5"
+    :imgs="[Img01, Img02, Img03, Img04]"
+  ></Vcode>
+</template>
+<style lang="scss" scoped>
+.slider-verification {
+  width: 400px;
+  height: 373px;
+  padding: 40px;
+  .tips {
+    text-align: center;
+  }
+}
+</style>
+<style lang="scss">
+// 整体框架
+.vue-auth-box_ {
+  width: 400px;
+  height: 373px;
+  padding: 40px;
+  background-color: var(--color-slider-bg);
+  border-radius: 16px;
+  box-shadow: -2px 2px 12px 0 rgba(0, 0, 0, 0.5);
+  .tips {
+    margin-bottom: 16px;
+    text-align: center;
+  }
+  .icon-border {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 16px !important;
+    height: 16px !important;
+    border-radius: 50%;
+    border: none !important;
+    span {
+      font-size: 14px !important;
+    }
+  }
+}
+
+div.vue-puzzle-vcode {
+  background-color: rgba(43, 47, 54, 0.7);
+}
+
+.vue-auth-box_ .auth-control_ div.range-box {
+  background-color: #87909e;
+  box-shadow: none;
+}
+.vue-auth-box_ div.auth-body_ {
+  border-radius: 6px;
+}
+// 已滑动区域的样式
+.vue-auth-box_ .auth-control_ .range-box div.range-slider {
+  background-color: var(--color-success);
+}
+
+.vue-auth-box_ .auth-body_ div.loading-box_.hide_ {
+  display: none;
+}
+
+// 成功的提示
+.vue-auth-box_ .auth-body_ div.info-box_ {
+  background: var(--color-success);
+}
+// 失败的提示
+.vue-auth-box_ .auth-body_ div.info-box_.fail {
+  background: #c7353f;
+}
+
+.vue-auth-box_ .auth-control_ .range-box .range-slider {
+  border-radius: 6px;
+}
+
+.vue-auth-box_ .auth-control_ div.range-box {
+  border-radius: 6px;
+}
+// 滑块
+.vue-auth-box_ .auth-control_ .range-box .range-slider .range-btn {
+  border-radius: 6px;
+}
+
+.vue-auth-box_ .auth-body_ .reset_ {
+  width: 20px;
+  height: 20px;
+  top: 10px;
+  right: 10px;
+}
+
+.vue-auth-box_ .auth-control_ .range-box .range-text {
+  color: #fff;
+}
+</style>

二進制
src/components/VSliderVerification/src/image/icon_refresh_bold_b.png


二進制
src/components/VSliderVerification/src/image/verification-img-1.png


二進制
src/components/VSliderVerification/src/image/verification-img-2.png


二進制
src/components/VSliderVerification/src/image/verification-img-3.png


二進制
src/components/VSliderVerification/src/image/verification-img-4.png


+ 11 - 2
src/components/VTag/src/VTag.vue

@@ -9,6 +9,7 @@ interface internalProps {
     | 'Departure'
     | 'Arrived'
     | 'Completed'
+    | 'Departed'
   large?: boolean
 }
 
@@ -20,7 +21,8 @@ const mappingTable = new Map([
   ['Cargo Received', 'cargo-received'],
   ['Departure', 'departure'],
   ['Arrived', 'arrived'],
-  ['Completed', 'completed']
+  ['Completed', 'completed'],
+  ['Departed', 'Departed']
 ])
 defineProps<internalProps>()
 </script>
@@ -38,7 +40,7 @@ defineProps<internalProps>()
   justify-content: center;
   cursor: default;
   align-items: center;
-  padding: 4px 8px;
+  padding: 5px 8px;
   height: 22px;
   line-height: 28px;
   font-size: 12px;
@@ -113,6 +115,13 @@ defineProps<internalProps>()
       background-color: var(--color-tag-completed);
     }
   }
+  &.v-tag__Departed {
+    background-color: var(--color-tag-Departed-bg);
+    color: var(--color-tag-Departed);
+    .dot {
+      background-color: var(--color-tag-Departed);
+    }
+  }
   & + .v-tag {
     margin-left: 8px;
   }

+ 48 - 23
src/components/selectAutoSelect/src/selectAutoSelect.vue

@@ -1,11 +1,9 @@
 <script setup lang="ts">
 import { ref, watch } from 'vue'
 import IconDropDown from '@/components/IconDropDown'
-import VerrifyInformation from '@/components/VerrifyInformation'
 interface TypeItem {
   partyType: ''
   partyname: []
-  isshowVerfication: boolean
 }
 interface ListItem {
   value: string
@@ -19,19 +17,31 @@ interface Props {
   AddDateType: TypeItem[]
   ASPlaceholder: string
   DateTypeoptions: dateoptions[]
-  Verification: string
   selectedPartyTypeoptions: Array<string>
+  ASSearchMode: String
+  ASSearchObj: Object
 }
 interface optionsItem {
   value: string
   label: string
 }
+
 const list = ref<ListItem[]>([])
 const options = ref<ListItem[]>([])
 const loading = ref(false)
 const props = withDefaults(defineProps<Props>(), {})
 const AddType = ref(props.AddDateType)
-const value = ref()
+watch(
+  () => props.AddDateType,
+  (val) => {
+    AddType.value = val
+  },
+  {
+    immediate: true,
+    deep: true
+  }
+)
+// const ErrorNumber = ref(0)
 const dataTypeoptions = ref<optionsItem[]>([])
 const typeSelectIndex = ref(-1)
 watch(
@@ -57,8 +67,11 @@ watch(
     deep: true
   }
 )
+const ErrorNumber = ref(true)
 const str = ref()
+const search_field = ref()
 const InputAutoSelect = (val: any) => {
+  search_field.value = val
   if (val.includes('Agent')) {
     str.value = 'apex'
   } else {
@@ -72,7 +85,10 @@ const remoteMethod = (query: string) => {
       $api
         .getMoreFiltersData({
           term: query,
-          type: str.value
+          type: str.value,
+          search_field: search_field.value,
+          search_mode: props.ASSearchMode,
+          ...props.ASSearchObj
         })
         .then((res: any) => {
           if (res.code == 200) {
@@ -102,18 +118,16 @@ const changeSelect = (val: any) => {
 // 选中name改变
 const emit = defineEmits(['changeAutoSelectAddType', 'delSelect', 'changeAutoSelect'])
 let AutoSelectObj: any = {}
+let AutoSelectObj2: any = {}
 const changeAutoSelect = (val: any, value: any) => {
   AutoSelectObj[val] = value.join()
-  emit('changeAutoSelect', AutoSelectObj)
-}
-// 清除警告样式
-const removeClass = (val: any, index: any) => {
-  const input_change = document.getElementsByClassName('input_change')
-  if (input_change.length && val.partyname.length != 0) {
-    if (input_change[index].classList.value.indexOf('AlertInput') != -1) {
-      input_change[index].classList.remove('AlertInput')
-    }
+  AutoSelectObj2[val] = value
+  if (value.length) {
+    ErrorNumber.value = true
+  } else {
+    ErrorNumber.value = false
   }
+  emit('changeAutoSelect', AutoSelectObj, AutoSelectObj2, ErrorNumber.value)
 }
 const typeSelectFocus = (index: any, e: any) => {
   typeSelectIndex.value = index
@@ -201,11 +215,12 @@ const typeSelectClick = (index: any, val: any) => {
         multiple
         filterable
         remote
-        class="input_change"
+        :class="{
+          is_error: AddType[index].partyType != '' && AddType[index].partyname.length == 0
+        }"
         :reserve-keyword="false"
         :placeholder="props.ASPlaceholder"
         collapse-tags
-        @blur="removeClass(AddType[index], index)"
         @input="InputAutoSelect(AddType[index].partyType)"
         @change="changeAutoSelect(AddType[index].partyType, AddType[index].partyname)"
         :disabled="AddType[index].partyType ? false : true"
@@ -220,14 +235,16 @@ const typeSelectClick = (index: any, val: any) => {
           :label="item.label"
           :value="item.value"
         >
-          <el-checkbox :checked="value?.includes(item.value)"></el-checkbox>
+          <el-checkbox :checked="AddType[index].partyname?.includes(item.value)"></el-checkbox>
           <div class="label">{{ item.value }}</div>
         </el-option>
       </el-select>
-      <VerrifyInformation
-        :isshowVerfication="AddDateType[index].isshowVerfication"
-        :verification="props.Verification"
-      ></VerrifyInformation>
+      <div
+        class="error"
+        v-if="AddType[index].partyType != '' && AddType[index].partyname.length == 0"
+      >
+        Please Input Party Details
+      </div>
     </div>
   </div>
 </template>
@@ -280,7 +297,15 @@ const typeSelectClick = (index: any, val: any) => {
   }
 }
 
-.AlertInput :deep(.el-select__wrapper) {
-  box-shadow: 0 0 0 0.5px var(--color-danger);
+.is_error {
+  :deep(.el-select__wrapper) {
+    box-shadow: 0 0 0 0.5px var(--color-danger);
+  }
+}
+.error {
+  font-size: 12px;
+  color: var(--color-danger);
+  line-height: 14px;
+  margin-top: 5px;
 }
 </style>

+ 6 - 0
src/components/transportationMode.ts

@@ -0,0 +1,6 @@
+export const transportationMode: any = {
+  'Ocean Freight': 'icon_ocean_b',
+  'Air Freight': 'icon_airplane_b',
+  'Road Freight': 'icon_truck_b',
+  'Rail Freight': 'icon_railway_b'
+}

+ 1 - 1
src/hooks/rowClickStyle.ts

@@ -1,6 +1,6 @@
 import { onMounted, onBeforeUnmount } from 'vue'
 
-export function useRowClickStyle(tableRef: any, rowClass: string = 'row--clicked') {
+export function useRowClickStyle(tableRef: any, rowClass: string = 'vxe-table-row-clicked-style') {
   const handleMouseDown = (event: any) => {
     const trElement = event.target.closest('tr')
     if (trElement && trElement.hasAttribute('rowid')) {

+ 49 - 0
src/hooks/useOverflow.ts

@@ -0,0 +1,49 @@
+import { ref, watch, onMounted, nextTick } from 'vue'
+
+export const useOverflow = (elementRef, dataRef) => {
+  // 根据 elementRef 类型来初始化 isOverflow
+  const isOverflow = Array.isArray(elementRef.value) ? ref([]) : ref(false)
+
+  const checkOverflow = (element) => {
+    if (element) {
+      return element.scrollWidth > element.clientWidth
+    }
+    return false
+  }
+
+  // 用于处理单个或多个元素的溢出检查
+  const updateOverflowStatus = () => {
+    if (Array.isArray(elementRef.value)) {
+      // 如果是数组,检查每个元素
+      isOverflow.value = elementRef.value.map((el) => checkOverflow(el))
+    } else {
+      // 如果是单个元素,直接返回布尔值
+      isOverflow.value = checkOverflow(elementRef.value)
+    }
+  }
+
+  // 初次 mounted 时检查是否溢出
+  onMounted(() => {
+    nextTick(() => {
+      updateOverflowStatus()
+    })
+  })
+
+  // 监听数据变化,更新溢出状态
+  watch(
+    () => dataRef,
+    () => {
+      nextTick(() => {
+        updateOverflowStatus()
+      })
+    },
+    {
+      deep: true,
+      immediate: true
+    }
+  )
+
+  return {
+    isOverflow
+  }
+}

+ 47 - 1
src/main.ts

@@ -19,6 +19,7 @@ import { createPinia } from 'pinia'
 
 import App from './App.vue'
 import router from './router'
+import { useThemeStore } from '@/stores/modules/theme'
 
 const app = createApp(App)
 
@@ -41,4 +42,49 @@ app.use(Antd)
 // 注册全局指令
 app.directive('vloading', VLoading)
 
-app.mount('#app')
+const themeStore = useThemeStore()
+
+// 动态加载暗黑主题
+async function loadDarkTheme() {
+  await import('element-plus/theme-chalk/dark/css-vars.css') // 动态导入暗黑主题
+}
+// 动态移除暗黑主题
+function unloadDarkTheme() {
+  const darkThemeStylesheet = document.getElementById('dark-theme-style')
+  if (darkThemeStylesheet) {
+    darkThemeStylesheet.remove()
+  }
+}
+// 用户没有手动切换主题时,根据系统设置自动切换
+if (!themeStore.isManualChange) {
+  // 根据用户偏好或系统设置决定是否添加暗黑模式类名
+  if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
+    themeStore.toggleTheme('dark')
+    loadDarkTheme()
+  } else {
+    unloadDarkTheme()
+    themeStore.toggleTheme('light')
+  }
+} else {
+  // 用户手动切换主题时,根据用户设置切换
+  if (themeStore.theme === 'dark') {
+    loadDarkTheme()
+    themeStore.toggleTheme('dark')
+  }
+}
+
+// 提供一个全局方法来切换主题
+app.config.globalProperties.$toggleDarkMode = () => {
+  const html = document.documentElement
+  if (html.classList.contains('dark')) {
+    unloadDarkTheme()
+    html.classList.remove('dark')
+    localStorage.setItem('theme', 'light')
+  } else {
+    loadDarkTheme()
+    html.classList.add('dark')
+    localStorage.setItem('theme', 'dark')
+  }
+}
+
+app.mount('#app')

+ 62 - 13
src/router/index.ts

@@ -1,13 +1,14 @@
 import { createRouter, createWebHistory } from 'vue-router'
-import { useParentPathStore } from '@/stores/modules/parentPath'
+import { useUserStore } from '@/stores/modules/user'
+import { useBreadCrumb } from '@/stores/modules/breadCrumb'
 
 const router = createRouter({
-  history: createWebHistory(import.meta.env.BASE_URL),
+  history: createWebHistory(`${import.meta.env.VITE_BASE_URL}`),
   routes: [
     {
       path: '/',
       name: 'Home',
-      redirect: '/booking',
+      redirect: '/dashboard',
       component: () => import('../views/Layout'),
       children: [
         {
@@ -25,7 +26,7 @@ const router = createRouter({
           name: 'Booking Detail',
           component: () => import('../views/Booking/src/components/BookingDetail'),
           meta: {
-            parentPath: '/booking'
+            activeMenu: '/booking'
           }
         },
         {
@@ -36,12 +37,27 @@ const router = createRouter({
         {
           path: '/tracking/detail',
           name: 'Tracking Detail',
-          component: () => import('../views/Tracking/src/components/TrackingDetail')
+          component: () => import('../views/Tracking/src/components/TrackingDetail'),
+          meta: {
+            activeMenu: '/tracking'
+          }
+        },
+        {
+          path: '/tracking/add-vgm',
+          name: 'Add VGM',
+          component: () =>
+            import('../views/Tracking/src/components/TrackingTable/src/components/VGMView.vue'),
+          meta: {
+            activeMenu: '/tracking'
+          }
         },
         {
           path: '/public-tracking',
           name: 'Public Tracking',
-          component: () => import('../views/Tracking/src/components/PublicTracking')
+          component: () => import('../views/Tracking/src/components/PublicTracking'),
+          meta: {
+            activeMenu: '/tracking'
+          }
         },
         {
           path: '/public-tracking/detail',
@@ -49,12 +65,23 @@ const router = createRouter({
           component: () =>
             import(
               '../views/Tracking/src/components/PublicTracking/src/components/PublicTrackingDetail.vue'
-            )
+            ),
+          meta: {
+            activeMenu: '/tracking'
+          }
         },
         {
           path: '/login',
           name: 'Login',
-          component: () => import('../views/Login')
+          component: () => import('../views/Login'),
+          meta: {
+            activeMenu: '/tracking'
+          }
+        },
+        {
+          path: '/reset-password',
+          name: 'Reset Password',
+          component: () => import('../views/Login/src/components/ChangePasswordCard.vue')
         },
         {
           path: '/Operationlog',
@@ -68,11 +95,33 @@ const router = createRouter({
 
 // * 路由拦截 beforeEach
 router.beforeEach(async (to, from, next) => {
-  const parentPathStore = useParentPathStore()
-  if (to.path.includes('/detail')) {
-    parentPathStore.setParentPath(from)
-  } else {
-    parentPathStore.clearParentPath()
+  useBreadCrumb().setRouteList(to)
+  // 如果手动跳转登录页,清除登录信息
+  if (to.path === '/login') {
+    if (localStorage.getItem('username')) {
+      const userStore = useUserStore()
+      await userStore.logout()
+    }
+    sessionStorage.removeItem('trackingTablePageInfo')
+    sessionStorage.removeItem('bookingTablePageInfo')
+  }
+
+  // 未登录白名单
+  const whiteList = ['/login', '/public-tracking', '/public-tracking/detail', '/reset-password']
+  // 判断是否登录
+  if (!whiteList.includes(to.path) && !localStorage.getItem('username')) {
+    const userStore = useUserStore()
+    await userStore.logout()
+    if (whiteList.includes(from.path)) {
+      ElMessage.warning({
+        message: 'Please log in to use this feature.',
+        grouping: true
+      })
+      next(false)
+      return
+    } else {
+      next('/login')
+    }
   }
   next()
 })

+ 58 - 0
src/stores/modules/breadCrumb.ts

@@ -0,0 +1,58 @@
+import { defineStore } from 'pinia'
+
+interface Route {
+  label: string
+  path: string
+  query?: string
+}
+interface BreadCrumb {
+  routeList: Route[]
+}
+// 需要添加多级菜单的页面,值为route的name
+const whiteList = ['Booking Detail', 'Tracking Detail', 'Add VGM', 'Public Tracking Detail']
+
+export const useBreadCrumb = defineStore('breadCrumb', {
+  state: (): BreadCrumb => ({
+    routeList: JSON.parse(localStorage.getItem('routeList')) || []
+  }),
+  getters: {},
+  actions: {
+    setRouteList(toRoute: any) {
+      const index = this.routeList.findIndex((item) => item.label === toRoute.name)
+      if (index !== -1) {
+        this.routeList.splice(index + 1)
+      } else if (toRoute.name === 'Public Tracking Detail') {
+        this.routeList = [
+          {
+            label: 'Public Tracking',
+            path: '/public-tracking',
+            query: ''
+          },
+          {
+            label: 'Public Tracking Detail',
+            path: '/public-tracking/detail',
+            query: toRoute.query
+          }
+        ]
+      } else if (toRoute.name && whiteList.includes(toRoute.name)) {
+        this.routeList.push({
+          label: toRoute.name,
+          path: toRoute.path,
+          query: toRoute.query
+        })
+      } else {
+        this.routeList = [
+          {
+            label: toRoute.name,
+            path: toRoute.path,
+            query: toRoute.query
+          }
+        ]
+      }
+      localStorage.setItem('routeList', JSON.stringify(this.routeList))
+    },
+    getUpperRoute() {
+      return this.routeList[this.routeList.length - 2]
+    }
+  }
+})

+ 30 - 0
src/stores/modules/headerSearch.ts

@@ -0,0 +1,30 @@
+import { defineStore } from 'pinia'
+
+interface HeaderSearch {
+  searchValue: string
+  searchResult?: string
+  trackingData?: any
+}
+export const useHeaderSearch = defineStore('headerSearch', {
+  state: (): HeaderSearch => ({
+    searchValue: JSON.parse(localStorage.getItem('searchData'))?.searchValue || '',
+    searchResult: JSON.parse(localStorage.getItem('searchData'))?.searchResult || '',
+    trackingData: JSON.parse(localStorage.getItem('searchData'))?.searchResult || {}
+  }),
+  getters: {},
+  actions: {
+    setSearchData(searchData: any) {
+      localStorage.setItem('searchData', JSON.stringify(searchData))
+      this.searchValue = searchData.searchValue
+      this.searchResult = searchData?.searchResult
+      this.trackingData = searchData?.trackingData
+    },
+
+    clearSearchData() {
+      localStorage.removeItem('searchData')
+      this.searchValue = ''
+      this.searchResult = ''
+      this.trackingData = ''
+    }
+  }
+})

+ 18 - 0
src/stores/modules/loadingState.ts

@@ -0,0 +1,18 @@
+import { defineStore } from 'pinia'
+
+interface LoadingState {
+  trackingTableLoading: boolean
+}
+
+export const useLoadingState = defineStore('loadingState', {
+  state: (): LoadingState => ({
+    trackingTableLoading: JSON.parse(localStorage.getItem('trackingTableLoading')) || false
+  }),
+  getters: {},
+  actions: {
+    setTrackingTableLoading(state: boolean) {
+      localStorage.setItem('trackingTableLoading', JSON.stringify(state))
+      this.trackingTableLoading = state
+    }
+  }
+})

+ 0 - 28
src/stores/modules/parentPath.ts

@@ -1,28 +0,0 @@
-import { defineStore } from 'pinia'
-interface ParentPath {
-  parentPathInfo: {
-    fullPath?: string
-    name?: string
-  }
-}
-
-export const useParentPathStore = defineStore('parentPath', {
-  state: (): ParentPath => ({
-    parentPathInfo: JSON.parse(localStorage.getItem('parentPathInfo') as string) || {}
-  }),
-  getters: {},
-  actions: {
-    setParentPath(route: any) {
-      const pathInfo = {
-        name: route.name,
-        fullPath: route.fullPath
-      }
-      localStorage.setItem('parentPath', JSON.stringify(pathInfo))
-      this.parentPathInfo = pathInfo
-    },
-    clearParentPath() {
-      localStorage.removeItem('parentPath')
-      this.parentPathInfo = {}
-    }
-  }
-})

+ 44 - 0
src/stores/modules/theme.ts

@@ -0,0 +1,44 @@
+import { defineStore } from 'pinia'
+
+interface ThemeState {
+  theme: string
+  isManualChange: boolean
+}
+export const useThemeStore = defineStore('theme', {
+  state: (): ThemeState => ({
+    theme: localStorage.getItem('theme') || 'light',
+    isManualChange: JSON.parse(localStorage.getItem('isManualChange')) || false
+  }),
+  actions: {
+    toggleTheme(theme: string, isManualChange = false) {
+      localStorage.setItem('theme', theme)
+      this.theme = theme
+
+      const html = document.documentElement
+      if (html.classList.contains('dark') && theme === 'light') {
+        unloadDarkTheme()
+        html.classList.remove('dark')
+      } else if (!html.classList.contains('dark') && theme === 'dark') {
+        loadDarkTheme()
+        html.classList.add('dark')
+      }
+      // 主动修改主题后,不再跟随系统设置
+      if (isManualChange) {
+        localStorage.setItem('isManualChange', JSON.stringify(isManualChange))
+        this.isManualChange = isManualChange
+      }
+    }
+  }
+})
+
+// 动态加载暗黑主题
+async function loadDarkTheme() {
+  await import('element-plus/theme-chalk/dark/css-vars.css') // 动态导入暗黑主题
+}
+// 动态移除暗黑主题
+function unloadDarkTheme() {
+  const darkThemeStylesheet = document.getElementById('dark-theme-style')
+  if (darkThemeStylesheet) {
+    darkThemeStylesheet.remove()
+  }
+}

+ 38 - 0
src/stores/modules/user.ts

@@ -0,0 +1,38 @@
+import { defineStore } from 'pinia'
+import { useVisitedRowState } from './visitedRow'
+
+interface UserState {
+  username: string
+  isFirstLogin: boolean
+}
+export const useUserStore = defineStore('user', {
+  state: (): UserState => ({
+    username: localStorage.getItem('username') || '',
+    isFirstLogin: localStorage.getItem('isFirstLogin')
+      ? JSON.parse(localStorage.getItem('isFirstLogin'))
+      : false
+  }),
+  getters: {},
+  actions: {
+    setUsername(username: any, isFirstLogin?: boolean) {
+      localStorage.setItem('username', username)
+      this.username = username
+      if (isFirstLogin !== undefined) {
+        localStorage.setItem('isFirstLogin', JSON.stringify(isFirstLogin))
+        this.isFirstLogin = isFirstLogin
+      }
+    },
+    async logout(isNeedLogout: boolean = true) {
+      if (isNeedLogout) {
+        await $api.logout().then(() => {})
+      }
+      localStorage.removeItem('username')
+      this.username = ''
+      if (localStorage.getItem('isFirstLogin')) {
+        localStorage.removeItem('isFirstLogin')
+      }
+      this.isFirstLogin = false
+      useVisitedRowState().clearVisitedRow()
+    }
+  }
+})

+ 30 - 0
src/stores/modules/visitedRow.ts

@@ -0,0 +1,30 @@
+import { defineStore } from 'pinia'
+
+interface VisitedRowState {
+  trackingTableData: Array<String>
+  bookingTableData: Array<String>
+}
+
+export const useVisitedRowState = defineStore('visitedRowState', {
+  state: (): VisitedRowState => ({
+    trackingTableData: JSON.parse(localStorage.getItem('trackingTableData')) || [],
+    bookingTableData: JSON.parse(localStorage.getItem('bookingTableData')) || []
+  }),
+  getters: {},
+  actions: {
+    setTrackingTableData(item: String) {
+      this.trackingTableData.push(item)
+      localStorage.setItem('trackingTableData', JSON.stringify(this.trackingTableData))
+    },
+    setBookingTableData(item: String) {
+      this.bookingTableData.push(item)
+      localStorage.setItem('bookingTableData', JSON.stringify(this.bookingTableData))
+    },
+    clearVisitedRow() {
+      this.trackingTableData = []
+      this.bookingTableData = []
+      localStorage.removeItem('trackingTableData')
+      localStorage.removeItem('bookingTableData')
+    }
+  }
+})

+ 58 - 21
src/styles/Antdui.scss

@@ -1,31 +1,36 @@
-:where(.css-dev-only-do-not-override-19iuou).ant-picker-range {
+.ant-picker {
+  background-color: var(--management-bg-color);
+  color: var(--color-neutral-1);
+}
+.ant-picker-range {
   height: 40px;
-  border: 1px solid var(--color-border-1);
+  background-color: var(--management-bg-color);
+  border: 1px solid var(--color-select-border);
 }
-:where(.css-dev-only-do-not-override-19iuou).ant-picker:hover, :where(.css-dev-only-do-not-override-19iuou).ant-picker-focused {
+.ant-picker:hover, .ant-picker-focused {
   border-color: var(--color-theme);
   box-shadow: none;
 }
 .ant-picker-active-bar {
   display: none;
 }
-:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown-range {
-  z-index: 9999;
+.ant-picker-dropdown-range {
+  z-index: 9999 ;
 }
-:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-today .ant-picker-cell-inner::before {
+.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-today .ant-picker-cell-inner::before {
   border: none;
 }
-:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-selected .ant-picker-cell-inner, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-start .ant-picker-cell-inner, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-end .ant-picker-cell-inner {
+.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-selected .ant-picker-cell-inner, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-start .ant-picker-cell-inner, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-end .ant-picker-cell-inner {
   background-color: var(--color-theme);
   color: #FFFFFF;
 }
-:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range::before {
+.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range::before {
   background-color: var(--color-orange-6);
 }
-:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-start:not(.ant-picker-cell-range-start-single)::before, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-end:not(.ant-picker-cell-range-end-single)::before {
+.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-start:not(.ant-picker-cell-range-start-single)::before, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-end:not(.ant-picker-cell-range-end-single)::before {
   background-color: var(--color-orange-6);
 }
-:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range {
+.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range {
   color: var(--color-theme);
 }
 .ant-picker-cell:hover:not(.ant-picker-cell-in-view).ant-picker-cell-inner,
@@ -36,31 +41,63 @@
       background-color: var(--color-orange-6) !important;
       color: var(--color-theme);
   }
-  :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-start .ant-picker-cell-inner::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-end .ant-picker-cell-inner::after {
+  .ant-picker-dropdown .ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-start .ant-picker-cell-inner::after, .ant-picker-dropdown .ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-end .ant-picker-cell-inner::after {
     background-color: var(--color-orange-6);
   }
-  :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover::before, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-start.ant-picker-cell-range-hover::before, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-end.ant-picker-cell-range-hover::before, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-start:not(.ant-picker-cell-range-start-single).ant-picker-cell-range-hover-start::before, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-end:not(.ant-picker-cell-range-end-single).ant-picker-cell-range-hover-end::before, .ant-picker-panel>:not(.ant-picker-date-panel) :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-start::before, .ant-picker-panel>:not(.ant-picker-date-panel) :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-end::before {
+  .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover::before, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-start.ant-picker-cell-range-hover::before, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-end.ant-picker-cell-range-hover::before, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-start:not(.ant-picker-cell-range-start-single).ant-picker-cell-range-hover-start::before, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-end:not(.ant-picker-cell-range-end-single).ant-picker-cell-range-hover-end::before, .ant-picker-panel>:not(.ant-picker-date-panel) .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-start::before, .ant-picker-panel>:not(.ant-picker-date-panel) .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-end::before {
     background-color: var(--color-orange-6);
   }
-  :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:not(.ant-picker-cell-in-range):not(.ant-picker-cell-range-start):not(.ant-picker-cell-range-end)::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end:not(.ant-picker-cell-in-range):not(.ant-picker-cell-range-start):not(.ant-picker-cell-range-end)::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start.ant-picker-cell-range-start-single::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start.ant-picker-cell-range-start.ant-picker-cell-range-end.ant-picker-cell-range-end-near-hover::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end.ant-picker-cell-range-start.ant-picker-cell-range-end.ant-picker-cell-range-start-near-hover::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end.ant-picker-cell-range-end-single::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover:not(.ant-picker-cell-in-range)::after {
+  .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:not(.ant-picker-cell-in-range):not(.ant-picker-cell-range-start):not(.ant-picker-cell-range-end)::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end:not(.ant-picker-cell-in-range):not(.ant-picker-cell-range-start):not(.ant-picker-cell-range-end)::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start.ant-picker-cell-range-start-single::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start.ant-picker-cell-range-start.ant-picker-cell-range-end.ant-picker-cell-range-end-near-hover::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end.ant-picker-cell-range-start.ant-picker-cell-range-end.ant-picker-cell-range-start-near-hover::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end.ant-picker-cell-range-end-single::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover:not(.ant-picker-cell-in-range)::after {
     border-top: none;
     border-bottom: none;
   }
-  tr>:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover:first-child::after, tr>:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end:first-child::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-start.ant-picker-cell-range-hover-edge-start.ant-picker-cell-range-hover-edge-start-near-range::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-edge-start:not(.ant-picker-cell-range-hover-edge-start-near-range)::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start::after {
+  tr>.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover:first-child::after, tr>.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end:first-child::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-start.ant-picker-cell-range-hover-edge-start.ant-picker-cell-range-hover-edge-start-near-range::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-edge-start:not(.ant-picker-cell-range-hover-edge-start-near-range)::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start::after {
     border-inline-start: none;
   }
-  tr>:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover:last-child::after, tr>:where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-end.ant-picker-cell-range-hover-edge-end.ant-picker-cell-range-hover-edge-end-near-range::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-edge-end:not(.ant-picker-cell-range-hover-edge-end-near-range)::after, :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end::after {
+  tr>.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover:last-child::after, tr>.ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-end.ant-picker-cell-range-hover-edge-end.ant-picker-cell-range-hover-edge-end-near-range::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-edge-end:not(.ant-picker-cell-range-hover-edge-end-near-range)::after, .ant-picker-dropdown .ant-picker-cell-in-view.ant-picker-cell-range-hover-end::after {
     border-inline-end: none;
   }
-  :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-header-view button:hover {
+  .ant-picker-dropdown .ant-picker-header-view button:hover {
     color: var(--color-theme);
   }
-  :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-panel-container .ant-picker-panels .ant-picker-panel {
-    border-left: 1px solid var(--color-border);
+  .ant-picker-dropdown .ant-picker-panel-container {
+    background-color: var(--management-bg-color);
+    border: 1px solid var(--border-color-2);
   }
   .ant-picker-footer {
-    border-top: 1px solid var(--color-border);
+    border-top: 1px solid var(--border-color-2);
   }
-  :where(.css-dev-only-do-not-override-19iuou).ant-picker-dropdown .ant-picker-panel {
+  .ant-picker-dropdown .ant-picker-panel {
     border: none;
-  }
+  }
+  .ant-picker-dropdown .ant-picker-panel-container .ant-picker-presets ul li:hover {
+    background: var(--color-orange-6);
+  }
+ .ant-picker-dropdown .ant-picker-date-panel .ant-picker-content th {
+  color: var(--color-neutral-2);
+ }
+.ant-picker-dropdown .ant-picker-decade-panel,.ant-picker-dropdown .ant-picker-year-panel,.ant-picker-dropdown .ant-picker-quarter-panel,.ant-picker-dropdown .ant-picker-month-panel,.ant-picker-dropdown .ant-picker-week-panel,.ant-picker-dropdown .ant-picker-date-panel,.ant-picker-dropdown .ant-picker-time-panel {
+  border-left: 1px solid var(--border-color-2);
+}
+.ant-picker .ant-picker-input >input, .ant-picker .ant-picker-input >input::placeholder {
+  color: var(--color-neutral-1);
+}
+.ant-picker-dropdown .ant-picker-cell .ant-picker-cell-inner {
+  color: var(--color-neutral-1);
+}
+.ant-picker-dropdown .ant-picker-header {
+  border-bottom: 1px solid var(--border-color-2);
+}
+.ant-picker .ant-picker-clear {
+  background-color: var(--management-bg-color);
+  color: var(--color-neutral-1);
+}
+.ant-picker .ant-picker-clear:hover {
+  color: var(--color-neutral-1);
+}
+.ant-picker.ant-picker-disabled {
+  border-color: var(--border-color-2);
+}
+.ant-picker-dropdown.ant-picker-dropdown-placement-bottomLeft .ant-picker-range-arrow {
+  display: none;
+}

+ 306 - 48
src/styles/elementui.scss

@@ -1,7 +1,7 @@
 // button
 .el-button.el-button--noborder {
   border: none;
-  background-color: var(--color-white);
+  background-color: var(--management-bg-color);
   span {
     color: var(--color-theme);
   }
@@ -20,19 +20,23 @@ button.el-button.el-button--text {
   padding: 4px 8px;
   border: none;
   background-color: transparent;
-  span {
-    color: var(--color-theme);
-  }
+
   &:hover {
     background-color: var(--color-btn-default-bg-hover);
-    color: var(--color-theme);
+  }
+  &:active {
+    span {
+      color: var(--color-theme);
+    }
   }
 }
 
 .el-button.el-button--default {
-  background-color: var(--color-white);
+  background-color: var(--color-btn-default-bg-color);
   color: var(--color-neutral-1);
-  border: 1px solid var(--color-border);
+  fill: var(--color-neutral-1);
+  border: 1px solid var(--color-select-border);
+  margin-left: 8px !important;
   &:hover {
     border: 1px solid var(--color-btn-default-bg-hover);
     background-color: var(--color-btn-default-bg-hover);
@@ -41,22 +45,15 @@ button.el-button.el-button--text {
       color: var(--color-theme);
     }
   }
-  &:focus {
-    border: 1px solid var(--color-btn-default-bg-hover);
-    background-color: var(--color-btn-default-bg-hover);
-    fill: var(--color-theme);
-    span {
-      color: var(--color-theme);
-    }
-  }
 }
 
-.el-button.el-button--main.is-plain {
+.el-button--main.is-plain {
   background-color: var(--color-white);
   border: 1px solid var(--color-border);
   span {
     color: var(--color-theme);
   }
+  fill: var(--color-theme);
   &:hover {
     border: 1px solid var(--color-btn-main-plain-bg-hover);
     background-color: var(--color-btn-main-plain-bg-hover);
@@ -65,12 +62,13 @@ button.el-button.el-button--text {
   }
 }
 
-.el-button.el-button--main {
+button.el-button--main {
   border: none;
   background-color: var(--color-theme);
   span {
     color: var(--color-white);
   }
+  fill: var(--color-white);
   &:hover {
     background-color: var(--color-btn-main-bg-hover);
     color: var(--color-white);
@@ -78,12 +76,30 @@ button.el-button.el-button--text {
   }
 }
 
+button.el-button.el-button--pain-theme {
+  border: 1px solid var(--color-el-btn-pain-theme-border);
+  background-color: var(--color-el-btn-pain-theme-bg);
+
+  fill: var(--color-el-btn-pain-theme-text);
+  color: var(--color-el-btn-pain-theme-text);
+  span {
+    color: var(--color-el-btn-pain-theme-text);
+  }
+  &:hover {
+    border-color: var(--color-el-btn-pain-theme-border);
+    background-color: var(--color-el-btn-pain-theme-bg-hover);
+    color: var(--color-white);
+    fill: var(--color-white);
+  }
+}
+
 .el-button.el-button--success {
   border: none;
   background-color: var(--color-success);
   span {
     color: var(--color-white);
   }
+  fill: var(--color-white);
   &:hover {
     background-color: var(--color-btn-success-bg-hover);
     color: var(--color-white);
@@ -97,6 +113,7 @@ button.el-button.el-button--text {
   span {
     color: var(--color-white);
   }
+  fill: var(--color-white);
   &:hover {
     background-color: var(--color-btn-warning-bg-hover);
     color: var(--color-white);
@@ -110,6 +127,7 @@ button.el-button.el-button--text {
   span {
     color: var(--color-white);
   }
+  fill: var(--color-white);
   &:hover {
     background-color: var(--color-btn-danger-bg-hover);
     color: var(--color-white);
@@ -120,7 +138,8 @@ button.el-button.el-button--text {
 .el-button.el-button--grey {
   border: none;
   background-color: var(--color-grey);
-  color: var(--color-accent-1);
+  color: var(--color-neutral-1);
+  fill: var(--color-neutral-1);
   &:hover {
     background-color: var(--color-btn-default-bg-hover);
     fill: var(--color-theme);
@@ -133,8 +152,9 @@ button.el-button.el-button--text {
 .el-button.el-button--blue {
   border: none;
   padding: 0 4px;
-  background-color: #f6f6fe;
-  color: var(--color-accent-1);
+  background-color: var(--color-btn-blue-bg);
+  color: var(--color-neutral-1);
+  fill: var(--color-neutral-1);
   &:hover {
     background-color: var(--color-btn-default-bg-hover);
     fill: var(--color-theme);
@@ -149,9 +169,9 @@ button.el-button.el-button--icon {
   height: auto;
   padding: 4px;
   border: none;
-  background-color: #f6f6fe;
+  background-color: var(--color-btn-icon-bg);
   &:hover {
-    background-color: #f6f6fe;
+    background-color: var(--color-btn-icon-bg);
   }
 }
 // 初始为黑色
@@ -162,9 +182,10 @@ button.el-button.el-button--icon {
   span {
     color: var(--color-white);
   }
+  fill: var(--color-white);
   &:hover {
-    background-color: var(--color-btn-default-dark-bg);
-    fill: var(--color-btn-default-dark-hover);
+    background-color: var(--color-btn-default-dark-hover-bg);
+    fill: var(--color-btn-default-dark-hover-bg);
     span {
       color: var(--color-btn-default-dark-hover) !important;
     }
@@ -173,6 +194,9 @@ button.el-button.el-button--icon {
 
 button.el-button {
   border-radius: 6px;
+  & + .el-button {
+    margin-left: 8px;
+  }
 }
 
 // pagination
@@ -207,6 +231,7 @@ div.el-dialog {
   padding: 0 0 8px;
   border-radius: 12px;
   overflow: hidden;
+  background-color: var(--color-dialog-body-bg);
 }
 header.el-dialog__header {
   padding: 12px 16px;
@@ -222,6 +247,13 @@ footer.el-dialog__footer {
 div.el-dialog__body {
   padding: 16px;
 }
+button.el-dialog__headerbtn:focus .el-dialog__close,
+button.el-dialog__headerbtn:hover .el-dialog__close {
+  color: var(--color-theme);
+}
+div.el-overlay {
+  background-color: rgba(43, 47, 54, 0.7);
+}
 
 // radio
 label.el-radio {
@@ -239,6 +271,70 @@ label.el-radio {
   }
 }
 
+// message
+div.el-message {
+  display: flex;
+  justify-content: center;
+  width: 800px;
+  .el-badge.el-message__badge {
+    display: none;
+  }
+}
+div.el-message--error {
+  --el-message-bg-color: #faebec;
+  --el-message-border-color: #faebec;
+  --el-message-text-color: var(--color-danger);
+}
+div.el-message--success {
+  --el-message-bg-color: #e5f6f1;
+  --el-message-border-color: #e5f6f1;
+  --el-message-text-color: var(--color-success);
+}
+
+div.el-message--warning {
+  --el-message-bg-color: #fef5eb;
+  --el-message-border-color: #fef5eb;
+  --el-message-text-color: #f19d38;
+}
+
+// message box
+div.el-message-box {
+  --el-messagebox-width: 640px;
+  --el-messagebox-border-radius: 12px;
+  padding: 0;
+  .el-message-box__header {
+    height: 56px;
+    padding: 16px;
+    background-color: var(--color-message-box-header-bg);
+    & > span {
+      font-weight: 700;
+      font-size: var(--font-size-4);
+    }
+  }
+  .el-message-box__container {
+    padding: 24px 16px;
+    gap: 6px;
+  }
+  .el-message-box__headerbtn {
+    height: 56px;
+  }
+  .el-message-box__status {
+    font-size: 16px;
+  }
+  .el-message-box__title {
+    font-weight: 700;
+    font-size: var(--font-size-4);
+  }
+  .el-message-box__message {
+    font-size: var(--font-size-3);
+  }
+  .el-message-box__btns {
+    padding: 8px;
+    padding-right: 16px;
+    border-top: 1px solid var(--color-border);
+  }
+}
+
 // drawer抽屉
 div.el-drawer {
   .el-drawer__header {
@@ -253,6 +349,11 @@ div.el-drawer {
   }
   .el-drawer__body {
     padding: 16px;
+    background-color: var(--color-drawer-body-bg);
+  }
+  .el-drawer__close-btn:focus i,
+  .el-drawer__close-btn:hover i {
+    color: var(--color-theme);
   }
 }
 
@@ -260,7 +361,7 @@ div .el-input__inner {
   color: var(--color-neutral-1);
   font-size: var(--font-size-3);
 }
-input.el-input__inner::placeholder {
+.el-input__inner::placeholder {
   color: var(--color-neutral-3);
   font-size: var(--font-size-3);
 }
@@ -271,12 +372,12 @@ div .el-select__placeholder.is-transparent {
   }
 }
 div.el-input__wrapper {
-  box-shadow: 0 0 0 1px var(--color-border) inset;
-  padding-left: 8px;
+  box-shadow: 0 0 0 1px var(--el-border) inset;
+  padding: 0 8px;
 }
 div.el-input div.el-input__wrapper.is-focus {
   box-shadow: 0 0 0 1px var(--color-theme) inset;
-  background-color: #ffffff !important;
+  background-color: var(--color-mode) !important;
 }
 div.el-input__wrapper:hover {
   box-shadow: 0 0 0 1px var(--color-theme) inset;
@@ -302,22 +403,61 @@ div .el-dropdown__popper .el-dropdown__list {
   user-select: none;
 }
 div .el-checkbox__inner:hover {
-  border-color: var(--color-border);
+  border-color: var(--color-select-border);
+}
+div .el-checkbox__inner {
+  border-color: var(--color-select-border);
+  background-color: #fff;
+}
+div .el-checkbox__input.is-checked .el-checkbox__inner:after {
+  border-color: var(--color-mode);
 }
 div .el-checkbox__input.is-checked .el-checkbox__inner {
   background-color: var(--color-theme);
   border-color: var(--color-theme);
 }
+div .el-checkbox.el-checkbox--large .el-checkbox__inner {
+  height: 16px;
+  width: 16px;
+  font-size: 16px;
+  border-radius: 3px;
+}
+div .el-checkbox--large .el-checkbox__label {
+  margin-top: 1px;
+  padding-left: 4px;
+}
+span.el-checkbox__input.is-checked + .el-checkbox__label {
+  color: var(--color-neutral-2);
+}
+/* 修改选中时打勾图标的大小 */
+div .el-checkbox.el-checkbox--large span.el-checkbox__inner::after {
+  left: 4px; /* 调整左边距 */
+  top: 0px; /* 调整上边距 */
+  width: 5px; /* 打勾图标宽度 */
+  height: 10px; /* 打勾图标高度 */
+}
+/* 修改暗黑模式下选中时打勾图标的大小 */
+html.dark .el-checkbox.el-checkbox--large span.el-checkbox__inner::after {
+  left: 5px; /* 调整左边距 */
+  top: 1px; /* 调整上边距 */
+  width: 5px; /* 打勾图标宽度 */
+  height: 10px; /* 打勾图标高度 */
+}
 div .el-popper__arrow,
 div .el-popper__arrow:before {
-  height: 0;
-  width: 0;
+  // height: 0;
+  // width: 0;
+}
+.el-popper.is-dark,
+div.el-popper.is-dark > .el-popper__arrow:before {
+  background-color: var(--color-el-popper-bg);
+  border: var(--color-el-popper-bg);
 }
 div .el-popper[data-popper-placement^='bottom'] > .el-popper__arrow {
   top: 0;
 }
 div .el-dropdown-menu__item {
-  border: 1px solid var(--color-border);
+  border: 1px solid var(--color-select-border);
   border-radius: var(--border-radius-6);
 }
 div .el-dropdown__popper.el-popper,
@@ -338,10 +478,12 @@ div .el-popper[data-popper-placement^='bottom'] .el-popper__arrow:before {
 div .el-popover.el-popper {
   padding: 0;
 }
-.el-popper.is-dark {
+div.el-popper.is-dark {
   span {
     color: #fff;
   }
+  background-color: var(--color-el-popper-bg);
+  border-color: var(--color-el-popper-bg);
 }
 div .el-collapse-item__arrow,
 .el-tabs__nav {
@@ -359,7 +501,7 @@ div .el-collapse-item__content {
   }
 }
 div .el-select__wrapper {
-  box-shadow: 0 0 0 1px var(--color-border);
+  box-shadow: 0 0 0 1px var(--color-select-border);
 }
 div .el-select__wrapper.is-focused {
   box-shadow: 0 0 0 1px var(--color-theme);
@@ -376,6 +518,11 @@ div .el-select-dropdown__item.is-hovering {
 .el-select-dropdown__item {
   border-radius: var(--border-radius-6);
   margin: 0 8px;
+
+  margin-bottom: 4px;
+  &:last-child {
+    margin-bottom: 0;
+  }
 }
 
 div .el-badge__content--warning {
@@ -389,6 +536,53 @@ div .el-badge {
   margin: 8px 0 0 8px;
 }
 
+.el-date-table td.current:not(.disabled) span.el-date-table-cell__text {
+  background-color: var(--color-theme);
+}
+.el-month-table td.current:not(.disabled) span.el-date-table-cell__text {
+  background-color: var(--color-theme);
+}
+.el-month-table td span.el-date-table-cell__text:hover {
+  color: var(--color-theme);
+}
+.el-year-table td.current:not(.disabled) span.el-date-table-cell__text {
+  background-color: var(--color-theme);
+}
+.el-year-table td.today span.el-date-table-cell__text {
+  color: var(--color-theme);
+}
+.el-year-table td span.el-date-table-cell__text:hover {
+  color: var(--color-theme);
+}
+div.el-date-picker {
+  --el-datepicker-header-text-color: #b5b9bf;
+}
+div.el-date-picker__header {
+  padding-top: 4px;
+}
+span.el-date-picker__header-label {
+  display: inline-block;
+  margin-top: 11px;
+}
+div.el-picker-panel__content {
+  margin-top: 6px;
+}
+button.el-picker-panel__icon-btn:hover {
+  color: var(--color-theme);
+}
+span.el-date-picker__header-label:hover {
+  color: var(--color-theme);
+}
+button.el-time-panel__btn.confirm {
+  color: var(--color-theme);
+}
+.el-picker-panel__footer {
+  .el-button.is-plain {
+    --el-button-hover-text-color: var(--color-theme);
+    --el-button-hover-border-color: var(--color-theme);
+  }
+}
+
 div .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell {
   background-color: var(--color-table-header-bg);
 }
@@ -399,9 +593,18 @@ div .el-range-editor.is-active,
   box-shadow: 0 0 0 1px var(--color-theme) !important;
   border-color: var(--color-theme);
 }
-div .el-date-table td.today .el-date-table-cell__text,
-.el-date-table td.available:hover {
-  color: var(--color-theme);
+
+table.el-date-table td.available:hover {
+  span {
+    color: var(--color-theme);
+  }
+}
+div .el-date-table td.today .el-date-table-cell__text {
+  color: var(--color-neutral-1);
+  font-weight: 400;
+}
+.el-date-table td .el-date-table-cell span.el-date-table-cell__text {
+  border-radius: 6px;
 }
 div .el-date-table td.in-range .el-date-table-cell {
   background-color: var(--color-orange-6) !important;
@@ -447,16 +650,30 @@ div .el-select-dropdown.is-multiple .el-select-dropdown__item.is-selected:after
 div .el-select__wrapper.is-disabled,
 .el-select__wrapper.is-disabled:hover {
   box-shadow: none !important;
+  background-color: var(--input-disabled-bg-color);
+  color: var(--input-disabled-text-color);
 }
 div .scoreDialog header.el-dialog__header {
-  background: linear-gradient(
-    251deg,
-    rgba(255, 255, 255, 0.3),
-    rgba(255, 244, 235, 0.5) 22.66%,
-    rgba(240, 243, 255, 0.5) 44.57%,
-    rgba(224, 247, 249, 0.6) 80.46%,
-    rgba(255, 255, 255, 0.3)
-  );
+  background: var(--dashboard-scoring-bg-color);
+  position: fixed;
+  width: 640px;
+  height: 48px;
+  border-radius: 6px 6px 0 0;
+}
+div .el-dialog.scoreDialog {
+  background-color: var(--management-bg-color);
+}
+div .scoreDialog .el-dialog__body {
+  margin-top: 40px;
+}
+div .scoreDialog2 header.el-dialog__header {
+  background: var(--dashboard-scoring-bg-color);
+  width: 640px;
+  border-radius: 6px 6px 0 0;
+  height: 48px;
+}
+div .scoreDialog2 .el-dialog__body {
+  margin-top: 40px;
 }
 
 div .el-textarea__inner:hover {
@@ -512,10 +729,14 @@ div .el-tabs__active-bar {
   background-color: var(--color-accent-2);
 }
 
-div .el-radio-button.is-active .el-radio-button__original-radio:not(:disabled)+.el-radio-button__inner {
+div
+  .el-radio-button.is-active
+  .el-radio-button__original-radio:not(:disabled)
+  + .el-radio-button__inner {
   background-color: var(--color-theme);
   border-color: var(--color-theme);
-  box-shadow:none
+  box-shadow: none;
+  font-weight: 700;
 }
 div .el-radio-button__inner:hover {
   color: var(--color-theme);
@@ -523,4 +744,41 @@ div .el-radio-button__inner:hover {
 div .el-space {
   flex-wrap: wrap;
   margin: 3px 0 0 0;
-}
+}
+div .el-loading-spinner .path {
+  stroke: var(--color-theme);
+}
+div .ShowAlerIcon {
+  width: 342px;
+  background-color: var(--tips-bg-color) !important;
+  border-color: var(--tips-bg-color) !important;
+}
+div .el-month-table td .el-date-table-cell__text {
+  color: var(--color-neutral-1);
+}
+div .el-month-table td.today .el-date-table-cell__text {
+  color: var(--color-neutral-1);
+  font-weight: 400;
+}
+div .el-select-dropdown {
+  background-color: var(--management-bg-color);
+  border-color: var(--color-header-bg);
+}
+div label.smile_radio .el-radio__inner {
+  background-color: var(--management-bg-color);
+}
+span.el-radio__inner {
+  border: 1px solid var(--el-radio-input-border);
+}
+div .el-radio__inner:hover {
+  border-color: var(--color-theme);
+}
+div .dash_popver {
+  background-color: var(--management-bg-color) !important;
+  border-radius: 12px !important;
+}
+div .DaterangeClass {
+  background-color: var(--management-bg-color) !important;
+  border-color: var(--management-bg-color) !important;
+  border-radius: 12px !important;
+}

+ 244 - 12
src/styles/icons/iconfont.css

@@ -1,9 +1,9 @@
 @font-face {
   font-family: "font_family"; /* Project id 4672385 */
-  src: url('iconfont.woff2?t=1726717215398') format('woff2'),
-       url('iconfont.woff?t=1726717215398') format('woff'),
-       url('iconfont.ttf?t=1726717215398') format('truetype'),
-       url('iconfont.svg?t=1726717215398#font_family') format('svg');
+  src: url('iconfont.woff2?t=1736324058852') format('woff2'),
+       url('iconfont.woff?t=1736324058852') format('woff'),
+       url('iconfont.ttf?t=1736324058852') format('truetype'),
+       url('iconfont.svg?t=1736324058852#font_family') format('svg');
 }
 
 .font_family {
@@ -14,6 +14,246 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-icon_currentlink_b:before {
+  content: "\e6fc";
+}
+
+.icon-icon_jumplink_b1:before {
+  content: "\e6fd";
+}
+
+.icon-icon_arrow_b:before {
+  content: "\e6fb";
+}
+
+.icon-icon_dark_b1:before {
+  content: "\e6f9";
+}
+
+.icon-icon_manual_b:before {
+  content: "\e6fa";
+}
+
+.icon-a-KLNLogo-Orange:before {
+  content: "\e6f8";
+}
+
+.icon-icon_themes_b:before {
+  content: "\e6f5";
+}
+
+.icon-icon_light_b:before {
+  content: "\e6f6";
+}
+
+.icon-icon_dark_b:before {
+  content: "\e6f7";
+}
+
+.icon-icon_list_b:before {
+  content: "\e6f4";
+}
+
+.icon-icon_tracking__line_b:before {
+  content: "\e6f1";
+}
+
+.icon-icon_form_b:before {
+  content: "\e6f2";
+}
+
+.icon-icon_filters_b:before {
+  content: "\e6f3";
+}
+
+.icon-icon_submit_b:before {
+  content: "\e6f0";
+}
+
+.icon-icon_previous_b:before {
+  content: "\e6ee";
+}
+
+.icon-icon_next_b:before {
+  content: "\e6ef";
+}
+
+.icon-icon_view_b:before {
+  content: "\e6ed";
+}
+
+.icon-icon_index_b:before {
+  content: "\e6eb";
+}
+
+.icon-icon_preference_b:before {
+  content: "\e6ec";
+}
+
+.icon-icon_container__load_plan_b:before {
+  content: "\e6e9";
+}
+
+.icon-icon_company_b1:before {
+  content: "\e6ea";
+}
+
+.icon-icon_my_shipment_b:before {
+  content: "\e6d7";
+}
+
+.icon-icon_air_booking_b:before {
+  content: "\e6d8";
+}
+
+.icon-icon_data_insight_b:before {
+  content: "\e6d9";
+}
+
+.icon-icon_exception__maintenace_b:before {
+  content: "\e6da";
+}
+
+.icon-icon_destination__delivery_b:before {
+  content: "\e6db";
+}
+
+.icon-icon_my_cargo_b:before {
+  content: "\e6dc";
+}
+
+.icon-icon_po__confirmation_b:before {
+  content: "\e6dd";
+}
+
+.icon-icon_my_po_b:before {
+  content: "\e6de";
+}
+
+.icon-icon_my_booking_b:before {
+  content: "\e6df";
+}
+
+.icon-icon_my__shipment_b:before {
+  content: "\e6e0";
+}
+
+.icon-icon_document__maintenance_b:before {
+  content: "\e6e1";
+}
+
+.icon-icon_po_cancel_b:before {
+  content: "\e6e2";
+}
+
+.icon-icon_dashboard_b:before {
+  content: "\e6e3";
+}
+
+.icon-icon_administration_fill_b:before {
+  content: "\e6e4";
+}
+
+.icon-icon_data_insight__fill_b:before {
+  content: "\e6e5";
+}
+
+.icon-icon_administration_b:before {
+  content: "\e6e6";
+}
+
+.icon-icon_container_b:before {
+  content: "\e6e7";
+}
+
+.icon-icon_exception__approval_b:before {
+  content: "\e6e8";
+}
+
+.icon-icon_po_mass__maintenance_b:before {
+  content: "\e6cf";
+}
+
+.icon-icon_security_b:before {
+  content: "\e6d0";
+}
+
+.icon-icon_packing_b:before {
+  content: "\e6d1";
+}
+
+.icon-icon_my__shipment_fill_b:before {
+  content: "\e6d2";
+}
+
+.icon-icon_general__maintenace_b:before {
+  content: "\e6d3";
+}
+
+.icon-icon_invoice_b:before {
+  content: "\e6d4";
+}
+
+.icon-icon_control__tower_search_b:before {
+  content: "\e6d5";
+}
+
+.icon-icon_po_follow_up_b:before {
+  content: "\e6d6";
+}
+
+.icon-icon_seabooking_b:before {
+  content: "\e6c8";
+}
+
+.icon-icon_sku__maintenace_b:before {
+  content: "\e6c9";
+}
+
+.icon-icon_po_restore_b:before {
+  content: "\e6ca";
+}
+
+.icon-icon_road__booking_b:before {
+  content: "\e6cb";
+}
+
+.icon-icon_po_close_b:before {
+  content: "\e6cc";
+}
+
+.icon-icon_reports_b:before {
+  content: "\e6cd";
+}
+
+.icon-icon_po__maintenance_b:before {
+  content: "\e6ce";
+}
+
+.icon-icon_warning_fill_b:before {
+  content: "\e6c6";
+}
+
+.icon-icon_fail_fill_b:before {
+  content: "\e6c7";
+}
+
+.icon-icon_publish_fill_b:before {
+  content: "\e6c5";
+}
+
+.icon-icon_refresh_bold_b:before {
+  content: "\e6c4";
+}
+
+.icon-icon_drag__line_b:before {
+  content: "\e6c3";
+}
+
+.icon-icon_success_b:before {
+  content: "\e6c2";
+}
+
 .icon-icon_location_fill_b:before {
   content: "\e6c0";
 }
@@ -510,18 +750,10 @@
   content: "\e654";
 }
 
-.icon-icon_view_b:before {
-  content: "\e639";
-}
-
 .icon-icon_createpo_b:before {
   content: "\e63a";
 }
 
-.icon-icon_submit_b:before {
-  content: "\e63b";
-}
-
 .icon-icon_save_b:before {
   content: "\e63c";
 }

File diff suppressed because it is too large
+ 0 - 0
src/styles/icons/iconfont.js


File diff suppressed because it is too large
+ 10 - 0
src/styles/icons/iconfont.svg


二進制
src/styles/icons/iconfont.ttf


二進制
src/styles/icons/iconfont.woff


二進制
src/styles/icons/iconfont.woff2


二進制
src/styles/images/dashboard_scoring.png


+ 4 - 0
src/styles/index.scss

@@ -9,6 +9,7 @@
   font-size: var(--font-size-3);
   color: var(--color-neutral-1);
   // user-select: none;
+  background-color: var(--color-mode);
 }
 @font-face {
   font-family: 'Lato-Light'; /* 为字体定义一个名称 */
@@ -46,3 +47,6 @@
   border-radius: var(--border-radius-6);
   background: var(--border-hover-color);
 }
+.icon_dark {
+  fill: var(--color-neutral-1);
+}

+ 72 - 0
src/styles/theme-g.scss

@@ -0,0 +1,72 @@
+:root.dark {
+  // 菜单栏
+  --color-mune-active-bg: rgba(255, 117, 0, 0.2);
+  // 横幅
+  --dashboard-scoring-bg-color: linear-gradient(
+    270deg,
+    rgba(255, 182, 121, 0.1) 0.9%,
+    rgba(118, 145, 255, 0.1) 49.92%,
+    rgba(96, 242, 255, 0.1) 98.78%
+  );
+  --scoring-colurful-color: linear-gradient(251deg, rgba(113, 103, 99) 0%, rgba(92, 106, 125) 100%);
+
+  // button
+  --color-btn-default-bg-color: transparent;
+  --color-btn-default-bg-hover: rgba(255, 117, 0, 0.2);
+  --color-btn-default-dark-bg: #ed6d00;
+  --color-btn-default-dark-hover: #fff;
+  --color-grey: #3c414a;
+
+  --management-bg-color: #3e454f;
+  --more-type-bg-color: #343a43;
+
+  // filterstag
+  --color-tag-checked-all: rgba(255, 117, 0, 0.2);
+  --color-tag-all-bg: rgba(255, 117, 0, 0.2);
+  --color-tag-all-bg-color: rgba(226, 99, 148, 0.2);
+  --color-tag-created-bg: rgba(1, 103, 251, 0.2);
+  --color-tag-confirmed-bg: rgba(179, 232, 93, 0.15);
+  --color-tag-cancelled-bg: rgba(240, 241, 243, 0.2);
+  --color-tag-cancelled: rgba(240, 241, 243, 0.7);
+  --color-tag-departure: #40a6e5;
+  --color-tag-departure-bg: rgba(64, 166, 229, 0.2);
+  --color-tag-cargo-received-bg: rgba(111, 124, 241, 0.2);
+  --color-tag-cargo-received: #6f7cf1;
+  --color-tag-arrived-bg: rgba(1, 183, 161, 0.2);
+  --color-tag-completed-bg: rgba(91, 180, 98, 0.2);
+
+  --color-select-border: #656f7d;
+  --border-color-2: #4c515a;
+  --border-hover-color: rgba(255, 117, 0, 0.2);
+
+  --el-color-info: #fff;
+  --el-border-color-light: #3e454f;
+  --el-checkbox-bg-color: #656f7d;
+
+  // 日历
+  --color-orange-6: #614d3f;
+  --color-range-text: #ed6d00;
+
+  // more filters
+  --color-table-header-bg: #343a43;
+  --icon-color-black: #fff;
+  --more-filters-background-color: #2a2e34;
+  --addparties-background-color: #343a43;
+  --color-border-top: #3f434a;
+
+  // tag
+  --tag-bg-color: rgba(239, 239, 240, 0.1);
+  --tag-info-text-color: #fff;
+  --tips-bg-color: rgba(26, 28, 32, 1);
+  --tag-info-bg-color: rgba(239, 239, 240, 0.1);
+
+  // 评分
+  --scoring-bg-color: #525b69;
+  --scoring-smile-radio-color: #626871;
+
+  // 输入框禁用的颜色
+  --input-disabled-bg-color: rgba(244, 244, 244, 0.2);
+  --input-disabled-text-color: #66696f;
+  --color-recent-name: rgba(240, 241, 243, 0.1);
+  --color-disabled-bg: #2b2b2c;
+}

Some files were not shown because too many files changed in this diff