Browse Source

完成饼状图

Purpose 3 months ago
parent
commit
c23a90007f

+ 192 - 10
package-lock.json

@@ -3740,8 +3740,7 @@
     "decamelize": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
-      "dev": true
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
     },
     "decode-uri-component": {
       "version": "0.2.2",
@@ -3928,6 +3927,11 @@
         }
       }
     },
+    "dijkstrajs": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+      "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
+    },
     "dir-glob": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
@@ -4129,12 +4133,22 @@
         }
       }
     },
+    "emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+    },
     "emojis-list": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
       "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
       "dev": true
     },
+    "encode-utf8": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
+      "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
+    },
     "encodeurl": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@@ -8470,6 +8484,11 @@
       "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
       "dev": true
     },
+    "pngjs": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
+      "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="
+    },
     "portfinder": {
       "version": "1.0.32",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
@@ -11014,6 +11033,173 @@
       "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
       "dev": true
     },
+    "qrcode": {
+      "version": "1.5.3",
+      "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
+      "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
+      "requires": {
+        "dijkstrajs": "^1.0.1",
+        "encode-utf8": "^1.0.3",
+        "pngjs": "^5.0.0",
+        "yargs": "^15.3.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+          "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+        },
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "camelcase": {
+          "version": "5.3.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+        },
+        "cliui": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+          "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+          "requires": {
+            "string-width": "^4.2.0",
+            "strip-ansi": "^6.0.0",
+            "wrap-ansi": "^6.2.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+        },
+        "find-up": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+          "requires": {
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "get-caller-file": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+          "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+        },
+        "locate-path": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+          "requires": {
+            "p-locate": "^4.1.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+          "requires": {
+            "p-limit": "^2.2.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+        },
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+        },
+        "require-main-filename": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+        },
+        "string-width": {
+          "version": "4.2.3",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+          "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.1"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+          "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+          "requires": {
+            "ansi-regex": "^5.0.1"
+          }
+        },
+        "wrap-ansi": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "yargs": {
+          "version": "15.4.1",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+          "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+          "requires": {
+            "cliui": "^6.0.0",
+            "decamelize": "^1.2.0",
+            "find-up": "^4.1.0",
+            "get-caller-file": "^2.0.1",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^2.0.0",
+            "set-blocking": "^2.0.0",
+            "string-width": "^4.2.0",
+            "which-module": "^2.0.0",
+            "y18n": "^4.0.0",
+            "yargs-parser": "^18.1.2"
+          }
+        },
+        "yargs-parser": {
+          "version": "18.1.3",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+          "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+          "requires": {
+            "camelcase": "^5.0.0",
+            "decamelize": "^1.2.0"
+          }
+        }
+      }
+    },
     "qs": {
       "version": "6.12.1",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
@@ -11386,8 +11572,7 @@
     "require-directory": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
-      "dev": true
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
     },
     "require-from-string": {
       "version": "1.2.1",
@@ -11971,8 +12156,7 @@
     "set-blocking": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
-      "dev": true
+      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
     },
     "set-function-length": {
       "version": "1.2.2",
@@ -14457,8 +14641,7 @@
     "which-module": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
-      "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
-      "dev": true
+      "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
     },
     "which-typed-array": {
       "version": "1.1.15",
@@ -14584,8 +14767,7 @@
     "y18n": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
-      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
-      "dev": true
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
     },
     "yallist": {
       "version": "2.1.2",

+ 1 - 0
package.json

@@ -18,6 +18,7 @@
     "html2canvas": "^1.4.1",
     "jspdf": "^2.5.1",
     "print-js": "^1.6.0",
+    "qrcode": "^1.5.3",
     "qs": "^6.12.1",
     "vue": "^2.5.2",
     "vue-barcode": "^1.3.0",

+ 8 - 0
src/api/DataStatisticsApi.js

@@ -0,0 +1,8 @@
+import { api } from '@@/utils/api'
+
+export default {
+  getTagTypeCountData: () => api({
+    url: '/data/statistics/tag/type/count',
+    method: 'GET'
+  })
+}

+ 5 - 2
src/assets/main.scss

@@ -37,17 +37,20 @@
 }
 
 .table-operator-item {
-  gap: 2px;
+  gap: 5px;
   user-select: none;
   cursor: pointer;
 
   &:hover {
+    > i,
+    > svg,
     > span {
       color: var(--brand-border-color);
     }
   }
 
-  > i {
+  > i,
+  > svg {
     color: #BDBDBC
   }
 

+ 97 - 0
src/components/EChart.vue

@@ -0,0 +1,97 @@
+<template>
+<div style="position:relative;width:100%;height:100%">
+  <div ref="chart" class="chart"></div>
+</div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+
+export default {
+  name: 'EChart',
+  props: {
+    showBackBtn: Boolean
+  },
+  methods: {
+    afterInit (chart) {
+      this.$emit('initialized', chart)
+    },
+    destroy () {
+      this.$emit('destroy', this.myChart)
+    },
+    getChartWrapper () {
+      return this.$refs.chart
+    },
+    clear () {
+      let myChart = this.myChart
+      myChart && myChart.clear()
+    },
+    setOpt (option, isReal) {
+      let myChart = this.myChart
+
+      if (!myChart) {
+        return
+      }
+
+      if (!isReal) {
+        this.clear()
+      }
+
+      myChart.setOption(option)
+    },
+    getOpt () {
+      let {myChart} = this
+      return myChart && myChart.getOption()
+    },
+    refreshOpt (opt, updateOpt) {
+      let {myChart} = this
+
+      if (!myChart) {
+        return
+      }
+
+      myChart.setOption(opt, updateOpt)
+    },
+    getLinear (x1, y1, x2, y2, opts) {
+      return new echarts.graphic.LinearGradient(x1, y1, x2, y2, opts)
+    },
+    getData (list, callback) {
+      return echarts.util.map(list, callback)
+    },
+    connect (chartComponentList) {
+      echarts.connect(chartComponentList.map(chartComponent => chartComponent.myChart))
+    },
+    resize () {
+      this.myChart && document.body.contains(this.$el) && this.myChart.resize()
+    },
+    onWindowResize () {
+      this.resize()
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.afterInit(this.myChart = echarts.init(this.getChartWrapper()))
+      window.addEventListener('resize', this.onWindowResize, true)
+    })
+  },
+  beforeDestroy () {
+    let myChart = this.myChart
+
+    if (myChart) {
+      this.destroy()
+      this.clear()
+      myChart.dispose()
+      this.myChart = null
+    }
+
+    window.removeEventListener('resize', this.onWindowResize, true)
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.chart {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 4 - 1
src/components/EditButton.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="table-operator-item flex valign-center" @click="onClick(data)">
-    <i class="el-icon-edit"></i><span class="">编辑</span>
+    <slot name="icon"><i :class="icon"></i></slot><span><slot /></span>
   </div>
 </template>
 
@@ -12,6 +12,9 @@ export default {
       required: true,
       type: Object
     },
+    icon: {
+      type: String
+    },
     onClick: {
       required: true,
       type: Function

+ 70 - 0
src/components/QrCodeView.vue

@@ -0,0 +1,70 @@
+<template>
+  <div class="wrapper relative">
+    <canvas ref="qrCodeCanvas" />
+    <slot v-if="!text" name="empty" />
+  </div>
+</template>
+
+<script>
+import QrCode from 'qrcode'
+
+export default {
+  name: 'QrCodeView',
+  props: {
+    text: {
+      type: String,
+      required: true
+    }
+  },
+  methods: {
+    setSize () {
+      const el = this.$el
+      const qrCodeCanvas = this.$refs.qrCodeCanvas
+      qrCodeCanvas.width = el.offsetWidth
+      qrCodeCanvas.height = el.offsetHeight
+    },
+    genQRCode () {
+      const { qrCodeCanvas } = this.$refs
+      const { text } = this
+      if (text) {
+        QrCode.toCanvas(qrCodeCanvas, text, error => {
+          if (error) console.error(error)
+        })
+      } else {
+        const ctx = qrCodeCanvas.getContext('2d')
+        ctx.clearRect(0, 0, qrCodeCanvas.width, qrCodeCanvas.height)
+      }
+    },
+    render () {
+      this.setSize()
+      this.genQRCode()
+    },
+    clearResizeTimer () {
+      clearTimeout(this.resizeTimer)
+    },
+    onWindowResize () {
+      this.clearResizeTimer()
+      this.resizeTimer = setTimeout(() => {
+        this.render()
+      }, 100)
+    }
+  },
+  watch: {
+    text () {
+      this.genQRCode()
+    }
+  },
+  created () {
+    window.addEventListener('resize', this.onWindowResize)
+  },
+  mounted () {
+    this.render()
+  },
+  beforeDestroy () {
+    this.clearResizeTimer()
+    window.removeEventListener('resize', this.onWindowResize)
+  }
+}
+</script>
+
+<style lang="scss"></style>

+ 7 - 8
src/entries/TagCode.js

@@ -5,10 +5,10 @@ import tagCodeApi from '@@/api/TagCodeApi'
 export default class TagCode extends BaseCurdEntry {
   orderNo
 
-  serialNumber
-  get formatSerialNumber () {
-    const { serialNumber } = this
-    return serialNumber ? serialNumber.join('-') : ''
+  serialNumberRange
+  get formatSerialNumberRange () {
+    const { serialNumberRange } = this
+    return serialNumberRange ? serialNumberRange.join('-') : ''
   }
 
   dataTime
@@ -16,10 +16,9 @@ export default class TagCode extends BaseCurdEntry {
     return new Date(this.dataTime).format('YYYY-MM-DD')
   }
 
-  receiveDate
-  get formatReceiveDate () {
-    const { receiveDate } = this
-    return receiveDate ? new Date(receiveDate).format('YYYY-MM-DD') : ''
+  expectedReceiptDate
+  get formatExpectedReceiptDate () {
+    return new Date(this.expectedReceiptDate).format('YYYY-MM-DD')
   }
 
   providerName

+ 37 - 0
src/mock/index.js

@@ -105,4 +105,41 @@ Mock.mock(/\/tag\/purchase\/in-storage/, 'put', {
   data: true
 })
 
+Mock.mock(/\/tag\/code\/page/, 'post', {
+  type: 'success',
+  data: {
+    'count|10-40': 1,
+    'list|1-20': [{
+      'id|1-20': 1,
+      dataTime: '2024/01/01 00:00:00',
+      orderNo: '123456',
+      expectedReceiptDate: '2024/01/02 00:00:00',
+      serialNumberRange: ['0000001', '000800'],
+      'providerName|1': ['人民电器集团有限公司', '上海东生供用电器材厂', '上海辉电电力设备工程有限公司'],
+      'tagTypeName|1': ['高性能不干胶标签', '柔性抗金属标签', '扎带标签'],
+      number: 123,
+      'amount|1-100.1-2': 30,
+      'tagApplyStateName|1': ['待支付', '待发货', '已发货'],
+      operatorName: '操作员',
+      applicantName: '申领人',
+      'unitPrice|1-100.1-2': 10,
+      createTime: '2024/01/01 00:00:00'
+    }]
+  }
+})
+
+Mock.mock(`${API_BASE_PATH}/data/statistics/tag/type/count`, 'get', {
+  type: 'success',
+  data: [{
+    name: '高性能不干胶标签',
+    'value|50-300': 50
+  }, {
+    name: '柔性抗金属标签',
+    'value|50-300': 50
+  }, {
+    name: '扎带标签',
+    'value|50-300': 50
+  }]
+})
+
 export default Mock

+ 3 - 3
src/utils/BaseCurdList.js

@@ -7,7 +7,7 @@ export default (Target, hasPagination = true) => ({
   extends: BaseCurd(Target),
   data: () => ({
     optionGroup: Object.freeze({}),
-    query: Target.$$getQuery(),
+    query: Target.$$getQuery() || {},
     oQuery: {},
     pagination: {
       pageNo: 0,
@@ -76,9 +76,9 @@ export default (Target, hasPagination = true) => ({
     onRowClick (data) {
       this.selectedData = data
     },
-    onOpenEditorBtnClick (data) {
+    onOpenEditorBtnClick (data, isView) {
       const editor = this.getEditor()
-      data instanceof Event ? editor.open() : editor.open(data)
+      data instanceof Event ? editor.open() : editor.open(data, isView)
     },
     deleteSuccess () {
       this.loadList()

+ 206 - 2
src/views/TagCode.vue

@@ -1,5 +1,193 @@
 <template>
-  <div></div>
+  <div class="wrapper flex column layout-gap">
+    <el-card
+      shadow="hover"
+      class="z-card flex column flex-1 fit-size"
+    >
+      <div class="wrapper flex column layout-gap">
+        <div class="flex valign-center">
+          <el-button
+           :disabled="selectedList.length === 0"
+            plain
+            icon="el-icon-plus"
+            type="primary"
+            size="small"
+            class="custom-plain-button"
+            @click="onCodeBtnClick"
+          >赋码</el-button>
+
+          <el-button
+            :disabled="selectedList.length === 0"
+            plain
+            type="primary"
+            size="small"
+            class="custom-plain-button"
+            @click="onBatchPrintBtnClick"
+          >
+            <div class="flex center" style="height:1em">
+              <svg
+                viewBox="0 0 1024 1024"
+                version="1.1"
+                xmlns="http://www.w3.org/2000/svg"
+                width="14"
+                height="14"
+              >
+                <path d="M928 288H96v384h160v224h512V672h160zM704 832H320V544h384z m160-224h-96v-128H256v128h-96V352h704zM320 192h384v64h64V128H256v128h64v-64z" fill="currentColor"></path>
+                <path d="M384 608h256v64H384zM384 704h256v64H384z" fill="currentColor"></path>
+                <path d="M800 416m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" fill="currentColor"></path>
+              </svg>
+              <span style="margin-left:5px;">批量打印</span>
+            </div>
+          </el-button>
+        </div>
+
+        <div class="flex-1 fit-size">
+          <el-table
+            ref="table"
+            :data="list"
+            stripe
+            border
+            height="100%"
+            size="small"
+            class="custom-el-table-style"
+            @selection-change="onSelectionChange"
+          >
+            <el-table-column
+              type="selection"
+              width="55"
+              align="center"
+              fixed
+            ></el-table-column>
+            <el-table-column
+              type="index"
+              label="序号"
+              width="60"
+              align="center"
+              fixed
+            ></el-table-column>
+            <el-table-column
+              label="订单编号"
+              prop="orderNo"
+              min-width="120"
+              header-align="center"
+              align="center"
+              fixed
+            ></el-table-column>
+            <el-table-column
+              label="流水号范围"
+              prop="formatSerialNumberRange"
+              min-width="200"
+              header-align="center"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              label="申领日期"
+              prop="formatDataTime"
+              min-width="100"
+              header-align="center"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              label="预期收货日期"
+              prop="formatExpectedReceiptDate"
+              min-width="100"
+              header-align="center"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              label="供应商名称"
+              prop="providerName"
+              min-width="200"
+              header-align="center"
+              align="left"
+            ></el-table-column>
+            <el-table-column
+              label="标签类型"
+              prop="tagTypeName"
+              min-width="150"
+              header-align="center"
+              align="left"
+            ></el-table-column>
+            <el-table-column
+              label="需求数量"
+              prop="number"
+              min-width="85"
+              header-align="center"
+              align="right"
+            ></el-table-column>
+            <el-table-column
+              label="费用(元)"
+              prop="amount"
+              min-width="84"
+              header-align="center"
+              align="right"
+            ></el-table-column>
+            <el-table-column
+              label="状态"
+              prop="tagApplyStateName"
+              min-width="70"
+              header-align="center"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              label="操作员"
+              prop="operatorName"
+              min-width="85"
+              header-align="center"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              label="操作栏"
+              min-width="260"
+              header-align="center"
+              align="center"
+            >
+              <template v-slot="{ row }">
+                <div class="flex center layout-gap">
+                  <edit-button :data="row" :on-click="onOpenEditorBtnClick" icon="el-icon-edit">编辑</edit-button>
+                  <edit-button :data="row" :on-click="onOpenDetailEditorBtnClick" icon="el-icon-view">详情</edit-button>
+                  <edit-button :data="row" :on-click="onPreviewBtnClick" icon="el-icon-view">预览</edit-button>
+                  <edit-button :data="row" :on-click="onPrintBtnClick" icon="el-icon-view">
+                    <template #icon>
+                      <svg
+                        viewBox="0 0 1024 1024"
+                        version="1.1"
+                        xmlns="http://www.w3.org/2000/svg"
+                        width="14"
+                        height="14"
+                      >
+                        <path d="M928 288H96v384h160v224h512V672h160zM704 832H320V544h384z m160-224h-96v-128H256v128h-96V352h704zM320 192h384v64h64V128H256v128h64v-64z" fill="currentColor"></path>
+                        <path d="M384 608h256v64H384zM384 704h256v64H384z" fill="currentColor"></path>
+                        <path d="M800 416m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" fill="currentColor"></path>
+                      </svg>
+                    </template>
+                    打印
+                  </edit-button>
+                </div>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+
+        <my-pagination
+          :total="total"
+          :pagination="pagination"
+          @current-change="currentPageNoChange"
+        />
+      </div>
+    </el-card>
+
+    <el-card
+      shadow="hover"
+      class="z-card"
+      style="background:#f8f8f8;"
+    >
+      <div class="flex column center layout-gap">
+        <div class="flex center">打印预览</div>
+        <div></div>
+      </div>
+    </el-card>
+  </div>
 </template>
 
 <script>
@@ -9,7 +197,23 @@ import TagCode from '@@/entries/TagCode'
 export default {
   name: 'TagCode',
   extends: BaseCurdList(TagCode),
-  methods: {}
+  methods: {
+    onOpenDetailEditorBtnClick (data) {
+      this.onOpenEditorBtnClick(data, true)
+    },
+    onCodeBtnClick () {
+
+    },
+    onBatchPrintBtnClick () {
+
+    },
+    onPreviewBtnClick () {
+
+    },
+    onPrintBtnClick () {
+
+    }
+  }
 }
 </script>
 

+ 49 - 2
src/views/TagInventory.vue

@@ -1,10 +1,57 @@
 <template>
-  <div></div>
+  <div class="wrapper flex column layout-gap">
+    <el-card
+      shadow="hover"
+      class="z-card flex column flex-1 fit-size"
+    >
+      <div class="wrapper flex column layout-gap">
+        <div style="font-weight:bolder">饼状图</div>
+        <div class="flex-1 fit-size">
+          <e-chart ref="eChart"></e-chart>
+        </div>
+      </div>
+    </el-card>
+  </div>
 </template>
 
 <script>
+import BasePage from '@@/utils/BasePage'
+
+import dataStatisticsApi from '@@/api/DataStatisticsApi'
+
 export default {
-  name: 'TagInventory'
+  name: 'TagInventory',
+  extends: BasePage,
+  methods: {
+    getData () {
+      this.$$request(dataStatisticsApi.getTagTypeCountData).then(tagTypeCountDataList => {
+        if (tagTypeCountDataList.length > 0) {
+          this.$refs.eChart.setOpt({
+            series: [{
+              type: 'pie',
+              data: tagTypeCountDataList,
+              color: '#0078da',
+              itemStyle: {
+                borderColor: '#fff',
+                borderWidth: 1
+              },
+              label: {
+                formatter: '{b}\n{c}({d}%)',
+                position: 'inside',
+                fontSize: 14,
+                lineHeight: 20
+              }
+            }]
+          })
+        } else {
+          this.$refs.eChart.clear()
+        }
+      }).catch(console.error).finally(() => {})
+    }
+  },
+  created () {
+    this.getData()
+  }
 }
 </script>
 

+ 1 - 1
src/views/TagPurchase.vue

@@ -166,7 +166,7 @@
             >
               <template v-slot="{ row }">
                 <div class="flex center layout-gap">
-                  <edit-button :data="row" :on-click="onOpenEditorBtnClick"></edit-button>
+                  <edit-button :data="row" :on-click="onOpenEditorBtnClick" icon="el-icon-edit">编辑</edit-button>
                 </div>
               </template>
             </el-table-column>