li.shaoyi 3 年之前
父節點
當前提交
3eea21fcac
共有 45 個文件被更改,包括 912 次插入428 次删除
  1. 74 118
      package-lock.json
  2. 1 1
      package.json
  3. 0 18
      src/business/admin/index.ts
  4. 9 4
      src/business/goods/index.ts
  5. 58 0
      src/business/notice/index.ts
  6. 1 1
      src/business/order/desting.ts
  7. 84 61
      src/business/order/list.ts
  8. 11 5
      src/business/order/listing.ts
  9. 7 3
      src/business/search/index.ts
  10. 9 9
      src/business/table/index.ts
  11. 62 84
      src/hooks/auth/index.ts
  12. 0 23
      src/hooks/auth/interface.ts
  13. 4 4
      src/hooks/datatable/index.ts
  14. 11 11
      src/hooks/datatable/interface.ts
  15. 81 0
      src/mock/router.ts
  16. 5 6
      src/packages/pc/App.vue
  17. 3 1
      src/packages/pc/components/base/drawer/index.vue
  18. 13 0
      src/packages/pc/components/layouts/header/components/calculator/index.vue
  19. 13 0
      src/packages/pc/components/layouts/header/components/certificate/index.vue
  20. 69 0
      src/packages/pc/components/layouts/header/components/notice/index.vue
  21. 7 2
      src/packages/pc/components/layouts/header/index.less
  22. 46 22
      src/packages/pc/components/layouts/header/index.vue
  23. 6 6
      src/packages/pc/components/layouts/main/index.vue
  24. 3 8
      src/packages/pc/components/layouts/sidebar/index.less
  25. 5 7
      src/packages/pc/components/layouts/sidebar/index.vue
  26. 7 8
      src/packages/pc/components/layouts/sidemenu/submenu.vue
  27. 9 0
      src/packages/pc/views/favorite/main/index.vue
  28. 13 0
      src/packages/pc/views/home/main/index.less
  29. 27 2
      src/packages/pc/views/home/main/index.vue
  30. 3 9
      src/packages/pc/views/listing/inquire/index.vue
  31. 7 0
      src/packages/pc/views/listing/sale/components/details/index.vue
  32. 8 0
      src/packages/pc/views/message/buy/index.vue
  33. 8 0
      src/packages/pc/views/message/sell/index.vue
  34. 9 0
      src/packages/pc/views/order/buy/index.vue
  35. 9 0
      src/packages/pc/views/order/sell/index.vue
  36. 1 1
      src/packages/pc/views/search/fancy/index.vue
  37. 12 0
      src/packages/pc/views/search/jewelry/index.less
  38. 71 0
      src/packages/pc/views/search/jewelry/index.vue
  39. 86 6
      src/packages/pc/views/warehousing/goods/components/details/index.vue
  40. 14 0
      src/services/api/common/index.ts
  41. 1 1
      src/services/api/order/index.ts
  42. 1 1
      src/services/language/index.ts
  43. 38 0
      src/types/ermcp/common.d.ts
  44. 2 2
      src/types/ermcp/goods.d.ts
  45. 4 4
      src/types/ermcp/order.d.ts

+ 74 - 118
package-lock.json

@@ -23,7 +23,7 @@
         "vant": "^3.4.8",
         "vue": "^3.2.13",
         "vue-class-component": "^8.0.0-0",
-        "vue-i18n": "^9.1.10",
+        "vue-i18n": "^9.2.2",
         "vue-router": "^4.0.3",
         "vuedraggable": "^4.1.0"
       },
@@ -1810,43 +1810,40 @@
       "dev": true
     },
     "node_modules/@intlify/core-base": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz",
-      "integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.2.2.tgz",
+      "integrity": "sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==",
       "dependencies": {
-        "@intlify/devtools-if": "9.1.10",
-        "@intlify/message-compiler": "9.1.10",
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/runtime": "9.1.10",
-        "@intlify/shared": "9.1.10",
-        "@intlify/vue-devtools": "9.1.10"
+        "@intlify/devtools-if": "9.2.2",
+        "@intlify/message-compiler": "9.2.2",
+        "@intlify/shared": "9.2.2",
+        "@intlify/vue-devtools": "9.2.2"
       },
       "engines": {
-        "node": ">= 10"
+        "node": ">= 14"
       }
     },
     "node_modules/@intlify/devtools-if": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz",
-      "integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.2.2.tgz",
+      "integrity": "sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==",
       "dependencies": {
-        "@intlify/shared": "9.1.10"
+        "@intlify/shared": "9.2.2"
       },
       "engines": {
-        "node": ">= 10"
+        "node": ">= 14"
       }
     },
     "node_modules/@intlify/message-compiler": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz",
-      "integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.2.tgz",
+      "integrity": "sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==",
       "dependencies": {
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/shared": "9.1.10",
+        "@intlify/shared": "9.2.2",
         "source-map": "0.6.1"
       },
       "engines": {
-        "node": ">= 10"
+        "node": ">= 14"
       }
     },
     "node_modules/@intlify/message-compiler/node_modules/source-map": {
@@ -1857,46 +1854,24 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/@intlify/message-resolver": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz",
-      "integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==",
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/@intlify/runtime": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz",
-      "integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==",
-      "dependencies": {
-        "@intlify/message-compiler": "9.1.10",
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/shared": "9.1.10"
-      },
-      "engines": {
-        "node": ">= 10"
-      }
-    },
     "node_modules/@intlify/shared": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz",
-      "integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.2.tgz",
+      "integrity": "sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==",
       "engines": {
-        "node": ">= 10"
+        "node": ">= 14"
       }
     },
     "node_modules/@intlify/vue-devtools": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz",
-      "integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz",
+      "integrity": "sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==",
       "dependencies": {
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/runtime": "9.1.10",
-        "@intlify/shared": "9.1.10"
+        "@intlify/core-base": "9.2.2",
+        "@intlify/shared": "9.2.2"
       },
       "engines": {
-        "node": ">= 10"
+        "node": ">= 14"
       }
     },
     "node_modules/@jridgewell/resolve-uri": {
@@ -3315,9 +3290,9 @@
       "dev": true
     },
     "node_modules/@vue/devtools-api": {
-      "version": "6.1.4",
-      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz",
-      "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ=="
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.1.tgz",
+      "integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ=="
     },
     "node_modules/@vue/eslint-config-typescript": {
       "version": "9.1.0",
@@ -11768,17 +11743,17 @@
       "dev": true
     },
     "node_modules/vue-i18n": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz",
-      "integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.2.2.tgz",
+      "integrity": "sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==",
       "dependencies": {
-        "@intlify/core-base": "9.1.10",
-        "@intlify/shared": "9.1.10",
-        "@intlify/vue-devtools": "9.1.10",
-        "@vue/devtools-api": "^6.0.0-beta.7"
+        "@intlify/core-base": "9.2.2",
+        "@intlify/shared": "9.2.2",
+        "@intlify/vue-devtools": "9.2.2",
+        "@vue/devtools-api": "^6.2.1"
       },
       "engines": {
-        "node": ">= 10"
+        "node": ">= 14"
       },
       "peerDependencies": {
         "vue": "^3.0.0"
@@ -13971,33 +13946,30 @@
       "dev": true
     },
     "@intlify/core-base": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz",
-      "integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.2.2.tgz",
+      "integrity": "sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==",
       "requires": {
-        "@intlify/devtools-if": "9.1.10",
-        "@intlify/message-compiler": "9.1.10",
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/runtime": "9.1.10",
-        "@intlify/shared": "9.1.10",
-        "@intlify/vue-devtools": "9.1.10"
+        "@intlify/devtools-if": "9.2.2",
+        "@intlify/message-compiler": "9.2.2",
+        "@intlify/shared": "9.2.2",
+        "@intlify/vue-devtools": "9.2.2"
       }
     },
     "@intlify/devtools-if": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz",
-      "integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.2.2.tgz",
+      "integrity": "sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==",
       "requires": {
-        "@intlify/shared": "9.1.10"
+        "@intlify/shared": "9.2.2"
       }
     },
     "@intlify/message-compiler": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz",
-      "integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.2.tgz",
+      "integrity": "sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==",
       "requires": {
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/shared": "9.1.10",
+        "@intlify/shared": "9.2.2",
         "source-map": "0.6.1"
       },
       "dependencies": {
@@ -14008,34 +13980,18 @@
         }
       }
     },
-    "@intlify/message-resolver": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz",
-      "integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w=="
-    },
-    "@intlify/runtime": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz",
-      "integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==",
-      "requires": {
-        "@intlify/message-compiler": "9.1.10",
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/shared": "9.1.10"
-      }
-    },
     "@intlify/shared": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz",
-      "integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA=="
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.2.tgz",
+      "integrity": "sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q=="
     },
     "@intlify/vue-devtools": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz",
-      "integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==",
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz",
+      "integrity": "sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==",
       "requires": {
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/runtime": "9.1.10",
-        "@intlify/shared": "9.1.10"
+        "@intlify/core-base": "9.2.2",
+        "@intlify/shared": "9.2.2"
       }
     },
     "@jridgewell/resolve-uri": {
@@ -15163,9 +15119,9 @@
       }
     },
     "@vue/devtools-api": {
-      "version": "6.1.4",
-      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz",
-      "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ=="
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.1.tgz",
+      "integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ=="
     },
     "@vue/eslint-config-typescript": {
       "version": "9.1.0",
@@ -21429,14 +21385,14 @@
       "dev": true
     },
     "vue-i18n": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz",
-      "integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==",
-      "requires": {
-        "@intlify/core-base": "9.1.10",
-        "@intlify/shared": "9.1.10",
-        "@intlify/vue-devtools": "9.1.10",
-        "@vue/devtools-api": "^6.0.0-beta.7"
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.2.2.tgz",
+      "integrity": "sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==",
+      "requires": {
+        "@intlify/core-base": "9.2.2",
+        "@intlify/shared": "9.2.2",
+        "@intlify/vue-devtools": "9.2.2",
+        "@vue/devtools-api": "^6.2.1"
       }
     },
     "vue-loader": {

+ 1 - 1
package.json

@@ -25,7 +25,7 @@
     "vant": "^3.4.8",
     "vue": "^3.2.13",
     "vue-class-component": "^8.0.0-0",
-    "vue-i18n": "^9.1.10",
+    "vue-i18n": "^9.2.2",
     "vue-router": "^4.0.3",
     "vuedraggable": "^4.1.0"
   },

+ 0 - 18
src/business/admin/index.ts

@@ -1,18 +0,0 @@
-import { reactive } from 'vue'
-
-export function useAdmin() {
-    const admin = reactive({
-        realName: '李兔饼',
-        avatar: '',
-    })
-
-    // 用户登出
-    const logout = () => {
-        console.log('登出')
-    }
-
-    return {
-        admin,
-        logout,
-    }
-}

+ 9 - 4
src/business/goods/index.ts

@@ -10,7 +10,6 @@ import { addZSGoods, queryDiamondList, queryDiamondDetails, goodsFavoriteOperate
 import { sessionData } from '@/stores'
 import {
     Category,
-    getCategoryList,
     getCurrencyTypeList,
     getShapeTypeList,
     getColorTypeList,
@@ -36,12 +35,18 @@ export function useDiamond() {
     const loading = shallowRef(false)
     const columns = shallowRef(getTableColumns('warehousing_diamond'))
 
+    const categoryList = [
+        { label: '单颗裸钻', value: Category.Diamond },
+        { label: '单颗彩钻', value: Category.Fancy },
+        { label: '钻石首饰', value: Category.Jewelry }
+    ]
+
     selectList.value = [
         {
             label: '商品分类',
             key: 'zscategory',
-            selectedValue: Category.Diamonds,
-            options: getCategoryList(),
+            selectedValue: Category.Diamond,
+            options: categoryList,
         },
         {
             label: '仓库',
@@ -62,7 +67,7 @@ export function useDiamond() {
                 page: pageIndex.value,
                 pagesize: pageSize.value,
                 wruserid: UserID,
-                zscategory: selectList.value[0].selectedValue as Ermcp.MyWRPositionRsp['zscategory'],
+                zscategorys: param.zscategory ? param.zscategory.toString() : categoryList.map((e) => e.value).join(','),
                 zsallproperties: param.goodsno,
                 warehouseid: param.warehouseid,
             },

+ 58 - 0
src/business/notice/index.ts

@@ -0,0 +1,58 @@
+import { shallowRef, computed } from 'vue'
+import { timerTask } from '@/utils/timer'
+import { queryNotice, postNoticeReaded } from '@/services/api/common'
+import { sessionData } from '@/stores'
+
+export function useNotice() {
+    const { LoginID } = sessionData.getValue('loginInfo')
+    const dataList = shallowRef<Ermcp.NoticeRsp[]>()
+    const loading = shallowRef(false)
+
+    // 未读列表
+    const unreadList = computed(() => {
+        const data = dataList.value ?? []
+        return data.filter((e) => !e.readed)
+    })
+
+    const getNoticeList = () => {
+        timerTask.clearTimeout('systemNotice')
+        loading.value = true
+        return queryNotice({
+            data: {
+                loginID: LoginID
+            },
+            success: (res) => {
+                dataList.value = res.data
+            },
+            complete: () => {
+                loading.value = false
+                // 轮询查询系统通知
+                timerTask.setTimeout(() => {
+                    getNoticeList()
+                }, 60 * 1000, 'systemNotice')
+            }
+        })
+    }
+
+    const updateNoticeReaded = () => {
+        const asyncTask: Promise<void>[] = []
+        unreadList.value.forEach((e) => {
+            const task = postNoticeReaded({
+                data: {
+                    loginID: LoginID,
+                    noticeID: e.autoid,
+                }
+            })
+            asyncTask.push(task)
+        })
+        Promise.all(asyncTask).then(() => getNoticeList())
+    }
+
+    return {
+        loading,
+        dataList,
+        unreadList,
+        getNoticeList,
+        updateNoticeReaded,
+    }
+}

+ 1 - 1
src/business/order/desting.ts

@@ -148,7 +148,7 @@ export function useSellOrderInquiry(selectedRow: Ermcp.BuyOrderRsp) {
         return queryDiamondList({
             data: {
                 wruserid: UserID,
-                zscategory: selectedRow.zscategory,
+                zscategorys: selectedRow.zscategory.toString(),
             },
             success: (res) => {
                 dataList.value = res.data.filter((e) => e.ftotalqty - e.ffreezeqty > 0)

+ 84 - 61
src/business/order/list.ts

@@ -1,10 +1,16 @@
-import { shallowRef } from 'vue'
+import { shallowRef, reactive } from 'vue'
 import { useDataTable } from '@/hooks/datatable'
+import { FilterSelect, FilterButton } from '@/hooks/datatable/interface'
 import { getTableColumns } from '@/business/table'
 import { queryBuyOrder, querySellOrder, queryMyBuyOrder, queryMySellOrder, queryMyDeListing, queryMyBargainApply, queryMyDelistingApply } from '@/services/api/order'
 import { sessionData } from '@/stores'
-import { getBuyOrSellList } from '@/constants/order'
-import { Category, getCategoryList } from '@/constants/diamond'
+import { getBuyOrSellList, BuyOrSell } from '@/constants/order'
+import { Category } from '@/constants/diamond'
+
+const categoryList = [
+    { label: '单颗裸钻', value: Category.Diamond },
+    { label: '单颗彩钻', value: Category.Fancy }
+]
 
 /**
  * 求购大厅
@@ -19,7 +25,7 @@ export function useBuyOrder() {
         {
             label: '商品分类',
             key: 'zscategory',
-            options: getCategoryList(),
+            options: categoryList,
         },
     ]
 
@@ -37,7 +43,7 @@ export function useBuyOrder() {
             data: {
                 page: pageIndex.value,
                 pagesize: pageSize.value,
-                zscategory: param.zscategory,
+                zscategorys: param.zscategory ? param.zscategory.toString() : categoryList.map((e) => e.value).join(','),
                 wrtradeorderid: param.wrtradeorderid,
                 zsallproperties: param.zstabledisplay,
                 buyusername: param.buyusername,
@@ -89,7 +95,7 @@ export function useSellOrder() {
         {
             label: '商品分类',
             key: 'zscategory',
-            options: getCategoryList(),
+            options: categoryList,
         },
     ]
 
@@ -107,7 +113,7 @@ export function useSellOrder() {
             data: {
                 page: pageIndex.value,
                 pagesize: pageSize.value,
-                zscategory: param.zscategory,
+                zscategorys: param.zscategory ? param.zscategory.toString() : categoryList.map((e) => e.value).join(','),
                 wrtradeorderid: param.wrtradeorderid,
                 zsallproperties: param.goodsno,
                 buyusername: param.sellusername,
@@ -158,7 +164,7 @@ export function useSaleOrder() {
         {
             label: '商品分类',
             key: 'zscategory',
-            options: getCategoryList(),
+            options: categoryList,
         },
     ]
 
@@ -176,7 +182,7 @@ export function useSaleOrder() {
                 page: pageIndex.value,
                 pagesize: pageSize.value,
                 userid: sessionData.getLoginInfo('UserID'),
-                zscategory: param.zscategory,
+                zscategorys: param.zscategory ? param.zscategory.toString() : categoryList.map((e) => e.value).join(','),
                 wrtradeorderid: param.wrtradeorderid,
                 zsallproperties: param.goodsno,
             },
@@ -226,7 +232,7 @@ export function usePurchaseOrder() {
         {
             label: '商品分类',
             key: 'zscategory',
-            options: getCategoryList(),
+            options: categoryList,
         },
     ]
 
@@ -244,7 +250,7 @@ export function usePurchaseOrder() {
                 page: pageIndex.value,
                 pagesize: pageSize.value,
                 userid: sessionData.getLoginInfo('UserID'),
-                zscategory: param.zscategory,
+                zscategorys: param.zscategory ? param.zscategory.toString() : categoryList.map((e) => e.value).join(','),
                 wrtradeorderid: param.wrtradeorderid,
                 zsallproperties: param.zstabledisplay,
             },
@@ -286,24 +292,21 @@ export function usePurchaseOrder() {
  * 我的摘牌
  */
 export function useDelistingOrder() {
-    const { dataList, total, pageIndex, pageSize, inputList, selectList, buttonList, getQueryParam, resetFilter } = useDataTable<Ermcp.MyDeListingRsp>()
+    const { dataList, total, pageIndex, pageSize, inputList, selectList, buttonList, getQueryParam } = useDataTable<Ermcp.MyDeListingRsp>()
     const loading = shallowRef(false)
     const columns = shallowRef(getTableColumns('listing_delisting'))
 
-    const categoryList = [
-        { label: '单颗裸钻', value: Category.Diamond },
-        { label: '单颗彩钻', value: Category.Fancy }
-    ]
-
     selectList.value = [
         {
             label: '商品分类',
             key: 'zscategory',
+            selectedValue: Category.Diamond,
             options: categoryList,
         },
         {
             label: '方向',
             key: 'buyorsell',
+            selectedValue: BuyOrSell.Buy,
             options: getBuyOrSellList(),
         },
     ]
@@ -339,7 +342,8 @@ export function useDelistingOrder() {
 
     const [reset, search] = buttonList.value
     reset.onClick = () => {
-        resetFilter()
+        pageIndex.value = 1
+        inputList.value.forEach((e) => e.value = undefined)
         getDelistingOrderList()
     }
     search.onClick = () => {
@@ -368,19 +372,36 @@ export function useInquireOrder() {
     const { dataList, total, pageIndex, pageSize } = useDataTable<Ermcp.MyBargainApplyRsp | Ermcp.MyDelistingApplyRsp>()
     const loading = shallowRef(false)
     const columns = shallowRef<Ermcp.TableColumn[]>([])
-    const selectedBuyOrSell = shallowRef(0)
-    const selectedStatus = shallowRef(1)
 
-    // 询价方向
-    const buyOrSell = [
-        { label: '求购', value: 0 },
-        { label: '出售', value: 1 }
-    ]
+    const selectList = reactive<FilterSelect<{ buyorsell: number, status: number }>[]>([
+        {
+            label: '方向',
+            key: 'buyorsell',
+            selectedValue: BuyOrSell.Buy,
+            options: [
+                { label: '求购', value: BuyOrSell.Buy },
+                { label: '出售', value: BuyOrSell.Sell }
+            ],
+        },
+        {
+            label: '状态',
+            key: 'status',
+            selectedValue: 1,
+            options: [
+                { label: '全部', value: 0 },
+                { label: '待确认', value: 1 }
+            ],
+        },
+    ])
 
-    // 询价状态
-    const status = [
-        { label: '全部', value: 0 },
-        { label: '待确认', value: 1 }
+    const buttonList: FilterButton[] = [
+        {
+            lable: '查询',
+            className: 'el-button--primary',
+            onClick: () => {
+                getInquireOrderList()
+            }
+        },
     ]
 
     // 获取我的询价列表
@@ -388,40 +409,44 @@ export function useInquireOrder() {
         loading.value = true
         dataList.value = []
 
+        const [buyOrSell, applyStatus] = selectList
         const param: Ermcp.MyBargainApplyReq | Ermcp.MyDelistingApplyReq = {
             page: pageIndex.value,
             pagesize: pageSize.value,
             userid: sessionData.getLoginInfo('UserID'),
+            applystatus: applyStatus.selectedValue,
         }
 
-        if (selectedStatus.value) {
-            param.applystatus = selectedStatus.value
-        }
-
-        if (selectedBuyOrSell.value) {
-            columns.value = getTableColumns('listing_inquire_sell')
-            return queryMyDelistingApply({
-                data: param,
-                success: (res) => {
-                    total.value = res.total
-                    dataList.value = res.data
-                },
-                complete: () => {
-                    loading.value = false
-                }
-            })
-        } else {
-            columns.value = getTableColumns('listing_inquire_buy')
-            return queryMyBargainApply({
-                data: param,
-                success: (res) => {
-                    total.value = res.total
-                    dataList.value = res.data
-                },
-                complete: () => {
-                    loading.value = false
-                }
-            })
+        switch (buyOrSell.selectedValue) {
+            case BuyOrSell.Buy: {
+                columns.value = getTableColumns('listing_inquire_buy')
+                return queryMyBargainApply({
+                    data: param,
+                    success: (res) => {
+                        total.value = res.total
+                        dataList.value = res.data
+                    },
+                    complete: () => {
+                        loading.value = false
+                    }
+                })
+            }
+            case BuyOrSell.Sell: {
+                columns.value = getTableColumns('listing_inquire_sell')
+                return queryMyDelistingApply({
+                    data: param,
+                    success: (res) => {
+                        total.value = res.total
+                        dataList.value = res.data
+                    },
+                    complete: () => {
+                        loading.value = false
+                    }
+                })
+            }
+            default: {
+                return Promise.reject('参数错误')
+            }
         }
     }
 
@@ -432,10 +457,8 @@ export function useInquireOrder() {
         pageIndex,
         pageSize,
         columns,
-        buyOrSell,
-        status,
-        selectedBuyOrSell,
-        selectedStatus,
+        selectList,
+        buttonList,
         getInquireOrderList,
     }
 }

+ 11 - 5
src/business/order/listing.ts

@@ -36,7 +36,7 @@ export function useBuyOrderListing() {
     const formData = reactive<Proto.GZBuyOrderDetailExInfo>({
         UserID,
         AccountID: AccountIDs[0],
-        ZSCategory: Category.Diamonds,
+        ZSCategory: Category.Diamond,
         ZSCurrencyType: [],
         ZSShapeType: [],
         ZSColorType: [],
@@ -53,7 +53,10 @@ export function useBuyOrderListing() {
     })
 
     const enums = {
-        categoryList: getCategoryList(),
+        categoryList: [
+            { label: '单颗裸钻', value: Category.Diamond },
+            { label: '单颗彩钻', value: Category.Fancy }
+        ],
         currencyTypeList: getCurrencyTypeList(),
         shapeTypeList: getShapeTypeList(),
         colorTypeList: getColorTypeList(),
@@ -114,8 +117,11 @@ export function useSellOrderListing(selectedRow?: Ermcp.MyWRPositionRsp) {
     const submitLoading = shallowRef(false)
     const tableLoading = shallowRef(false)
     const columns = shallowRef<Ermcp.TableColumn[]>([])
-    const categoryList = getCategoryList() // 分类列表
-    const selectedCategoryId = shallowRef(zscategory ?? Category.Diamonds)
+    const categoryList = [
+        { label: '单颗裸钻', value: Category.Diamond },
+        { label: '单颗彩钻', value: Category.Fancy }
+    ]
+    const selectedCategoryId = shallowRef(zscategory ?? Category.Diamond)
 
     const formData = reactive<Proto.ZSSellOrderListingReq>({
         Header: {
@@ -143,7 +149,7 @@ export function useSellOrderListing(selectedRow?: Ermcp.MyWRPositionRsp) {
         queryDiamondList({
             data: {
                 wruserid: UserID,
-                zscategory: selectedCategoryId.value,
+                zscategorys: selectedCategoryId.value.toString(),
             },
             success: (res) => {
                 dataList.value = res.data.filter((e) => e.ftotalqty - e.ffreezeqty > 0)

+ 7 - 3
src/business/search/index.ts

@@ -15,6 +15,7 @@ import {
     getSymmetryTypeList,
     getFluorescenceTypeList,
     getCertTypeList,
+    getStyleTypeList,
 } from '@/constants/diamond'
 
 export function useSearch(category: Category) {
@@ -24,10 +25,11 @@ export function useSearch(category: Category) {
     const warehouseList = shallowRef<Ermcp.WarehouseInfoRsp[]>([]) // 仓库列表
 
     // 部分请求参数类型重定义
-    type SellOrderSearchReq = Omit<Ermcp.SellOrderSearchReq, 'zsshapetype' | 'zscurrencytype' | 'zscerttype'> & {
+    type SellOrderSearchReq = Omit<Ermcp.SellOrderSearchReq, 'zsshapetype' | 'zscurrencytype' | 'zscerttype' | 'zsstyletype'> & {
         zsshapetype?: number[],
         zscurrencytype?: number[],
         zscerttype?: number[],
+        zsstyletype?: number[],
     }
 
     const formData = ref<SellOrderSearchReq>({
@@ -44,11 +46,12 @@ export function useSearch(category: Category) {
         symmetryTypeList: getSymmetryTypeList(),
         fluorescenceTypeList: getFluorescenceTypeList(),
         certTypeList: getCertTypeList(),
+        styleTypeList: getStyleTypeList(),
     }
 
     // 获取出售大厅委托单
     const getSellOrderList = () => {
-        const { zsshapetype, zscurrencytype, zscerttype, warehouseid, ...param } = formData.value
+        const { zsshapetype, zscurrencytype, zscerttype, warehouseid, zsstyletype, ...param } = formData.value
         loading.value = true
         return searchSellOrder({
             data: {
@@ -58,7 +61,8 @@ export function useSearch(category: Category) {
                 warehouseid: warehouseid || undefined,
                 zsshapetype: zsshapetype?.map((val) => val.toString()),
                 zscurrencytype: zscurrencytype?.map((val) => val.toString()),
-                zscerttype: zscerttype?.map((val) => val.toString())
+                zscerttype: zscerttype?.map((val) => val.toString()),
+                zsstyletype: zsstyletype?.map((val) => val.toString()),
             },
             success: (res) => {
                 total.value = res.total

+ 9 - 9
src/business/table/index.ts

@@ -132,7 +132,7 @@ const pcTableColumnMap = new Map<TableColumnKey, Ermcp.TableColumn[]>([
     ['listing_inquire_buy', [
         { prop: 'sellusername', label: '卖方' },
         { prop: 'warehousenamedisplay', label: '仓库' },
-        { prop: 'zsshapetypedisplay', label: '形状' },
+        { prop: 'zsshapetypedisplay', label: '形状', width: 200 },
         { prop: 'zscolortype1display', label: '颜色' },
         { prop: 'zsclaritytype1display', label: '净度' },
         { prop: 'zscuttype1display', label: '切工' },
@@ -151,14 +151,14 @@ const pcTableColumnMap = new Map<TableColumnKey, Ermcp.TableColumn[]>([
     // 挂牌大厅-我的询价-出售
     ['listing_inquire_sell', [
         { prop: 'buyusername', label: '买方' },
-        { prop: 'zsshapetypedisplay', label: '形状' },
-        { prop: 'zscolortype1display', label: '颜色' },
-        { prop: 'zsclaritytype1display', label: '净度' },
-        { prop: 'zscuttype1display', label: '切工' },
-        { prop: 'zspolishtype1display', label: '抛光' },
-        { prop: 'zssymmetrytype1display', label: '对称' },
-        { prop: 'zsfluorescencetype1display', label: '荧光' },
-        { prop: 'sizedisplay', label: '尺寸' },
+        { prop: 'zsshapetypedisplay', label: '形状', width: 200 },
+        { prop: 'zscolortypedisplay', label: '颜色' },
+        { prop: 'zsclaritytypedisplay', label: '净度' },
+        { prop: 'zscuttypedisplay', label: '切工' },
+        { prop: 'zspolishtypedisplay', label: '抛光' },
+        { prop: 'zssymmetrytypedisplay', label: '对称' },
+        { prop: 'zsfluorescencetypedisplay', label: '荧光' },
+        { prop: 'zssizedisplay', label: '尺寸' },
         { prop: 'goodsno', label: '我的商品' },
         { prop: 'applyqty', label: '克拉重量' },
         { prop: 'applyprice', label: '我的出价' },

+ 62 - 84
src/hooks/auth/index.ts

@@ -2,89 +2,70 @@ import { defineAsyncComponent, Component } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { sessionData } from '@/stores'
 import { AuthType } from '@/constants/menu'
-import { AuthMenu } from './interface'
 
-export function useAuth(code?: string) {
+export function useAuth(authCode?: string) {
     const route = useRoute()
     const router = useRouter()
     const userMenus = sessionData.getValue('userMenus')
     const componentMap = new Map<string, Component>()
 
-    /**
-     * 获取路由菜单(无限级)
-     * @param level 
-     * @returns 
-     */
-    const getMenus = (level = 0) => {
-        // 过滤层级
-        const filterLevel = (list: Ermcp.UserMenu[], n: number): Ermcp.UserMenu[] => {
-            if (level) {
-                return list.map((e) => ({ ...e, children: n <= 1 ? [] : filterLevel(e.children ?? [], n - 1) }))
+    // 过滤菜单
+    const filterMenu = (data: Ermcp.UserMenu[], parentPath = '') => {
+        const result: Ermcp.UserMenu[] = []
+        data.forEach((e) => {
+            if (!e.hidden && e.authType === AuthType.Menu) {
+                const routePath = (parentPath ? parentPath + '/' : '') + e.url
+                result.push({
+                    ...e,
+                    url: routePath,
+                    children: e.children ? filterMenu(e.children, routePath) : [],
+                })
             }
-            return list
-        }
-        // 过滤菜单
-        const filterMenu = (list: Ermcp.UserMenu[], parentPath = '') => {
-            const result: AuthMenu[] = []
-            list.forEach((e) => {
-                if (e.authType === AuthType.Menu) {
-                    const routePath = (parentPath ? parentPath + '/' : '') + e.url
-                    result.push({
-                        path: routePath,
-                        name: e.code,
-                        label: e.title,
-                        icon: e.icon,
-                        children: e.children ? filterMenu(e.children, routePath) : [],
-                    })
-                }
-            })
-            return result
-        }
-        return filterMenu(filterLevel(userMenus, level))
+        })
+        return result
     }
 
     /**
-     * 获取路由子菜单
-     * @param routeName 
+     * 根据 code 查找对应的子菜单
      * @returns 
      */
-    const getChildrenMenus = (routeName?: string) => {
-        const filter = (list: AuthMenu[]): AuthMenu[] => {
-            if (routeName) {
-                for (const item of list) {
-                    const { name, children } = item
-                    if (name === routeName) return children ?? []
-                    if (children) {
-                        const res = filter(children)
-                        if (res.length) return res
-                    }
-                }
+    const findChildren = (data: Ermcp.UserMenu[], code?: string): Ermcp.UserMenu[] => {
+        const routeName = code ?? route.name?.toString()
+        for (const item of data) {
+            const { code, children } = item
+            if (code === routeName) return children ?? []
+            if (children) {
+                const res = findChildren(children, routeName)
+                if (res.length) return res
             }
-            return []
         }
-        return filter(getMenus())
+        return []
     }
 
     /**
-     * 获取权限子菜单
+     * 获取路由菜单(无限级)
+     * @param level 
      * @returns 
      */
-    const getChildrenAuth = () => {
-        const routeName = code ?? route.name?.toString()
-        const filter = (list: Ermcp.UserMenu[]): Ermcp.UserMenu | undefined => {
-            if (routeName) {
-                for (const item of list) {
-                    const { code, children } = item;
-                    if (code === routeName) return item;
-                    if (children) {
-                        const res = filter(children);
-                        if (res) return res;
-                    }
-                }
+    const getMenus = (level = 0) => {
+        // 过滤层级
+        const filterLevel = (data: Ermcp.UserMenu[], n: number): Ermcp.UserMenu[] => {
+            if (level) {
+                return data.map((e) => ({ ...e, children: n <= 1 ? [] : filterLevel(e.children ?? [], n - 1) }))
             }
-            return undefined;
+            return data
         }
-        return filter(userMenus);
+        return filterMenu(filterLevel(userMenus, level))
+    }
+
+    /**
+    * 获取路由子菜单
+    * @param code 
+    * @returns 
+    */
+    const getChildrenMenus = (code?: string) => {
+        const children = findChildren(userMenus, code)
+        return filterMenu(children)
     }
 
     /**
@@ -92,24 +73,21 @@ export function useAuth(code?: string) {
      * @returns 
      */
     const getAuth = (authType: AuthType) => {
-        const auth = getChildrenAuth();
-        if (auth && auth.children) {
-            return auth.children.reduce((res, cur) => {
-                if (cur.authType === authType) {
-                    if (!componentMap.get(cur.code) && cur.component) {
-                        const componentString = cur.component.replace(/^\/+/, ''); // 过滤字符串前面所有 '/' 字符
-                        const componentPath = componentString.replace(/\.\w+$/, ''); // 过滤后缀名,为了让 import 加入 .vue ,不然会有警告提示...
-                        const asyncComponent = defineAsyncComponent({
-                            loader: () => import('/' + process.env.VUE_APP_ROOT + componentPath + '.vue'),
-                        });
-                        componentMap.set(cur.code, asyncComponent);
-                    }
-                    res.push(cur);
+        const children = findChildren(userMenus, authCode)
+        return children.reduce((res, cur) => {
+            if (cur.authType === authType) {
+                if (!componentMap.get(cur.code) && cur.component) {
+                    const componentString = cur.component.replace(/^\/+/, '') // 过滤字符串前面所有 '/' 字符
+                    const componentPath = componentString.replace(/\.\w+$/, '') // 过滤后缀名,为了让 import 加入 .vue ,不然会有警告提示...
+                    const asyncComponent = defineAsyncComponent({
+                        loader: () => import('/' + process.env.VUE_APP_ROOT + componentPath + '.vue'),
+                    })
+                    componentMap.set(cur.code, asyncComponent)
                 }
-                return res;
-            }, [] as Ermcp.UserMenu[])
-        }
-        return [];
+                res.push(cur)
+            }
+            return res
+        }, [] as Ermcp.UserMenu[])
     }
 
     /**
@@ -123,13 +101,13 @@ export function useAuth(code?: string) {
         if (filtered.length) {
             if (reverse) {
                 // 返回除指定的权限代码
-                return auth.filter((e) => !filtered.includes(e.code));
+                return auth.filter((e) => !filtered.includes(e.code))
             } else {
                 // 返回指定的权限代码
-                return auth.filter((e) => filtered.includes(e.code));
+                return auth.filter((e) => filtered.includes(e.code))
             }
         }
-        return auth;
+        return auth
     }
 
     /**
@@ -138,7 +116,7 @@ export function useAuth(code?: string) {
      * @param reverse 
      * @returns 
      */
-    const getAuthButton = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Button, filtered, reverse);
+    const getAuthButton = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Button, filtered, reverse)
 
     /**
      * 获取权限组件
@@ -146,7 +124,7 @@ export function useAuth(code?: string) {
      * @param reverse 
      * @returns 
      */
-    const getAuthComponent = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Component, filtered, reverse);
+    const getAuthComponent = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Component, filtered, reverse)
 
     return {
         route,

+ 0 - 23
src/hooks/auth/interface.ts

@@ -1,23 +0,0 @@
-import { Component } from 'vue'
-
-/** 
- * 权限菜单
- */
-export interface AuthMenu {
-    name: string;
-    label: string;
-    path: string;
-    icon: string;
-    children?: AuthMenu[];
-}
-
-/** 
- * 权限数据
- */
-export interface AuthData {
-    code: string;
-    title: string;
-    icon: string;
-    buttonType: string;
-    component: Component;
-}

+ 4 - 4
src/hooks/datatable/index.ts

@@ -11,9 +11,9 @@ export function useDataTable<T>() {
     // 每页条数
     const pageSize = shallowRef(20)
     // 过滤筛选值
-    const filters = shallowRef<FilterValue<T, keyof T>[]>([])
+    const filters = shallowRef<FilterValue<T>[]>([])
     // 过滤选项
-    const filterOptons: { selectList: FilterSelect<T, keyof T>[], inputList: FilterInput<T, keyof T>[], buttonList: FilterButton[] } = reactive({
+    const filterOptons: { selectList: FilterSelect<T>[], inputList: FilterInput<T>[], buttonList: FilterButton[] } = reactive({
         selectList: [],
         inputList: [],
         buttonList: [
@@ -51,7 +51,7 @@ export function useDataTable<T>() {
 
     // 获取过滤参数,支持多条件查询
     const getFilterParam = () => {
-        const options: FilterValue<T, keyof T>[] = []
+        const options: FilterValue<T>[] = []
         filterOptons.selectList.forEach((e) => {
             const { key, selectedValue } = e;
             if (selectedValue !== undefined) {
@@ -77,7 +77,7 @@ export function useDataTable<T>() {
     const getQueryParam = () => {
         const params: { [K in keyof T]?: T[K] } = {}
         filterOptons.selectList.forEach((e) => {
-            if (e.selectedValue) {
+            if (e.selectedValue !== undefined) {
                 params[e.key] = e.selectedValue
             }
         })

+ 11 - 11
src/hooks/datatable/interface.ts

@@ -1,33 +1,33 @@
 /** 
  * 数据过滤项
  */
-export interface FilterValue<T, K extends keyof T> {
-    keys: K[], // 多条件字段
-    filteredValue: (T[K])[], // 多选过滤或模糊查询
+export interface FilterValue<T> {
+    keys: (keyof T)[], // 多条件字段
+    filteredValue: (T[keyof T])[], // 多选过滤或模糊查询
 }
 
 /** 
  * 过滤选择框
  */
-export interface FilterSelect<T, K extends keyof T> {
-    key: K,
+export interface FilterSelect<T> {
+    key: keyof T,
     label?: string,
-    selectedValue?: T[K],
+    selectedValue?: T[keyof T],
     placeholder?: string,
     options: {
         label: string,
-        value: T[K],
+        value: T[keyof T],
     }[],
-    onChange?: (value: T[K]) => void
+    onChange?: (value: T[keyof T]) => void
 }
 
 /** 
  * 过滤输入框
  */
-export interface FilterInput<T, K extends keyof T> {
-    keys: K[],
+export interface FilterInput<T> {
+    keys: (keyof T)[],
     label?: string,
-    value?: T[K],
+    value?: T[keyof T],
     type?: 'text' | 'number',
     placeholder?: string
 }

+ 81 - 0
src/mock/router.ts

@@ -48,6 +48,16 @@ const appmenu = {
             },
             {
                 authType: 1,
+                sort: 2,
+                title: '钻石首饰',
+                code: 'search_jewelry',
+                url: '/search/jewelry',
+                urlType: 1,
+                component: 'views/search/jewelry/index.vue',
+                icon: 'TrendCharts',
+            },
+            {
+                authType: 1,
                 sort: 3,
                 title: '挂牌大厅',
                 code: 'listing',
@@ -232,6 +242,46 @@ const appmenu = {
             },
             {
                 authType: 1,
+                sort: 3,
+                title: '我的收藏',
+                code: 'favorite',
+                url: '/favorite',
+                urlType: 1,
+                component: 'views/favorite/main/index.vue',
+                icon: 'List',
+            },
+            {
+                authType: 1,
+                sort: 3,
+                title: '订单管理',
+                code: 'order',
+                url: '/order',
+                urlType: 1,
+                component: 'Main',
+                icon: 'List',
+                children: [
+                    {
+                        authType: 1,
+                        sort: 1,
+                        title: '我的买履约',
+                        code: 'order_buy',
+                        url: '',
+                        urlType: 1,
+                        component: 'views/order/buy/index.vue',
+                    },
+                    {
+                        authType: 1,
+                        sort: 2,
+                        title: '我的卖履约',
+                        code: 'order_sell',
+                        url: 'sell',
+                        urlType: 1,
+                        component: 'views/order/sell/index.vue'
+                    },
+                ]
+            },
+            {
+                authType: 1,
                 sort: 4,
                 title: '我的仓储',
                 code: 'warehousing',
@@ -440,6 +490,37 @@ const appmenu = {
             },
             {
                 authType: 1,
+                sort: 1,
+                title: '询价消息',
+                code: 'message',
+                url: '/message',
+                urlType: 1,
+                component: 'Main',
+                icon: 'ChatDotRound',
+                hidden: true,
+                children: [
+                    {
+                        authType: 1,
+                        sort: 1,
+                        title: '买方询价',
+                        code: 'message_buy',
+                        url: '',
+                        urlType: 1,
+                        component: 'views/message/buy/index.vue',
+                    },
+                    {
+                        authType: 1,
+                        sort: 1,
+                        title: '卖方询价',
+                        code: 'message_sell',
+                        url: 'sell',
+                        urlType: 1,
+                        component: 'views/message/sell/index.vue',
+                    }
+                ]
+            },
+            {
+                authType: 1,
                 sort: 6,
                 title: '系统管理',
                 code: 'system',

+ 5 - 6
src/packages/pc/App.vue

@@ -30,17 +30,16 @@ eventBus.$on('LogoutNotify', (msg) => {
     if (msg) {
       ElMessageBox.alert(msg as string)
     }
-    isReady.value = false
     router.replace({ name: 'login' })
   })
 })
 
 watch(() => route.name, (routeName) => {
-  if (!isReady.value) {
-    const token = sessionData.getLoginInfo('Token')
-    if (routeName !== 'boot' && token) {
-      isReady.value = true
-    }
+  const token = sessionData.getLoginInfo('Token')
+  if (routeName !== 'boot' && token) {
+    isReady.value = true
+  } else {
+    isReady.value = false
   }
 })
 </script>

+ 3 - 1
src/packages/pc/components/base/drawer/index.vue

@@ -3,7 +3,9 @@
   <app-modal class="app-drawer" :show="show" :close-on-click-mask="false" @mask="close">
     <div class="app-drawer__wrapper" v-loading="loading">
       <div class="app-drawer__header">
-        <h1>{{  title  }}</h1>
+        <slot name="header">
+          <h1>{{ title }}</h1>
+        </slot>
         <el-icon @click="close">
           <Close />
         </el-icon>

+ 13 - 0
src/packages/pc/components/layouts/header/components/calculator/index.vue

@@ -0,0 +1,13 @@
+<!-- 钻石计算器 -->
+<template>
+    <app-drawer title="计算器" v-model:show="show">
+        钻石计算器
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef } from 'vue'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+
+const show = shallowRef(true)
+</script>

+ 13 - 0
src/packages/pc/components/layouts/header/components/certificate/index.vue

@@ -0,0 +1,13 @@
+<!-- 证书查询 -->
+<template>
+    <app-drawer title="证书查询" v-model:show="show">
+        证书查询
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef } from 'vue'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+
+const show = shallowRef(true)
+</script>

+ 69 - 0
src/packages/pc/components/layouts/header/components/notice/index.vue

@@ -0,0 +1,69 @@
+<!-- 系统公告 -->
+<template>
+    <app-drawer title="系统公告" :width="800" v-model:show="show">
+        <template #header>
+            <el-radio-group v-model="selectedTab">
+                <el-radio-button label="notice">公告</el-radio-button>
+                <el-radio-button label="message">消息</el-radio-button>
+            </el-radio-group>
+        </template>
+        <!-- <el-timeline>
+            <template v-for="(item,index) in tableList" :key="index">
+                <el-timeline-item :timestamp="moment(item.createtime).format('YYYY-MM-DD HH:mm:ss')" placement="top">
+                    <el-card shadow="never">
+                        <h4 style="margin-bottom: 10px;font-weight: bold;">{{ item.title }}</h4>
+                        <p>{{ item.content }}</p>
+                    </el-card>
+                </el-timeline-item>
+            </template>
+        </el-timeline> -->
+        <el-collapse v-model="selectedItem" accordion v-if="tableList.length">
+            <template v-for="(item,index) in tableList" :key="index">
+                <el-collapse-item :name="index">
+                    <template #title>
+                        <h4 :style="selectedItem === index ? 'font-weight: bold;' : 'color: #666;'">
+                            <el-badge :is-dot="!item.readed" style="margin-right: 8px;" />
+                            <span>{{ item.title }}</span>
+                        </h4>
+                    </template>
+                    <p style="padding-left: 28px;color: #999;">{{
+                    moment(item.createtime).format('YYYY-MM-DD HH:mm:ss')
+                    }}</p>
+                    <p style="padding-left: 28px;">{{ item.content }}</p>
+                </el-collapse-item>
+            </template>
+        </el-collapse>
+        <el-empty v-else />
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType, computed } from 'vue'
+import moment from 'moment'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+
+const props = defineProps({
+    dataList: {
+        type: Array as PropType<Ermcp.NoticeRsp[]>,
+        default: () => ([])
+    }
+})
+
+const show = shallowRef(true)
+const selectedTab = shallowRef('notice')
+const selectedItem = shallowRef(0)
+
+const tableList = computed(() => {
+    switch (selectedTab.value) {
+        case 'notice': {
+            return props.dataList.filter((e) => e.msgtype === 1)
+        }
+        case 'message': {
+            return props.dataList.filter((e) => e.msgtype === 2)
+        }
+        default: {
+            return []
+        }
+    }
+})
+</script>

+ 7 - 2
src/packages/pc/components/layouts/header/index.less

@@ -27,7 +27,7 @@
                 cursor: pointer;
 
                 &:before {
-                    font-size: 18px;
+                    font-size: 20px;
                 }
             }
 
@@ -45,8 +45,13 @@
                 }
             }
 
+            .el-icon {
+                cursor   : pointer;
+                font-size: 20px;
+            }
+
             >* {
-                margin-right: 20px;
+                margin-right: 16px;
             }
         }
 

+ 46 - 22
src/packages/pc/components/layouts/header/index.vue

@@ -2,7 +2,7 @@
     <div class="app-header">
         <div class="app-header__left">
             <slot name="left"></slot>
-            <el-breadcrumb :separator-icon="ArrowRight" v-show="!state.isMobile">
+            <el-breadcrumb separator-icon="ArrowRight" v-show="!state.isMobile">
                 <template v-for="(item, index) in $route.matched" :key="index">
                     <el-breadcrumb-item :to="{ path: item.path }">
                         <!--<i :class="item.meta.icon" v-if="item.meta.icon"></i>-->
@@ -14,58 +14,82 @@
         <div class="app-header__right">
             <slot name="right"></slot>
             <div class="iconbar">
-                <el-badge type="danger" is-dot>
-                    <span class="g-icon--notice"></span>
+                <el-badge type="danger" :is-dot="unreadList.length > 0">
+                    <app-icon icon="g-icon--notice" @click="openComponent('notice')" />
                 </el-badge>
-                <span class="g-icon--minimize" @click="exitFullSreen" v-if="fullScreen"></span>
-                <span class="g-icon--maximize" @click="setFullSreen" v-else></span>
+                <app-icon icon="ChatDotRound" @click="routerTo('message_buy')" />
+                <app-icon icon="SetUp" @click="openComponent('calculator')" />
+                <app-icon icon="Collection" @click="openComponent('certificate')" />
+                <app-icon icon="g-icon--minimize" @click="exitFullSreen" v-if="fullScreen" />
+                <app-icon icon="g-icon--maximize" @click="setFullSreen" v-else />
             </div>
             <el-dropdown class="user-dropdown" trigger="click">
                 <span class="user-dropdown__link">
-                    <img class="g-image--avatar" :src="admin.avatar" :title="admin.realName" />
-                    <span v-if="!state.isMobile">{{ admin.realName }}</span>
-                    <el-icon class="el-icon--right">
-                        <arrow-down />
-                    </el-icon>
+                    <img class="g-image--avatar" :title="accountName" />
+                    <span v-if="!state.isMobile">{{ accountName }}</span>
+                    <app-icon class="el-icon--right" icon="ArrowDown" />
                 </span>
                 <template #dropdown>
                     <el-dropdown-menu>
-                        <el-dropdown-item :icon="Key">修改密码</el-dropdown-item>
-                        <el-dropdown-item :icon="SwitchButton" @click="logout">退出登录</el-dropdown-item>
+                        <el-dropdown-item icon="Key">修改密码</el-dropdown-item>
+                        <el-dropdown-item icon="SwitchButton" @click="signOut()">退出登录</el-dropdown-item>
                     </el-dropdown-menu>
                 </template>
             </el-dropdown>
         </div>
+        <component :is="componentMap.get(componentId)" v-bind="{ dataList }" @closed="closeComponent"
+            v-if="componentId" />
     </div>
 </template>
 
 <script lang="ts" setup>
-import { ref, onMounted } from 'vue'
-import { ArrowRight, Key, SwitchButton, ArrowDown } from '@element-plus/icons-vue'
+import { ref, onMounted, defineAsyncComponent } from 'vue'
+import { useRouter } from 'vue-router'
 import client from '@/utils/client'
-import { useAdmin } from '@/business/admin'
+import { commonStore } from '@/stores'
+import { useSign } from '@/business/sign'
+import { useComponent } from '@/hooks/component'
+import { useNotice } from '@/business/notice'
+import AppIcon from '@pc/components/base/icon/index.vue'
 
-const { state } = client;
-const { admin, logout } = useAdmin();
-const fullScreen = ref(false);
+const componentMap = new Map<string, unknown>([
+    ['notice', defineAsyncComponent(() => import('./components/notice/index.vue'))],
+    ['calculator', defineAsyncComponent(() => import('./components/calculator/index.vue'))],
+    ['certificate', defineAsyncComponent(() => import('./components/certificate/index.vue'))],
+])
+
+const { componentId, openComponent, closeComponent } = useComponent()
+const { dataList, unreadList, getNoticeList } = useNotice()
+const { state } = client
+const { signOut } = useSign()
+const accountName = commonStore.getAccountName()
+const router = useRouter()
+const fullScreen = ref(false)
 
 // 全屏
 const setFullSreen = () => {
-    document.documentElement.requestFullscreen();
+    document.documentElement.requestFullscreen()
 }
 
 // 退出全屏
 const exitFullSreen = () => {
-    document.exitFullscreen();
+    document.exitFullscreen()
+}
+
+// 路由跳转
+const routerTo = (name: string) => {
+    router.push({ name })
 }
 
+getNoticeList()
+
 onMounted(() => {
     // 监听全屏变化
     window.addEventListener('fullscreenchange', () => {
         if (document.fullscreenElement) {
-            fullScreen.value = true;
+            fullScreen.value = true
         } else {
-            fullScreen.value = false;
+            fullScreen.value = false
         }
     })
 })

+ 6 - 6
src/packages/pc/components/layouts/main/index.vue

@@ -1,5 +1,6 @@
 <template>
-    <app-tabs class="app-main" :data-list="secondMenus" v-model:data-index="dataIndex" @change="onTabChange">
+    <app-tabs class="app-main" prop-label="title" :data-list="secondMenus" v-model:data-index="dataIndex"
+        @change="onTabChange">
         <div id="appMainTeleport" class="app-main__teleport"></div>
         <el-scrollbar class="app-main__scrollbar" view-class="app-main__container" always>
             <!-- 二级路由 -->
@@ -13,17 +14,16 @@
 <script lang="ts" setup>
 import { shallowRef } from 'vue'
 import { useAuth } from '@/hooks/auth'
-import { AuthMenu } from '@/hooks/auth/interface'
 import AppTabs from '@/components/base/tabs/index.vue'
 
 const { route, router, getChildrenMenus } = useAuth()
 const parentRoute = route.matched[route.matched.length - 2] // 父级路由信息
-const secondMenus = shallowRef<AuthMenu[]>([]) // 二级菜单
+const secondMenus = shallowRef<Ermcp.UserMenu[]>([]) // 二级菜单
 const dataIndex = shallowRef(0) // 选中的标签
 
 if (parentRoute) {
     const menus = getChildrenMenus(parentRoute.name?.toString())
-    const index = menus.findIndex((e) => e.name === route.name)
+    const index = menus.findIndex((e) => e.code === route.name)
     secondMenus.value = menus
     if (index > -1) {
         dataIndex.value = index
@@ -31,8 +31,8 @@ if (parentRoute) {
 }
 
 // 切换标签
-const onTabChange = (index: number, { name }: AuthMenu) => {
-    router.push({ name })
+const onTabChange = (index: number, { code }: Ermcp.UserMenu) => {
+    router.push({ name: code })
 }
 </script>
 

+ 3 - 8
src/packages/pc/components/layouts/sidebar/index.less

@@ -9,22 +9,17 @@
 
     &__header,
     &__copyright {
+        display    : inline-flex;
         width      : 0;
         height     : 0;
         white-space: nowrap;
         overflow   : hidden;
-        transform  : translate3d(-100%, 0, 0);
         transition : all 300ms;
 
         &.is-hide {
             border : 0;
             padding: 0;
         }
-
-        &:not(.is-hide) {
-            display  : inline-flex;
-            transform: translate3d(0, 0, 0);
-        }
     }
 
     &__header {
@@ -45,14 +40,14 @@
     &__copyright {
         flex-direction: column;
         font-size     : 12px;
+        height        : auto;
         line-height   : 20px;
         color         : #697b8f;
         padding       : 10px;
         margin-top    : auto;
 
         &:not(.is-hide) {
-            width : var(--sidebar-width);
-            height: auto;
+            width: var(--sidebar-width);
         }
 
         a {

+ 5 - 7
src/packages/pc/components/layouts/sidebar/index.vue

@@ -1,12 +1,12 @@
 <template>
   <el-scrollbar :class="['app-sidebar', collapse && 'is-hide']" view-class="app-sidebar__view">
-    <div :class="['app-sidebar__header', collapse && 'is-hide']">
+    <div :class="['app-sidebar__header', state.isMobile ? 'is-show' : collapse && 'is-hide']">
       <span class="logo">{{ $t('app.name') }}</span>
     </div>
     <div class="app-sidebar__menu">
-      <app-sidemenu :collapse="collapse" @click="routerTo" />
+      <app-sidemenu :collapse="state.isMobile ? false : collapse" @click="routerTo" />
     </div>
-    <div :class="['app-sidebar__copyright', collapse && 'is-hide']">
+    <div :class="['app-sidebar__copyright', state.isMobile ? 'is-show' : collapse && 'is-hide']">
       <span>&copy;{{ year }} Muchinfo</span>
     </div>
     <div :class="['app-sidebar__mask', collapse && 'is-hide']" @click="hideSidebar()" v-if="state.isMobile"></div>
@@ -36,13 +36,11 @@ const hideSidebar = () => {
 
 // 路由跳转
 const routerTo = (active: string) => {
-  if (state.isMobile) {
-    hideSidebar()
-  }
+  hideSidebar()
   const submenus = getChildrenMenus(active)
   // 判断是否存在子菜单
   if (submenus.length) {
-    router.push({ name: submenus[0].name })
+    router.push({ name: submenus[0].code })
   } else {
     router.push({ name: active })
   }

+ 7 - 8
src/packages/pc/components/layouts/sidemenu/submenu.vue

@@ -1,23 +1,23 @@
 <template>
     <template v-for="(item, index) in dataList" :key="index">
-        <el-sub-menu :index="item.name" :show-timeout="100" :hide-timeout="100" v-if="item.children?.length">
+        <el-sub-menu :index="item.code" :show-timeout="100" :hide-timeout="100" v-if="item.children?.length">
             <template #title>
                 <!--如果没有图标,用标题第一个字代替-->
                 <template v-if="item.icon">
                     <app-icon class="menu-icon" :icon="item.icon" />
-                    <span>{{ item.label }}</span>
+                    <span>{{ item.title }}</span>
                 </template>
                 <template v-else>
-                    <i class="menu-icon menu-icon--text">{{ item.label.slice(0, 1) }}</i>
-                    <span>{{ item.label.slice(1) }}</span>
+                    <i class="menu-icon menu-icon--text">{{ item.title.slice(0, 1) }}</i>
+                    <span>{{ item.title.slice(1) }}</span>
                 </template>
             </template>
             <!--如果存在子级,递归组件自身-->
             <app-submenu :data-list="item.children" />
         </el-sub-menu>
-        <el-menu-item :index="item.name" @click="onMenuClick" v-else>
+        <el-menu-item :index="item.code" @click="onMenuClick" v-else>
             <app-icon class="menu-icon" :icon="item.icon" v-if="item.icon" />
-            <span>{{ item.label }}</span>
+            <span>{{ item.title }}</span>
         </el-menu-item>
     </template>
 </template>
@@ -25,7 +25,6 @@
 <script lang="ts">
 import { defineComponent, PropType } from 'vue'
 import type { MenuItemRegistered } from 'element-plus'
-import { AuthMenu } from '@/hooks/auth/interface'
 import AppIcon from '@pc/components/base/icon/index.vue'
 
 export default defineComponent({
@@ -36,7 +35,7 @@ export default defineComponent({
     emits: ['click'],
     props: {
         dataList: {
-            type: Array as PropType<AuthMenu[]>,
+            type: Array as PropType<Ermcp.UserMenu[]>,
             required: true,
         },
     },

+ 9 - 0
src/packages/pc/views/favorite/main/index.vue

@@ -0,0 +1,9 @@
+<!-- 我的收藏 -->
+<template>
+    <app-view>
+        我的收藏
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+</script>

+ 13 - 0
src/packages/pc/views/home/main/index.less

@@ -0,0 +1,13 @@
+.home-main {
+    &__card {
+        display: flex;
+
+        .el-card {
+            flex: 1;
+
+            +.el-card {
+                margin-left: 20px;
+            }
+        }
+    }
+}

+ 27 - 2
src/packages/pc/views/home/main/index.vue

@@ -1,8 +1,33 @@
 <template>
     <app-view class="home-main">
-        首页
+        <div class="home-main__card">
+            <el-card>
+                <h2>1</h2>
+                <p>出售中的交易</p>
+            </el-card>
+            <el-card>
+                <h2>2</h2>
+                <p>求购中的交易</p>
+            </el-card>
+            <el-card>
+                <h2>3</h2>
+                <p>已购买的交易</p>
+            </el-card>
+            <el-card>
+                <h2>4</h2>
+                <p>已卖出的交易</p>
+            </el-card>
+            <el-card>
+                <h2>5</h2>
+                <p>未处理消息</p>
+            </el-card>
+        </div>
     </app-view>
 </template>
 
 <script lang="ts" setup>
-</script>
+</script>
+
+<style lang="less" scoped>
+@import './index.less';
+</style>

+ 3 - 9
src/packages/pc/views/listing/inquire/index.vue

@@ -2,14 +2,7 @@
 <template>
     <app-view>
         <template #header>
-            <el-radio-group v-model="selectedBuyOrSell" :disabled="loading" @change="getInquireOrderList">
-                <el-radio-button :label="item.value" v-for="(item, index) in buyOrSell" :key="index">
-                    {{ item.label }}
-                </el-radio-button>
-            </el-radio-group>
-            <el-select v-model="selectedStatus" :disabled="loading" @change="getInquireOrderList" style="width:160px">
-                <el-option v-for="option in status" :key="option.value" :value="option.value" :label="option.label" />
-            </el-select>
+            <app-filter v-bind="{ selectList,  buttonList }" :loading="loading" />
         </template>
         <!-- 表格数据 -->
         <app-table :data="dataList" v-model:columns="columns" :loading="loading">
@@ -37,8 +30,9 @@ import { getApplyStatusName, ApplyStatus } from '@/constants/order'
 import AppTable from '@pc/components/base/table/index.vue'
 import AppPagination from '@pc/components/base/pagination/index.vue'
 import AppAuthOperation from '@pc/components/modules/auth-operation/index.vue'
+import AppFilter from '@pc/components/base/table-filter/index.vue'
 
-const { loading, dataList, total, pageIndex, pageSize, columns, buyOrSell, status, selectedBuyOrSell, selectedStatus, getInquireOrderList } = useInquireOrder()
+const { loading, dataList, total, pageIndex, pageSize, columns, selectList, buttonList, getInquireOrderList } = useInquireOrder()
 
 // “待确认”状态 有撤销按钮
 const handleTableButtons = (row: Ermcp.MyBargainApplyRsp | Ermcp.MyDelistingApplyRsp) => {

+ 7 - 0
src/packages/pc/views/listing/sale/components/details/index.vue

@@ -0,0 +1,7 @@
+<template>
+    <div>详情</div>
+</template>
+
+<script lang="ts" setup>
+
+</script>

+ 8 - 0
src/packages/pc/views/message/buy/index.vue

@@ -0,0 +1,8 @@
+<template>
+    <app-view>
+        买方询价
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+</script>

+ 8 - 0
src/packages/pc/views/message/sell/index.vue

@@ -0,0 +1,8 @@
+<template>
+    <app-view>
+        卖方询价
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+</script>

+ 9 - 0
src/packages/pc/views/order/buy/index.vue

@@ -0,0 +1,9 @@
+<!-- 订单管理-我的买履约 -->
+<template>
+    <app-view>
+        我的买履约
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+</script>

+ 9 - 0
src/packages/pc/views/order/sell/index.vue

@@ -0,0 +1,9 @@
+<!-- 订单管理-我的卖履约 -->
+<template>
+    <app-view>
+        我的卖履约
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+</script>

+ 1 - 1
src/packages/pc/views/search/fancy/index.vue

@@ -69,7 +69,7 @@ import AppTable from '@pc/components/base/table/index.vue'
 import AppAuthOperation from '@pc/components/modules/auth-operation/index.vue'
 import AppPagination from '@pc/components/base/pagination/index.vue'
 
-const { loading, warehouseList, dataList, columns, total, pageIndex, pageSize, formData, enums, getSellOrderList, onSearch, onReset } = useSearch(Category.Diamond)
+const { loading, warehouseList, dataList, columns, total, pageIndex, pageSize, formData, enums, getSellOrderList, onSearch, onReset } = useSearch(Category.Fancy)
 const formRef = ref<FormInstance>()
 
 const formRules: FormRules = {

+ 12 - 0
src/packages/pc/views/search/jewelry/index.less

@@ -0,0 +1,12 @@
+.search-jewelry {
+    &__list {
+        display  : flex;
+        flex-wrap: wrap;
+        gap      : 20px;
+
+        li {
+            border: 1px solid #ccc;
+            cursor: pointer;
+        }
+    }
+}

+ 71 - 0
src/packages/pc/views/search/jewelry/index.vue

@@ -0,0 +1,71 @@
+<!-- 钻石搜索-钻石首饰 -->
+<template>
+    <app-view class="search-jewelry">
+        <template #header>
+            <el-form ref="formRef" label-width="80px" :rules="formRules">
+                <el-form-item label="款式">
+                    <app-multiple :data-list="enums.styleTypeList" v-model="formData.zsstyletype" checkbox />
+                </el-form-item>
+                <el-form-item label="形状">
+                    <app-multiple :data-list="enums.shapeTypeList" v-model="formData.zsshapetype" checkbox />
+                </el-form-item>
+                <el-form-item label="颜色">
+                    <app-multiple :data-list="enums.colorTypeList" v-model="formData.zscolortype" checkbox />
+                </el-form-item>
+                <el-form-item label="净度">
+                    <app-multiple :data-list="enums.clarityTypeList" v-model="formData.zsclaritytype" checkbox />
+                </el-form-item>
+                <el-form-item label="切工">
+                    <app-multiple :data-list="enums.cutTypeList" v-model="formData.zscuttype" checkbox />
+                </el-form-item>
+                <el-form-item label="对称">
+                    <app-multiple :data-list="enums.symmetryTypeList" v-model="formData.zssymmetrytype" checkbox />
+                </el-form-item>
+                <el-form-item label="抛光">
+                    <app-multiple :data-list="enums.polishTypeList" v-model="formData.zspolishtype" checkbox />
+                </el-form-item>
+                <el-form-item label="荧光">
+                    <app-multiple :data-list="enums.fluorescenceTypeList" v-model="formData.zsfluorescencetype"
+                        checkbox />
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" :loading="loading" @click="onSearch">搜索</el-button>
+                    <el-button :disabled="loading" @click="onReset">重置</el-button>
+                </el-form-item>
+            </el-form>
+        </template>
+        <div class="search-jewelry__list" v-if="dataList.length">
+            <template v-for="(item,index) in dataList" :key="index">
+                <el-card shadow="hover" @click="openComponent('details')">
+                    <h4>{{item.goodsno}}</h4>
+                    <p>{{item.zsstyletypedisplay}}</p>
+                </el-card>
+            </template>
+        </div>
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+import { ref } from 'vue'
+import { ElMessage } from 'element-plus'
+import type { FormInstance, FormRules } from 'element-plus'
+import { useSearch } from '@/business/search'
+import { Category } from '@/constants/diamond'
+import AppMultiple from '@pc/components/base/multiple/index.vue'
+
+const { loading, dataList, formData, enums, getSellOrderList, onSearch, onReset } = useSearch(Category.Jewelry)
+const formRef = ref<FormInstance>()
+const formRules: FormRules = {}
+const componentId = ref<string>()
+
+const openComponent = (code: string) => {
+    componentId.value = code
+    console.log('打开详情')
+}
+
+getSellOrderList().catch((err) => ElMessage.error(err))
+</script>
+
+<style lang="less" scoped>
+@import './index.less';
+</style>

+ 86 - 6
src/packages/pc/views/warehousing/goods/components/details/index.vue

@@ -13,19 +13,99 @@
                 </div>
             </template>
             <template v-if="details">
-                <div class="app-details__intro">
+                <div class="app-details__intro" style="line-height:normal;margin-bottom:48px">
                     <div class="gallery">
 
                     </div>
                     <div class="info">
-                        <h1>商品详情</h1>
+                        <h1>【{{details.zscategorydisplay}}】 商品编号 {{details.goodsno}}</h1>
+                        <table>
+                            <tbody>
+                                <tr>
+                                    <td>商品备注</td>
+                                    <td>{{details.remark}}</td>
+                                </tr>
+                                <tr>
+                                    <td>克拉重量</td>
+                                    <td>{{details.weight}}</td>
+                                </tr>
+                                <tr>
+                                    <td>价格</td>
+                                    <td>{{details.price}}</td>
+                                </tr>
+                                <tr>
+                                    <td>克拉单价</td>
+                                    <td>{{details.priceper}}</td>
+                                </tr>
+                                <tr>
+                                    <td>市场价</td>
+                                    <td>{{details.marketprice}}</td>
+                                </tr>
+                                <tr>
+                                    <td>汇率</td>
+                                    <td></td>
+                                </tr>
+                                <tr>
+                                    <td>卖家名称</td>
+                                    <td></td>
+                                </tr>
+                                <tr>
+                                    <td>仓库地址</td>
+                                    <td></td>
+                                </tr>
+                            </tbody>
+                        </table>
                     </div>
                 </div>
-                <div class="rule">
-
+                <div class="rule" style="margin-bottom:48px">
+                    <h1>履约规则</h1>
                 </div>
                 <div class="property" style="line-height:normal">
-                    {{ details }}
+                    <h1>钻石属性</h1>
+                    <table>
+                        <tbody>
+                            <tr>
+                                <td>形状</td>
+                                <td>{{details.zsshapetypedisplay}}</td>
+                            </tr>
+                            <tr>
+                                <td>颜色</td>
+                                <td>{{details.zscolortype1display}}</td>
+                            </tr>
+                            <tr>
+                                <td>净度</td>
+                                <td>{{details.zsclaritytype1display}}</td>
+                            </tr>
+                            <tr>
+                                <td>切工</td>
+                                <td>{{details.zscuttype1display}}</td>
+                            </tr>
+                            <tr>
+                                <td>对称度</td>
+                                <td>{{details.zssymmetrytype1display}}</td>
+                            </tr>
+                            <tr>
+                                <td>抛光度</td>
+                                <td>{{details.zspolishtype1display}}</td>
+                            </tr>
+                            <tr>
+                                <td>荧光</td>
+                                <td>{{details.zsfluorescencetype1display}}</td>
+                            </tr>
+                            <tr>
+                                <td>尺寸</td>
+                                <td>{{details.size1}}</td>
+                            </tr>
+                            <tr>
+                                <td>证书类型</td>
+                                <td>{{details.zscerttypedisplay}}</td>
+                            </tr>
+                            <tr>
+                                <td>证书编号</td>
+                                <td>{{details.cerno}}</td>
+                            </tr>
+                        </tbody>
+                    </table>
                 </div>
             </template>
         </app-view>
@@ -49,7 +129,7 @@ const componentMap = new Map<string, unknown>([
 const props = defineProps({
     teleport: {
         type: String as PropType<'#appPageTeleport' | '#appMainTeleport'>,
-        default: '#appMainTeleport'
+        default: '#appPageTeleport'
     },
     selectedRow: {
         type: Object as PropType<Ermcp.SellOrderRsp & Ermcp.MyWRPositionRsp>,

+ 14 - 0
src/services/api/common/index.ts

@@ -55,4 +55,18 @@ export function deleteNewFuncmenu(params: HttpRequest<{ req: Partial<Ermcp.NewFu
  */
 export function queryRates(params: HttpRequest<{ req: Ermcp.RatesReq, rsp: Ermcp.RatesRsp }>) {
     return httpRequest('/Common/QueryRates', 'get', params);
+}
+
+/**
+ * 通知公告系统消息查询
+ */
+export function queryNotice(params: HttpRequest<{ req: Ermcp.NoticeReq, rsp: Ermcp.NoticeRsp[] }>) {
+    return httpRequest('/Common/QueryNotice', 'get', params);
+}
+
+/**
+ * 通知公告设置已读
+ */
+export function postNoticeReaded(params: HttpRequest<{ req: Ermcp.NoticeReadedReq }>) {
+    return httpRequest('/Common/NoticeReaded', 'post', params);
 }

+ 1 - 1
src/services/api/order/index.ts

@@ -112,6 +112,6 @@ export function queryMyBargainApply(params: HttpRequest<{ req: Ermcp.MyBargainAp
 /**
  * 查询我的询价-出售
  */
-export function queryMyDelistingApply(params: HttpRequest<{ req: Ermcp.MyDelistingApplyReq, rsp: Ermcp.MyBargainApplyRsp[] }>) {
+export function queryMyDelistingApply(params: HttpRequest<{ req: Ermcp.MyDelistingApplyReq, rsp: Ermcp.MyDelistingApplyRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyDelistingApply', 'get', params);
 }

+ 1 - 1
src/services/language/index.ts

@@ -4,7 +4,7 @@ import { Language } from '@/constants/language'
 import { localData } from '@/stores'
 
 export default new (class {
-    i18n = createI18n()
+    i18n = createI18n({})
 
     constructor() {
         const lang = localData.getValue('lang')

+ 38 - 0
src/types/ermcp/common.d.ts

@@ -15,4 +15,42 @@ declare namespace Ermcp {
         oricurrencyid: number; // 源币种ID
         remark: string; // 备注
     }
+
+    /** 通知公告系统消息查询 请求 */
+    interface NoticeReq {
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+        loginID: number; // 登录账号
+        msgType?: number; // 消息类型 - 1:公告通知 2:系统消息
+        onlyUnRead?: boolean; // 是否只获取未读信息
+        lastID?: number; // 自增ID,传入后会返回这个ID后面的记录
+    }
+
+    /** 通知公告系统消息查询 响应 */
+    interface NoticeRsp {
+        auditoruserid: number; // 审核人
+        auditremark: string; // 审核备注
+        audittime: string; // 审核日期
+        autoid: number; // 自增ID
+        content: string; // 内容
+        createtime: string; // 创建时间
+        creatorid: number; // 建仓人
+        endtime: string; // 结束时间
+        istop: number; // 是否置顶 - 0:不置顶 1:置顶
+        msgiconurl: string; // 消息图标Url
+        msgtype: number; // 消息类型 - 1:公告通知 2:系统消息 3:商品到期提货通知
+        publisher: string; // 消息发布者
+        readed: boolean; // 是否已读
+        scheduletime: string; // 计划发送时间
+        sendtype: number; // 推送方式 - 1:全体广播 2:按会员广播 3:个人推送 4:按会员广播(仅会员)
+        sentstatus: number; // 推送状态 - 0:未推送 1:已推送 2:审核拒绝
+        title: string; // 标题
+        userid: number; // 会员/投资者ID推送方式 为 个人时,填写投资者ID
+    }
+
+    /** 通知公告设置已读 请求 */
+    interface NoticeReadedReq {
+        loginID: number; // 登录账号
+        noticeID: number; // 通知公告ID
+    }
 }

+ 2 - 2
src/types/ermcp/goods.d.ts

@@ -14,7 +14,7 @@ declare namespace Ermcp {
         pagesize?: number; // 每页条数
         wruserid: number; // 登录用户ID
         zsallproperties?: string; // 商品(查询字段-模糊查询)
-        zscategory?: number; // 钻石分类枚举ID
+        zscategorys?: string; // 钻石分类, 格式:1,2,3
         warehouseid?: number; // 仓库ID
     }
 
@@ -101,7 +101,7 @@ declare namespace Ermcp {
         goodsno: string; // 商品编号
     }
 
-    /** 获取钻石详情请求 */
+    /** 获取钻石详情响应 */
     interface DiamondDetailsRsp {
         cerno: string; // 证书编号 - 类型:2,4,5
         cpcertno: string; // 金伯利证书编号 - 类型:3

+ 4 - 4
src/types/ermcp/order.d.ts

@@ -30,7 +30,7 @@ declare namespace Ermcp {
         page?: number; // 页码
         pagesize?: number; // 每页条数
         zsallproperties?: string; // 商品(查询字段-模糊查询)
-        zscategory?: number; // 钻石分类枚举ID
+        zscategorys?: string; // 钻石分类, 格式:1,2,3
         wrtradeorderid?: string; // 委托单号
         buyusername?: string; // 卖方(查询字段-模糊查询)
     }
@@ -135,7 +135,7 @@ declare namespace Ermcp {
         page?: number; // 页码
         pagesize?: number; // 每页条数
         zsallproperties?: string; // 商品(查询字段-模糊查询)
-        zscategory?: number; // 钻石分类枚举ID
+        zscategorys?: string; // 钻石分类, 格式:1,2,3
         wrtradeorderid?: string; // 委托单号
         buyusername?: string; // 买方(查询字段-模糊查询)
     }
@@ -192,7 +192,7 @@ declare namespace Ermcp {
         page?: number; // 页码
         pagesize?: number; // 每页条数
         zsallproperties?: string; // 商品(查询字段-模糊查询)
-        zscategory?: number; // 钻石分类枚举ID
+        zscategorys?: string; // 钻石分类, 格式:1,2,3
         wrtradeorderid?: string; // 委托单号
         ishis?: string; // 是否历史查询
     }
@@ -297,7 +297,7 @@ declare namespace Ermcp {
         page?: number; // 页码
         pagesize?: number; // 每页条数
         zsallproperties?: string; // 商品(查询字段-模糊查询)
-        zscategory?: number; // 钻石分类枚举ID
+        zscategorys?: string; // 钻石分类, 格式:1,2,3
         wrtradeorderid?: string; // 委托单号
         ishis?: string; // 是否历史查询
     }