Browse Source

Merge branch 'deploy' of jianguan-web/qpls-md-html into master

陈瑞 4 years ago
parent
commit
fb041e7596

+ 79 - 38
package-lock.json

@@ -1148,6 +1148,22 @@
       "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
       "dev": true
     },
+    "@simonwep/pickr": {
+      "version": "1.7.4",
+      "resolved": "https://registry.npmjs.org/@simonwep/pickr/-/pickr-1.7.4.tgz",
+      "integrity": "sha512-fq7jgKJT21uWGC1mARBHvvd1JYlEf93o7SuVOB4Lr0x/2UPuNC9Oe9n/GzVeg4oVtqMDfh1wIEJpsdOJEZb+3g==",
+      "requires": {
+        "core-js": "^3.6.5",
+        "nanopop": "^2.1.0"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "3.15.2",
+          "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz",
+          "integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q=="
+        }
+      }
+    },
     "@soda/friendly-errors-webpack-plugin": {
       "version": "1.7.1",
       "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz",
@@ -2313,12 +2329,13 @@
       "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
     },
     "ant-design-vue": {
-      "version": "1.4.0-beta.0",
-      "resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-1.4.0-beta.0.tgz",
-      "integrity": "sha512-MZnb5Pwr4mlYoE2pHB5XMeL22pmPlKF7WkQszS18t7VygS9Q/gF8nJl94nebv6EHJRrKg0i/6Axh1gR0vXb6Hg==",
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-1.7.6.tgz",
+      "integrity": "sha512-EOS6g/deT53xHxZDMOxedyBehXSNMGnxdOeQtDksmiRvCBrZs+yoFYoVOe9pmQ8EJ7XQLn8TMReiYbXi78kppA==",
       "requires": {
         "@ant-design/icons": "^2.1.1",
         "@ant-design/icons-vue": "^2.0.0",
+        "@simonwep/pickr": "~1.7.0",
         "add-dom-event-listener": "^1.0.2",
         "array-tree-filter": "^2.1.0",
         "async-validator": "^3.0.3",
@@ -2326,13 +2343,14 @@
         "babel-runtime": "6.x",
         "classnames": "^2.2.5",
         "component-classes": "^1.2.6",
-        "dom-align": "^1.7.0",
+        "dom-align": "^1.10.4",
         "dom-closest": "^0.2.0",
-        "dom-scroll-into-view": "^1.2.1",
+        "dom-scroll-into-view": "^2.0.0",
         "enquire.js": "^2.1.6",
         "intersperse": "^1.0.0",
+        "is-mobile": "^2.2.1",
         "is-negative-zero": "^2.0.0",
-        "ismobilejs": "^0.5.1",
+        "ismobilejs": "^1.0.0",
         "json2mq": "^0.2.0",
         "lodash": "^4.17.5",
         "moment": "^2.21.0",
@@ -2343,8 +2361,8 @@
         "resize-observer-polyfill": "^1.5.1",
         "shallow-equal": "^1.0.0",
         "shallowequal": "^1.0.2",
-        "vue-ref": "^1.0.4",
-        "warning": "^3.0.0"
+        "vue-ref": "^2.0.0",
+        "warning": "^4.0.0"
       }
     },
     "any-promise": {
@@ -2570,9 +2588,9 @@
       "dev": true
     },
     "async-validator": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.2.0.tgz",
-      "integrity": "sha512-QBuW7Qrg8wbh7Wtqw1QdN162GUmXDs9gayxFaXcCOf3bCqHJ/TQep0H4I63iVk7Q3kIGWU4wbAr/C0Uj64JiMw=="
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.5.2.tgz",
+      "integrity": "sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ=="
     },
     "asynckit": {
       "version": "0.4.0",
@@ -3720,9 +3738,9 @@
       }
     },
     "classnames": {
-      "version": "2.2.6",
-      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
-      "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
+      "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
     },
     "clean-css": {
       "version": "4.2.1",
@@ -5505,9 +5523,9 @@
       }
     },
     "dom-align": {
-      "version": "1.10.2",
-      "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.10.2.tgz",
-      "integrity": "sha512-AYZUzLepy05E9bCY4ExoqHrrIlM49PEak9oF93JEFoibqKL0F7w5DLM70/rosLOawerWZ3MlepQcl+EmHskOyw=="
+      "version": "1.12.2",
+      "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.2.tgz",
+      "integrity": "sha512-pHuazgqrsTFrGU2WLDdXxCFabkdQDx72ddkraZNih1KsMcN5qsRSTR9O4VJRlwTPCPb5COYg3LOfiMHHcPInHg=="
     },
     "dom-closest": {
       "version": "0.2.0",
@@ -5538,9 +5556,9 @@
       "integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
     },
     "dom-scroll-into-view": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz",
-      "integrity": "sha1-6PNnMt0ImwIBqI14Fdw/iObWbH4="
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz",
+      "integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w=="
     },
     "dom-serializer": {
       "version": "0.2.1",
@@ -5655,6 +5673,14 @@
         "safer-buffer": "^2.1.0"
       }
     },
+    "echarts": {
+      "version": "4.9.0",
+      "resolved": "https://registry.npmjs.org/echarts/-/echarts-4.9.0.tgz",
+      "integrity": "sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==",
+      "requires": {
+        "zrender": "4.3.2"
+      }
+    },
     "editorconfig": {
       "version": "0.15.3",
       "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
@@ -8975,10 +9001,15 @@
         "is-extglob": "^2.1.1"
       }
     },
+    "is-mobile": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.2.tgz",
+      "integrity": "sha512-wW/SXnYJkTjs++tVK5b6kVITZpAZPtUrt9SF80vvxGiF/Oywal+COk1jlRkiVq15RFNEQKQY31TkV24/1T5cVg=="
+    },
     "is-negative-zero": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
-      "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE="
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
+      "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w=="
     },
     "is-number": {
       "version": "3.0.0",
@@ -9131,9 +9162,9 @@
       "dev": true
     },
     "ismobilejs": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-0.5.2.tgz",
-      "integrity": "sha512-ta9UdV60xVZk/ZafFtSFslQaE76SvNkcs1r73d2PVR21zVzx9xuYv9tNe4MxA1NN7WoeCc2RjGot3Bz1eHDx3Q=="
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz",
+      "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw=="
     },
     "isobject": {
       "version": "3.0.1",
@@ -11817,9 +11848,9 @@
       "dev": true
     },
     "mutationobserver-shim": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
-      "integrity": "sha512-gciOLNN8Vsf7YzcqRjKzlAJ6y7e+B86u7i3KXes0xfxx/nfLmozlW1Vn+Sc9x3tPIePFgc1AeIFhtRgkqTjzDQ=="
+      "version": "0.3.7",
+      "resolved": "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.7.tgz",
+      "integrity": "sha512-oRIDTyZQU96nAiz2AQyngwx1e89iApl2hN5AOYwyxLUB47UYsU3Wv9lJWqH5y/QdiYkc5HQLi23ZNB3fELdHcQ=="
     },
     "mute-stream": {
       "version": "0.0.7",
@@ -11872,6 +11903,11 @@
         }
       }
     },
+    "nanopop": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/nanopop/-/nanopop-2.1.0.tgz",
+      "integrity": "sha512-jGTwpFRexSH+fxappnGQtN9dspgE2ipa1aOjtR24igG0pv6JCxImIAmrLRHX+zUF5+1wtsFVbKyfP51kIGAVNw=="
+    },
     "natural-compare": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -14694,9 +14730,9 @@
       }
     },
     "shallow-equal": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.0.tgz",
-      "integrity": "sha512-Z21pVxR4cXsfwpMKMhCEIO1PCi5sp7KEp+CmOpBQ+E8GpHwKOw2sEzk7sgblM3d/j4z4gakoWEoPcjK0VJQogA=="
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
+      "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
     },
     "shallowequal": {
       "version": "1.1.0",
@@ -16551,9 +16587,9 @@
       }
     },
     "vue-ref": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/vue-ref/-/vue-ref-1.0.6.tgz",
-      "integrity": "sha512-UzD8t1CG+aoWVOOpGd5KcaCNtCgUc0byaKhJMH+6N7H/p1ThVkYl/VCt7DmCrdhUlzZK+hT5JPTKAdrbWi0nNw=="
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/vue-ref/-/vue-ref-2.0.0.tgz",
+      "integrity": "sha512-uKNKpFOVeWNqS2mrBZqnpLyXJo5Q+vnkex6JvpENvhXHFNBW/SJTP8vJywLuVT3DpxwXcF9N0dyIiZ4/NpTexQ=="
     },
     "vue-router": {
       "version": "3.1.3",
@@ -16669,9 +16705,9 @@
       "integrity": "sha1-+9PB1JdpI8nt67hbKdMLNVEq0Dk="
     },
     "warning": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
-      "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
+      "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
       "requires": {
         "loose-envify": "^1.0.0"
       }
@@ -17352,6 +17388,11 @@
           "dev": true
         }
       }
+    },
+    "zrender": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/zrender/-/zrender-4.3.2.tgz",
+      "integrity": "sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g=="
     }
   }
 }

+ 2 - 1
package.json

@@ -35,7 +35,8 @@
     "vue-router": "^3.1.2",
     "vue-svg-component-runtime": "^1.0.1",
     "vuex": "^3.1.1",
-    "wangeditor": "^3.1.1"
+    "wangeditor": "^3.1.1",
+    "echarts": "^4.9.0"
   },
   "devDependencies": {
     "@ant-design/colors": "^3.2.1",

+ 229 - 0
src/components/Echarts/bar.vue

@@ -0,0 +1,229 @@
+<template>
+  <div ref="dom" class="charts chart-bar"></div>
+</template>
+
+<script>
+import echarts from 'echarts'
+import tdTheme from './theme.json'
+import { on, off } from '@/libs/tools'
+
+echarts.registerTheme('tdTheme', tdTheme)
+export default {
+  name: 'ChartBar',
+  props: {
+    // 单列柱状图,列name为x轴,value为y轴
+    value: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    text: String,
+    subtext: String,
+    color: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // 当有多列柱状图展示时的X轴坐标数据
+    xAxisData: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // y轴坐标单位
+    yUnit: {
+      type: String,
+      default: ''
+    },
+    // 当有多列柱状图展示时的y轴坐标数据
+    seriesData: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // x轴标签旋转角度
+    xAxisRotate: {
+      type: Number,
+      default: 0
+    }
+  },
+  watch: {
+    xAxisData: {
+      handler (nVal, oVal) {
+        // console.log(nVal, 'nnnnnnnn')
+        if (nVal) {
+          // 根据x轴时间长度控制滚动条位置及显示状态 x轴长度大于25时,显示滚动条并且滚动条结束位置在80%
+          if (nVal.length > 25) {
+            this.isShowZoom = true
+            this.xZoomEnd = 80
+          } else {
+            this.isShowZoom = false
+            this.xZoomEnd = 100
+          }
+          if (nVal.length > 30) {
+            this.xZoomEnd = 70
+          }
+          if (nVal.length > 35) {
+            this.xZoomEnd = 60
+          }
+          if (nVal.length > 40) {
+            this.xZoomEnd = 50
+          }
+          if (nVal.length > 45) {
+            this.xZoomEnd = 40
+          }
+          if (nVal.length > 50) {
+            this.xZoomEnd = 30
+          }
+          this.pageInit()
+        }
+      },
+      deep: true,
+      immediate: true // 代表如果在 wacth 里声明了 xAxisData 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行
+    },
+    xAxisRotate: {
+      handler (nVal, oVal) {
+        if (nVal !== '') {
+          this.pageInit()
+        }
+      },
+      deep: true,
+      immediate: true
+    },
+    value: {
+      handler (nVal, oVal) {
+        if (nVal) {
+          this.pageInit()
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  data () {
+    return {
+      dom: null,
+      isShowZoom: false, // 是否展示滚动条
+      xZoomEnd: 100 // x轴滚动条结束位置
+    }
+  },
+  methods: {
+    resize () {
+      this.dom.resize()
+    },
+    pageInit () {
+      const that = this
+      const legend = this.seriesData.map(_ => _.name)
+      this.$nextTick(() => {
+        const keys = this.value.map(item => (item = item.name))
+        const values = this.value.map(item => (item = item.value))
+        const xAxisData = this.value.length ? keys : this.xAxisData
+        const seriesData = this.value.length ? values : this.seriesData
+        const yMax = this.getYMax(this.seriesData) // 计算最大值
+        const option = {
+          color: this.color,
+          title: {
+            text: this.text,
+            subtext: this.subtext,
+            x: 'left'
+          },
+          legend: {
+            data: legend
+          },
+          tooltip: {
+            trigger: 'axis'
+          },
+          dataZoom: [
+            {
+              type: 'slider',
+              show: this.isShowZoom, // flase直接隐藏图形
+              xAxisIndex: [0],
+              left: '9%', // 滚动条靠左侧的百分比
+              bottom: -5,
+              start: 0, // 滚动条的起始位置
+              end: this.xZoomEnd, // 滚动条的截止位置(按比例分割你的柱状图x轴长度)
+              zoomLock: true // 锁定区域禁止缩放(鼠标滚动会缩放,所以禁止)
+            }
+          ],
+          xAxis: {
+            type: 'category',
+            data: xAxisData,
+            axisLabel: {
+              interval: 0,
+              rotate: this.xAxisRotate // 刻度标签旋转的角度,在类目轴的类目标签显示不下的时候可以通过旋转防止标签之间重叠。旋转的角度从 -90 度到 90 度。
+            }
+          },
+          yAxis: {
+            type: 'value',
+            min: 0,
+            max: yMax,
+            axisLabel: {
+              formatter: `{value} ${this.yUnit}`
+            },
+            // interval: 2,
+            position: 'left'
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+          }
+        }
+        // 单柱图
+        if (this.value.length) {
+          option.series = [
+            {
+              data: seriesData,
+              type: 'bar',
+              barWidth: 35,
+              label: {
+                normal: {
+                  show: true,
+                  position: 'top'
+                }
+              }
+            }
+          ]
+        } else {
+          option.series = this.seriesData
+        }
+        // 已创建的先销毁
+        if (this.dom) {
+          this.dom.dispose()
+        }
+        this.dom = echarts.init(this.$refs.dom, 'tdTheme')
+        this.dom.setOption(option)
+        // 更新y轴最大值
+        this.dom.on('legendselectchanged', function (params) {
+          // console.log(params, that.seriesData, 'legendselectchanged')
+          const data = that.seriesData.filter(item => params.selected[item.name])
+          option.yAxis.max = that.getYMax(data)
+          that.dom.setOption(option)
+        })
+        // 解决首次加载宽度超出容器bug
+        this.dom.resize()
+        on(window, 'resize', this.resize)
+      })
+    },
+    // 计算y轴最大值
+    getYMax (data) {
+      let max = []
+      data.map(item => {
+        max = max.concat(item.data)
+      })
+      return Math.max.apply(null, max)
+    }
+  },
+  mounted () {
+    this.pageInit()
+  },
+  beforeDestroy () {
+    off(window, 'resize', this.resize)
+  }
+}
+</script>

+ 4 - 0
src/components/Echarts/index.js

@@ -0,0 +1,4 @@
+import ChartPie from './pie.vue'
+import ChartBar from './bar.vue'
+import ChartLine from './line.vue'
+export { ChartPie, ChartBar, ChartLine }

+ 210 - 0
src/components/Echarts/line.vue

@@ -0,0 +1,210 @@
+<template>
+  <div ref="dom" class="charts chart-line"></div>
+</template>
+
+<script>
+import echarts from 'echarts'
+import tdTheme from './theme.json'
+import {
+  on,
+  off
+} from '@/libs/tools'
+
+echarts.registerTheme('tdTheme', tdTheme)
+export default {
+  name: 'ChartLine',
+  props: {
+    value: Object, // 单列折线图,key为x轴,value为y轴
+    text: String,
+    subtext: String,
+    color: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // 当有多列折线图展示时的X轴坐标数据
+    xAxisData: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // 当有多列折线图展示时的y轴坐标数据
+    seriesData: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // y轴坐标单位
+    yUnit: {
+      type: String,
+      default: ''
+    },
+    // x轴标签旋转角度
+    xAxisRotate: {
+      type: Number,
+      default: 0
+    }
+  },
+  watch: {
+    xAxisData: {
+      handler (nVal, oVal) {
+        if (nVal) {
+          // 根据x轴时间长度控制滚动条位置及显示状态 x轴长度大于25时,显示滚动条并且滚动条结束位置在80%
+          if (nVal.length > 25) {
+            this.isShowZoom = true
+            this.xZoomEnd = 80
+          } else {
+            this.isShowZoom = false
+            this.xZoomEnd = 100
+          }
+          if (nVal.length > 30) {
+            this.xZoomEnd = 70
+          }
+          if (nVal.length > 35) {
+            this.xZoomEnd = 60
+          }
+          if (nVal.length > 40) {
+            this.xZoomEnd = 50
+          }
+          if (nVal.length > 45) {
+            this.xZoomEnd = 40
+          }
+          if (nVal.length > 50) {
+            this.xZoomEnd = 30
+          }
+          this.pageInit()
+        }
+      },
+      deep: true,
+      immediate: true // 代表如果在 wacth 里声明了 xAxisData 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行
+    },
+    xAxisRotate: {
+      handler (nVal, oVal) {
+        if (nVal !== '') {
+          this.pageInit()
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  data () {
+    return {
+      dom: null, // echarts实例对象
+      isShowZoom: false, // 是否展示滚动条
+      xZoomEnd: 100, // x轴滚动条结束位置
+      yMax: 1000 // y轴最大值
+    }
+  },
+  methods: {
+    resize () {
+      this.dom.resize()
+    },
+    pageInit () {
+      const that = this
+      const legend = this.seriesData.map(_ => _.name)
+      this.$nextTick(() => {
+        const xAxisData = this.value ? Object.keys(this.value) : this.xAxisData
+        const seriesData = this.value ? Object.values(this.value) : this.seriesData
+        const yMax = this.getYMax(this.seriesData) // 计算最大值
+        const option = {
+          color: this.color,
+          title: {
+            text: this.text,
+            subtext: this.subtext,
+            x: 'left'
+          },
+          legend: {
+            data: legend
+          },
+          // 鼠标放上去遮罩层提示信息
+          tooltip: {
+            trigger: 'axis'
+          },
+          dataZoom: [{ // Y轴固定,让内容滚动
+            type: 'slider',
+            show: this.isShowZoom, // flase直接隐藏图形
+            xAxisIndex: [0],
+            left: '9%', // 滚动条靠左侧的百分比
+            bottom: -5,
+            start: 0, // 滚动条的起始位置
+            end: this.xZoomEnd, // 滚动条的截止位置(按比例分割你的柱状图x轴长度)
+            zoomLock: true // 锁定区域禁止缩放(鼠标滚动会缩放,所以禁止)
+          }],
+          xAxis: {
+            type: 'category',
+            boundaryGap: false, // 两边是否留白
+            data: xAxisData,
+            axisLabel: {
+              interval: 0,
+              rotate: this.xAxisRotate
+            },
+            axisTick: {
+              inside: true,
+              lignWithLabel: true // 这两行代码可以让刻度正对刻度名
+            }
+          },
+          yAxis: {
+            type: 'value',
+            min: 0,
+            max: yMax,
+            axisLabel: {
+              formatter: `{value} ${this.yUnit}`
+            },
+            // interval: 2,
+            position: 'left'
+          }
+        }
+        if (this.value) {
+          option.series = [{
+            data: seriesData,
+            type: 'line',
+            barWidth: 35,
+            label: {
+              normal: {
+                show: true,
+                position: 'top'
+              }
+            }
+          }]
+        } else {
+          option.series = this.seriesData
+        }
+        // 已创建的先销毁
+        if (this.dom) {
+          this.dom.dispose()
+        }
+        this.dom = echarts.init(this.$refs.dom, 'tdTheme')
+        this.dom.setOption(option)
+        // 更新y轴最大值
+        this.dom.on('legendselectchanged', function (params) {
+          // console.log(params, that.seriesData, 'legendselectchanged')
+          const data = that.seriesData.filter(item => params.selected[item.name])
+          option.yAxis.max = that.getYMax(data)
+          that.dom.setOption(option)
+        })
+        // 重置图标大小
+        this.dom.resize()
+        on(window, 'resize', this.resize)
+      })
+    },
+    // 计算y轴最大值
+    getYMax (data) {
+      let max = []
+      data.map(item => {
+        max = max.concat(item.data)
+      })
+      return Math.max.apply(null, max)
+    }
+  },
+  mounted () {
+    this.pageInit()
+  },
+  beforeDestroy () {
+    off(window, 'resize', this.resize)
+  }
+}
+</script>

+ 200 - 0
src/components/Echarts/pie.vue

@@ -0,0 +1,200 @@
+<template>
+  <div ref="dom" class="charts chart-pie"></div>
+</template>
+
+<script>
+import echarts from 'echarts'
+import tdTheme from './theme.json'
+import { on, off } from '@/libs/tools'
+echarts.registerTheme('tdTheme', tdTheme)
+export default {
+  name: 'ChartPie',
+  props: {
+    subtext: String,
+    // 图表标题
+    text: {
+      type: String,
+      default: ''
+    },
+    // 数据值
+    value: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // 查询时间
+    searchData: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // 圆环中心标题
+    title: {
+      type: String,
+      default: ''
+    },
+    // 圆环中心金额
+    total: {
+      type: [Number, String],
+      default: ''
+    },
+    // 圆环各类型颜色
+    color: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    // x轴标签旋转角度
+    xAxisRotate: {
+      type: Number,
+      default: 0
+    },
+    // 单位
+    unit: {
+      type: String,
+      default: ''
+    }
+  },
+  watch: {
+    total: {
+      handler (nVal, oVal) {
+        // console.log(nVal, 'total111111111')
+        // 为防止当为0时不执行函数
+        if (nVal !== '') {
+          this.pageInit()
+        }
+      },
+      deep: true,
+      immediate: true // 代表如果在 wacth 里声明了 xAxisData 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行
+    }
+  },
+  data () {
+    return {
+      dom: null // echarts实例
+    }
+  },
+  methods: {
+    resize () {
+      this.dom.resize()
+    },
+    pageInit () {
+      this.$nextTick(() => {
+        const legend = this.value.map(_ => _.name)
+        const option = {
+          color: this.color,
+          title: [{
+            text: '{name|' + this.title + '}\n{val|' + this.formatNumber(this.total) + '}',
+            top: 'center',
+            left: 'center',
+            textStyle: {
+              rich: {
+                name: {
+                  fontSize: 14,
+                  fontWeight: 'normal',
+                  color: '#666666',
+                  padding: [10, 0]
+                },
+                val: {
+                  fontSize: 24,
+                  fontWeight: 'bold',
+                  color: '#333333'
+                }
+              }
+            }
+          }],
+          tooltip: {
+            trigger: 'item',
+            formatter: `{b} : {c}${this.unit} ${this.unit == '%' ? '' : '({d}%)'}`
+          },
+          legend: {
+            orient: 'horizontal',
+            left: 'center',
+            bottom: 'bottom',
+            padding: 5,
+            data: legend
+          },
+          series: [
+            {
+              type: 'pie',
+              radius: ['35%', '50%'],
+              center: ['50%', '50%'],
+              avoidLabelOverlap: true, // 在标签拥挤重叠的情况下会挪动各个标签的位置,防止标签间的重叠
+              hoverAnimation: false,
+              label: {
+                normal: {
+                  formatter: params => {
+                    return (
+                      '{icon|●}{name|' + params.name + '}{value|' +
+                            this.formatNumber(params.value) + this.unit + '}'
+                    )
+                  },
+                  padding: [0, -140, 25, -140],
+                  rich: {
+                    icon: {
+                      fontSize: 12
+                    },
+                    name: {
+                      fontSize: 14,
+                      padding: [0, 10, 0, 4],
+                      color: '#666666'
+                    },
+                    value: {
+                      fontSize: 16,
+                      fontWeight: 'bold',
+                      color: '#333333'
+                    }
+                  }
+                }
+              },
+              labelLine: {
+                normal: {
+                  length: 20,
+                  length2: 120,
+                  lineStyle: {
+                    color: '#e6e6e6'
+                  }
+                }
+              },
+              data: this.value,
+              itemStyle: {
+                emphasis: {
+                  shadowBlur: 10,
+                  shadowOffsetX: 0,
+                  shadowColor: 'rgba(255, 170, 0, 0.5)'
+                },
+                normal: {
+                  borderColor: '#fff',
+                  borderWidth: 2
+                }
+              }
+            }
+          ]
+        }
+        // 已创建的先销毁
+        if (this.dom) {
+          this.dom.dispose()
+        }
+        this.dom = echarts.init(this.$refs.dom, 'tdTheme')
+        console.log(option, 'option')
+        this.dom.setOption(option)
+        this.dom.resize()
+        on(window, 'resize', this.resize)
+      })
+    },
+    // 格式化金额
+    formatNumber (num) {
+      const reg = /(?=(\B)(\d{3})+$)/g
+      return num.toString().replace(reg, ',')
+    }
+  },
+  mounted () {
+    this.pageInit()
+  },
+  beforeDestroy () {
+    off(window, 'resize', this.resize)
+  }
+}
+</script>

+ 491 - 0
src/components/Echarts/theme.json

@@ -0,0 +1,491 @@
+
+{
+    "color": [
+        "#2d8cf0",
+        "#19be6b",
+        "#ff9900",
+        "#E46CBB",
+        "#9A66E4",
+        "#ed3f14"
+    ],
+    "backgroundColor": "rgba(0,0,0,0)",
+    "textStyle": {},
+    "title": {
+        "textStyle": {
+            "color": "#516b91"
+        },
+        "subtextStyle": {
+            "color": "#93b7e3"
+        }
+    },
+    "line": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": "2"
+            }
+        },
+        "lineStyle": {
+            "normal": {
+                "width": "2"
+            }
+        },
+        "symbolSize": "6",
+        "symbol": "emptyCircle",
+        "smooth": true
+    },
+    "radar": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": "2"
+            }
+        },
+        "lineStyle": {
+            "normal": {
+                "width": "2"
+            }
+        },
+        "symbolSize": "6",
+        "symbol": "emptyCircle",
+        "smooth": true
+    },
+    "bar": {
+        "itemStyle": {
+            "normal": {
+                "barBorderWidth": 0,
+                "barBorderColor": "#ccc"
+            },
+            "emphasis": {
+                "barBorderWidth": 0,
+                "barBorderColor": "#ccc"
+            }
+        }
+    },
+    "pie": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            },
+            "emphasis": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            }
+        }
+    },
+    "scatter": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            },
+            "emphasis": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            }
+        }
+    },
+    "boxplot": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            },
+            "emphasis": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            }
+        }
+    },
+    "parallel": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            },
+            "emphasis": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            }
+        }
+    },
+    "sankey": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            },
+            "emphasis": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            }
+        }
+    },
+    "funnel": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            },
+            "emphasis": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            }
+        }
+    },
+    "gauge": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            },
+            "emphasis": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            }
+        }
+    },
+    "candlestick": {
+        "itemStyle": {
+            "normal": {
+                "color": "#edafda",
+                "color0": "transparent",
+                "borderColor": "#d680bc",
+                "borderColor0": "#8fd3e8",
+                "borderWidth": "2"
+            }
+        }
+    },
+    "graph": {
+        "itemStyle": {
+            "normal": {
+                "borderWidth": 0,
+                "borderColor": "#ccc"
+            }
+        },
+        "lineStyle": {
+            "normal": {
+                "width": 1,
+                "color": "#aaa"
+            }
+        },
+        "symbolSize": "6",
+        "symbol": "emptyCircle",
+        "smooth": true,
+        "color": [
+            "#2d8cf0",
+            "#19be6b",
+            "#f5ae4a",
+            "#9189d5",
+            "#56cae2",
+            "#cbb0e3"
+        ],
+        "label": {
+            "normal": {
+                "textStyle": {
+                    "color": "#eee"
+                }
+            }
+        }
+    },
+    "map": {
+        "itemStyle": {
+            "normal": {
+                "areaColor": "#f3f3f3",
+                "borderColor": "#516b91",
+                "borderWidth": 0.5
+            },
+            "emphasis": {
+                "areaColor": "rgba(165,231,240,1)",
+                "borderColor": "#516b91",
+                "borderWidth": 1
+            }
+        },
+        "label": {
+            "normal": {
+                "textStyle": {
+                    "color": "#000"
+                }
+            },
+            "emphasis": {
+                "textStyle": {
+                    "color": "rgb(81,107,145)"
+                }
+            }
+        }
+    },
+    "geo": {
+        "itemStyle": {
+            "normal": {
+                "areaColor": "#f3f3f3",
+                "borderColor": "#516b91",
+                "borderWidth": 0.5
+            },
+            "emphasis": {
+                "areaColor": "rgba(165,231,240,1)",
+                "borderColor": "#516b91",
+                "borderWidth": 1
+            }
+        },
+        "label": {
+            "normal": {
+                "textStyle": {
+                    "color": "#000"
+                }
+            },
+            "emphasis": {
+                "textStyle": {
+                    "color": "rgb(81,107,145)"
+                }
+            }
+        }
+    },
+    "categoryAxis": {
+        "axisLine": {
+            "show": true,
+            "lineStyle": {
+                "color": "#cccccc"
+            }
+        },
+        "axisTick": {
+            "show": false,
+            "lineStyle": {
+                "color": "#333"
+            }
+        },
+        "axisLabel": {
+            "show": true,
+            "textStyle": {
+                "color": "#999999"
+            }
+        },
+        "splitLine": {
+            "show": true,
+            "lineStyle": {
+                "color": [
+                    "#eeeeee"
+                ]
+            }
+        },
+        "splitArea": {
+            "show": false,
+            "areaStyle": {
+                "color": [
+                    "rgba(250,250,250,0.05)",
+                    "rgba(200,200,200,0.02)"
+                ]
+            }
+        }
+    },
+    "valueAxis": {
+        "axisLine": {
+            "show": true,
+            "lineStyle": {
+                "color": "#cccccc"
+            }
+        },
+        "axisTick": {
+            "show": false,
+            "lineStyle": {
+                "color": "#333"
+            }
+        },
+        "axisLabel": {
+            "show": true,
+            "textStyle": {
+                "color": "#999999"
+            }
+        },
+        "splitLine": {
+            "show": true,
+            "lineStyle": {
+                "color": [
+                    "#eeeeee"
+                ]
+            }
+        },
+        "splitArea": {
+            "show": false,
+            "areaStyle": {
+                "color": [
+                    "rgba(250,250,250,0.05)",
+                    "rgba(200,200,200,0.02)"
+                ]
+            }
+        }
+    },
+    "logAxis": {
+        "axisLine": {
+            "show": true,
+            "lineStyle": {
+                "color": "#cccccc"
+            }
+        },
+        "axisTick": {
+            "show": false,
+            "lineStyle": {
+                "color": "#333"
+            }
+        },
+        "axisLabel": {
+            "show": true,
+            "textStyle": {
+                "color": "#999999"
+            }
+        },
+        "splitLine": {
+            "show": true,
+            "lineStyle": {
+                "color": [
+                    "#eeeeee"
+                ]
+            }
+        },
+        "splitArea": {
+            "show": false,
+            "areaStyle": {
+                "color": [
+                    "rgba(250,250,250,0.05)",
+                    "rgba(200,200,200,0.02)"
+                ]
+            }
+        }
+    },
+    "timeAxis": {
+        "axisLine": {
+            "show": true,
+            "lineStyle": {
+                "color": "#cccccc"
+            }
+        },
+        "axisTick": {
+            "show": false,
+            "lineStyle": {
+                "color": "#333"
+            }
+        },
+        "axisLabel": {
+            "show": true,
+            "textStyle": {
+                "color": "#999999"
+            }
+        },
+        "splitLine": {
+            "show": true,
+            "lineStyle": {
+                "color": [
+                    "#eeeeee"
+                ]
+            }
+        },
+        "splitArea": {
+            "show": false,
+            "areaStyle": {
+                "color": [
+                    "rgba(250,250,250,0.05)",
+                    "rgba(200,200,200,0.02)"
+                ]
+            }
+        }
+    },
+    "toolbox": {
+        "iconStyle": {
+            "normal": {
+                "borderColor": "#999"
+            },
+            "emphasis": {
+                "borderColor": "#666"
+            }
+        }
+    },
+    "legend": {
+        "textStyle": {
+            "color": "#999999"
+        }
+    },
+    "tooltip": {
+        "axisPointer": {
+            "lineStyle": {
+                "color": "#ccc",
+                "width": 1
+            },
+            "crossStyle": {
+                "color": "#ccc",
+                "width": 1
+            }
+        }
+    },
+    "timeline": {
+        "lineStyle": {
+            "color": "#8fd3e8",
+            "width": 1
+        },
+        "itemStyle": {
+            "normal": {
+                "color": "#8fd3e8",
+                "borderWidth": 1
+            },
+            "emphasis": {
+                "color": "#8fd3e8"
+            }
+        },
+        "controlStyle": {
+            "normal": {
+                "color": "#8fd3e8",
+                "borderColor": "#8fd3e8",
+                "borderWidth": 0.5
+            },
+            "emphasis": {
+                "color": "#8fd3e8",
+                "borderColor": "#8fd3e8",
+                "borderWidth": 0.5
+            }
+        },
+        "checkpointStyle": {
+            "color": "#8fd3e8",
+            "borderColor": "rgba(138,124,168,0.37)"
+        },
+        "label": {
+            "normal": {
+                "textStyle": {
+                    "color": "#8fd3e8"
+                }
+            },
+            "emphasis": {
+                "textStyle": {
+                    "color": "#8fd3e8"
+                }
+            }
+        }
+    },
+    "visualMap": {
+        "color": [
+            "#516b91",
+            "#59c4e6",
+            "#a5e7f0"
+        ]
+    },
+    "dataZoom": {
+        "backgroundColor": "rgba(0,0,0,0)",
+        "dataBackgroundColor": "rgba(255,255,255,0.3)",
+        "fillerColor": "rgba(167,183,204,0.4)",
+        "handleColor": "#a7b7cc",
+        "handleSize": "100%",
+        "textStyle": {
+            "color": "#333"
+        }
+    },
+    "markPoint": {
+        "label": {
+            "normal": {
+                "textStyle": {
+                    "color": "#eee"
+                }
+            },
+            "emphasis": {
+                "textStyle": {
+                    "color": "#eee"
+                }
+            }
+        }
+    }
+}

+ 213 - 0
src/config/router.config.js

@@ -1789,6 +1789,219 @@ export const asyncRouterMap = [
           }
         ]
       },
+      // 报表
+      {
+        path: '/reportData',
+        redirect: '/reportData/chainStockReport',
+        component: PageView,
+        meta: {
+          title: '报表',
+          icon: 'project'
+          // permission: 'M_basicData'
+        },
+        children: [
+          {
+            path: '/reportData/chainStockReport',
+            redirect: '/reportData/chainStockReport/list',
+            name: 'chainStockReport',
+            component: RouteView,
+            meta: {
+              title: '连锁库存总表(天)',
+              icon: 'profile'
+              // permission: 'M_warehouseList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'chainStockReportList',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/chainStockReport/list.vue'),
+                meta: {
+                  title: '连锁库存总表列表',
+                  icon: 'profile',
+                  hidden: true
+                  // permission: 'M_warehouseList'
+                }
+              }
+            ]
+          },
+          {
+            path: '/reportData/chainSalesReport',
+            redirect: '/reportData/chainSalesReport/list',
+            name: 'chainSalesReport',
+            component: RouteView,
+            meta: {
+              title: '连锁销售报表(天)',
+              icon: 'profile'
+              // permission: 'M_warehouseList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'chainSalesReportList',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/chainSalesReport/list.vue'),
+                meta: {
+                  title: '连锁销售报表列表',
+                  icon: 'profile',
+                  hidden: true
+                  // permission: 'M_warehouseList'
+                }
+              }
+            ]
+          },
+          {
+            path: '/reportData/chainSalesDetailReport',
+            redirect: '/reportData/chainSalesDetailReport/list',
+            name: 'chainSalesDetailReport',
+            component: RouteView,
+            meta: {
+              title: '连锁销售明细报表(天)',
+              icon: 'profile'
+              // permission: 'M_warehouseList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'chainSalesDetailReportList',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/chainSalesDetailReport/list.vue'),
+                meta: {
+                  title: '连锁销售明细报表列表',
+                  icon: 'profile',
+                  hidden: true
+                  // permission: 'M_warehouseList'
+                }
+              }
+            ]
+          },
+          // {
+          //   path: '/reportData/chainReceivedSendStorageReport',
+          //   redirect: '/reportData/chainReceivedSendStorageReport/list',
+          //   name: 'chainReceivedSendStorageReport',
+          //   component: RouteView,
+          //   meta: {
+          //     title: '连锁收发存报表',
+          //     icon: 'profile'
+          //     // permission: 'M_warehouseList'
+          //   },
+          //   hideChildrenInMenu: true,
+          //   children: [
+          //     {
+          //       path: 'list',
+          //       name: 'chainReceivedSendStorageReportList',
+          //       component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/chainReceivedSendStorageReport/list.vue'),
+          //       meta: {
+          //         title: '连锁收发存报表列表',
+          //         icon: 'profile',
+          //         hidden: true
+          //         // permission: 'M_warehouseList'
+          //       }
+          //     }
+          //   ]
+          // },
+          {
+            path: '/reportData/customerReport',
+            redirect: '/reportData/customerReport/list',
+            name: 'customerReport',
+            component: RouteView,
+            meta: {
+              title: '大客户报表(天)',
+              icon: 'profile'
+              // permission: 'M_warehouseList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'customerReportList',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/customerReport/list.vue'),
+                meta: {
+                  title: '大客户报表列表',
+                  icon: 'profile',
+                  hidden: true
+                  // permission: 'M_warehouseList'
+                }
+              }
+            ]
+          },
+          {
+            path: '/reportData/stockIncomeReport',
+            redirect: '/reportData/stockIncomeReport/list',
+            name: 'stockIncomeReport',
+            component: RouteView,
+            meta: {
+              title: '库存总入报表',
+              icon: 'profile'
+              // permission: 'M_warehouseList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'stockIncomeReportList',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/stockIncomeReport/list.vue'),
+                meta: {
+                  title: '库存总入报表列表',
+                  icon: 'profile',
+                  hidden: true
+                  // permission: 'M_warehouseList'
+                }
+              }
+            ]
+          },
+          {
+            path: '/reportData/stockExpenditureReport',
+            redirect: '/reportData/stockExpenditureReport/list',
+            name: 'stockExpenditureReport',
+            component: RouteView,
+            meta: {
+              title: '库存总出报表',
+              icon: 'profile'
+              // permission: 'M_warehouseList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'stockExpenditureReportList',
+                component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/stockExpenditureReport/list.vue'),
+                meta: {
+                  title: '库存总出报表列表',
+                  icon: 'profile',
+                  hidden: true
+                  // permission: 'M_warehouseList'
+                }
+              }
+            ]
+          }
+          // {
+          //   path: '/reportData/receivedSendStorageReport',
+          //   redirect: '/reportData/receivedSendStorageReport/list',
+          //   name: 'receivedSendStorageReport',
+          //   component: RouteView,
+          //   meta: {
+          //     title: '收发存报表',
+          //     icon: 'profile'
+          //     // permission: 'M_warehouseList'
+          //   },
+          //   hideChildrenInMenu: true,
+          //   children: [
+          //     {
+          //       path: 'list',
+          //       name: 'receivedSendStorageReportList',
+          //       component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/receivedSendStorageReport/list.vue'),
+          //       meta: {
+          //         title: '收发存报表列表',
+          //         icon: 'profile',
+          //         hidden: true
+          //         // permission: 'M_warehouseList'
+          //       }
+          //     }
+          //   ]
+          // }
+        ]
+      },
       // auth
       {
         path: '/auth',

+ 428 - 0
src/libs/tools.js

@@ -3,3 +3,431 @@ export const getOperationalPrecision = (num1, num2) => {
   const val = ((num1 * 10000) * (num2 * 10000) / 100000000).toFixed(2) || 0
   return val != 0 ? val : 0
 }
+export const forEach = (arr, fn) => {
+  if (!arr.length || !fn) return
+  let i = -1
+  const len = arr.length
+  while (++i < len) {
+    const item = arr[i]
+    fn(item, i, arr)
+  }
+}
+
+/**
+ * @param {Array} arr1
+ * @param {Array} arr2
+ * @description 得到两个数组的交集, 两个数组的元素为数值或字符串
+ */
+export const getIntersection = (arr1, arr2) => {
+  const len = Math.min(arr1.length, arr2.length)
+  let i = -1
+  const res = []
+  while (++i < len) {
+    const item = arr2[i]
+    if (arr1.indexOf(item) > -1) res.push(item)
+  }
+  return res
+}
+
+/**
+ * @param {Array} arr1
+ * @param {Array} arr2
+ * @description 得到两个数组的并集, 两个数组的元素为数值或字符串
+ */
+export const getUnion = (arr1, arr2) => {
+  return Array.from(new Set([...arr1, ...arr2]))
+}
+
+/**
+ * @param {Array} target 目标数组
+ * @param {Array} arr 需要查询的数组
+ * @description 判断要查询的数组是否至少有一个元素包含在目标数组中
+ */
+export const hasOneOf = (targetarr, arr) => {
+  if (!targetarr) return true
+  if (!arr) return true
+  return targetarr.some(_ => arr.indexOf(_) > -1)
+}
+
+/**
+ * @param {String|Number} value 要验证的字符串或数值
+ * @param {*} validList 用来验证的列表
+ */
+export function oneOf (value, validList) {
+  for (let i = 0; i < validList.length; i++) {
+    if (value === validList[i]) {
+      return true
+    }
+  }
+  return false
+}
+
+/**
+ * @param {Number} timeStamp 判断时间戳格式是否是毫秒
+ * @returns {Boolean}
+ */
+const isMillisecond = timeStamp => {
+  const timeStr = String(timeStamp)
+  return timeStr.length > 10
+}
+
+/**
+ * @param {Number} timeStamp 传入的时间戳
+ * @param {Number} currentTime 当前时间时间戳
+ * @returns {Boolean} 传入的时间戳是否早于当前时间戳
+ */
+const isEarly = (timeStamp, currentTime) => {
+  return timeStamp < currentTime
+}
+
+/**
+ * @param {Number} num 数值
+ * @returns {String} 处理后的字符串
+ * @description 如果传入的数值小于10,即位数只有1位,则在前面补充0
+ */
+const getHandledValue = num => {
+  return num < 10 ? '0' + num : num
+}
+
+/**
+ * @param {Number} timeStamp 传入的时间戳
+ * @param {Number} startType 要返回的时间字符串的格式类型,传入'year'则返回年开头的完整时间
+ */
+const getDate = (timeStamp, startType) => {
+  const d = new Date(timeStamp * 1000)
+  const year = d.getFullYear()
+  const month = getHandledValue(d.getMonth() + 1)
+  const date = getHandledValue(d.getDate())
+  const hours = getHandledValue(d.getHours())
+  const minutes = getHandledValue(d.getMinutes())
+  const second = getHandledValue(d.getSeconds())
+  let resStr = ''
+  if (startType === 'year') resStr = year + '-' + month + '-' + date + ' ' + hours + ':' + minutes + ':' + second
+  else resStr = month + '-' + date + ' ' + hours + ':' + minutes
+  return resStr
+}
+/**
+ * @param {Number} timeStamp 传入的时间戳
+ * @param {Number} fmt 格式化字符串
+ */
+export const formtDate = (timeStamp, fmt) => {
+  const d = new Date(timeStamp)
+  var o = {
+    'M+': d.getMonth() + 1, // 月份
+    'd+': d.getDate(), // 日
+    'h+': d.getHours(), // 小时
+    'm+': d.getMinutes(), // 分
+    's+': d.getSeconds(), // 秒
+    'q+': Math.floor((d.getMonth() + 3) / 3), // 季度
+    'S': d.getMilliseconds() // 毫秒
+  }
+  if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (d.getFullYear() + '').substr(4 - RegExp.$1.length))
+  for (var k in o) { if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) }
+  return fmt
+}
+//  获取三个月后的时间戳
+export const getThreeMonthsAfter = (dtstr) => {
+  var s = dtstr.split('-')
+  var yy = parseInt(s[0])
+  var mm = parseInt(s[1])
+  var dd = parseInt(s[2])
+  var dt = new Date(yy, mm + 2, dd)
+  return dt.valueOf()
+}
+/**
+ * @param {String|Number} timeStamp 时间戳
+ * @returns {String} 相对时间字符串
+ */
+export const getRelativeTime = timeStamp => {
+  // 判断当前传入的时间戳是秒格式还是毫秒
+  const IS_MILLISECOND = isMillisecond(timeStamp)
+  // 如果是毫秒格式则转为秒格式
+  if (IS_MILLISECOND) Math.floor(timeStamp /= 1000)
+  // 传入的时间戳可以是数值或字符串类型,这里统一转为数值类型
+  timeStamp = Number(timeStamp)
+  // 获取当前时间时间戳
+  const currentTime = Math.floor(Date.parse(new Date()) / 1000)
+  // 判断传入时间戳是否早于当前时间戳
+  const IS_EARLY = isEarly(timeStamp, currentTime)
+  // 获取两个时间戳差值
+  let diff = currentTime - timeStamp
+  // 如果IS_EARLY为false则差值取反
+  if (!IS_EARLY) diff = -diff
+  let resStr = ''
+  const dirStr = IS_EARLY ? '前' : '后'
+  // 少于等于59秒
+  if (diff <= 59) resStr = diff + '秒' + dirStr
+  // 多于59秒,少于等于59分钟59秒
+  else if (diff > 59 && diff <= 3599) resStr = Math.floor(diff / 60) + '分钟' + dirStr
+  // 多于59分钟59秒,少于等于23小时59分钟59秒
+  else if (diff > 3599 && diff <= 86399) resStr = Math.floor(diff / 3600) + '小时' + dirStr
+  // 多于23小时59分钟59秒,少于等于29天59分钟59秒
+  else if (diff > 86399 && diff <= 2623859) resStr = Math.floor(diff / 86400) + '天' + dirStr
+  // 多于29天59分钟59秒,少于364天23小时59分钟59秒,且传入的时间戳早于当前
+  else if (diff > 2623859 && diff <= 31567859 && IS_EARLY) resStr = getDate(timeStamp)
+  else resStr = getDate(timeStamp, 'year')
+  return resStr
+}
+
+// 日期格式化
+export const formatSubmitDate = (val, type) => {
+  if (val == null || val == '' || val == undefined) {
+    return ''
+  } else {
+    const _date = new Date(val)
+    const _year = _date.getFullYear()
+    const _montn = (_date.getMonth() + 1) < 10 ? '0' + (_date.getMonth() + 1) : (_date.getMonth() + 1)
+    const _day = _date.getDate() < 10 ? '0' + _date.getDate() : _date.getDate()
+    const _hour = _date.getHours() < 10 ? '0' + _date.getHours() : _date.getHours()
+    const _minutes = _date.getMinutes() < 10 ? '0' + _date.getMinutes() : _date.getMinutes()
+    const _seconds = _date.getSeconds() < 10 ? '0' + _date.getSeconds() : _date.getSeconds()
+
+    if (type == 'minutes') return _year + '-' + _montn + '-' + _day + ' ' + _hour + ':' + _minutes
+    else if (type == 'seconds') return _year + '-' + _montn + '-' + _day + ' ' + _hour + ':' + _minutes + ':' + _seconds
+    else return _year + '-' + _montn + '-' + _day
+  }
+}
+// 正则验证车牌,验证通过返回true,不通过返回false
+export const isLicensePlate = function (str) {
+  return /^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(str)
+}
+// 车牌可输入字符
+export const isCarNumber = function (str) {
+  let _value = str + ''
+  _value = _value.replace(/[^\w\.挂学警港澳使领]/ig, '')
+
+  return _value
+}
+// 小数点后两位
+export const numberToFixed = function (val, num) {
+  let _value = val + ''
+  _value = _value.replace(/[^\d.]/g, '')// 清楚数字和.以外的字数
+  _value = _value.replace(/^\./g, '')
+  _value = _value.replace(/\.{2,}/g, '')// 保留第一个,清楚多余的
+
+  if (num == 1)_value = _value.replace(/^(\-)*(\d+)\.(\d).*$/, '$1$2.$3')
+  else if (num == 3)_value = _value.replace(/^(\-)*(\d+)\.(\d\d\d).*$/, '$1$2.$3')
+  else if (num == 4)_value = _value.replace(/^(\-)*(\d+)\.(\d\d\d\d).*$/, '$1$2.$3')
+  else if (num == 5)_value = _value.replace(/^(\-)*(\d+)\.(\d\d\d\d\d).*$/, '$1$2.$3')
+  else if (num == 0)_value = _value.replace(/^(\-)*(\d+)\.*$/, '$1$2')
+  else _value = _value.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
+
+  return _value
+}// 只能输入数字
+export const justNumber = function (val) {
+  let _value = val + ''
+  _value = _value.replace(/\D/g, '')
+
+  return _value
+}
+
+/**
+ * @returns {String} 当前浏览器名称
+ */
+export const getExplorer = () => {
+  const ua = window.navigator.userAgent
+  const isExplorer = (exp) => {
+    return ua.indexOf(exp) > -1
+  }
+  if (isExplorer('MSIE')) return 'IE'
+  else if (isExplorer('Firefox')) return 'Firefox'
+  else if (isExplorer('Chrome')) return 'Chrome'
+  else if (isExplorer('Opera')) return 'Opera'
+  else if (isExplorer('Safari')) return 'Safari'
+}
+
+/**
+ * @description 绑定事件 on(element, event, handler)
+ */
+export const on = (function () {
+  if (document.addEventListener) {
+    return function (element, event, handler) {
+      if (element && event && handler) {
+        element.addEventListener(event, handler, false)
+      }
+    }
+  } else {
+    return function (element, event, handler) {
+      if (element && event && handler) {
+        element.attachEvent('on' + event, handler)
+      }
+    }
+  }
+})()
+
+/**
+ * @description 解绑事件 off(element, event, handler)
+ */
+export const off = (function () {
+  if (document.removeEventListener) {
+    return function (element, event, handler) {
+      if (element && event) {
+        element.removeEventListener(event, handler, false)
+      }
+    }
+  } else {
+    return function (element, event, handler) {
+      if (element && event) {
+        element.detachEvent('on' + event, handler)
+      }
+    }
+  }
+})()
+
+/**
+ * 判断一个对象是否存在key,如果传入第二个参数key,则是判断这个obj对象是否存在key这个属性
+ * 如果没有传入key这个参数,则判断obj对象是否有键值对
+ */
+export const hasKey = (obj, key) => {
+  if (key) return key in obj
+  else {
+    const keysArr = Object.keys(obj)
+    return keysArr.length
+  }
+}
+
+/**
+ * @param {*} obj1 对象
+ * @param {*} obj2 对象
+ * @description 判断两个对象是否相等,这两个对象的值只能是数字或字符串
+ */
+export const objEqual = (obj1, obj2) => {
+  const keysArr1 = Object.keys(obj1)
+  const keysArr2 = Object.keys(obj2)
+  if (keysArr1.length !== keysArr2.length) return false
+  else if (keysArr1.length === 0 && keysArr2.length === 0) return true
+  /* eslint-disable-next-line */
+  else return !keysArr1.some(key => obj1[key] != obj2[key])
+}
+
+/*
+ * @param {*} id 数字
+ * @param {*} list 数组
+ * @description 根据id从数组列表中删除某一项
+*/
+export const removeListById = (id, list) => {
+  list.splice(list.findIndex(item => item.id === id), 1)
+}
+
+/**
+ * @param {*} obj1 对象
+ * @param {*} obj2 对象
+ * @description 遍历赋值
+*/
+export const objExtend = (obj1, obj2) => {
+  for (var a in obj1) {
+    obj2[a] = obj1[a]
+  }
+  return obj2
+}
+/**
+ * @param {*} obj 对象
+ * @description 浅拷贝
+*/
+export const cloneObj = (obj) => {
+  const ret = {}
+  for (var a in obj) {
+    ret[a] = obj[a]
+  }
+  return ret
+}
+
+/**
+ * 校验身份证号合法性
+ */
+export const checkIdNumberValid = (tex) => {
+  // var tip = '输入的身份证号有误,请检查后重新输入!'
+  let num = tex
+  num = num.toUpperCase()
+
+  const len = num.length
+  let re
+  if (len == 0) return true
+
+  // 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X。
+  if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(num))) {
+    return false
+  }
+
+  // 验证前两位地区是否有效
+  const aCity = { 11: '北京',
+    12: '天津',
+    13: '河北',
+    14: '山西',
+    15: '内蒙古',
+    21: '辽宁',
+    22: '吉林',
+    23: '黑龙江',
+    31: '上海',
+    32: '江苏',
+    33: '浙江',
+    34: '安徽',
+    35: '福建',
+    36: '江西',
+    37: '山东',
+    41: '河南',
+    42: '湖北',
+    43: '湖南',
+    44: '广东',
+    45: '广西',
+    46: '海南',
+    50: '重庆',
+    51: '四川',
+    52: '贵州',
+    53: '云南',
+    54: '西藏',
+    61: '陕西',
+    62: '甘肃',
+    63: '青海',
+    64: '宁夏',
+    65: '新疆',
+    71: '台湾',
+    81: '香港',
+    82: '澳门',
+    91: '国外' }
+
+  if (aCity[parseInt(num.substr(0, 2))] == null) {
+    return false
+  }
+
+  // 当身份证为15位时的验证出生日期。
+  if (len == 15) {
+    re = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/)
+    const arrSplit = num.match(re)
+
+    // 检查生日日期是否正确
+    const dtmBirth = new Date('19' + arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4])
+    const bGoodDay = (dtmBirth.getYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4]))
+    if (!bGoodDay) {
+      return false
+    }
+  }
+
+  // 当身份证号为18位时,校验出生日期和校验位。
+  if (len == 18) {
+    re = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/)
+    const arrSplit = num.match(re)
+    // 检查生日日期是否正确
+    const dtmBirth = new Date(arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4])
+    const bGoodDay = (dtmBirth.getFullYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4]))
+    if (!bGoodDay) {
+      return false
+    } else {
+      // 检验18位身份证的校验码是否正确。
+      // 校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
+      let valnum
+      const arrInt = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
+      const arrCh = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
+      let nTemp = 0
+      let i
+      for (i = 0; i < 17; i++) {
+        nTemp += num.substr(i, 1) * arrInt[i]
+      }
+      valnum = arrCh[nTemp % 11]
+      if (valnum != num.substr(17, 1)) {
+        return false
+      }
+    }
+  }
+  return true
+}

+ 116 - 103
src/views/allocationManagement/chainTransferIn/edit.vue

@@ -1,109 +1,111 @@
 <template>
   <div class="chainTransferInEdit-wrap">
-    <a-page-header :ghost="false" :backIcon="false" class="chainTransferInEdit-back" >
-      <!-- 自定义的二级文字标题 -->
-      <template slot="subTitle">
-        <a id="chainTransferInEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
-      </template>
-      <!-- 操作区,位于 title 行的行尾 -->
-      <template slot="extra">
-        <a-radio-group key="3" v-model="printerType">
-          <a-radio value="NEEDLE">针式</a-radio>
-          <a-radio value="INK">喷墨</a-radio>
-        </a-radio-group>
-        <a-button key="2" id="chainTransferInEdit-preview-btn" :disabled="loadData.length==0" @click="handlePrint('preview')">打印预览</a-button>
-        <a-button key="1" type="primary" id="chainTransferInEdit-print-btn" :disabled="loadData.length==0" @click="handlePrint('print')">快捷打印</a-button>
-      </template>
-    </a-page-header>
-    <!-- 基础信息 -->
-    <a-card size="small" :bordered="false" class="chainTransferInDetail-cont">
-      <a-collapse :activeKey="['1']">
-        <a-collapse-panel key="1" header="基础信息">
-          <a-descriptions :column="3">
-            <a-descriptions-item label="调入单号">{{ (basicInfoData&&basicInfoData.allocationLinkagePutNo) || '--' }}</a-descriptions-item>
-            <a-descriptions-item label="调出对象">{{ (basicInfoData&&basicInfoData.outTenantName) || '--' }}</a-descriptions-item>
-            <a-descriptions-item label="业务状态">{{ (basicInfoData&&basicInfoData.stateDictValue) || '--' }}</a-descriptions-item>
-            <a-descriptions-item label="财务状态">{{ (basicInfoData&&basicInfoData.settleStateDictValue) || '--' }}</a-descriptions-item>
-          </a-descriptions>
-        </a-collapse-panel>
-      </a-collapse>
-    </a-card>
-    <!-- 总计 -->
-    <a-alert type="info" showIcon style="margin-bottom:15px">
-      <div slot="message">总款数 <strong>{{ (basicInfoData&&basicInfoData.productTotalCategory) || 0 }}</strong> ,总数量 <strong>{{ (basicInfoData&&basicInfoData.productTotalQty) || 0 }}</strong> ,总成本¥<strong>{{ (basicInfoData&&basicInfoData.productTotalCost) || 0 }}</strong></div>
-    </a-alert>
-    <a-card size="small" :bordered="false" class="chainTransferInEdit-cont">
-      <!-- 筛选条件 -->
-      <div class="table-page-search-wrapper">
-        <a-form layout="inline" @keyup.enter.native="getProductList(1)">
-          <a-row :gutter="15">
-            <a-col :md="6" :sm="24">
-              <a-form-item label="产品编码" prop="productCode">
-                <a-input id="chainTransferInEdit-productCode" v-model="queryParam.productCode" placeholder="请输入产品编码" allowClear />
-              </a-form-item>
-            </a-col>
-            <a-col :md="6" :sm="24">
-              <a-form-item label="产品名称" prop="productName">
-                <a-input id="chainTransferInEdit-productName" v-model="queryParam.productName" placeholder="请输入产品名称" allowClear />
-              </a-form-item>
-            </a-col>
-            <a-col :md="6" :sm="24">
-              <a-form-item label="产品分类">
-                <a-cascader
-                  @change="changeProductType"
-                  change-on-select
-                  v-model="productType"
-                  expand-trigger="hover"
-                  :options="productTypeList"
-                  :fieldNames="{ label: 'productTypeName', value: 'productTypeSn', children: 'children' }"
-                  id="chainTransferInEdit-productType"
-                  placeholder="请选择产品分类"
-                  allowClear />
-              </a-form-item>
-            </a-col>
-            <a-col :md="6" :sm="24" style="margin-bottom: 24px;">
-              <a-button type="primary" @click="getProductList(1)" :disabled="disabled" id="chainTransferInEdit-refresh">查询</a-button>
-              <a-button style="margin-left: 8px" @click="resetSearchForm" :disabled="disabled" id="chainTransferInEdit-reset">重置</a-button>
-            </a-col>
-          </a-row>
-        </a-form>
-      </div>
-      <!-- 列表 -->
-      <a-table
-        class="sTable"
-        ref="table"
-        size="small"
-        :rowKey="(record) => record.id"
-        :columns="columns"
-        :dataSource="loadData"
-        :scroll="{ x: 1415 }"
-        bordered>
-        <!-- 仓库仓位 -->
-        <template slot="warehouse" slot-scope="text, record, index">
-          <a-cascader
-            @change="e => changeWarehouseCascade(e, record, index)"
-            v-model="record.warehouseCascade"
-            expand-trigger="hover"
-            :allowClear="false"
-            :options="warehouseCascadeData"
-            :fieldNames="{ label: 'name', value: 'sn', children: 'warehouseLocationList' }"
-            id="chainTransferInEdit-warehouseCascade"
-            placeholder="请选择仓库仓位"
-            style="width: 100%;" />
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-page-header :ghost="false" :backIcon="false" class="chainTransferInEdit-back" >
+        <!-- 自定义的二级文字标题 -->
+        <template slot="subTitle">
+          <a id="chainTransferInEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
         </template>
-      </a-table>
-    </a-card>
-    <a-affix :offset-bottom="0">
-      <div style="text-align: center;width: 100%;background-color: #fff;padding: 12px 0;box-shadow: 0 0 20px #dcdee2;">
-        <a-button
-          type="primary"
-          id="chainTransferInEdit-submit"
-          size="large"
-          class="button-primary"
-          @click="handleSubmit"
-          style="padding: 0 60px;">提交入库</a-button>
-      </div>
-    </a-affix>
+        <!-- 操作区,位于 title 行的行尾 -->
+        <template slot="extra">
+          <a-radio-group key="3" v-model="printerType">
+            <a-radio value="NEEDLE">针式</a-radio>
+            <a-radio value="INK">喷墨</a-radio>
+          </a-radio-group>
+          <a-button key="2" id="chainTransferInEdit-preview-btn" :disabled="loadData.length==0" @click="handlePrint('preview')">打印预览</a-button>
+          <a-button key="1" type="primary" id="chainTransferInEdit-print-btn" :disabled="loadData.length==0" @click="handlePrint('print')">快捷打印</a-button>
+        </template>
+      </a-page-header>
+      <!-- 基础信息 -->
+      <a-card size="small" :bordered="false" class="chainTransferInDetail-cont">
+        <a-collapse :activeKey="['1']">
+          <a-collapse-panel key="1" header="基础信息">
+            <a-descriptions :column="3">
+              <a-descriptions-item label="调入单号">{{ (basicInfoData&&basicInfoData.allocationLinkagePutNo) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="调出对象">{{ (basicInfoData&&basicInfoData.outTenantName) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="业务状态">{{ (basicInfoData&&basicInfoData.stateDictValue) || '--' }}</a-descriptions-item>
+              <a-descriptions-item label="财务状态">{{ (basicInfoData&&basicInfoData.settleStateDictValue) || '--' }}</a-descriptions-item>
+            </a-descriptions>
+          </a-collapse-panel>
+        </a-collapse>
+      </a-card>
+      <!-- 总计 -->
+      <a-alert type="info" showIcon style="margin-bottom:15px">
+        <div slot="message">总款数 <strong>{{ (basicInfoData&&basicInfoData.productTotalCategory) || 0 }}</strong> ,总数量 <strong>{{ (basicInfoData&&basicInfoData.productTotalQty) || 0 }}</strong> ,总成本¥<strong>{{ (basicInfoData&&basicInfoData.productTotalCost) || 0 }}</strong></div>
+      </a-alert>
+      <a-card size="small" :bordered="false" class="chainTransferInEdit-cont">
+        <!-- 筛选条件 -->
+        <div class="table-page-search-wrapper">
+          <a-form layout="inline" @keyup.enter.native="getProductList(1)">
+            <a-row :gutter="15">
+              <a-col :md="6" :sm="24">
+                <a-form-item label="产品编码" prop="productCode">
+                  <a-input id="chainTransferInEdit-productCode" v-model="queryParam.productCode" placeholder="请输入产品编码" allowClear />
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="产品名称" prop="productName">
+                  <a-input id="chainTransferInEdit-productName" v-model="queryParam.productName" placeholder="请输入产品名称" allowClear />
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24">
+                <a-form-item label="产品分类">
+                  <a-cascader
+                    @change="changeProductType"
+                    change-on-select
+                    v-model="productType"
+                    expand-trigger="hover"
+                    :options="productTypeList"
+                    :fieldNames="{ label: 'productTypeName', value: 'productTypeSn', children: 'children' }"
+                    id="chainTransferInEdit-productType"
+                    placeholder="请选择产品分类"
+                    allowClear />
+                </a-form-item>
+              </a-col>
+              <a-col :md="6" :sm="24" style="margin-bottom: 24px;">
+                <a-button type="primary" @click="getProductList(1)" :disabled="disabled" id="chainTransferInEdit-refresh">查询</a-button>
+                <a-button style="margin-left: 8px" @click="resetSearchForm" :disabled="disabled" id="chainTransferInEdit-reset">重置</a-button>
+              </a-col>
+            </a-row>
+          </a-form>
+        </div>
+        <!-- 列表 -->
+        <a-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :dataSource="loadData"
+          :scroll="{ x: 1415 }"
+          bordered>
+          <!-- 仓库仓位 -->
+          <template slot="warehouse" slot-scope="text, record, index">
+            <a-cascader
+              @change="e => changeWarehouseCascade(e, record, index)"
+              v-model="record.warehouseCascade"
+              expand-trigger="hover"
+              :allowClear="false"
+              :options="warehouseCascadeData"
+              :fieldNames="{ label: 'name', value: 'sn', children: 'warehouseLocationList' }"
+              id="chainTransferInEdit-warehouseCascade"
+              placeholder="请选择仓库仓位"
+              style="width: 100%;" />
+          </template>
+        </a-table>
+      </a-card>
+      <a-affix :offset-bottom="0">
+        <div style="text-align: center;width: 100%;background-color: #fff;padding: 12px 0;box-shadow: 0 0 20px #dcdee2;">
+          <a-button
+            type="primary"
+            id="chainTransferInEdit-submit"
+            size="large"
+            class="button-primary"
+            @click="handleSubmit"
+            style="padding: 0 60px;">提交入库</a-button>
+        </div>
+      </a-affix>
+    </a-spin>
     <!-- 打印 -->
     <div id="print"></div>
   </div>
@@ -119,6 +121,7 @@ export default {
   components: { STable, VSelect },
   data () {
     return {
+      spinning: false,
       queryParam: {
         productCode: '', //  产品编码
         productName: '', //  产品名称
@@ -181,10 +184,14 @@ export default {
     },
     //  提交
     handleSubmit () {
+      this.spinning = true
       allocLinkagePutSubmit({ sn: this.$route.params.sn }).then(res => {
         if (res.status == 200) {
           this.$message.success(res.message)
           this.handleBack()
+          this.spinning = false
+        } else {
+          this.spinning = false
         }
       })
     },
@@ -277,10 +284,14 @@ export default {
         warehouseLocationSn: row.warehouseLocationSn,
         warehouseSn: row.warehouseSn
       }
+      this.spinning = true
       allocLinkagePutDetailUpdate(params).then(res => {
         if (res.status == 200) {
           this.$message.success(res.message)
           this.getProductList()
+          this.spinning = false
+        } else {
+          this.spinning = false
         }
       })
     },
@@ -315,7 +326,9 @@ export default {
     // 打印预览/快捷打印
     handlePrint (type) {
       const _this = this
+      _this.spinning = true
       allocLinkagePutDetailPrint({ sn: this.$route.params.sn, type: this.printerType }).then(res => {
+        _this.spinning = false
         if (res.type == 'application/json') {
           var reader = new FileReader()
           reader.addEventListener('loadend', function () {

+ 8 - 0
src/views/reportData/chainReceivedSendStorageReport/list.vue

@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

+ 362 - 0
src/views/reportData/chainSalesDetailReport/list.vue

@@ -0,0 +1,362 @@
+<template>
+  <a-card size="small" :bordered="false" class="chainStockReportList-wrap">
+    <a-alert :show-icon="false" type="error" message="注:连锁销售单报表包含急件销售数量、售价,连锁销售明细报表不包含急件销售数量、成本、售价" banner style="margin-bottom: 10px;" />
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form-model
+        id="chainStockReportList-form"
+        ref="ruleForm"
+        :model="queryParam"
+        :rules="rules"
+        :labelCol="labelCol"
+        :wrapperCol="wrapperCol"
+        @keyup.enter.native="handleSearch" >
+        <a-row :gutter="15">
+          <a-col :md="6" :sm="24">
+            <a-form-model-item label="连锁店" prop="targetName">
+              <a-select
+                placeholder="请选择连锁店"
+                id="chainStockReportList-targetName"
+                allowClear
+                v-model="queryParam.targetName"
+                :showSearch="true"
+                option-filter-prop="children"
+                :filter-option="filterOption">
+                <a-select-option v-for="item in allocateTypeList" :key="item.brandSn" :value="item.brandSn">{{ item.brandName }}</a-select-option>
+              </a-select>
+            </a-form-model-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="审核时间">
+              <rangeDate ref="rangeDate" @change="dateChange" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="客户名称">
+              <a-input id="chainStockReportList-targetName" v-model.trim="queryParam.code" allowClear placeholder="请输入客户名称"/>
+            </a-form-item>
+          </a-col>
+          <template v-if="advanced">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="客户类型">
+                <a-select id="chainStockReportList-targetName" v-model="queryParam.allocateTypeSn" placeholder="请选择客户类型" allowClear >
+                  <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="12" :sm="24">
+              <a-row>
+                <a-form-item label="客户所在区" :labelCol="{span: 4}" :wrapperCol="{ span: 20 }">
+                  <a-col span="7">
+                    <a-form-item prop="dealerProvinceSn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerProvinceSn" @change="getCityList" placeholder="请选择省">
+                        <a-select-option v-for="item in addrProvinceList" :value="item.id" :key="item.id + 'a'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                  <a-col span="7" offset="1">
+                    <a-form-item prop="dealerCitySn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerCitySn" @change="getAreaList" placeholder="请选择市">
+                        <a-select-option v-for="item in addrCityList" :value="item.id" :key="item.id + 'b'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                  <a-col span="7" offset="1">
+                    <a-form-item prop="dealerCountySn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerCountySn" placeholder="请选择区/县">
+                        <a-select-option v-for="item in addrDistrictList" :value="item.id" :key="item.id + 'c'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                </a-form-item>
+              </a-row>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="支付方式">
+                <a-select id="chainStockReportList-targetName" v-model="queryParam.allocateTypeSn" placeholder="请选择收款方式" allowClear >
+                  <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="收款方式">
+                <a-select id="chainStockReportList-targetName" v-model="queryParam.allocateTypeSn" placeholder="请选择收款方式" allowClear >
+                  <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="12" :sm="24">
+              <a-row>
+                <a-form-item label="产品类别" :labelCol="{span: 4}" :wrapperCol="{ span: 20 }">
+                  <a-col span="7">
+                    <a-form-item prop="dealerProvinceSn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerProvinceSn" @change="getCityList" placeholder="请选择">
+                        <a-select-option v-for="item in addrProvinceList" :value="item.id" :key="item.id + 'a'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                  <a-col span="7" offset="1">
+                    <a-form-item prop="dealerCitySn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerCitySn" @change="getAreaList" placeholder="请选择">
+                        <a-select-option v-for="item in addrCityList" :value="item.id" :key="item.id + 'b'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                  <a-col span="7" offset="1">
+                    <a-form-item prop="dealerCountySn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerCountySn" placeholder="请选择">
+                        <a-select-option v-for="item in addrDistrictList" :value="item.id" :key="item.id + 'c'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                </a-form-item>
+              </a-row>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="产品编码">
+                <a-input id="chainStockReportList-targetName" v-model.trim="queryParam.code" allowClear placeholder="请输入单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="产品名称">
+                <a-input id="chainStockReportList-targetName" v-model.trim="queryParam.code" allowClear placeholder="请输入业务员"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="12" :sm="24">
+              <a-row>
+                <a-form-item label="仓库仓位" :labelCol="{span: 4}" :wrapperCol="{ span: 20 }">
+                  <a-col span="7">
+                    <a-form-item prop="dealerProvinceSn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerProvinceSn" @change="getCityList" placeholder="请选择">
+                        <a-select-option v-for="item in addrProvinceList" :value="item.id" :key="item.id + 'a'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                  <a-col span="7" offset="1">
+                    <a-form-item prop="dealerCitySn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerCitySn" @change="getAreaList" placeholder="请选择">
+                        <a-select-option v-for="item in addrCityList" :value="item.id" :key="item.id + 'b'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                </a-form-item>
+              </a-row>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="单号">
+                <a-input id="chainStockReportList-targetName" v-model.trim="queryParam.code" allowClear placeholder="请输入单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="业务员">
+                <a-input id="chainStockReportList-targetName" v-model.trim="queryParam.code" allowClear placeholder="请输入业务员"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="订单类型">
+                <a-select id="chainStockReportList-targetName" v-model="queryParam.allocateTypeSn" placeholder="请选择收款方式" allowClear >
+                  <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="handleSearch" :disabled="disabled" id="chainStockReportList-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="chainStockReportList-reset">重置</a-button>
+            <a @click="advanced=!advanced" style="margin-left: 8px">
+              {{ advanced ? '收起' : '展开' }}
+              <a-icon :type="advanced ? 'up' : 'down'"/>
+            </a>
+          </a-col>
+        </a-row>
+      </a-form-model>
+    </div>
+    <!-- 合计 -->
+    <a-alert type="info" showIcon style="margin-bottom:15px">
+      <div class="ftext" slot="message">
+        总成本:<strong>¥33.00</strong>;
+        总售价:<strong>¥48.00</strong>;
+        总毛利:<strong>¥15.00</strong>。
+      </div>
+    </a-alert>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :scroll="{ x: 1170 }"
+      bordered>
+    </s-table>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { getArea } from '@/api/data'
+// import { allocateBillList, allocateBillDel, allocateBillAudit, allocateBillExport } from '@/api/allocateBill'
+// import { allocateTypeAllList } from '@/api/allocateType'
+export default {
+  components: { STable, VSelect, rangeDate },
+  data () {
+    return {
+      labelCol: { span: 8 },
+      wrapperCol: { span: 16 },
+      advanced: false, // 高级搜索 展开/关闭
+      tableHeight: 0,
+      queryParam: { //  查询条件
+        beginDate: '',
+        endDate: '',
+        targetName: undefined,
+        code: '', //  产品编码
+        name: '', //  产品名称
+        origCode: '', //  原厂编码
+        productBrandSn: undefined, //  产品品牌
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '' //  产品三级分类
+      },
+      rules: {
+        'targetName': [{ required: true, message: '请选择连锁店', trigger: 'change' }]
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      exportLoading: false,
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center', fixed: 'left' },
+        { title: '销售单号', dataIndex: 'code', width: 220, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '客户名称', dataIndex: 'name', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '订单类型', dataIndex: 'orderType', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '支付方式', dataIndex: 'payType', width: 165, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '收款方式', dataIndex: 'currentStockCost', width: 165, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品编码', dataIndex: 'proCode', width: 165, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'proName', width: 165, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '单位', dataIndex: 'unit', width: 165, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '数量', dataIndex: 'totalQty', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '成本', dataIndex: 'totalCost', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? ('¥' + text) : '--') } },
+        { title: '售价', dataIndex: 'totalAmount', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? ('¥' + text) : '--') } },
+        { title: '毛利', dataIndex: 'totalMl', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? ('¥' + text) : '--') } },
+        { title: '审核时间', dataIndex: 'auditDate', width: 165, align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        // return allocateBillList(Object.assign(parameter, this.queryParam)).then(res => {
+        //   const data = res.data
+        //   const no = (data.pageNo - 1) * data.pageSize
+        //   for (var i = 0; i < data.list.length; i++) {
+        //     data.list[i].no = no + i + 1
+        //   }
+        //   this.disabled = false
+        //   return data
+        // })
+        const _this = this
+        return new Promise(function (resolve, reject) {
+          const data = {
+            pageNo: 1,
+            pageSize: 10,
+            list: [
+              { id: '1', code: '159177', name: '支持市级', orderType: '线下', payType: '货到付款', currentStockCost: '现金', proCode: '00004', proName: 'xl测试00004', unit: '个', totalCategory: '3', totalQty: '3', totalCost: '33.00', totalAmount: '48.00', totalMl: '15.00', billName: '', auditDate: '2021-03-19 18:27:48' }
+            ],
+            count: 10
+          }
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = i + 1
+          }
+          _this.disabled = false
+          resolve(data)
+        })
+      },
+      addrProvinceList: [], //  省下拉
+      addrCityList: [], //  市下拉
+      addrDistrictList: [], //  区下拉
+      allocateTypeList: [] //  调拨类型
+    }
+  },
+  methods: {
+    //  创建时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    //  查询
+    handleSearch () {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.$refs.table.refresh(true)
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.targetName = undefined
+      this.queryParam.code = ''
+      this.queryParam.name = ''
+      this.queryParam.origCode = ''
+      this.queryParam.productBrandSn = undefined
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.productType = []
+      this.$refs.table.refresh(true)
+    },
+    filterOption (input, option) {
+      return (
+        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+      )
+    },
+    // 获取城市列表
+    getCityList (val) {
+      this.addrCityList = []
+      this.addrDistrictList = []
+      this.queryParam.dealerCitySn = undefined
+      this.queryParam.dealerCountySn = undefined
+      this.getArea('city', val)
+    },
+    // 获取区县列表
+    getAreaList (val) {
+      this.addrDistrictList = []
+      this.queryParam.dealerCountySn = undefined
+      this.getArea('district', val)
+    },
+    //  省/市/区
+    getArea (leve, sn) {
+      let params
+      if (leve == 'province') {
+        params = { type: '2' }
+      } else {
+        params = { parentId: sn, type: leve == 'city' ? '3' : '4' }
+      }
+      getArea(params).then(res => {
+        if (res.status == 200) {
+          if (leve == 'province') {
+            this.addrProvinceList = res.data || []
+          } else if (leve == 'city') {
+            this.addrCityList = res.data || []
+          } else if (leve == 'district') {
+            this.addrDistrictList = res.data || []
+          }
+        } else {
+          if (leve == 'province') {
+            this.addrProvinceList = []
+          } else if (leve == 'city') {
+            this.addrCityList = []
+          } else if (leve == 'district') {
+            this.addrDistrictList = []
+          }
+        }
+      })
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.getArea('province')
+    })
+  }
+}
+</script>

+ 290 - 0
src/views/reportData/chainSalesReport/list.vue

@@ -0,0 +1,290 @@
+<template>
+  <a-card size="small" :bordered="false" class="chainStockReportList-wrap">
+    <a-alert :show-icon="false" type="error" message="注:连锁销售单报表包含急件销售数量、售价,连锁销售明细报表不包含急件销售数量、成本、售价" banner style="margin-bottom: 10px;" />
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form-model
+        id="chainStockReportList-form"
+        ref="ruleForm"
+        :model="queryParam"
+        :rules="rules"
+        :labelCol="labelCol"
+        :wrapperCol="wrapperCol"
+        @keyup.enter.native="handleSearch" >
+        <a-row :gutter="15">
+          <a-col :md="6" :sm="24">
+            <a-form-model-item label="连锁店" prop="targetName">
+              <a-select
+                placeholder="请选择连锁店"
+                id="chainStockReportList-targetName"
+                allowClear
+                v-model="queryParam.targetName"
+                :showSearch="true"
+                option-filter-prop="children"
+                :filter-option="filterOption">
+                <a-select-option v-for="item in allocateTypeList" :key="item.brandSn" :value="item.brandSn">{{ item.brandName }}</a-select-option>
+              </a-select>
+            </a-form-model-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="审核时间">
+              <rangeDate ref="rangeDate" @change="dateChange" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="客户名称">
+              <a-input id="chainStockReportList-targetName" v-model.trim="queryParam.code" allowClear placeholder="请输入客户名称"/>
+            </a-form-item>
+          </a-col>
+          <template v-if="advanced">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="客户类型">
+                <a-select id="chainStockReportList-targetName" v-model="queryParam.allocateTypeSn" placeholder="请选择客户类型" allowClear >
+                  <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="12" :sm="24">
+              <a-row>
+                <a-form-item label="客户所在区" :labelCol="{span: 4}" :wrapperCol="{ span: 20 }">
+                  <a-col span="7">
+                    <a-form-item prop="dealerProvinceSn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerProvinceSn" @change="getCityList" placeholder="请选择省">
+                        <a-select-option v-for="item in addrProvinceList" :value="item.id" :key="item.id + 'a'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                  <a-col span="7" offset="1">
+                    <a-form-item prop="dealerCitySn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerCitySn" @change="getAreaList" placeholder="请选择市">
+                        <a-select-option v-for="item in addrCityList" :value="item.id" :key="item.id + 'b'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                  <a-col span="7" offset="1">
+                    <a-form-item prop="dealerCountySn" style="margin: 0;">
+                      <a-select v-model="queryParam.dealerCountySn" placeholder="请选择区/县">
+                        <a-select-option v-for="item in addrDistrictList" :value="item.id" :key="item.id + 'c'">{{ item.name }}</a-select-option>
+                      </a-select>
+                    </a-form-item>
+                  </a-col>
+                </a-form-item>
+              </a-row>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="收款方式">
+                <a-select id="chainStockReportList-targetName" v-model="queryParam.allocateTypeSn" placeholder="请选择收款方式" allowClear >
+                  <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="单号">
+                <a-input id="chainStockReportList-targetName" v-model.trim="queryParam.code" allowClear placeholder="请输入单号"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="业务员">
+                <a-input id="chainStockReportList-targetName" v-model.trim="queryParam.code" allowClear placeholder="请输入业务员"/>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="handleSearch" :disabled="disabled" id="chainStockReportList-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="chainStockReportList-reset">重置</a-button>
+            <a @click="advanced=!advanced" style="margin-left: 8px">
+              {{ advanced ? '收起' : '展开' }}
+              <a-icon :type="advanced ? 'up' : 'down'"/>
+            </a>
+          </a-col>
+        </a-row>
+      </a-form-model>
+    </div>
+    <!-- 合计 -->
+    <a-alert type="info" showIcon style="margin-bottom:15px">
+      <div class="ftext" slot="message">
+        总单数:<strong>1</strong>;
+        产品总数量:<strong>3</strong>;
+        总成本:<strong>¥33.00</strong>;
+        总售价:<strong>¥48.00</strong>;
+        总毛利:<strong>¥15.00</strong>。
+      </div>
+    </a-alert>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :scroll="{ x: 1170 }"
+      bordered>
+    </s-table>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { getArea } from '@/api/data'
+// import { allocateBillList, allocateBillDel, allocateBillAudit, allocateBillExport } from '@/api/allocateBill'
+// import { allocateTypeAllList } from '@/api/allocateType'
+export default {
+  components: { STable, VSelect, rangeDate },
+  data () {
+    return {
+      labelCol: { span: 8 },
+      wrapperCol: { span: 16 },
+      advanced: false, // 高级搜索 展开/关闭
+      tableHeight: 0,
+      queryParam: { //  查询条件
+        beginDate: '',
+        endDate: '',
+        targetName: undefined,
+        code: '', //  产品编码
+        name: '', //  产品名称
+        origCode: '', //  原厂编码
+        productBrandSn: undefined, //  产品品牌
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '' //  产品三级分类
+      },
+      rules: {
+        'targetName': [{ required: true, message: '请选择连锁店', trigger: 'change' }]
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      exportLoading: false,
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center', fixed: 'left' },
+        { title: '销售单号', dataIndex: 'code', width: 220, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '客户名称', dataIndex: 'name', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '收款方式', dataIndex: 'currentStockCost', width: 165, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '款数', dataIndex: 'totalCategory', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '数量', dataIndex: 'totalQty', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+        { title: '成本', dataIndex: 'totalCost', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? ('¥' + text) : '--') } },
+        { title: '售价', dataIndex: 'totalAmount', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? ('¥' + text) : '--') } },
+        { title: '毛利', dataIndex: 'totalMl', width: 165, align: 'center', customRender: function (text) { return ((text || text == 0) ? ('¥' + text) : '--') } },
+        { title: '业务员', dataIndex: 'billName', width: 165, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '审核时间', dataIndex: 'auditDate', width: 165, align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        // return allocateBillList(Object.assign(parameter, this.queryParam)).then(res => {
+        //   const data = res.data
+        //   const no = (data.pageNo - 1) * data.pageSize
+        //   for (var i = 0; i < data.list.length; i++) {
+        //     data.list[i].no = no + i + 1
+        //   }
+        //   this.disabled = false
+        //   return data
+        // })
+        const _this = this
+        return new Promise(function (resolve, reject) {
+          const data = {
+            pageNo: 1,
+            pageSize: 10,
+            list: [
+              { id: '1', code: '159177', name: '支持市级', currentStockCost: '现金', totalCategory: '3', totalQty: '3', totalCost: '33.00', totalAmount: '48.00', totalMl: '15.00', billName: '', auditDate: '2021-03-19 18:27:48' }
+            ],
+            count: 10
+          }
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = i + 1
+          }
+          _this.disabled = false
+          resolve(data)
+        })
+      },
+      addrProvinceList: [], //  省下拉
+      addrCityList: [], //  市下拉
+      addrDistrictList: [], //  区下拉
+      allocateTypeList: [] //  调拨类型
+    }
+  },
+  methods: {
+    //  创建时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    //  查询
+    handleSearch () {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.$refs.table.refresh(true)
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.targetName = undefined
+      this.queryParam.code = ''
+      this.queryParam.name = ''
+      this.queryParam.origCode = ''
+      this.queryParam.productBrandSn = undefined
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.productType = []
+      this.$refs.table.refresh(true)
+    },
+    filterOption (input, option) {
+      return (
+        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+      )
+    },
+    // 获取城市列表
+    getCityList (val) {
+      this.addrCityList = []
+      this.addrDistrictList = []
+      this.queryParam.dealerCitySn = undefined
+      this.queryParam.dealerCountySn = undefined
+      this.getArea('city', val)
+    },
+    // 获取区县列表
+    getAreaList (val) {
+      this.addrDistrictList = []
+      this.queryParam.dealerCountySn = undefined
+      this.getArea('district', val)
+    },
+    //  省/市/区
+    getArea (leve, sn) {
+      let params
+      if (leve == 'province') {
+        params = { type: '2' }
+      } else {
+        params = { parentId: sn, type: leve == 'city' ? '3' : '4' }
+      }
+      getArea(params).then(res => {
+        if (res.status == 200) {
+          if (leve == 'province') {
+            this.addrProvinceList = res.data || []
+          } else if (leve == 'city') {
+            this.addrCityList = res.data || []
+          } else if (leve == 'district') {
+            this.addrDistrictList = res.data || []
+          }
+        } else {
+          if (leve == 'province') {
+            this.addrProvinceList = []
+          } else if (leve == 'city') {
+            this.addrCityList = []
+          } else if (leve == 'district') {
+            this.addrDistrictList = []
+          }
+        }
+      })
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.getArea('province')
+    })
+  }
+}
+</script>

+ 155 - 0
src/views/reportData/chainStockReport/detailModal.vue

@@ -0,0 +1,155 @@
+<template>
+  <a-modal
+    centered
+    class="chainStockReportDetail-modal"
+    :footer="null"
+    :maskClosable="false"
+    :title="modalTit"
+    v-model="isShow"
+    @cancle="isShow=false"
+    :width="960">
+    <!-- 合计 -->
+    <a-alert type="info" showIcon style="margin-bottom:15px">
+      <div class="ftext" slot="message">现有库存总数量(个):
+        <strong>
+          <!-- {{ currentStock.currentQty || 0 }} -->207
+        </strong>;现有库存总成本(¥):
+        <strong>
+          <!-- {{ currentStock.putCost || 0 }} -->1550.5
+        </strong>。</div>
+    </a-alert>
+    <!-- 详情 -->
+    <s-table
+      v-if="openModal"
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :scroll="{ x: 1580 }"
+      bordered>
+      <!-- 库存数量 -->
+      <template slot="currentQty" slot-scope="text, record">
+        {{ (record.currentQty + record.freezeQty) || 0 }}
+        <span v-if="record.freezeQty">(冻结{{ record.freezeQty }})</span>
+      </template>
+    </s-table>
+    <div class="btn-cont">
+      <a-button id="chainStockReportDetail-detail-modal-back" @click="isShow = false">返回列表</a-button>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { STable } from '@/components'
+import { stockDetailList, stockDetailCount } from '@/api/stock'
+export default {
+  name: 'InventoryQueryDetailModal',
+  components: { STable },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemId: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  computed: {
+    modalTit () {
+      return '详情'
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center', fixed: 'left' },
+        { title: '产品编码', dataIndex: 'productCode', width: 220, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'productName', align: 'center', ellipsis: true, customRender: function (text) { return text || '--' } },
+        { title: '原厂编码', dataIndex: 'productOrigCode', width: 220, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '入库时间', dataIndex: 'putTime', width: 160, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '仓库', dataIndex: 'warehouseName', width: 140, align: 'center', ellipsis: true, customRender: function (text) { return text || '--' } },
+        { title: '仓位', dataIndex: 'warehouseLocationName', width: 140, align: 'center', ellipsis: true, customRender: function (text) { return text || '--' } },
+        { title: '入库类型', dataIndex: 'putBizTypeDictValue', width: 140, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '库存数量', scopedSlots: { customRender: 'currentQty' }, width: 180, align: 'center' },
+        { title: '成本单价', dataIndex: 'putCost', width: 100, align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        // return stockDetailList(Object.assign(parameter, { stockSn: this.itemId })).then(res => {
+        //   const data = res.data
+        //   const no = (data.pageNo - 1) * data.pageSize
+        //   for (var i = 0; i < data.list.length; i++) {
+        //     data.list[i].no = no + i + 1
+        //   }
+        //   this.disabled = false
+        //   // 总计
+        //   this.getTotal(Object.assign(parameter, { stockSn: this.itemId }))
+        //   return data
+        // })
+        const _this = this
+        return new Promise(function (resolve, reject) {
+          const data = {
+            pageNo: 1,
+            pageSize: 10,
+            list: [
+              { id: '1', productCode: 'GA-11078N', productName: '冠牌空气滤清器 丰田新款佳美2.4 12款逸致1.8', productOrigCode: '17807-20040', putTime: '2021-01-28 14:56:11', warehouseName: '默认仓库', warehouseLocationName: '默认仓位', putBizTypeDictValue: '散件入库', currentQty: '207', freezeQty: '', putCost: '1550.50' }
+            ],
+            count: 10
+          }
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = i + 1
+          }
+          _this.disabled = false
+          resolve(data)
+        })
+      },
+      currentStock: { // 合计信息
+        currentQty: '',
+        putCost: ''
+      }
+    }
+  },
+  methods: {
+    // 合计
+    getTotal (param) {
+      stockDetailCount(param).then(res => {
+        if (res.status == 200 && res.data) {
+          this.currentStock = res.data
+        } else {
+          this.currentStock = { // 合计信息
+            currentQty: '',
+            putCost: ''
+          }
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .chainStockReportDetail-modal{
+    .btn-cont {
+      text-align: center;
+      margin: 5px 0 10px;
+    }
+  }
+</style>

+ 272 - 0
src/views/reportData/chainStockReport/list.vue

@@ -0,0 +1,272 @@
+<template>
+  <a-card size="small" :bordered="false" class="chainStockReportList-wrap">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form-model
+        id="chainStockReportList-form"
+        ref="ruleForm"
+        :model="queryParam"
+        :rules="rules"
+        :labelCol="labelCol"
+        :wrapperCol="wrapperCol"
+        @keyup.enter.native="handleSearch" >
+        <a-row :gutter="15">
+          <a-col :md="6" :sm="24">
+            <a-form-model-item label="连锁店" prop="targetName">
+              <a-select
+                placeholder="请选择连锁店"
+                id="chainStockReportList-targetName"
+                allowClear
+                v-model="queryParam.targetName"
+                :showSearch="true"
+                option-filter-prop="children"
+                :filter-option="filterOption">
+                <a-select-option v-for="item in allocateTypeList" :key="item.brandSn" :value="item.brandSn">{{ item.brandName }}</a-select-option>
+              </a-select>
+            </a-form-model-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="产品编码">
+              <a-input id="productInfoList-code" v-model.trim="queryParam.code" allowClear placeholder="请输入产品编码"/>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="产品名称">
+              <a-input id="productInfoList-name" v-model.trim="queryParam.name" allowClear placeholder="请输入产品名称"/>
+            </a-form-item>
+          </a-col>
+          <template v-if="advanced">
+            <a-col :md="6" :sm="24">
+              <a-form-item label="原厂编码">
+                <a-input id="productInfoList-origCode" v-model.trim="queryParam.origCode" allowClear placeholder="请输入原厂编码"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="产品品牌">
+                <a-select
+                  placeholder="请选择产品品牌"
+                  id="productInfoList-productBrandSn"
+                  allowClear
+                  v-model="queryParam.productBrandSn"
+                  :showSearch="true"
+                  option-filter-prop="children"
+                  :filter-option="filterOption">
+                  <a-select-option v-for="item in productBrandList" :key="item.brandSn" :value="item.brandSn">{{ item.brandName }}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="产品分类">
+                <a-cascader
+                  @change="changeProductType"
+                  change-on-select
+                  v-model="productType"
+                  expand-trigger="hover"
+                  :options="productTypeList"
+                  :fieldNames="{ label: 'productTypeName', value: 'productTypeSn', children: 'children' }"
+                  id="productInfoList-productType"
+                  placeholder="请选择产品分类"
+                  allowClear />
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="handleSearch" :disabled="disabled" id="chainStockReportList-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="chainStockReportList-reset">重置</a-button>
+            <a @click="advanced=!advanced" style="margin-left: 8px">
+              {{ advanced ? '收起' : '展开' }}
+              <a-icon :type="advanced ? 'up' : 'down'"/>
+            </a>
+          </a-col>
+        </a-row>
+      </a-form-model>
+    </div>
+    <!-- 合计 -->
+    <a-alert type="info" showIcon style="margin-bottom:15px">
+      <div class="ftext" slot="message">现有库存总数量(个):
+        <strong>
+          <!-- {{ currentStock.currentQty || 0 }} -->207
+        </strong>;现有库存总成本(¥):
+        <strong>
+          <!-- {{ currentStock.putCost || 0 }} -->1550.5
+        </strong>。</div>
+    </a-alert>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :scroll="{ x: 1170 }"
+      bordered>
+      <!-- 现有库存数量 -->
+      <template slot="currentStockQty" slot-scope="text, record">
+        {{ (record.currentStockQty + record.freezeQty) || 0 }}
+        <span v-if="record.freezeQty">(冻结{{ record.freezeQty }})</span>
+      </template>
+      <template slot="currentStockCost" slot-scope="text, record">
+        {{ (Number(record.currentStockCost)*100 + Number(record.freezeCost)*100)/100 || 0 }}
+      </template>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-button size="small" type="link" class="button-success" @click="goDetail(record)" id="chainStockReportList-detail-btn">详情</a-button>
+      </template>
+    </s-table>
+    <!-- 详情 -->
+    <chain-stock-report-detail-modal :openModal="openModal" :itemId="itemId" @close="closeModal" />
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import chainStockReportDetailModal from './detailModal.vue'
+import { dealerProductBrandQuery } from '@/api/dealerProductBrand'
+import { dealerProductTypeList } from '@/api/dealerProductType'
+// import { allocateBillList, allocateBillDel, allocateBillAudit, allocateBillExport } from '@/api/allocateBill'
+// import { allocateTypeAllList } from '@/api/allocateType'
+export default {
+  components: { STable, VSelect, chainStockReportDetailModal },
+  data () {
+    return {
+      advanced: false, // 高级搜索 展开/关闭
+      tableHeight: 0,
+      queryParam: { //  查询条件
+        targetName: undefined,
+        code: '', //  产品编码
+        name: '', //  产品名称
+        origCode: '', //  原厂编码
+        productBrandSn: undefined, //  产品品牌
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '' //  产品三级分类
+      },
+      labelCol: { span: 8 },
+      wrapperCol: { span: 16 },
+      rules: {
+        'targetName': [{ required: true, message: '请选择连锁店', trigger: 'change' }]
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      exportLoading: false,
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center', fixed: 'left' },
+        { title: '产品编码', dataIndex: 'code', width: 220, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'name', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '原厂编码', dataIndex: 'origCode', width: 220, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '现有库存数量(个)', dataIndex: 'currentStockQty', scopedSlots: { customRender: 'currentStockQty' }, width: 165, align: 'center', sorter: true },
+        { title: '现有库存成本(¥)', dataIndex: 'currentStockCost', scopedSlots: { customRender: 'currentStockCost' }, width: 165, align: 'center', sorter: true },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: 100, align: 'center', fixed: 'right' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        // return allocateBillList(Object.assign(parameter, this.queryParam)).then(res => {
+        //   const data = res.data
+        //   const no = (data.pageNo - 1) * data.pageSize
+        //   for (var i = 0; i < data.list.length; i++) {
+        //     data.list[i].no = no + i + 1
+        //   }
+        //   this.disabled = false
+        //   return data
+        // })
+        const _this = this
+        return new Promise(function (resolve, reject) {
+          const data = {
+            pageNo: 1,
+            pageSize: 10,
+            list: [
+              { id: '1', code: 'GA-11078N', name: '冠牌空气滤清器 丰田新款佳美2.4 12款逸致1.8', origCode: '17807-20040', currentStockQty: '207', freezeQty: '', currentStockCost: '1550.50', freezeCost: '' }
+            ],
+            count: 10
+          }
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = i + 1
+          }
+          _this.disabled = false
+          resolve(data)
+        })
+      },
+      productType: [],
+      productBrandList: [], //  品牌下拉数据
+      productTypeList: [], //  分类下拉数据
+      allocateTypeList: [], //  调拨类型
+      itemId: '', //  当前id
+      openModal: false //  弹框
+    }
+  },
+  methods: {
+    //  查询
+    handleSearch () {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.$refs.table.refresh(true)
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.targetName = undefined
+      this.queryParam.code = ''
+      this.queryParam.name = ''
+      this.queryParam.origCode = ''
+      this.queryParam.productBrandSn = undefined
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.productType = []
+      this.$refs.table.refresh(true)
+    },
+    //  详情
+    goDetail (row) {
+      this.itemId = row.stockSn
+      this.openModal = true
+    },
+    //  关闭弹框
+    closeModal () {
+      this.itemId = ''
+      this.openModal = false
+    },
+    //  产品分类  change
+    changeProductType (val, opt) {
+      this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
+      this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
+      this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
+    },
+    //  产品品牌  列表
+    getProductBrand () {
+      dealerProductBrandQuery({ 'sysFlag': '0' }).then(res => {
+        if (res.status == 200) {
+          this.productBrandList = res.data
+        } else {
+          this.productBrandList = []
+        }
+      })
+    },
+    //  产品分类  列表
+    getProductType () {
+      dealerProductTypeList({ 'sysFlag': '0' }).then(res => {
+        if (res.status == 200) {
+          this.productTypeList = res.data
+        } else {
+          this.productTypeList = []
+        }
+      })
+    },
+    filterOption (input, option) {
+      return (
+        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+      )
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.getProductBrand()
+      vm.getProductType()
+    })
+  }
+}
+</script>

+ 219 - 0
src/views/reportData/customerReport/list.vue

@@ -0,0 +1,219 @@
+<template>
+  <a-card size="small" :bordered="false" class="chainStockReportList-wrap">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form-model
+        id="chainStockReportList-form"
+        ref="ruleForm"
+        :model="queryParam"
+        :rules="rules"
+        :labelCol="labelCol"
+        :wrapperCol="wrapperCol"
+        @keyup.enter.native="handleSearch" >
+        <a-row :gutter="15">
+          <a-col :md="6" :sm="24">
+            <a-form-item label="添加时间">
+              <rangeDate ref="rangeDate" @change="dateChange" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="产品分类">
+              <a-select id="chainStockReportList-targetName" v-model="queryParam.allocateTypeSn" placeholder="请选择产品分类" allowClear >
+                <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="区域">
+              <a-select id="chainStockReportList-targetName" v-model="queryParam.allocateTypeSn" placeholder="请选择" allowClear >
+                <a-select-option v-for="item in allocateTypeList" :key="item.allocateTypeSn" :value="item.allocateTypeSn">{{ item.name }}</a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="handleSearch" :disabled="disabled" id="chainStockReportList-refresh">查询</a-button>
+            <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="chainStockReportList-reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form-model>
+    </div>
+    <!-- 合计 -->
+    <a-alert type="info" showIcon style="margin-bottom:15px">
+      <div class="ftext" slot="message">
+        总交易金额:<strong>3638.55</strong>;
+        总毛利率:<strong>54.97%</strong>
+      </div>
+    </a-alert>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      bordered>
+    </s-table>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { getArea } from '@/api/data'
+// import { allocateBillList, allocateBillDel, allocateBillAudit, allocateBillExport } from '@/api/allocateBill'
+// import { allocateTypeAllList } from '@/api/allocateType'
+export default {
+  components: { STable, VSelect, rangeDate },
+  data () {
+    return {
+      labelCol: { span: 8 },
+      wrapperCol: { span: 16 },
+      advanced: false, // 高级搜索 展开/关闭
+      tableHeight: 0,
+      queryParam: { //  查询条件
+        beginDate: '',
+        endDate: '',
+        targetName: undefined,
+        code: '', //  产品编码
+        name: '', //  产品名称
+        origCode: '', //  原厂编码
+        productBrandSn: undefined, //  产品品牌
+        productTypeSn1: '', //  产品一级分类
+        productTypeSn2: '', //  产品二级分类
+        productTypeSn3: '' //  产品三级分类
+      },
+      rules: {
+        'targetName': [{ required: true, message: '请选择连锁店', trigger: 'change' }]
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      exportLoading: false,
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center', fixed: 'left' },
+        { title: '客户名称', dataIndex: 'name', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '交易金额', dataIndex: 'currentStockCost', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '毛利率', dataIndex: 'totalCategory', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        // return allocateBillList(Object.assign(parameter, this.queryParam)).then(res => {
+        //   const data = res.data
+        //   const no = (data.pageNo - 1) * data.pageSize
+        //   for (var i = 0; i < data.list.length; i++) {
+        //     data.list[i].no = no + i + 1
+        //   }
+        //   this.disabled = false
+        //   return data
+        // })
+        const _this = this
+        return new Promise(function (resolve, reject) {
+          const data = {
+            pageNo: 1,
+            pageSize: 10,
+            list: [
+              { id: '1', code: '159177', name: '测试修理厂', currentStockCost: '¥1729.55', totalCategory: '44.58%' },
+              { id: '2', code: '159177', name: '常青二路总店', currentStockCost: '¥395.00', totalCategory: '45.32%' },
+              { id: '3', code: '159177', name: '支持市级', currentStockCost: '¥1136.00', totalCategory: '90.05%' },
+              { id: '4', code: '159177', name: '支持特约测试', currentStockCost: '¥378.00', totalCategory: '7.04%' }
+            ],
+            count: 10
+          }
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = i + 1
+          }
+          _this.disabled = false
+          resolve(data)
+        })
+      },
+      addrProvinceList: [], //  省下拉
+      addrCityList: [], //  市下拉
+      addrDistrictList: [], //  区下拉
+      allocateTypeList: [] //  调拨类型
+    }
+  },
+  methods: {
+    //  创建时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    //  查询
+    handleSearch () {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.$refs.table.refresh(true)
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    //  重置
+    resetSearchForm () {
+      this.queryParam.targetName = undefined
+      this.queryParam.code = ''
+      this.queryParam.name = ''
+      this.queryParam.origCode = ''
+      this.queryParam.productBrandSn = undefined
+      this.queryParam.productTypeSn1 = ''
+      this.queryParam.productTypeSn2 = ''
+      this.queryParam.productTypeSn3 = ''
+      this.productType = []
+      this.$refs.table.refresh(true)
+    },
+    filterOption (input, option) {
+      return (
+        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+      )
+    },
+    // 获取城市列表
+    getCityList (val) {
+      this.addrCityList = []
+      this.addrDistrictList = []
+      this.queryParam.dealerCitySn = undefined
+      this.queryParam.dealerCountySn = undefined
+      this.getArea('city', val)
+    },
+    // 获取区县列表
+    getAreaList (val) {
+      this.addrDistrictList = []
+      this.queryParam.dealerCountySn = undefined
+      this.getArea('district', val)
+    },
+    //  省/市/区
+    getArea (leve, sn) {
+      let params
+      if (leve == 'province') {
+        params = { type: '2' }
+      } else {
+        params = { parentId: sn, type: leve == 'city' ? '3' : '4' }
+      }
+      getArea(params).then(res => {
+        if (res.status == 200) {
+          if (leve == 'province') {
+            this.addrProvinceList = res.data || []
+          } else if (leve == 'city') {
+            this.addrCityList = res.data || []
+          } else if (leve == 'district') {
+            this.addrDistrictList = res.data || []
+          }
+        } else {
+          if (leve == 'province') {
+            this.addrProvinceList = []
+          } else if (leve == 'city') {
+            this.addrCityList = []
+          } else if (leve == 'district') {
+            this.addrDistrictList = []
+          }
+        }
+      })
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.getArea('province')
+    })
+  }
+}
+</script>

+ 8 - 0
src/views/reportData/receivedSendStorageReport/list.vue

@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

+ 275 - 0
src/views/reportData/stockExpenditureReport/list.vue

@@ -0,0 +1,275 @@
+<template>
+  <a-card size="small" :bordered="false" class="noticeList-wrap">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="handelSearch(1)">
+        <a-row :gutter="15">
+          <a-col :md="6" :sm="24">
+            <a-form-item label="出库完成时间">
+              <rangeDate ref="rangeDate" @change="dateChange" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="handelSearch(1)" id="noticeList-refresh">查询</a-button>
+            <a-button style="margin-left: 8px" @click="resetSearchForm" id="noticeList-reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 列表 -->
+    <a-row :gutter="15">
+      <a-col :md="12" :sm="24">
+        <div class="chart-box">
+          <div class="chart-hj">库存总出数量:372,总成本:¥4315.50</div>
+          <div id="con1" class="chart"></div>
+        </div>
+      </a-col>
+      <a-col :md="12" :sm="24">
+        <a-table
+          class="sTable"
+          ref="table"
+          size="default"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :dataSource="loadData"
+          :loading="listLoading"
+          :pagination="false"
+          bordered>
+        </a-table>
+      </a-col>
+    </a-row>
+  </a-card>
+</template>
+
+<script>
+import rangeDate from '@/views/common/rangeDate.vue'
+import echarts from 'echarts'
+export default {
+  components: { rangeDate },
+  data () {
+    return {
+      queryParam: { //  查询条件
+        beginDate: '',
+        endDate: ''
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      columns: [
+        { title: '明细项', dataIndex: 'itemName', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '数量(件)', dataIndex: 'qty', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '成本(元)', dataIndex: 'cost', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '售价(元)', dataIndex: 'price', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 统计图
+      pieData: [],
+      pieColor: ['#00aaff', '#ffaa00', '#00aa00', '#ff55ff', '#1dc5d4', '#8465c7', '#00ffff'],
+      loadData: [],
+      listLoading: false,
+      chart1: null
+    }
+  },
+
+  methods: {
+    // 初始化饼图 title: 标题 data:数据 bit:单位
+    initPie (chart, title, data, bit) {
+      const legend = []
+      if (bit) {
+        data.map(item => {
+    			 const p = `${item.name}: ${item.value}${bit}`
+    			 legend.push(p)
+        })
+      }
+      const option = {
+        color: this.pieColor,
+        title: {
+          text: title,
+          top: 20,
+          left: 20,
+          textStyle: {
+            color: '#abd7ff'
+          },
+          textAlingn: 'left'
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: `{b} : {d}%`
+        },
+        legend: {
+    		  orient: 'horizontal',
+    		  left: 'center',
+    		  bottom: '5',
+    		  padding: 5,
+    		  textStyle: {
+    		    color: '#abd7ff',
+            fontSize: 10
+    		  },
+    		  show: !!bit,
+    		  formatter: function (name) {
+    			  if (bit) {
+              const p = data.find(item => item.name == name)
+              return name + (p ? (':' + p.value + bit) : '')
+    			  }
+    		  }
+        },
+        series: [{
+          type: 'pie',
+          radius: ['30%', '50%'],
+          startAngle: 75,
+          top: 50,
+          avoidLabelOverlap: true, // 在标签拥挤重叠的情况下会挪动各个标签的位置,防止标签间的重叠
+          label: {
+            normal: {
+              formatter: params => {
+                return (
+                  '{name|' + params.name + '}{value|' +
+    										params.percent + '%' + '}'
+                )
+              },
+              padding: [0, -70, 25, -70],
+              rich: {
+                name: {
+                  fontSize: 12,
+                  padding: [0, 4, 0, 4],
+                  color: '#999'
+                },
+                value: {
+                  fontSize: 12,
+                  color: '#999'
+                }
+              }
+            }
+          },
+          labelLine: {
+            normal: {
+              length: 20,
+              length2: 70,
+              lineStyle: {
+                color: '#e6e6e6'
+              }
+            }
+          },
+          data: data,
+          insideLabel: {
+            show: true
+          }
+        }]
+      }
+      return option
+    },
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0] ? date[0] + ' 00:00:00' : ''
+      this.queryParam.endDate = date[1] ? date[1] + ' 23:59:59' : ''
+    },
+    // 查询列表
+    handelSearch () {
+      const params = {
+        beginDate: this.queryParam.beginDate,
+        endDate: this.queryParam.endDate
+      }
+      // 开始查询
+      this.listLoading = true
+      setTimeout(() => {
+        this.listLoading = false
+        this.loadData = [
+          {
+            itemName: '采购退货',
+            qty: '14',
+            cost: '84.50',
+            price: ''
+          },
+          {
+            itemName: '散件退货',
+            qty: '3',
+            cost: '28.00',
+            price: ''
+          },
+          {
+            itemName: '销售(含急件)',
+            qty: '77',
+            cost: '837.50',
+            price: '2672.55'
+          },
+          {
+            itemName: '急件冲减',
+            qty: '9',
+            cost: '109.50',
+            price: ''
+          },
+          {
+            itemName: '店内调出',
+            qty: '6',
+            cost: '55.00',
+            price: ''
+          },
+          {
+            itemName: '盘亏出库',
+            qty: '190',
+            cost: '2725.00',
+            price: ''
+          },
+          {
+            itemName: '连锁调出',
+            qty: '73',
+            cost: '476.00',
+            price: ''
+          },
+          {
+            itemName: '总出',
+            qty: '372',
+            cost: '4315.50',
+            price: '2672.55'
+          }
+        ]
+        this.chartInit()
+      }, 600)
+    },
+    chartInit () {
+      this.loadData.map((item, index) => {
+        if (index != this.loadData.length - 1) {
+          this.pieData.push({
+            name: item.itemName + '总成本',
+            value: item.cost
+          })
+        }
+      })
+      const con5 = document.getElementById('con1')
+      const chart1 = echarts.init(con1)
+      const option = this.initPie(chart1, '', this.pieData)
+      chart1.setOption(option)
+      this.chart1 = chart1
+      this.chart1.resize()
+    },
+    //  重置
+    resetSearchForm () {
+      this.$refs.rangeDate.resetDate()
+      this.handelSearch()
+    }
+  },
+  mounted () {
+    window.onresize = () => {
+      return (() => {
+        this.chart1.resize()
+      })()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.handelSearch()
+    })
+  }
+}
+</script>
+<style lang="less">
+  .chart-box{
+    height: 400px;
+    .chart-hj{
+      font-size: 22px;
+      text-align: center;
+    }
+    .chart{
+      width: 100%;
+      height: 450px;
+      overflow: auto;
+    }
+  }
+</style>

+ 269 - 0
src/views/reportData/stockIncomeReport/list.vue

@@ -0,0 +1,269 @@
+<template>
+  <a-card size="small" :bordered="false" class="noticeList-wrap">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="handelSearch(1)">
+        <a-row :gutter="15">
+          <a-col :md="6" :sm="24">
+            <a-form-item label="入库完成时间">
+              <rangeDate ref="rangeDate" @change="dateChange" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="handelSearch(1)" id="noticeList-refresh">查询</a-button>
+            <a-button style="margin-left: 8px" @click="resetSearchForm" id="noticeList-reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 列表 -->
+    <a-row :gutter="15">
+      <a-col :md="12" :sm="24">
+        <div class="chart-box">
+          <div class="chart-hj">库存总入数量:28,总成本:¥189.50</div>
+          <div id="con1" class="chart"></div>
+        </div>
+      </a-col>
+      <a-col :md="12" :sm="24">
+        <a-table
+          class="sTable"
+          ref="table"
+          size="default"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :dataSource="loadData"
+          :loading="listLoading"
+          :pagination="false"
+          bordered>
+        </a-table>
+      </a-col>
+    </a-row>
+  </a-card>
+</template>
+
+<script>
+import rangeDate from '@/views/common/rangeDate.vue'
+import echarts from 'echarts'
+export default {
+  components: { rangeDate },
+  data () {
+    return {
+      queryParam: { //  查询条件
+        beginDate: '',
+        endDate: ''
+      },
+      disabled: false, //  查询、重置按钮是否可操作
+      columns: [
+        { title: '明细项', dataIndex: 'itemName', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '数量(件)', dataIndex: 'qty', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '成本(元)', dataIndex: 'cost', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '售价(元)', dataIndex: 'price', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 统计图
+      pieData: [],
+      pieColor: ['#00aaff', '#ffaa00', '#00aa00', '#ff55ff', '#1dc5d4', '#8465c7', '#00ffff'],
+      loadData: [],
+      listLoading: false,
+      chart1: null
+    }
+  },
+
+  methods: {
+    // 初始化饼图 title: 标题 data:数据 bit:单位
+    initPie (chart, title, data, bit) {
+      const legend = []
+      if (bit) {
+        data.map(item => {
+    			 const p = `${item.name}: ${item.value}${bit}`
+    			 legend.push(p)
+        })
+      }
+      const option = {
+        color: this.pieColor,
+        title: {
+          text: title,
+          top: 20,
+          left: 20,
+          textStyle: {
+            color: '#abd7ff'
+          },
+          textAlingn: 'left'
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: `{b} : {d}%`
+        },
+        legend: {
+    		  orient: 'horizontal',
+    		  left: 'center',
+    		  bottom: '5',
+    		  padding: 5,
+    		  textStyle: {
+    		    color: '#abd7ff',
+            fontSize: 10
+    		  },
+    		  show: !!bit,
+    		  formatter: function (name) {
+    			  if (bit) {
+              const p = data.find(item => item.name == name)
+              return name + (p ? (':' + p.value + bit) : '')
+    			  }
+    		  }
+        },
+        series: [{
+          type: 'pie',
+          radius: ['30%', '50%'],
+          startAngle: 75,
+          top: 50,
+          avoidLabelOverlap: true, // 在标签拥挤重叠的情况下会挪动各个标签的位置,防止标签间的重叠
+          label: {
+            normal: {
+              formatter: params => {
+                return (
+                  '{name|' + params.name + '}{value|' +
+    										params.percent + '%' + '}'
+                )
+              },
+              padding: [0, -70, 25, -70],
+              rich: {
+                name: {
+                  fontSize: 12,
+                  padding: [0, 4, 0, 4],
+                  color: '#999'
+                },
+                value: {
+                  fontSize: 12,
+                  color: '#999'
+                }
+              }
+            }
+          },
+          labelLine: {
+            normal: {
+              length: 20,
+              length2: 70,
+              lineStyle: {
+                color: '#e6e6e6'
+              }
+            }
+          },
+          data: data,
+          insideLabel: {
+            show: true
+          }
+        }]
+      }
+      return option
+    },
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0] ? date[0] + ' 00:00:00' : ''
+      this.queryParam.endDate = date[1] ? date[1] + ' 23:59:59' : ''
+    },
+    // 查询列表
+    handelSearch () {
+      const params = {
+        beginDate: this.queryParam.beginDate,
+        endDate: this.queryParam.endDate
+      }
+      // 开始查询
+      this.listLoading = true
+      setTimeout(() => {
+        this.listLoading = false
+        this.loadData = [
+          {
+            itemName: '采购入库',
+            qty: '8',
+            cost: '52.00',
+            price: ''
+          },
+          {
+            itemName: '散件入库',
+            qty: '17',
+            cost: '115.00',
+            price: ''
+          },
+          {
+            itemName: '销售退货',
+            qty: '3',
+            cost: '22.50',
+            price: '30.00'
+          },
+          {
+            itemName: '盘盈入库',
+            qty: '0',
+            cost: '00.00',
+            price: ''
+          },
+          {
+            itemName: '连锁调入',
+            qty: '0',
+            cost: '00.00',
+            price: ''
+          },
+          {
+            itemName: '库存导入',
+            qty: '0',
+            cost: '00.00',
+            price: ''
+          },
+          {
+            itemName: '总入',
+            qty: '28',
+            cost: '189.50',
+            price: '30.00'
+          }
+        ]
+        this.chartInit()
+      }, 600)
+    },
+    chartInit () {
+      this.loadData.map((item, index) => {
+        if (index != this.loadData.length - 1) {
+          this.pieData.push({
+            name: item.itemName + '总成本',
+            value: item.cost
+          })
+        }
+      })
+      const con5 = document.getElementById('con1')
+      const chart1 = echarts.init(con1)
+      const option = this.initPie(chart1, '', this.pieData)
+      chart1.setOption(option)
+      this.chart1 = chart1
+      this.chart1.resize()
+    },
+    //  重置
+    resetSearchForm () {
+      this.$refs.rangeDate.resetDate()
+      this.handelSearch()
+    }
+  },
+  mounted () {
+    window.onresize = () => {
+      return (() => {
+        this.chart1.resize()
+      })()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.handelSearch()
+    })
+  }
+}
+</script>
+<style lang="less">
+  .chart-box{
+    height: 400px;
+    .chart-hj{
+      font-size: 22px;
+      text-align: center;
+    }
+    .chart{
+      width: 100%;
+      height: 450px;
+      overflow: auto;
+    }
+  }
+</style>

+ 1 - 1
src/views/salesManagement/outboundOrder/list.vue

@@ -217,7 +217,7 @@ export default {
         this.$message.warning('该出库类型对应页面未开发')
         // this.$router.push({ path: `/purchasingManagement/purchaseReturn/detail/${row.outBizSn}` })
       } else if (row.outBizType == 'LINKAGE_CALL_OUT') { // 连锁调出
-        this.$message.warning('该出库类型对应页面未开发')
+        this.$router.push({ path: `/allocationManagement/chainTransferOut/detail/${row.outBizSn}` })
         // this.$router.push({ path: `/purchasingManagement/purchaseReturn/detail/${row.outBizSn}` })
       } else if (row.outBizType == 'WAREHOUSE_CALL_OUT') { // 仓库调出
         this.$router.push({ path: `/allocationManagement/warehouseAllocation/detail/${row.outBizSn}` })