Browse Source

Merge branch 'master' of http://git.wdklian.com/allen/ncs_ui

* 'master' of http://git.wdklian.com/allen/ncs_ui:
  优化交互统计、其他优化
  新增设备的电话号码
  增加交互统计功能
  增加医院版病人管理的批量删除
  删除未知性别,将医院版的用户情况简述修改为病况描述,修复无法添加护工的问题
  修复选择设备时,空间出错的问题
wuyunfeng 3 năm trước cách đây
mục cha
commit
367bbcf69d

+ 0 - 1
dist/static/css/chunk-665577f1.e3b1b772.css

@@ -1 +0,0 @@
-[data-v-70c39c2b] .avatar-uploader .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload[data-v-70c39c2b]:hover{border-color:#409eff}.avatar-uploader-icon[data-v-70c39c2b]{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avatar[data-v-70c39c2b]{width:178px;height:178px;display:block}

+ 54 - 25
package-lock.json

@@ -2952,8 +2952,8 @@
     },
     "async-validator": {
       "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz",
-      "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
+      "resolved": "https://registry.npmmirror.com/async-validator/download/async-validator-1.8.5.tgz?cache=0&sync_timestamp=1634529574100&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fasync-validator%2Fdownload%2Fasync-validator-1.8.5.tgz",
+      "integrity": "sha1-3D4I7B/Q3dtn5ghC8CwM0c7G1/A=",
       "requires": {
         "babel-runtime": "6.x"
       }
@@ -3118,8 +3118,8 @@
     },
     "babel-helper-vue-jsx-merge-props": {
       "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
-      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
+      "resolved": "https://registry.nlark.com/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+      "integrity": "sha1-Iq69OzOQIyjlEyk6jkmSs4T58bY="
     },
     "babel-jest": {
       "version": "23.6.0",
@@ -5182,7 +5182,8 @@
     "console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+      "optional": true
     },
     "consolidate": {
       "version": "0.15.1",
@@ -6355,11 +6356,19 @@
       }
     },
     "echarts": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/echarts/-/echarts-4.2.1.tgz",
-      "integrity": "sha512-pw4xScRPsLegD/cqEcoXRKeA2SD4+s+Kyo0Na166NamOWhzNl2yI5RZ2rE97tBlAopNmhyMeBVpAeD5qb+ee1A==",
+      "version": "5.2.2",
+      "resolved": "https://registry.npmmirror.com/echarts/download/echarts-5.2.2.tgz",
+      "integrity": "sha1-7DyLKhUcu6cbo8LHz5svIEfOQ3A=",
       "requires": {
-        "zrender": "4.0.7"
+        "tslib": "2.3.0",
+        "zrender": "5.2.1"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.3.0",
+          "resolved": "https://registry.nlark.com/tslib/download/tslib-2.3.0.tgz?cache=0&sync_timestamp=1628722556410&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftslib%2Fdownload%2Ftslib-2.3.0.tgz",
+          "integrity": "sha1-gDuM2rPhK6WBpMpByIObuw2ssJ4="
+        }
       }
     },
     "editorconfig": {
@@ -6423,9 +6432,9 @@
       "dev": true
     },
     "element-ui": {
-      "version": "2.13.2",
-      "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.13.2.tgz",
-      "integrity": "sha512-r761DRPssMPKDiJZWFlG+4e4vr0cRG/atKr3Eqr8Xi0tQMNbtmYU1QXvFnKiFPFFGkgJ6zS6ASkG+sellcoHlQ==",
+      "version": "2.15.6",
+      "resolved": "https://registry.npmmirror.com/element-ui/download/element-ui-2.15.6.tgz?cache=0&sync_timestamp=1637231763572&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Felement-ui%2Fdownload%2Felement-ui-2.15.6.tgz",
+      "integrity": "sha1-yWCa3TWvWmhqS3aF3B11fHXgHfM=",
       "requires": {
         "async-validator": "~1.8.1",
         "babel-helper-vue-jsx-merge-props": "^2.0.0",
@@ -7753,7 +7762,8 @@
         "ansi-regex": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "optional": true
         },
         "is-fullwidth-code-point": {
           "version": "1.0.0",
@@ -7779,6 +7789,7 @@
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
           "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -11988,7 +11999,7 @@
     },
     "normalize-wheel": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
+      "resolved": "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz",
       "integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
     },
     "normalize.css": {
@@ -12008,7 +12019,8 @@
     "npm-normalize-package-bin": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
-      "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
+      "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
+      "optional": true
     },
     "npm-packlist": {
       "version": "1.4.8",
@@ -12768,7 +12780,8 @@
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
       "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
-      "dev": true
+      "dev": true,
+      "optional": true
     },
     "pify": {
       "version": "4.0.1",
@@ -13908,7 +13921,7 @@
       "version": "git+https://github.com/nhn/raphael.git#78a6ed3ec269f33b6457b0ec66f8c3d1f2ed70e0",
       "from": "git+https://github.com/nhn/raphael.git#2.2.0-c",
       "requires": {
-        "eve": "git://github.com/adobe-webplatform/eve.git#eef80ed8d188423c2272746fb8ae5cc8dad84cb1"
+        "eve": "git://github.com/adobe-webplatform/eve.git#eef80ed"
       }
     },
     "raw-body": {
@@ -16130,6 +16143,7 @@
           "version": "2.9.0",
           "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
           "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -16253,8 +16267,8 @@
     },
     "throttle-debounce": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
-      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg=="
+      "resolved": "https://registry.npm.taobao.org/throttle-debounce/download/throttle-debounce-1.1.0.tgz?cache=0&sync_timestamp=1604313832516&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fthrottle-debounce%2Fdownload%2Fthrottle-debounce-1.1.0.tgz",
+      "integrity": "sha1-UYU9o3vmihVctugns1FKPEIuic0="
     },
     "through": {
       "version": "2.3.8",
@@ -16508,7 +16522,7 @@
       "integrity": "sha512-DUJIutBG/tOdvJnGCo1PcBhFyGBWsY8VIMdXe3WRtGXynMwOcC5cojYpULf3qFJ4Jj1Riv3/kbF6Ygmi+BpjCw==",
       "requires": {
         "core-js": "^3.6.4",
-        "raphael": "git+https://github.com/nhn/raphael.git#78a6ed3ec269f33b6457b0ec66f8c3d1f2ed70e0",
+        "raphael": "git+https://github.com/nhn/raphael.git#2.2.0-c",
         "tui-code-snippet": "^2.3.1"
       },
       "dependencies": {
@@ -17010,8 +17024,8 @@
     },
     "vue-count-to": {
       "version": "1.0.13",
-      "resolved": "https://registry.npmjs.org/vue-count-to/-/vue-count-to-1.0.13.tgz",
-      "integrity": "sha512-6R4OVBVNtQTlcbXu6SJ8ENR35M2/CdWt3Jmv57jOUM+1ojiFmjVGvZPH8DfHpMDSA+ITs+EW5V6qthADxeyYOQ=="
+      "resolved": "https://registry.npm.taobao.org/vue-count-to/download/vue-count-to-1.0.13.tgz",
+      "integrity": "sha1-PnVz6m5kwrKXL2TgoqsuI8dZD/M="
     },
     "vue-draggable-resizable": {
       "version": "2.3.0",
@@ -17065,6 +17079,11 @@
       "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==",
       "dev": true
     },
+    "vue-i18n": {
+      "version": "8.26.7",
+      "resolved": "https://registry.npmmirror.com/vue-i18n/download/vue-i18n-8.26.7.tgz?cache=0&sync_timestamp=1637037936570&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue-i18n%2Fdownload%2Fvue-i18n-8.26.7.tgz",
+      "integrity": "sha1-rf1INzRJ/jFDjEjjs71DBE3DpoE="
+    },
     "vue-jest": {
       "version": "3.0.7",
       "resolved": "https://registry.npmjs.org/vue-jest/-/vue-jest-3.0.7.tgz",
@@ -18208,9 +18227,19 @@
       }
     },
     "zrender": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/zrender/-/zrender-4.0.7.tgz",
-      "integrity": "sha512-TNloHe0ums6zxbHfnaCryM61J4IWDajZwNq6dHk9vfWhhysO/OeFvvR0drBs/nbXha2YxSzfQj2FiCd6RVBe+Q=="
+      "version": "5.2.1",
+      "resolved": "https://registry.nlark.com/zrender/download/zrender-5.2.1.tgz",
+      "integrity": "sha1-X0u9qRW6bUErCxncJDG+qtBUF7s=",
+      "requires": {
+        "tslib": "2.3.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.3.0",
+          "resolved": "https://registry.nlark.com/tslib/download/tslib-2.3.0.tgz?cache=0&sync_timestamp=1628722556410&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftslib%2Fdownload%2Ftslib-2.3.0.tgz",
+          "integrity": "sha1-gDuM2rPhK6WBpMpByIObuw2ssJ4="
+        }
+      }
     }
   }
 }

+ 3 - 3
package.json

@@ -24,8 +24,8 @@
     "core-js": "3.6.5",
     "driver.js": "0.9.5",
     "dropzone": "5.5.1",
-    "echarts": "4.2.1",
-    "element-ui": "2.13.2",
+    "echarts": "^5.2.2",
+    "element-ui": "^2.15.6",
     "file-saver": "2.0.1",
     "fuse.js": "3.4.4",
     "js-cookie": "2.2.0",
@@ -45,7 +45,7 @@
     "vcolorpicker": "^1.0.3",
     "vue": "2.6.10",
     "vue-class-component": "^7.2.6",
-    "vue-count-to": "1.0.13",
+    "vue-count-to": "^1.0.13",
     "vue-draggable-resizable": "^2.3.0",
     "vue-i18n": "^8.26.1",
     "vue-property-decorator": "^9.1.2",

+ 20 - 0
src/api/ncs_interaction.js

@@ -27,3 +27,23 @@ export function clearRecord(id) {
   })
 }
 
+export function getLogChars(params) {
+  console.log(params)
+  return request({
+    url: `/ncs/interaction/getLogChars`,
+    method: 'GET',
+    loading: true,
+    params
+  })
+}
+
+export function getLogTable(params) {
+  console.log(params)
+  return request({
+    url: `/ncs/interaction/getLogTable`,
+    method: 'GET',
+    loading: true,
+    params
+  })
+}
+

+ 14 - 0
src/components/YearMonthPicker/index.js

@@ -0,0 +1,14 @@
+/**
+ * 选择年份或者月份选择
+ * 返回选择的年份或者月份
+ * 返回选择的年份区间或月份区间
+ */
+
+import Vue from 'vue'
+import YearMonthPicker from './src/main'
+
+YearMonthPicker.install = () => {
+  Vue.component(YearMonthPicker.name, YearMonthPicker)
+}
+
+export default YearMonthPicker

+ 139 - 0
src/components/YearMonthPicker/src/main.vue

@@ -0,0 +1,139 @@
+<template>
+  <div style="display: inline-block">
+    <el-select v-if="optional" v-model="date_type" :disabled="disabled" placeholder="请选择" style="width: 100px">
+      <el-option label="按月" value="month" />
+      <el-option label="按年" value="year" />
+      <el-option v-if="boolDay" label="按天" value="date" />
+    </el-select>
+    <el-date-picker
+      v-model="date_val"
+      style="width: 160px"
+      :disabled="disabled"
+      :editable="editable"
+      :clearable="clearable"
+      :type="date_type"
+      :value-format="date_type === 'year' ? 'yyyy' : date_type === 'month' ? 'yyyy-MM' : 'yyyy-MM-dd'"
+      :placeholder="date_type === 'month' ? '选择月份' : '选择年份'"
+      :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+      @change="handleDateChange" />
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'EnYearMonthPicker',
+    props: {
+      editable: {
+        type: Boolean,
+        default: false
+      },
+      clearable: {
+        type: Boolean,
+        default: false
+      },
+      optional: {
+        type: Boolean,
+        default: true
+      },
+      disabled: {
+        type: Boolean,
+        default: false
+      },
+      boolDay: {
+        type: Boolean,
+        default: false
+      }
+    },
+    data() {
+      return {
+        date_type: 'month',
+        date_val: this.getCurrentYearMonth().o,
+        l_date_val: this.getCurrentYearMonth().l_o
+      }
+    },
+    watch: {
+      date_type(newVal) {
+        // this.date_val = newVal === 'month'
+        //   ? this.getCurrentYearMonth().o
+        //   : this.getCurrentYear().o
+        // this.l_date_val = newVal === 'month'
+        //   ? this.getCurrentYearMonth().l_o
+        //   : this.getCurrentYear().l_o
+
+        this.date_val = newVal === 'year'
+          ? this.getCurrentYear().o
+          : newVal === 'month' ? this.getCurrentYearMonth().o : new Date()
+        this.l_date_val = newVal === 'year'
+          ? this.getCurrentYear().l_o
+          : newVal === 'month' ? this.getCurrentYearMonth().l_o : new Date()
+        this.handleDateChange()
+      }
+    },
+    mounted() {
+      this.handleDateChange()
+    },
+    methods: {
+      /** 获取当前年份 */
+      getCurrentYear() {
+        return {
+          o: new Date().getFullYear() + '',
+          l_o: new Date().getFullYear() - 1 + ''
+        }
+      },
+      /** 获取当前年月 */
+      getCurrentYearMonth() {
+        const _cy = new Date().getFullYear() + ''
+        const _l_cy = new Date().getFullYear() - 1 + ''
+        const _cm = (() => {
+          let __cm = new Date().getMonth() + 1
+          return __cm > 9 ? __cm : '0' + __cm
+        })()
+        const _l_cm = (() => {
+          let __cm = new Date().getMonth()
+          return __cm > 9 ? __cm : '0' + __cm
+        })()
+        return {
+          o: _cy + '-' + _cm,
+          l_o: _l_cy + '-' + _l_cm
+        }
+      },
+      /** 日期发生改变 */
+      handleDateChange() {
+        let obj
+        if (this.date_type === 'date') {
+          obj = {
+            type: this.date_type.toLocaleUpperCase(),
+            date_val: new Date(this.date_val)
+          }
+        } else {
+          const is_year = this.date_type === 'year'
+          const val = this.date_val
+          const l_val = this.l_date_val
+          const _y = val.substr(0, 4)
+          const l_y = l_val.substr(0, 4)
+          const _m = val.substr(5, 2)
+          const l_m = l_val.substr(5, 2)
+          obj = {
+            type: this.date_type.toLocaleUpperCase(),
+            year: _y,
+            last_year: l_y,
+            month: _m,
+            last_month: l_m,
+            year_month: val,
+            last_year_month: l_val,
+            start_time: val + (is_year ? '-01' : '') + '-01 00:00:00',
+            last_start_time: l_val + (is_year ? '-01' : '') + '-01 00:00:00',
+            end_time: val + (is_year ? '-12' : '') + '-' + new Date(_y, _m, 0).getDate() + ' 23:59:59',
+            last_end_time: l_val + (is_year ? '-12' : '') + '-' + new Date(l_y, l_m, 0).getDate() + ' 23:59:59'
+          }
+        }
+
+        this.$emit('changed', obj)
+      }
+    }
+  }
+</script>
+
+<style type="text/scss" lang="scss" scoped>
+
+</style>

+ 3 - 1
src/components/index.js

@@ -2,11 +2,13 @@
 import TableLayout from './TableLayout'
 import TableSearch from './TableSearch'
 import AgGridLayout from './AgGridLayout'
+import YearMonthPicker from './YearMonthPicker'
 
 const components = {
   TableLayout,
   TableSearch,
-  AgGridLayout
+  AgGridLayout,
+  YearMonthPicker
 }
 
 components.install = function(Vue, opts) {

+ 5 - 0
src/main.js

@@ -43,6 +43,11 @@ if (process.env.NODE_ENV === 'production') {
   const { mockXHR } = require('../mock')
   mockXHR()
 }
+// 全局注册echarts、jsonp
+import * as echarts from 'echarts'
+import 'echarts/theme/vintage.js'
+
+Vue.prototype.$echarts = echarts
 Vue.component('AgGridVue', AgGridVue)
 Vue.use(vcolorpicker)
 Vue.use(Components)

+ 13 - 0
src/router/index.js

@@ -364,6 +364,19 @@ export const partRoutes = [
   //   ]
   // },
   {
+    path: '/ncs-interaction-chars',
+    component: Layout,
+    redirect: '/ncs-interaction-chars/index',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/ncs-chars/index'),
+        name: 'interactionChars',
+        meta: { title: '交互统计', icon: 'el-icon-pie-chart', noCache: true }
+      }
+    ]
+  },
+  {
     path: '/calling-setting',
     component: Layout,
     redirect: '/calling-setting/index',

+ 2 - 0
src/utils/device_type.js

@@ -34,6 +34,8 @@ export function returnDeviceType(value) {
       return '信标'
     case 17:
       return '看板'
+    case 18:
+      return '门禁'
     case 20:
       return '485转换盒'
     case 21:

+ 4 - 3
src/views/customer/components/customerManager.vue

@@ -43,7 +43,7 @@
     <el-dialog :visible.sync="customerFormVisible" title="用户信息" class="customer-dialog">
       <el-tabs v-model="activeName" type="border-card" tab-position="bottom" width="50%" @tab-click="handleClick">
         <el-tab-pane label="基本信息" name="customerBaseInfo">
-          <div style="height: 450px">
+          <div style="height: 490px">
             <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="12">
@@ -63,7 +63,7 @@
                   <el-form-item label="性别" class="form-item-sex">
                     <el-radio v-model="formmodel.sex" :label="0">女</el-radio>
                     <el-radio v-model="formmodel.sex" :label="1">男</el-radio>
-                    <el-radio v-model="formmodel.sex" :label="2">未知</el-radio>
+<!--                    <el-radio v-model="formmodel.sex" :label="2">未知</el-radio>-->
                   </el-form-item>
                 </el-col>
 
@@ -336,7 +336,7 @@
                   <el-form-item label="性别" class="form-item-sex">
                     <el-radio v-model="relativeFormModel.sex" :label="0">女</el-radio>
                     <el-radio v-model="relativeFormModel.sex" :label="1">男</el-radio>
-                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>
+<!--                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>-->
                   </el-form-item>
                 </el-col>
                 <el-col :span="12">
@@ -1034,6 +1034,7 @@ export default {
               this.$message.success('修改成功!')
               this.customerFormVisible = false
               this.isDisabled = false
+              this.getList()
               this.$emit('saved')
             })
           }

+ 26 - 6
src/views/customer/components/patientManager.vue

@@ -23,6 +23,7 @@
         </div>
         <div class="toolbar-btns">
           <el-button type="primary" size="mini" :disabled="!isEmptyFrame" @click="handleAdd">入院登记</el-button>
+          <el-button type="danger" size="mini" @click="batchDelete">批量删除</el-button>
         </div>
       </div>
       <el-pagination
@@ -62,7 +63,7 @@
                   <el-form-item label="性别" class="form-item-sex">
                     <el-radio v-model="formmodel.sex" :label="0">女</el-radio>
                     <el-radio v-model="formmodel.sex" :label="1">男</el-radio>
-                    <el-radio v-model="formmodel.sex" :label="2">未知</el-radio>
+<!--                    <el-radio v-model="formmodel.sex" :label="2">未知</el-radio>-->
                   </el-form-item>
                 </el-col>
 
@@ -146,7 +147,7 @@
                       </el-form-item>
                     </el-col>
                   </el-row>
-                  <el-form-item label="用户情况简述">
+                  <el-form-item label="病况描述">
                     <el-input
                       v-model="formmodel.illness_desc"
                       type="textarea"
@@ -336,7 +337,7 @@
                   <el-form-item label="性别" class="form-item-sex">
                     <el-radio v-model="relativeFormModel.sex" :label="0">女</el-radio>
                     <el-radio v-model="relativeFormModel.sex" :label="1">男</el-radio>
-                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>
+<!--                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>-->
                   </el-form-item>
                 </el-col>
                 <el-col :span="12">
@@ -377,7 +378,7 @@
             <el-form-item label="性别" class="form-item-sex">
               <el-radio v-model="changeBedFormModel.sex" :label="0" disabled>女</el-radio>
               <el-radio v-model="changeBedFormModel.sex" :label="1" disabled>男</el-radio>
-              <el-radio v-model="changeBedFormModel.sex" :label="2" disabled>未知</el-radio>
+<!--              <el-radio v-model="changeBedFormModel.sex" :label="2" disabled>未知</el-radio>-->
             </el-form-item>
           </el-col>
 
@@ -1286,7 +1287,7 @@ export default {
             } else if (item[0] === '护士') {
               _this.nurses = item[1]
             } else if (item[0] === '护工') {
-              _this.workrs = item[1]
+              _this.workers = item[1]
             }
           })
         }
@@ -1319,7 +1320,7 @@ export default {
           } else {
             this.formmodel.nurse_Mapping_id = this.nurse_Mapping_id
           }
-        } else {
+        } else if (type === 3) {
           if (this.worker_mapping_id === null) {
             this.formmodel.worker_mapping_id = 0 // 为0则新增,// 其他值为修改
           } else {
@@ -1353,6 +1354,25 @@ export default {
         //   if (nurseCfg) { this.$refs['patient_nurse_level' + i].$el.getElementsByClassName('el-input__inner')[0].style = 'color:#' + nurseCfg.nursecfg_color + ' !important' }
         // }
       })
+    },
+    /** 批量数据删除处理(删除选中的行) */
+    batchDelete: function() {
+      const rows = this.gridApi.getSelectedRows()
+      if (rows.length === 0) {
+        this.$message({ type: 'info', message: '请先勾选需要删除的数据' })
+        return
+      }
+      const ids = []
+      const uids = []
+      rows.forEach(function(item) {
+        ids.push(item.id)
+        uids.push(item.member_id)
+      })
+      this.handlerDelete(ids.join(','))
+      this.deleteMembers(uids) // 同时删除用户
+    },
+    async deleteMembers(ids) {
+      API_User.remove(ids)
     }
   }
 }

+ 384 - 386
src/views/customer/customerEdit.vue

@@ -2,16 +2,16 @@
   <div class="formwrap">
     <el-tabs v-model="activeName" @tab-click="handleClick">
       <el-tab-pane label="用户管理" name="customerEdit">
-        <el-form :model="formmodel" :rules="rules" ref="editForm" label-width="140px">
+        <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="140px">
           <el-row>
             <el-col :span="8">
               <el-form-item label="用户姓名" prop="named">
-                <el-input v-model="formmodel.named" clearable placeholder="请输入姓名" :maxlength="20"></el-input>
+                <el-input v-model="formmodel.named" clearable placeholder="请输入姓名" :maxlength="20" />
               </el-form-item>
             </el-col>
             <el-col :span="8">
               <el-form-item label="用户编号">
-                <el-input v-model="formmodel.card_no" clearable placeholder="请输入用户编号" :maxlength="20"></el-input>
+                <el-input v-model="formmodel.card_no" clearable placeholder="请输入用户编号" :maxlength="20" />
               </el-form-item>
             </el-col>
             <el-col :span="8">
@@ -53,31 +53,31 @@
           <el-row>
             <el-col :span="8">
               <el-form-item label="证件号">
-                <el-input v-model="formmodel.id_no" clearable placeholder="请输入证件号" :maxlength="20"></el-input>
+                <el-input v-model="formmodel.id_no" clearable placeholder="请输入证件号" :maxlength="20" />
               </el-form-item>
             </el-col>
             <el-col :span="8">
               <el-form-item label="入院日期" prop="in_date">
                 <el-date-picker
-                        v-model="formmodel.in_date"
-                        type="date"
-                        :editable="false"
-                        value-format="timestamp"
-                        placeholder="选择入院日期"
-                        :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}">
-                </el-date-picker>
+                  v-model="formmodel.in_date"
+                  type="date"
+                  :editable="false"
+                  value-format="timestamp"
+                  placeholder="选择入院日期"
+                  :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+                />
               </el-form-item>
             </el-col>
             <el-col :span="8">
               <el-form-item label="出院日期" prop="out_date">
                 <el-date-picker
-                        v-model="formmodel.out_date"
-                        type="date"
-                        :editable="false"
-                        value-format="timestamp"
-                        placeholder="选择出院日期"
-                        :picker-options="{disabledDate(time) { return time.getTime() < Date.now() }}">
-                </el-date-picker>
+                  v-model="formmodel.out_date"
+                  type="date"
+                  :editable="false"
+                  value-format="timestamp"
+                  placeholder="选择出院日期"
+                  :picker-options="{disabledDate(time) { return time.getTime() < Date.now() }}"
+                />
               </el-form-item>
             </el-col>
           </el-row>
@@ -85,22 +85,22 @@
           <el-row>
             <el-col :span="8">
               <el-form-item label="责任医生">
-                <el-select placeholder="请选择医生" v-model="formmodel.doctor_id" @change="doctorChange(1)">
-                  <el-option :label="item.clerk_name" :key="index" v-for="(item,index) in doctors" :value="item.clerk_id"></el-option>
+                <el-select v-model="formmodel.doctor_id" placeholder="请选择医生" @change="doctorChange(1)">
+                  <el-option v-for="(item,index) in doctors" :key="index" :label="item.clerk_name" :value="item.clerk_id" />
                 </el-select>
               </el-form-item>
             </el-col>
             <el-col :span="8">
               <el-form-item label="责任护士">
-                <el-select placeholder="请选择护士" v-model="formmodel.nurse_id" @change="doctorChange(2)">
-                  <el-option :label="item.clerk_name" :key="index" v-for="(item,index) in nurses" :value="item.clerk_id"></el-option>
+                <el-select v-model="formmodel.nurse_id" placeholder="请选择护士" @change="doctorChange(2)">
+                  <el-option v-for="(item,index) in nurses" :key="index" :label="item.clerk_name" :value="item.clerk_id" />
                 </el-select>
               </el-form-item>
             </el-col>
             <el-col :span="8">
               <el-form-item label="责任护工">
-                <el-select placeholder="请选择护工" v-model="formmodel.worker_id" @change="doctorChange(3)">
-                  <el-option :label="item.clerk_name" :key="index" v-for="(item,index) in workrs" :value="item.clerk_id"></el-option>
+                <el-select v-model="formmodel.worker_id" placeholder="请选择护工" @change="doctorChange(3)">
+                  <el-option v-for="(item,index) in workrs" :key="index" :label="item.clerk_name" :value="item.clerk_id" />
                 </el-select>
               </el-form-item>
             </el-col>
@@ -109,7 +109,7 @@
           <el-row v-if="nurseData.length > 0">
             <el-col v-for="(item, index) in nurseList" :key="index" :span="24 / nurseList.length">
               <el-form-item :label="item[0]">
-                <el-select :placeholder="'请选择'+item[0]" v-model="nurseData[index].nurse_level" @change="changeNurseData(index)">
+                <el-select v-model="nurseData[index].nurse_level" :placeholder="'请选择'+item[0]" @change="changeNurseData(index)">
                   <el-option v-for="(t,i) in item[1]" :key="i" :label="t.option_name" :value="t.id">
                     <span style="float: left">{{ t.option_name }}</span>
                     <span :style="'float: right; background-color: #'+t.color_rgb+';color: #'+t.color_rgb">颜色</span>
@@ -123,88 +123,89 @@
             <el-col :span="16">
               <el-form-item label="病况描述">
                 <el-input
-                        type="textarea"
-                        :autosize="{ minRows: 2, maxRows: 4}"
-                        :minlength="2"
-                        :maxlength="50"
-                        :placeholder="'请输入文本内容,长度2~50'"
-                        v-model="formmodel.illness_desc">
-                </el-input>
+                  v-model="formmodel.illness_desc"
+                  type="textarea"
+                  :autosize="{ minRows: 2, maxRows: 4}"
+                  :minlength="2"
+                  :maxlength="50"
+                  :placeholder="'请输入文本内容,长度2~50'"
+                />
               </el-form-item>
             </el-col>
           </el-row>
 
           <el-form-item style="margin-top:15px;">
-            <el-button type="primary" @click="handlerSubmit('editForm')" :disabled="isDisabled" class="save">保存修改</el-button>
+            <el-button type="primary" :disabled="isDisabled" class="save" @click="handlerSubmit('editForm')">保存修改</el-button>
           </el-form-item>
         </el-form>
 
         <el-card v-if="this.customerId != 0" style="maring:15px">
           <div>
-            <div style="float: left"><h4 >用户备注</h4></div>
+            <div style="float: left"><h4>用户备注</h4></div>
             <div style="float: right">
               <el-button type="success" @click="dialogAddVisible = true">添加备注</el-button>
             </div>
           </div>
           <div style="clear:both">
-            <div >
+            <div>
               <el-card v-for="(item, index) in tableData" :key="index">
                 <div>
-                  <span style="margin-left: 20px;font-weight:bold">备注内容:</span><span style="line-height:1.5">{{item.content}}</span>
+                  <span style="margin-left: 20px;font-weight:bold">备注内容:</span><span style="line-height:1.5">{{ item.content }}</span>
                 </div>
                 <div style="margin: 10px">
                   <div style="float: left">
-                <span v-if="item.file_name">
-                  <el-link :href="item.file_path" icon="el-icon-folder" type="success" target="_blank" :download="item.file_name">{{item.file_name}}</el-link>
-                </span>
+                    <span v-if="item.file_name">
+                      <el-link :href="item.file_path" icon="el-icon-folder" type="success" target="_blank" :download="item.file_name">{{ item.file_name }}</el-link>
+                    </span>
                   </div>
                   <div style="float: right">
                     <p>
-                      <span style="font-weight:bold">创建时间:</span>{{forDate(item.create_time)}}
-                      <span style="font-weight:bold;margin-left: 10px;">创建人:</span>{{item.create_name}}
+                      <span style="font-weight:bold">创建时间:</span>{{ forDate(item.create_time) }}
+                      <span style="font-weight:bold;margin-left: 10px;">创建人:</span>{{ item.create_name }}
                     </p>
                   </div>
                 </div>
               </el-card>
               <!--翻页-->
               <el-pagination
-                      slot="pagination"
-                      v-if="pageData"
-                      :current-page="pageData.page_no"
-                      :page-sizes="[10, 30, 50, 100]"
-                      :page-size="pageData.page_size"
-                      @size-change="handlePageSizeChange"
-                      @current-change="handlePageCurrentChange"
-                      layout="total, sizes, prev, pager, next, jumper"
-                      :total="pageData.data_total">
-              </el-pagination>
+                v-if="pageData"
+                slot="pagination"
+                :current-page="pageData.page_no"
+                :page-sizes="[10, 30, 50, 100]"
+                :page-size="pageData.page_size"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="pageData.data_total"
+                @size-change="handlePageSizeChange"
+                @current-change="handlePageCurrentChange"
+              />
             </div>
           </div>
         </el-card>
         <el-dialog title="添加用户备注" :visible.sync="dialogAddVisible" :append-to-body="true" width="80%">
-          <el-form :model="formmodel" :rules="rules" ref="editForm" label-width="140px">
+          <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="140px">
             <el-form-item label="内容" prop="content">
               <el-input
-                      type="textarea"
-                      :autosize="{ minRows: 2, maxRows: 6}"
-                      :minlength="2"
-                      :maxlength="300"
-                      show-word-limit
-                      :placeholder="'请输入文本内容,长度300'"
-                      v-model="content">
-              </el-input>
+                v-model="content"
+                type="textarea"
+                :autosize="{ minRows: 2, maxRows: 6}"
+                :minlength="2"
+                :maxlength="300"
+                show-word-limit
+                :placeholder="'请输入文本内容,长度300'"
+              />
             </el-form-item>
             <el-form-item label="附件">
-              <el-upload v-if="!filePath"
-                         class="avatar-uploader"
-                         :action="`${uploadServer}?scene=avatar`"
-                         :show-file-list="false"
-                         :on-success="uploaded"
-                         :before-upload="handleShopLogoBefore"
+              <el-upload
+                v-if="!filePath"
+                class="avatar-uploader"
+                :action="`${uploadServer}?scene=avatar`"
+                :show-file-list="false"
+                :on-success="uploaded"
+                :before-upload="handleShopLogoBefore"
               >
                 <i class="el-icon-plus avatar-uploader-icon" />
               </el-upload>
-              <span v-if="filePath">{{fileName}}</span>
+              <span v-if="filePath">{{ fileName }}</span>
             </el-form-item>
             <el-form-item>
               <el-button type="primary" @click="addRemark">立即添加</el-button>
@@ -214,7 +215,7 @@
         </el-dialog>
       </el-tab-pane>
       <el-tab-pane v-if="customerId != 0" label="用户亲属" name="customer-relative">
-        <customer-relative :member-id="memberId"></customer-relative>
+        <customer-relative :member-id="memberId" />
       </el-tab-pane>
     </el-tabs>
 
@@ -223,349 +224,346 @@
 </template>
 
 <script>
-  import * as customer_API from '@/api/ncs_customer'
-  import * as clerk_API from '@/api/ncs_clerk'
-  import * as NurseConfig_API from '@/api/ncs_nurse_config'
-  import * as remark_API from '@/api/ncs_remark'
-  import * as RegExp from '@/utils/RegExp'
-  import { unixToDate } from '@/utils/Foundation'
-  import { serverUrl } from '@/utils/domain'
-  import customerRelative from '@/views/customer/customer_relative'
+import * as customer_API from '@/api/ncs_customer'
+import * as clerk_API from '@/api/ncs_clerk'
+import * as NurseConfig_API from '@/api/ncs_nurse_config'
+import * as remark_API from '@/api/ncs_remark'
+import * as RegExp from '@/utils/RegExp'
+import { unixToDate } from '@/utils/Foundation'
+import { serverUrl } from '@/utils/domain'
+import customerRelative from '@/views/customer/customer_relative'
 
-  export default {
-    components: { customerRelative },
-    name: 'patientInfoEdit',
-    props: {
-      customerId: {
-        type: Number,
-        default: 0
-      },
-      frameId: {
-        type: Number,
-        default: 0
-      }
+export default {
+  name: 'PatientInfoEdit',
+  components: { customerRelative },
+  props: {
+    customerId: {
+      type: Number,
+      default: 0
     },
-    data: function() {
-      return {
-        formmodel: {
-          sex: 1,
-          status: 0,
-          age_unit: '岁',
-          id_type: '身份证',
-          part_id: this.$store.getters.partId
-        },
-        nurseList: [],
-        nurseData: [],
-        nurseConfigDtos: [],
-        rules: {
-          named: [
-            this.MixinRequired('请输入真实姓名!'),
-            { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
-            {
-              validator: (rule, value, callback) => {
-                if (!RegExp.userName.test(value)) {
-                  callback(new Error('只支持汉字、字母、数字、“-”、“_”的组合!'))
-                } else {
-                  callback()
-                }
+    frameId: {
+      type: Number,
+      default: 0
+    }
+  },
+  data: function() {
+    return {
+      formmodel: {
+        sex: 1,
+        status: 0,
+        age_unit: '岁',
+        id_type: '身份证',
+        part_id: this.$store.getters.partId
+      },
+      nurseList: [],
+      nurseData: [],
+      nurseConfigDtos: [],
+      rules: {
+        named: [
+          this.MixinRequired('请输入真实姓名!'),
+          { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
+          {
+            validator: (rule, value, callback) => {
+              if (!RegExp.userName.test(value)) {
+                callback(new Error('只支持汉字、字母、数字、“-”、“_”的组合!'))
+              } else {
+                callback()
               }
             }
-          ],
-          age: [{required: true, message: '请输入年龄', trigger: 'blur'}],
-          content: [{required: true, message: '请输入备注内容', trigger: 'blur'}],
-          in_date: [{required: true, message: '请选择入院日期', trigger: 'blur'}],
-        },
-        isDisabled: false,
-        doctors: [],
-        nurses: [],
-        workrs: [],
-        doctor_mapping_id: false,
-        nurse_Mapping_id: false,
-        worker_mapping_id: false,
-        params: {
-          page_size: 10,
-          page_no: 1,
-          sort: 'create_time',
-          dir: 'desc'
-        },
-        tableData: [],
-        pageData: [],
-        dialogAddVisible: false,
-        fileName: null,
-        filePath: null,
-        uploadServer: serverUrl + '/ncs/upload/uploadFile',
-        userInfo: this.$store.getters.userInfo,
-        content: null,
-        activeName: 'customerEdit',
-        memberId: null
-      }
-    },
-    mounted() {
-      this.getEmployees()
-      if (this.nurseList.length === 0) {
-        this.getNurseConfigs()
-        this.hasCustomerId()
-      }
-    },
-    watch: {
-      frameId: function(newval) {
-        this.getNurseConfigs()
-        this.hasCustomerId()
-      }
-    },
-
-    methods: {
-      getEmployees() {
-        let _this = this
-        clerk_API.listByPartRoleId({partId: this.$store.getters.partId}).then(res => {
-          const groupBy = (arr, func) =>
-                  arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
-                    acc[val] = (acc[val] || []).concat(arr[i]);
-                    return acc;
-                  }, {});
-          let groupData = groupBy(res, item => item.role_name)
-          if (Object.entries(groupData).length > 0) {
-            Object.entries(groupData).forEach(item=> {
-              if (item[0] === '医生') {
-                _this.doctors = item[1]
-              } else if (item[0] === '护士') {
-                _this.nurses = item[1]
-              } else if (item[0] === '护工'){
-                _this.workrs = item[1]
-              }
-            })
           }
-        })
+        ],
+        age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],
+        content: [{ required: true, message: '请输入备注内容', trigger: 'blur' }],
+        in_date: [{ required: true, message: '请选择入院日期', trigger: 'blur' }]
       },
-      getNurseConfigs() {
-        this.nurseData = []
-        let _this = this
-        NurseConfig_API.listByPartId({partId: this.$store.getters.partId}).then(res => {
-          const groupBy = (arr, func) =>
-                  arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
-                    acc[val] = (acc[val] || []).concat(arr[i]);
-                    return acc;
-                  }, {});
-          // 以参数名称来分组
-          let groupData = groupBy(res, item => item.config_name)
-          _this.nurseList = Object.entries(groupData)
-          if (_this.nurseList.length > 0) {
-            _this.nurseList.forEach((item, index)=> {
-              _this.nurseData.push({nurse_level: null, id: null, nurse_config: item[1][0].ncfg_id})
-            })
-          }
-
-        })
+      isDisabled: false,
+      doctors: [],
+      nurses: [],
+      workrs: [],
+      doctor_mapping_id: false,
+      nurse_Mapping_id: false,
+      worker_mapping_id: false,
+      params: {
+        page_size: 10,
+        page_no: 1,
+        sort: 'create_time',
+        dir: 'desc'
       },
-      hasCustomerId() {
-        this.clearForm()
-        if (this.customerId !== 0) {
-          let _this = this
-          customer_API.getCustomerInfo(this.customerId).then(res => {
-            _this.formmodel = res
-            _this.doctor_mapping_id = res.doctor_mapping_id
-            _this.nurse_Mapping_id = res.nurse_Mapping_id
-            _this.worker_mapping_id = res.worker_mapping_id
-            _this.formmodel.doctor_mapping_id = null
-            _this.formmodel.nurse_Mapping_id = null
-            _this.formmodel.worker_mapping_id = null
-            if (_this.formmodel.in_date) {
-              _this.formmodel.in_date = _this.formmodel.in_date * 1000
-            }
-            if (_this.formmodel.out_date) {
-              _this.formmodel.out_date = _this.formmodel.out_date * 1000
-            }
-            console.log(_this.formmodel.in_date, _this.formmodel.out_date)
-            _this.getRemarks()
-            if (res.list !== null) {
-              _this.nurseData.forEach((item, index)=> {
-                res.list.forEach((t, i)=> { // 为护理项赋值
-                  if (item.nurse_config === t.nurse_config) {
-                    item.nurse_level = t.nurse_level
-                    item.id = t.id
-                  }
-                })
-              })
-            }
+      tableData: [],
+      pageData: [],
+      dialogAddVisible: false,
+      fileName: null,
+      filePath: null,
+      uploadServer: serverUrl + '/ncs/upload/uploadFile',
+      userInfo: this.$store.getters.userInfo,
+      content: null,
+      activeName: 'customerEdit',
+      memberId: null
+    }
+  },
+  watch: {
+    frameId: function(newval) {
+      this.getNurseConfigs()
+      this.hasCustomerId()
+    }
+  },
+  mounted() {
+    this.getEmployees()
+    if (this.nurseList.length === 0) {
+      this.getNurseConfigs()
+      this.hasCustomerId()
+    }
+  },
 
+  methods: {
+    getEmployees() {
+      const _this = this
+      clerk_API.listByPartRoleId({ partId: this.$store.getters.partId }).then(res => {
+        const groupBy = (arr, func) =>
+          arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
+            acc[val] = (acc[val] || []).concat(arr[i])
+            return acc
+          }, {})
+        const groupData = groupBy(res, item => item.role_name)
+        if (Object.entries(groupData).length > 0) {
+          Object.entries(groupData).forEach(item => {
+            if (item[0] === '医生') {
+              _this.doctors = item[1]
+            } else if (item[0] === '护士') {
+              _this.nurses = item[1]
+            } else if (item[0] === '护工') {
+              _this.workrs = item[1]
+            }
           })
         }
-
-      },
-      doctorChange(type) {
-        if (this.customerId !== 0) {
-          if (type === 1) {
-            if (this.doctor_mapping_id === null) {
-              this.formmodel.doctor_mapping_id = 0 // 为0则新增,// 其他值为修改
-            } else {
-              this.formmodel.doctor_mapping_id = this.doctor_mapping_id
-            }
-          } else if (type === 2) {
-            if (this.nurse_Mapping_id === null) {
-              this.formmodel.nurse_Mapping_id = 0 // 为0则新增,// 其他值为修改
-            } else {
-              this.formmodel.nurse_Mapping_id = this.nurse_Mapping_id
-            }
-          } else {
-            if (this.worker_mapping_id === null) {
-              this.formmodel.worker_mapping_id = 0 // 为0则新增,// 其他值为修改
-            } else {
-              this.formmodel.worker_mapping_id = this.worker_mapping_id
-            }
-          }
+      })
+    },
+    getNurseConfigs() {
+      this.nurseData = []
+      const _this = this
+      NurseConfig_API.listByPartId({ partId: this.$store.getters.partId }).then(res => {
+        const groupBy = (arr, func) =>
+          arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
+            acc[val] = (acc[val] || []).concat(arr[i])
+            return acc
+          }, {})
+          // 以参数名称来分组
+        const groupData = groupBy(res, item => item.config_name)
+        _this.nurseList = Object.entries(groupData)
+        if (_this.nurseList.length > 0) {
+          _this.nurseList.forEach((item, index) => {
+            _this.nurseData.push({ nurse_level: null, id: null, nurse_config: item[1][0].ncfg_id })
+          })
         }
-      },
-      /** 保存按钮处理事件 */
-      handlerSubmit(formName) {
-        this.$refs[formName].validate(valid => {
-          if (valid) {
-            this.isDisabled = true
-            if (this.formmodel.in_date) {
-              this.formmodel.in_date = this.formmodel.in_date / 1000
-            }
-            if (this.formmodel.out_date) {
-              this.formmodel.out_date = this.formmodel.out_date / 1000
-            }
-            if (this.customerId === 0) {
-              this.formmodel.frame_id = this.frameId
-              this.formmodel.list = this.nurseConfigDtos
-              customer_API.addAll(this.formmodel).then(res => {
-                this.$message.success('添加成功!')
-                this.clearForm()
-                this.$emit('saved')
-              }).catch( e =>{
-                this.isDisabled = false
-              })
-            } else {
-              this.formmodel.list = this.nurseConfigDtos
-              customer_API.updateAll(this.formmodel).then(res => {
-                this.$message.success('修改成功!')
-                this.isDisabled = false
-                this.$emit('saved')
+      })
+    },
+    hasCustomerId() {
+      this.clearForm()
+      if (this.customerId !== 0) {
+        const _this = this
+        customer_API.getCustomerInfo(this.customerId).then(res => {
+          _this.formmodel = res
+          _this.doctor_mapping_id = res.doctor_mapping_id
+          _this.nurse_Mapping_id = res.nurse_Mapping_id
+          _this.worker_mapping_id = res.worker_mapping_id
+          _this.formmodel.doctor_mapping_id = null
+          _this.formmodel.nurse_Mapping_id = null
+          _this.formmodel.worker_mapping_id = null
+          if (_this.formmodel.in_date) {
+            _this.formmodel.in_date = _this.formmodel.in_date * 1000
+          }
+          if (_this.formmodel.out_date) {
+            _this.formmodel.out_date = _this.formmodel.out_date * 1000
+          }
+          console.log(_this.formmodel.in_date, _this.formmodel.out_date)
+          _this.getRemarks()
+          if (res.list !== null) {
+            _this.nurseData.forEach((item, index) => {
+              res.list.forEach((t, i) => { // 为护理项赋值
+                if (item.nurse_config === t.nurse_config) {
+                  item.nurse_level = t.nurse_level
+                  item.id = t.id
+                }
               })
-            }
-          } else {
-            this.$message.error('表单填写有误,请检查!')
-            return false
+            })
           }
         })
-      },
-      clearForm() {
-        this.activeName = 'customerEdit'
-        this.formmodel = {
-          sex: 1,
-          status: 0,
-          age_unit: '岁',
-          id_type: '身份证',
-          part_id: this.$store.getters.partId,
-          named: null,
-          card_no: null,
-          id_no: null,
-          in_date: new Date(new Date().toLocaleDateString()).getTime(),
-          out_date: null,
-          doctor_id: null,
-          nurse_id: null,
-          worker_id: null,
-          illness_desc: null
-        }
-        this.isDisabled = false
-        this.nurseConfigDtos = []
-      },
-      // 选择了护理项
-      changeNurseData(index) {
-        let i = this.nurseConfigDtos.findIndex(item => {
-          return item.nurse_level === this.nurseData[index].nurse_level;
-        })
-        if (i !== -1) {
-          this.nurseConfigDtos.splice(i,1)
+      }
+    },
+    doctorChange(type) {
+      if (this.customerId !== 0) {
+        if (type === 1) {
+          if (this.doctor_mapping_id === null) {
+            this.formmodel.doctor_mapping_id = 0 // 为0则新增,// 其他值为修改
+          } else {
+            this.formmodel.doctor_mapping_id = this.doctor_mapping_id
+          }
+        } else if (type === 2) {
+          if (this.nurse_Mapping_id === null) {
+            this.formmodel.nurse_Mapping_id = 0 // 为0则新增,// 其他值为修改
+          } else {
+            this.formmodel.nurse_Mapping_id = this.nurse_Mapping_id
+          }
+        } else {
+          if (this.worker_mapping_id === null) {
+            this.formmodel.worker_mapping_id = 0 // 为0则新增,// 其他值为修改
+          } else {
+            this.formmodel.worker_mapping_id = this.worker_mapping_id
+          }
         }
-        this.nurseConfigDtos.push(this.nurseData[index])
-      },
-      getRemarks() {
-        let _this = this
-        this.params.fixedCondition = ' part_id=' + this.$store.getters.partId + ' and type=1 and member_id = '+ this.formmodel.member_id
-        remark_API.getRemarks(this.params).then(res=> {
-          _this.tableData = res.data
-          _this.pageData = {
-            page_no: res.page_no,
-            page_size: res.page_size,
-            data_total: res.data_total
+      }
+    },
+    /** 保存按钮处理事件 */
+    handlerSubmit(formName) {
+      this.$refs[formName].validate(valid => {
+        if (valid) {
+          this.isDisabled = true
+          if (this.formmodel.in_date) {
+            this.formmodel.in_date = this.formmodel.in_date / 1000
           }
-        })
-      },
-      /** 分页大小发生改变 */
-      handlePageSizeChange(size) {
-        this.params.page_size = size
-        this.getRemarks()
-      },
-      /** 分页页数发生改变 */
-      handlePageCurrentChange(page) {
-        this.params.page_no = page
-        this.getRemarks()
-      },
-      forDate(date) {
-        return unixToDate(date)
-      },
-      /** 上传成功后的钩子 更换图片 置空存储数组*/
-      uploaded(res) {
-        this.filePath = serverUrl + '/' + res
-      },
-      /** 图片上传之前的校验 */
-      handleShopLogoBefore(file) {
-        let _this = this
-        return new Promise((resolve, reject) => {
-          let hz = file.name
-          _this.fileName = hz
-          let index = hz .lastIndexOf(".");
-          hz  = hz .substring(index + 1, hz .length);
-          const isImg = hz === 'jpeg' || hz === 'png' || hz === 'jpg' || hz === 'txt'  || hz === 'doc' || hz === 'docx' || hz === 'xls' || hz === 'xlsx'
-          const isLt5M = file.size / 1024 / 1024 < 5
-          if (!isImg) {
-            _this.$message.error('上传附件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!')
-            reject()
+          if (this.formmodel.out_date) {
+            this.formmodel.out_date = this.formmodel.out_date / 1000
           }
-          if (!isLt5M) {
-            _this.$message.error('上传附件大小不能超过 5MB!')
-            reject()
+          if (this.customerId === 0) {
+            this.formmodel.frame_id = this.frameId
+            this.formmodel.list = this.nurseConfigDtos
+            customer_API.addAll(this.formmodel).then(res => {
+              this.$message.success('添加成功!')
+              this.clearForm()
+              this.$emit('saved')
+            }).catch(e => {
+              this.isDisabled = false
+            })
+          } else {
+            this.formmodel.list = this.nurseConfigDtos
+            customer_API.updateAll(this.formmodel).then(res => {
+              this.$message.success('修改成功!')
+              this.isDisabled = false
+              this.$emit('saved')
+            })
           }
-          resolve()
-        })
-      },
-      addRemark() {
-        if (!this.content) {
-          this.$message.info('请输入内容!')
-          return
+        } else {
+          this.$message.error('表单填写有误,请检查!')
+          return false
+        }
+      })
+    },
+    clearForm() {
+      this.activeName = 'customerEdit'
+      this.formmodel = {
+        sex: 1,
+        status: 0,
+        age_unit: '岁',
+        id_type: '身份证',
+        part_id: this.$store.getters.partId,
+        named: null,
+        card_no: null,
+        id_no: null,
+        in_date: new Date(new Date().toLocaleDateString()).getTime(),
+        out_date: null,
+        doctor_id: null,
+        nurse_id: null,
+        worker_id: null,
+        illness_desc: null
+      }
+      this.isDisabled = false
+      this.nurseConfigDtos = []
+    },
+    // 选择了护理项
+    changeNurseData(index) {
+      const i = this.nurseConfigDtos.findIndex(item => {
+        return item.nurse_level === this.nurseData[index].nurse_level
+      })
+      if (i !== -1) {
+        this.nurseConfigDtos.splice(i, 1)
+      }
+      this.nurseConfigDtos.push(this.nurseData[index])
+    },
+    getRemarks() {
+      const _this = this
+      this.params.fixedCondition = ' part_id=' + this.$store.getters.partId + ' and type=1 and member_id = ' + this.formmodel.member_id
+      remark_API.getRemarks(this.params).then(res => {
+        _this.tableData = res.data
+        _this.pageData = {
+          page_no: res.page_no,
+          page_size: res.page_size,
+          data_total: res.data_total
         }
-        if (!this.filePath) {
-          this.fileName = null
+      })
+    },
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.getRemarks()
+    },
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.getRemarks()
+    },
+    forDate(date) {
+      return unixToDate(date)
+    },
+    /** 上传成功后的钩子 更换图片 置空存储数组*/
+    uploaded(res) {
+      this.filePath = serverUrl + '/' + res
+    },
+    /** 图片上传之前的校验 */
+    handleShopLogoBefore(file) {
+      const _this = this
+      return new Promise((resolve, reject) => {
+        let hz = file.name
+        _this.fileName = hz
+        const index = hz.lastIndexOf('.')
+        hz = hz.substring(index + 1, hz.length)
+        const isImg = hz === 'jpeg' || hz === 'png' || hz === 'jpg' || hz === 'txt' || hz === 'doc' || hz === 'docx' || hz === 'xls' || hz === 'xlsx'
+        const isLt5M = file.size / 1024 / 1024 < 5
+        if (!isImg) {
+          _this.$message.error('上传附件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!')
+          reject()
         }
-        const data = {
-          partId: this.$store.getters.partId,
-          type: 1,
-          memberId: this.formmodel.member_id,
-          createName: this.userInfo.username,
-          content: this.content,
-          filePath: this.filePath,
-          fileName: this.fileName
+        if (!isLt5M) {
+          _this.$message.error('上传附件大小不能超过 5MB!')
+          reject()
         }
-        let _this = this
-        remark_API.save(data).then(res=> {
-          _this.$message.success('添加成功!')
-          _this.getRemarks()
-          _this.quxiao()
-        })
-      },
-      quxiao(){
-        this.dialogAddVisible = false
-        this.content = null
+        resolve()
+      })
+    },
+    addRemark() {
+      if (!this.content) {
+        this.$message.info('请输入内容!')
+        return
+      }
+      if (!this.filePath) {
         this.fileName = null
-        this.filePath = null
-      },
-      handleClick(tab) {
-        this.memberId = this.formmodel.member_id
       }
+      const data = {
+        partId: this.$store.getters.partId,
+        type: 1,
+        memberId: this.formmodel.member_id,
+        createName: this.userInfo.username,
+        content: this.content,
+        filePath: this.filePath,
+        fileName: this.fileName
+      }
+      const _this = this
+      remark_API.save(data).then(res => {
+        _this.$message.success('添加成功!')
+        _this.getRemarks()
+        _this.quxiao()
+      })
+    },
+    quxiao() {
+      this.dialogAddVisible = false
+      this.content = null
+      this.fileName = null
+      this.filePath = null
+    },
+    handleClick(tab) {
+      this.memberId = this.formmodel.member_id
     }
   }
+}
 </script>
 
 <style type="text/scss" scoped>

+ 5 - 4
src/views/hospital/ncs_customer/customerManager.vue

@@ -23,7 +23,7 @@
         </div>
         <div class="toolbar-btns">
           <el-button type="primary" size="mini" :disabled="!isEmptyFrame" @click="handleAdd">入住登记</el-button>
-          <el-button v-if="part_view" type="danger" size="mini" @click="batchDelete">批量删除</el-button>
+          <el-button type="danger" size="mini" @click="batchDelete">批量删除</el-button>
         </div>
       </div>
       <el-pagination
@@ -43,7 +43,7 @@
     <el-dialog :visible.sync="customerFormVisible" title="用户信息" class="customer-dialog">
       <el-tabs v-model="activeName" type="border-card" tab-position="bottom" width="50%" @tab-click="handleClick">
         <el-tab-pane label="基本信息" name="customerBaseInfo">
-          <div style="height: 450px">
+          <div style="height: 490px">
             <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="12">
@@ -63,7 +63,7 @@
                   <el-form-item label="性别" class="form-item-sex">
                     <el-radio v-model="formmodel.sex" :label="0">女</el-radio>
                     <el-radio v-model="formmodel.sex" :label="1">男</el-radio>
-                    <el-radio v-model="formmodel.sex" :label="2">未知</el-radio>
+<!--                    <el-radio v-model="formmodel.sex" :label="2">未知</el-radio>-->
                   </el-form-item>
                 </el-col>
 
@@ -336,7 +336,7 @@
                   <el-form-item label="性别" class="form-item-sex">
                     <el-radio v-model="relativeFormModel.sex" :label="0">女</el-radio>
                     <el-radio v-model="relativeFormModel.sex" :label="1">男</el-radio>
-                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>
+<!--                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>-->
                   </el-form-item>
                 </el-col>
                 <el-col :span="12">
@@ -1025,6 +1025,7 @@ export default {
               this.$message.success('修改成功!')
               this.customerFormVisible = false
               this.isDisabled = false
+              this.getList()
               this.$emit('saved')
             })
           }

+ 15 - 4
src/views/hospital/ncs_device/deviceManager.vue

@@ -127,8 +127,8 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="后备设备ID">
-              <el-input v-model="deviceModel.backup_id" clearable placeholder="" />
+            <el-form-item label="设备电话号码">
+              <el-input v-model="deviceModel.phone_number" clearable placeholder="请输入设备电话号码" />
             </el-form-item>
           </el-col>
         </el-row>
@@ -140,6 +140,11 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
+            <el-form-item label="后备设备ID">
+              <el-input v-model="deviceModel.backup_id" clearable placeholder="" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
             <el-form-item label="是否启用">
               <el-checkbox v-model="deviceModel.status" :true-label="1" :false-label="0">启用设备</el-checkbox>
               <!--              <el-radio v-model="formmodel.status" :label="1">启用</el-radio>-->
@@ -258,6 +263,9 @@ export default {
         frame_id: [
           { required: Object.keys(this.frame).length === 0, message: '请选安装位置!', trigger: 'blur' } // 没有传入frame 属性,必须选择安装位置
         ],
+        phone_number: [
+          { required: true, message: '请输入设备电话号码', trigger: 'blur' }
+        ],
         role_id: [
           { required: true, message: '请选择适用人', trigger: 'blur' }
         ],
@@ -360,6 +368,7 @@ export default {
       },
 
       { headerName: '部署位置', field: 'full_name', sortable: true, filter: 'agTextColumnFilter', valueFormatter: this.fullNameFormatter },
+      { headerName: '设备号码', field: 'phone_number', sortable: true, filter: 'agTextColumnFilter' },
       { headerName: '以太网MAC地址', field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter' },
       { headerName: '以太网IP地址', field: 'eth_ip', sortable: true, filter: 'agTextColumnFilter' },
       { headerName: '通讯端口', field: 'eth_ip_port', sortable: true, filter: 'agNumberColumnFilter' },
@@ -567,7 +576,8 @@ export default {
     /** 设备类型选中变化  **/
     deviceTypeChange(val) {
       this.deviceTypeChangeToFrameTypeChange(val)
-      if (val === DEVICE_TYPE.SIMULATE_BED_DEVICE || DEVICE_TYPE.RS485_DOOR ||
+      if (val === DEVICE_TYPE.SIMULATE_BED_DEVICE || // 只能直接在后面加设备,会判断错误,必须重新用val = 设备
+          val === DEVICE_TYPE.RS485_DOOR ||
           val === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON ||
           val === DEVICE_TYPE.SIMULATE_DOOR_LIGHT ||
           val === DEVICE_TYPE.EMERGENCY_BUTTON) { // 模拟设备不需要mac地址
@@ -603,7 +613,8 @@ export default {
           val === DEVICE_TYPE.RS485_TRANSFER) {
         this.getFramesByType(FRAME_TYPE.PART)
       } else if (val === DEVICE_TYPE.DOOR_DEVICE ||
-          val === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON || DEVICE_TYPE.RS485_DOOR ||
+          val === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON ||
+          val === DEVICE_TYPE.RS485_DOOR ||
           val === DEVICE_TYPE.SIMULATE_DOOR_LIGHT ||
           val === DEVICE_TYPE.BEACON) {
         this.getFramesByType(FRAME_TYPE.ROOM)

+ 554 - 0
src/views/ncs-chars/index.vue

@@ -0,0 +1,554 @@
+<template>
+  <div class="container">
+    <div style="margin: 10px">
+      <el-select v-model="sssparams.fromToType" filterable @change="handleClick">
+        <el-option label="全部" :value="0" />
+        <el-option label="客户与员工" :value="1" />
+        <el-option label="同事与同事" :value="2" />
+      </el-select>
+      <span>
+        <span>查询周期:</span>
+        <en-year-month-picker :bool-day="true" @changed="handleYearMonthChanged" />
+      </span>
+    </div>
+    <el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
+      <el-tab-pane name="ALL">
+        <span slot="label"><i class="el-icon-menu" /> 全部</span>
+        <div>
+          <div style="margin: 10px">
+            <el-row :gutter="30">
+              <el-col :span="8">
+                <div class="card-panel">
+                  <div class="card-panel-icon-wrapper icon-message">
+                    <!--            el-icon-s-shop-->
+                    <el-icon class="el-icon-receiving card-panel-icon" />
+                  </div>
+                  <div class="card-panel-description">
+                    <div class="card-panel-text">
+                      交互类型
+                    </div>
+                    <count-to :start-val="0" :end-val="partTotal.lx" :duration="4600" class="card-panel-num" />
+                  </div>
+                </div>
+              </el-col>
+              <el-col :span="8">
+                <div class="card-panel">
+                  <div class="card-panel-icon-wrapper icon-people">
+                    <el-icon class="el-icon-magic-stick card-panel-icon" />
+                  </div>
+                  <div class="card-panel-description">
+                    <div class="card-panel-text">
+                      交互次数
+                    </div>
+                    <count-to :start-val="0" :end-val="partTotal.count" :duration="8600" class="card-panel-num" />
+                  </div>
+                </div>
+              </el-col>
+              <el-col :span="8">
+                <div class="card-panel">
+                  <div class="card-panel-icon-wrapper icon-money">
+                    <el-icon class="el-icon-loading card-panel-icon" />
+                  </div>
+                  <div class="card-panel-description">
+                    <div class="card-panel-text">
+                      未完成次数
+                    </div>
+                    <!--            <span>高温</span>-->
+                    <count-to :start-val="0" :end-val="partTotal.noCount" :duration="3200" class="card-panel-num" />
+                    <!--            <span>低温</span>-->
+                    <!--            <count-to :start-val="0" :end-val="partTotal.loginNum" :duration="3200" class="card-panel-num" />-->
+                  </div>
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+          <div class="table-wrapper">
+            <el-table :data="tableData" stripe border style="width: 100%">
+              <el-table-column type="index" width="100" label="序号" align="center" />
+              <el-table-column prop="name" label="类型" min-width="130" align="center" />
+              <el-table-column prop="count" label="交互次数" min-width="130" align="center" />
+              <el-table-column prop="noCount" label="未完成次数" min-width="130" align="center" />
+            </el-table>
+          </div>
+          <el-card shadow="always" style="margin-top: 15px;">
+            <div id="btChart" style="height: 300px" />
+          </el-card>
+          <el-card shadow="always" style="margin-top: 15px;">
+            <div id="chart" style="height: 400px" />
+          </el-card>
+          <el-card shadow="always" style="margin-top: 15px;">
+            <div id="noChart" style="height: 400px" />
+          </el-card>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane name="VOICE">
+        <span slot="label"><i class="el-icon-phone-outline" /> 语音</span>
+      </el-tab-pane>
+      <el-tab-pane name="VIDEO">
+        <span slot="label"><i class="el-icon-video-camera" /> 视频</span>
+      </el-tab-pane>
+      <el-tab-pane name="IM">
+        <span slot="label"><i class="el-icon-microphone" /> 留言</span>
+      </el-tab-pane>
+      <el-tab-pane name="EVENT">
+        <span slot="label"><i class="el-icon-thumb" /> 事件</span>
+      </el-tab-pane>
+      <el-tab-pane name="ENTRACEGUARD">
+        <span slot="label"><i class="el-icon-wallet" /> 门禁</span>
+      </el-tab-pane>
+      <el-tab-pane name="SOS">
+        <span slot="label"><i class="el-icon-sunrise-1" /> 紧急按钮</span>
+      </el-tab-pane>
+    </el-tabs>
+    <div v-if="sssparams.type">
+      <div style="padding: 10px;margin: 10px;">
+        <el-descriptions class="margin-top" title="交互详情" :column="4" border>
+          <el-descriptions-item v-for="(item, index) in userActionList" :key="index">
+            <template slot="label">
+              <i class="el-icon-user" />
+              {{ item.name }}
+            </template>
+            {{ item.value }} 次
+          </el-descriptions-item>
+        </el-descriptions>
+      </div>
+      <el-card shadow="always" style="margin-top: 15px;">
+        <div id="actionChar" style="height: 450px" />
+      </el-card>
+      <el-card shadow="always" style="margin-top: 15px;">
+        <div id="zztChar" style="height: 450px" />
+      </el-card>
+    </div>
+
+  </div>
+</template>
+
+<script>
+import echarts from 'echarts'
+import CountTo from 'vue-count-to'
+import * as API_interaction from '@/api/ncs_interaction'
+import Storage from '@/utils/storage'
+export default {
+  name: 'Index',
+  components: { CountTo },
+  data() {
+    return {
+      sssparams: {
+        year: '',
+        month: '',
+        cycle_type: 'MONTH',
+        day: '',
+        seller_id: null,
+        fromToType: 0
+      },
+      chart: null,
+      chartData: {},
+      shopId: -1,
+      shopInfo: {},
+      partTotal: {
+        lx: 6,
+        count: 0,
+        noCount: 0
+      },
+      tableData: [],
+      dataList: ['语音', '视频', '留言', '事件', '门禁', '紧急按钮'],
+      activeName: 'ALL',
+      userActionList: []
+    }
+  },
+  mounted() {
+    this.shopInfo = JSON.parse(Storage.getItem('calling_shop'))
+    if (this.shopInfo.shop_type !== '5') {
+      // this.getPartList()
+      this.shopId = -1
+    } else {
+      this.shopId = this.shopInfo.shop_id
+      // this.getMemberList()
+    }
+    this.sssparams.seller_id = this.shopId
+    // this.getLogCharsJS()
+  },
+  methods: {
+    getLogCharsJS() {
+      const _this = this
+      API_interaction.getLogChars(this.sssparams).then(res => {
+        if (_this.sssparams.type) {
+          _this.buildZztChart(res)
+        } else {
+          _this.partTotal.count = res.count
+          _this.partTotal.noCount = res.noCount
+          _this.buildTable(res.btList, res.noBtList)
+          _this.buildBtChart(res.btList, res.noBtList) // 饼图
+          _this.buildChart(res.dataList, res.tilStr, res.xAxis, 'chart', '时间段交互统计')
+          _this.buildChart(res.noDataList, res.noTilStr, res.xAxis, 'noChart', '未完成交互统计')
+        }
+      })
+    },
+    buildTable(btList, noBtList) {
+      this.tableData = []
+      this.dataList.forEach(item => {
+        let count = 0
+        let noCount = 0
+        const data = btList.find(p => p.name === item)
+        if (data) {
+          count = data.value
+        }
+        const noData = noBtList.find(p => p.name === item)
+        if (noData) {
+          noCount = noData.value
+        }
+        this.tableData.push({
+          name: item,
+          count: count,
+          noCount: noCount
+        })
+      })
+    },
+    buildChart(dataList, tilStr, xAxis, elementId, title) {
+      this.chart = this.$echarts.init(document.getElementById(elementId), 'vintage')
+      this.chart.clear()
+      const series = []
+      if (dataList.length > 0) {
+        dataList.forEach((item, index) => {
+          const d = {
+            name: tilStr[index],
+            type: 'line',
+            stack: '总量' + index,
+            data: item,
+            smooth: true,
+            emphasis: {
+              focus: 'series',
+              blurScope: 'coordinateSystem'
+            }
+          }
+          series.push(d)
+        })
+      }
+      const options = {
+        title: {
+          text: title
+        },
+        tooltip: {
+          trigger: 'axis'
+        },
+        // legend: {
+        //   data: tilStr,
+        //   left: 'center',
+        //   top: 'bottom'
+        // },
+        legend: {
+          data: tilStr
+        },
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true
+        },
+        toolbox: {
+          feature: {
+            saveAsImage: {}
+          }
+        },
+        xAxis: {
+          type: 'category',
+          boundaryGap: false,
+          data: xAxis
+        },
+        yAxis: {
+          type: 'value',
+          min: 0,
+          axisTick: {
+            show: false
+          }
+        },
+        series: series
+      }
+      this.chart.setOption(options)
+      this.chart.resize()
+    },
+    buildBtChart(btList, noBtList) {
+      this.chart = this.$echarts.init(document.getElementById('btChart'), 'vintage')
+      this.chart.clear()
+      const options = {
+        title: {
+          text: '交互记录统计',
+          subtext: '数量统计',
+          left: 'center'
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: '{a} <br/>{b} : {c} ({d}%)'
+        },
+        legend: {
+          left: 'center',
+          top: 'bottom'
+        },
+        toolbox: {
+          show: true,
+          feature: {
+            mark: { show: true },
+            dataView: { show: true, readOnly: false },
+            restore: { show: true },
+            saveAsImage: { show: true }
+          }
+        },
+        series: [
+          {
+            name: '交互记录',
+            type: 'pie',
+            radius: [20, 140],
+            center: ['25%', '50%'],
+            roseType: 'radius',
+            itemStyle: {
+              borderRadius: 5
+            },
+            emphasis: {
+              label: {
+                show: true
+              }
+            },
+            data: btList
+          },
+          {
+            name: '未完成交互',
+            type: 'pie',
+            radius: [20, 140],
+            center: ['75%', '50%'],
+            roseType: 'area',
+            itemStyle: {
+              borderRadius: 5
+            },
+            data: noBtList
+          }
+        ]
+      }
+      this.chart.setOption(options)
+      this.chart.resize()
+    },
+    buildZztChart(res) {
+      this.chart = this.$echarts.init(document.getElementById('zztChar'), 'vintage')
+      this.chart.clear()
+      const mySeries = [
+        {
+          name: '交互记录',
+          type: 'bar',
+          emphasis: {
+            focus: 'series'
+          },
+          data: res.zztDate
+        },
+        {
+          name: '已响应交互',
+          type: 'bar',
+          stack: 'Ad',
+          barWidth: 5,
+          emphasis: {
+            focus: 'series'
+          },
+          data: res.hasZztDate
+        },
+        {
+          name: '未完成交互',
+          type: 'bar',
+          stack: 'Ad',
+          barWidth: 5,
+          emphasis: {
+            focus: 'series'
+          },
+          data: res.noZztDate
+        }
+      ]
+      if (res.errorDate) {
+        mySeries.push({
+          name: '未正常挂断交互',
+          type: 'bar',
+          stack: 'Ad',
+          barWidth: 5,
+          emphasis: {
+            focus: 'series'
+          },
+          data: res.errorDate
+        })
+      }
+      console.log(mySeries)
+      const options = {
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'shadow'
+          }
+        },
+        legend: {},
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true
+        },
+        xAxis: [
+          {
+            type: 'category',
+            data: res.xAxis
+          }
+        ],
+        yAxis: [
+          {
+            type: 'value'
+          }
+        ],
+        series: mySeries
+      }
+      this.chart.setOption(options)
+      this.chart.resize()
+    },
+    /** 年月份发生变化 */
+    handleYearMonthChanged(object) {
+      console.log(object)
+      if (object.type === 'DATE') {
+        this.sssparams.cycle_type = object.type
+        this.sssparams.year = object.date_val.getFullYear()
+        this.sssparams.month = this.checkTime(object.date_val.getMonth() + 1)
+        this.sssparams.day = this.checkTime(object.date_val.getDate())
+      } else {
+        this.sssparams.year = object.year
+        this.sssparams.month = object.month
+        this.sssparams.cycle_type = object.type
+      }
+      this.getLogCharsJS()
+      if (this.activeName !== 'ALL') {
+        this.Api_getLogTable()
+      }
+      // this.getTableByParentIdJS()
+    },
+    // 时间处理,如果时间小于10 ,则再前面加一个'0'
+    checkTime(i) {
+      if (i < 10) {
+        i = '0' + i
+      }
+      return i
+    },
+    formatterType(param) {
+      switch (param) {
+        case 'VOICE':
+          return '语音'
+        case 'VIDEO':
+          return '视频'
+        case 'IM':
+          return '留言'
+        case 'EVENT':
+          return '事件'
+        case 'ENTRACEGUARD':
+          return '门禁'
+        case 'SOS':
+          return '紧急按钮'
+        default:
+          return '未知'
+      }
+    },
+    handleClick(tab, event) {
+      console.log('this.activeName==', this.activeName)
+      if (this.activeName === 'ALL') {
+        delete this.sssparams.type
+      } else {
+        this.sssparams.type = this.activeName
+        this.Api_getLogTable()
+      }
+      this.getLogCharsJS()
+    },
+    Api_getLogTable() {
+      const _this = this
+      API_interaction.getLogTable(this.sssparams).then(res => {
+        console.log(res)
+        _this.buildChart(res.dataList, res.tilStr, res.xAxis, 'actionChar', '详情')
+        _this.userActionList = res.countList
+      })
+    }
+  }
+
+}
+</script>
+
+<style type="text/scss" lang="scss" scoped>
+.container .el-card {
+  .title {
+    margin-bottom:20px;
+    line-height: 30px;
+  }
+  .header_title {
+    color: #F1F1F3;
+    text-size: 2em;
+  }
+  .header_action {
+    color: #F1F1F3;
+    float:right;
+    padding:0 5px;
+  }
+}
+.card-panel-col {
+  margin-bottom: 32px;
+}
+
+.card-panel {
+  height: 108px;
+  font-size: 12px;
+  position: relative;
+  border-radius: 4px;
+  overflow: hidden;
+  /*color: #F1F1F3;*/
+  /*background: #0f202b;*/
+  border: solid 1px #41469f;
+  box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
+  border-color: #41469F;
+
+  &:hover {
+    .card-panel-icon-wrapper {
+      color: #666;
+    }
+    .icon-people {
+      background: #40c9c6;
+    }
+    .icon-message {
+      background: #36a3f7;
+    }
+    .icon-money {
+      background: #f4516c;
+    }
+  }
+  .icon-people {
+    color: #40c9c6;
+  }
+  .icon-message {
+    color: #36a3f7;
+  }
+  .icon-money {
+    color: #f4516c;
+  }
+  .card-panel-icon-wrapper {
+    float: left;
+    margin: 14px 0 0 14px;
+    padding: 16px;
+    transition: all 0.38s ease-out;
+    border-radius: 6px;
+  }
+  .card-panel-icon {
+    float: left;
+    font-size: 48px;
+  }
+  .card-panel-description {
+    float: right;
+    font-weight: bold;
+    margin: 26px;
+    margin-left: 0px;
+    .card-panel-text {
+      line-height: 18px;
+      /*color: #fff;*/
+      font-size: 16px;
+      margin-bottom: 12px;
+    }
+    .card-panel-num {
+      font-size: 20px;
+    }
+  }
+}
+</style>

+ 15 - 4
src/views/ncs-device/components/deviceManager.vue

@@ -124,8 +124,8 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="后备设备ID">
-              <el-input v-model="deviceModel.backup_id" clearable placeholder="" />
+            <el-form-item label="设备电话号码">
+              <el-input v-model="deviceModel.phone_number" clearable placeholder="请输入设备电话号码" />
             </el-form-item>
           </el-col>
         </el-row>
@@ -137,6 +137,11 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
+            <el-form-item label="后备设备ID">
+              <el-input v-model="deviceModel.backup_id" clearable placeholder="" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
             <el-form-item label="是否启用">
               <el-checkbox v-model="deviceModel.status" :true-label="1" :false-label="0">启用设备</el-checkbox>
               <!--              <el-radio v-model="formmodel.status" :label="1">启用</el-radio>-->
@@ -258,6 +263,9 @@ export default {
         frame_id: [
           { required: Object.keys(this.frame).length === 0, message: '请选安装位置!', trigger: 'blur' } // 没有传入frame 属性,必须选择安装位置
         ],
+        phone_number: [
+          { required: true, message: '请输入设备电话号码', trigger: 'blur' }
+        ],
         role_id: [
           { required: true, message: '请选择适用人', trigger: 'blur' }
         ],
@@ -389,6 +397,7 @@ export default {
         cellRenderer: this.onlineStateFormatter
       },
       { headerName: '部署位置', field: 'full_name', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '设备号码', field: 'phone_number', sortable: true, filter: 'agTextColumnFilter' },
       { headerName: '以太网MAC地址', field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter' },
       { headerName: '以太网IP地址', field: 'eth_ip', sortable: true, filter: 'agTextColumnFilter' },
       { headerName: '通讯端口', field: 'eth_ip_port', sortable: true, filter: 'agNumberColumnFilter' },
@@ -630,7 +639,8 @@ export default {
     /** 设备类型选中变化  **/
     deviceTypeChange(val) {
       this.deviceTypeChangeToFrameTypeChange(val)
-      if (val === DEVICE_TYPE.SIMULATE_BED_DEVICE || DEVICE_TYPE.RS485_DOOR ||
+      if (val === DEVICE_TYPE.SIMULATE_BED_DEVICE || // 只能直接在后面加设备,会判断错误,必须重新用val = 设备
+          val === DEVICE_TYPE.RS485_DOOR ||
           val === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON ||
           val === DEVICE_TYPE.SIMULATE_DOOR_LIGHT ||
           val === DEVICE_TYPE.EMERGENCY_BUTTON) { // 模拟设备不需要mac地址
@@ -666,7 +676,8 @@ export default {
           val === DEVICE_TYPE.RS485_TRANSFER) {
         this.getFramesByType(FRAME_TYPE.PART)
       } else if (val === DEVICE_TYPE.DOOR_DEVICE ||
-                 val === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON || DEVICE_TYPE.RS485_DOOR ||
+                 val === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON ||
+                 val === DEVICE_TYPE.RS485_DOOR ||
                  val === DEVICE_TYPE.SIMULATE_DOOR_LIGHT ||
                  val === DEVICE_TYPE.BEACON) {
         this.getFramesByType(FRAME_TYPE.ROOM)

+ 2 - 0
src/views/ncs-interaction/index.vue

@@ -322,6 +322,8 @@ export default {
           return '广播'
         case 'TIME':
           return '时间'
+        case 'ENTRACEGUARD':
+          return '门禁'
         default:
           return '未知'
       }