瀏覽代碼

Merge branch 'develop'

* develop:
  开发科室控制led点阵屏
  开发录音录像播放功能
  修改交互统计数据展示方式
  修复在修改设备时,不是报警设备却显示报警设置的问题
  开发频道留言历史功能
  增加跳过房间号和床位号
  增加设备空间的中文
  增加用户姓名隐藏选项
  修复亲属创建失败的问题
  修复亲属创建失败的问题
  增加英文的配置文件字样,修复多语言文件错误的问题
  485收到消息自动跳转
  每个版本加上足迹功能
wuyunfeng 2 年之前
父節點
當前提交
b2470c7d37

+ 46 - 7
languages/en.js

@@ -53,6 +53,7 @@ module.exports = {
     systemNoReturnMessage: 'The system has no return message!',
     failedGetReturnMessage: 'Failed to get the return message!',
     notDevelopedYet: 'Not yet developed',
+    search: 'Enter search',
     keywords: 'Please enter a search keyword',
     chooseLang: 'Choose language',
     perpetualLicence: 'Perpetual License',
@@ -87,6 +88,7 @@ module.exports = {
     to: 'to',
     index: 'Serial number',
     null: 'None',
+    all: 'All',
     choiceData: 'Choose date and time',
     startDate: 'Start date',
     endDate: 'End date',
@@ -136,12 +138,16 @@ module.exports = {
     uploadVersionCodeMsg: 'Version information cannot be empty',
     initialing: 'Initializing, please wait...',
     deviceFrame: 'Device space',
+    synchroDevice: 'Synchro device',
     excelFile: 'Excel file will be exported. Continue?',
     statisticalSubTable: 'statistical sub table',
     byPerson: 'By Person',
     byEvent: 'By Event',
     export: 'Export',
-    icon: 'Icon'
+    icon: 'Icon',
+    play: 'Play',
+    pause: 'Pause',
+    noFile: 'File does not exist, cannot be played'
   },
   member: {
     face: 'Avatar',
@@ -217,8 +223,11 @@ module.exports = {
     sureDelete: 'Sure to delete',
     allBad: 'And all the beds in it?',
     sureDeleteBed: 'Make sure to delete the bed',
+    part: 'Department',
     room: 'Room',
+    room2: 'Room',
     bed: 'Bed',
+    bed2: 'Bed',
     newOrganization: 'New Organization',
     partName: 'Department name',
     inputPartName: 'Please enter the department name',
@@ -227,7 +236,11 @@ module.exports = {
     adminPassword: 'Admin Password',
     inputAdminPassword: 'Please enter the administrator password',
     prefix: 'prefix',
-    prefixExample: 'One building, one unit'
+    prefixExample: 'One building, one unit',
+    skipRoomNo: 'TSkip-the-line room number',
+    skipBedNo: 'Skip-the-line bed number',
+    skipMsg1: 'Enter the numbers, separated by semicolons',
+    skipMsg2: '1,2,3'
   },
   deviceManage: {
     deviceManage: 'Device Management',
@@ -314,7 +327,21 @@ module.exports = {
     ledAddCustom: 'Add custom',
     hostDeviceList: 'Nurse host list',
     webSocketSuccess: 'WebSocket connection is successful',
-    webSocketError: 'An error occurred in the WebSocket connection'
+    webSocketError: 'An error occurred in the WebSocket connection',
+    deviceLocationLevel: 'Please select the device location level',
+    assignment: 'One-click assignment',
+    assignmentMsg: 'No spare allocated devices!',
+    assignmentMsg2: 'Rooms and beds have devices, and only department-level device can be automatically assigned!',
+    assignmentMsg3: 'Start auto-assigning!',
+    assignmentMsg4: 'The automatic assignment is complete, the full level of device needs to be manually assigned, after the assignment is completed, please click [Save]!',
+    reset: 'One-click reset',
+    resetMsg: 'Are you sure you want to reset all your devices?',
+    resetMsg2: 'Reset successfully!',
+    collapse: 'Collapse display',
+    card: 'Card display',
+    devices: ' devices',
+    roomNoDevice: 'The room was not equipped',
+    bedNoDevice: 'The bed was not equipped'
   },
   clerkManage: {
     clerkEdit: 'Edit member information',
@@ -450,7 +477,12 @@ module.exports = {
     channelAdd: 'Add channel',
     channelName: 'Channel name',
     inputChannelName: 'Please enter the channel name',
-    subscribeManage: 'Subscription Management'
+    subscribeManage: 'Management',
+    channelImHistory: 'History',
+    senderMemberName: 'Sender name',
+    senderTime: 'Send time',
+    audioPath: 'File address',
+    play: 'Play the message'
   },
   remark: {
     remarkAdd: 'New note',
@@ -519,7 +551,8 @@ module.exports = {
     MaxNum: 'Maximum response time',
     MaxNum2: 'Maximum on time',
     SumNum: 'Total call time',
-    total: 'Total'
+    total: 'Total',
+    recordPlay: 'Play the audio recording'
   },
   frameGroup: {
     frameGroupAdd: 'New area',
@@ -787,8 +820,13 @@ module.exports = {
     organizationAdd: 'New Organization',
     boardShowEmptyBed: 'The board shows empty beds',
     nursingColorRgb: 'Nursing door light color',
-    twoColorDoorLightValid: 'Two-color door lights are supported or not',
-    support: 'Support two-color door lights'
+    twoColorDoorLightValid: 'Two-color door lights are supported',
+    support: 'Support two-color door lights',
+    customerNameHidden: 'Turn on user name hide',
+    hidden: 'Turn on user name hide',
+    channelImHistoryStoreDays: 'The number of days that channel messages are retained',
+    recordEnabled: 'Turn on the audio and video recording function',
+    recordAble: 'Turn on the audio and video recording function'
   },
   role: {
     roleName: 'Role name',
@@ -815,6 +853,7 @@ module.exports = {
     userLocationManage: 'User Location',
     sosDeviceSettingManage: 'Alarm device',
     channelManage: 'Intercom channel',
+    channelImHistory: 'Channel message history',
     remarkManage: 'Note management',
     taskManage: 'Task management',
     interactionHistory: 'Interaction History',

+ 45 - 7
languages/zh-CN.js

@@ -54,6 +54,7 @@ module.exports = {
     systemNoReturnMessage: '系统无返回消息!',
     failedGetReturnMessage: '未能得到返回消息!',
     notDevelopedYet: '暂未开发',
+    search: '输入搜索',
     keywords: '请输入搜索关键字',
     chooseLang: '选择语言',
     perpetualLicence: '永久授权',
@@ -88,6 +89,7 @@ module.exports = {
     to: '至',
     index: '序号',
     null: '无',
+    all: '全部',
     choiceData: '选择日期时间',
     startDate: '开始日期',
     endDate: '结束日期',
@@ -143,7 +145,10 @@ module.exports = {
     byPerson: '按人',
     byEvent: '按事件',
     export: '导出',
-    icon: '图标'
+    icon: '图标',
+    play: '播放',
+    pause: '暂停',
+    noFile: '文件不存在,无法播放'
   },
   member: {
     face: '头像',
@@ -219,8 +224,11 @@ module.exports = {
     sureDelete: '确定要删除',
     allBad: '及其中的所有床位吗?',
     sureDeleteBed: '确定删除床位',
+    part: '科室',
     room: '房',
+    room2: '房间',
     bed: '床',
+    bed2: '床位',
     newOrganization: '新建组织',
     partName: '科室名称',
     inputPartName: '请输入科室名称',
@@ -229,7 +237,11 @@ module.exports = {
     adminPassword: '管理员密码',
     inputAdminPassword: '请输入管理员密码',
     prefix: '前缀',
-    prefixExample: '一栋一单元'
+    prefixExample: '一栋一单元',
+    skipRoomNo: '需要跳过的房间号',
+    skipBedNo: '需要跳过的床位号',
+    skipMsg1: '输入数字,用分号隔开',
+    skipMsg2: '1,2,3'
   },
   deviceManage: {
     deviceManage: '设备管理',
@@ -316,7 +328,21 @@ module.exports = {
     ledAddCustom: '添加自定义',
     hostDeviceList: '护士主机列表',
     webSocketSuccess: 'WebSocket连接成功',
-    webSocketError: 'WebSocket连接发生错误'
+    webSocketError: 'WebSocket连接发生错误',
+    deviceLocationLevel: '请选择设备位置级别',
+    assignment: '一键分配',
+    assignmentMsg: '没有空余分配的设备!',
+    assignmentMsg2: '房间及床位有设备,只能自动分配科室级设备!',
+    assignmentMsg3: '开始自动分配!',
+    assignmentMsg4: '自动分配已完成,全级别设备需手动分配,分配完成后请点击【保存】!',
+    reset: '一键重置',
+    resetMsg: '确定要重置所有设备吗?',
+    resetMsg2: '已成功重置!',
+    collapse: '折叠显示',
+    card: '卡片显示',
+    devices: '台设备',
+    roomNoDevice: '房间没有设备',
+    bedNoDevice: '床位没有设备'
   },
   clerkManage: {
     clerkEdit: '编辑成员信息',
@@ -452,7 +478,12 @@ module.exports = {
     channelAdd: '新增频道',
     channelName: '频道名称',
     inputChannelName: '请输入频道名称',
-    subscribeManage: '订阅管理'
+    subscribeManage: '订阅管理',
+    channelImHistory: '频道历史',
+    senderMemberName: '发送者姓名',
+    senderTime: '发送时间',
+    audioPath: '文件地址',
+    play: '播放留言'
   },
   remark: {
     remarkAdd: '新建便签',
@@ -521,7 +552,8 @@ module.exports = {
     MaxNum: '最大响应时间',
     MaxNum2: '最大接通时间',
     SumNum: '总通话时间',
-    total: '总量'
+    total: '总量',
+    recordPlay: '播放录音录像'
   },
   frameGroup: {
     frameGroupAdd: '新建区域',
@@ -789,8 +821,13 @@ module.exports = {
     organizationAdd: '新建组织',
     boardShowEmptyBed: '看板显示空床',
     nursingColorRgb: '护理门灯颜色',
-    twoColorDoorLightValid: '是否支持双色门灯',
-    support: '支持双色门灯'
+    twoColorDoorLightValid: '支持双色门灯',
+    support: '支持双色门灯',
+    customerNameHidden: '开启用户名隐藏',
+    hidden: '开启用户名隐藏',
+    channelImHistoryStoreDays: '频道留言保留天数',
+    recordEnabled: '开启录音录像功能',
+    recordAble: '开启录音录像功能'
   },
   role: {
     roleName: '角色名称',
@@ -817,6 +854,7 @@ module.exports = {
     userLocationManage: '用户位置',
     sosDeviceSettingManage: '报警设备',
     channelManage: '对讲频道',
+    channelImHistory: '频道留言历史',
     remarkManage: '便签管理',
     taskManage: '任务管理',
     interactionHistory: '交互历史',

+ 16 - 0
src/api/ncs_channel_im_history.js

@@ -0,0 +1,16 @@
+import request from '@/utils/request'
+
+/**
+ * 对讲频道相关接口
+ * @param params
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function getList(params) {
+  return request({
+    url: '/ncs/channel_im_history/channel_im_history_list',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}

+ 8 - 0
src/api/ncs_interaction.js

@@ -59,3 +59,11 @@ export function getListByHonePage(partId) {
     loading: true
   })
 }
+export function getStreaming(partId, id) {
+  return request({
+    url: `/ncs/record/get_record/${partId}/${id}`,
+    method: 'get',
+    loading: true
+  })
+}
+

+ 7 - 8
src/api/ncs_led.js

@@ -1,9 +1,9 @@
 import request from '@/utils/request'
 
 /** 发送默认节目 */
-export function updateDefaultProgramHospitalId(params) {
+export function updateDefaultProgramShopId(params) {
   return request({
-    url: '/ncs/led/update_default_program_hospital_id',
+    url: '/ncs/led/update_default_program_by_shop_id',
     method: 'POST',
     loading: true,
     data: params
@@ -11,9 +11,9 @@ export function updateDefaultProgramHospitalId(params) {
 }
 
 /** 开关屏 */
-export function powerOnOffByHospitalId(params) {
+export function powerOnOffByShopId(params) {
   return request({
-    url: '/ncs/led/power_on_off_by_hospital_id',
+    url: '/ncs/led/power_on_off_by_shop_id',
     method: 'POST',
     loading: true,
     data: params
@@ -23,7 +23,7 @@ export function powerOnOffByHospitalId(params) {
 /** 校时 */
 export function timing(params) {
   return request({
-    url: '/ncs/led/timing',
+    url: '/ncs/led/timing_by_shop_id',
     method: 'POST',
     loading: true,
     data: params
@@ -31,13 +31,12 @@ export function timing(params) {
 }
 
 /** 删除所有节目 */
-export function removeAllProgramByHospitalId(params) {
+export function removeAllProgramByShopId(params) {
   return request({
-    url: '/ncs/led/remove_all_program_by_hospital_id',
+    url: '/ncs/led/remove_all_program_by_shop_id',
     method: 'POST',
     loading: true,
     data: params
   })
 }
 
-

+ 62 - 0
src/components/AgGridCellRender/RecordButtonCellRender.vue

@@ -0,0 +1,62 @@
+<template>
+  <el-button v-if="show" :type="buttonType" :size="buttonSize" :icon="icon" :disabled="disabled" @click="buttonClick" ></el-button>
+  <span v-else-if="!show">{{ value }}</span>
+</template>
+
+<script>
+export default {
+  name: "RecordButtonCellRender",
+  data() {
+    return {
+      buttonType: 'primary',
+      buttonSize: 'mini',
+      label: 'button',
+      disabled: false,
+      show: true,
+      param: {},
+      icon: ''
+    }
+  },
+  beforeMount() {
+  },
+  mounted() {
+    const { buttonType, buttonSize, label, disabled, show, value, icon } = this.params
+    if (buttonType) {
+      this.buttonType = buttonType
+    }
+    if (buttonSize) {
+      this.buttonSize = buttonSize
+    }
+    if (label) {
+      this.label = label
+    }
+    if (disabled !== undefined) {
+      this.disabled = disabled
+    }
+    if (show !== undefined) {
+      this.show = show
+    }
+    if (value !== undefined) {
+      this.value = value
+    }
+    if (icon !== undefined) {
+      this.icon = icon
+    }
+  },
+  methods: {
+    buttonClick() {
+      console.log('click', typeof this.params.onClick === 'function')
+
+      if (typeof this.params.onClick === 'function') {
+        console.log(this.params.node.data)
+        this.params.onClick(this.params.node.data)
+        // this.params.context.componentParent.showDetail(this.params.node.data)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 22 - 2
src/router/index.js

@@ -211,8 +211,7 @@ export const partRoutes = [
         meta: { title: i18n.t('customerManage.footprint'), icon: 'area', noCache: true },
         hidden: true
       }
-    ],
-    hidden: uiVersion === 1
+    ]
   },
   {
     path: '/ncs-user-watch',
@@ -251,6 +250,13 @@ export const partRoutes = [
         component: () => import('@/views/ncs-channel/index'),
         name: 'ncsChannel',
         meta: { title: i18n.t('tab.channelManage'), icon: 'el-icon-mobile-phone', noCache: true }
+      },
+      {
+        path: '/ncs-channel/history/:id?',
+        component: () => import('@/views/ncs-channel/channelImHistory'),
+        name: 'channelImHistory',
+        meta: { title: i18n.t('tab.channelImHistory'), icon: 'area', noCache: true },
+        hidden: true
       }
     ],
     hidden: uiVersion !== 2
@@ -436,6 +442,20 @@ export const partRoutes = [
       }
     ]
   },
+  {
+    path: '/ncs_led',
+    component: Layout,
+    redirect: '/ncs_led/index',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/ncs-led/ledManager'),
+        name: 'part_led',
+        meta: { title: i18n.t('tab.ledDevice'), icon: 'el-icon-message-solid', noCache: true }
+      }
+    ],
+    hidden: uiVersion !== 1
+  },
   { path: '*', redirect: '/404', hidden: true }
 ]
 export const hospitalRoutes = [

+ 36 - 17
src/views/customer/components/customerManager.vue

@@ -409,6 +409,9 @@
             </div>
           </div>
         </el-tab-pane>
+        <el-tab-pane v-if="formmodel.id && boolDevice" :label="this.$t('customerManage.footprint')" name="footprint">
+          <my-map-html :map-url="mapUrl" style="width: 100%; height: 670px;"></my-map-html>
+        </el-tab-pane>
       </el-tabs>
     </el-dialog>
     <!-- 用户信息 -->
@@ -545,10 +548,12 @@ import * as API_SystemConfig from '@/api/ncs_systemconfig'
 import {RELATIVE_NAME_TYPE} from "@/utils/enum/RelativeNameTypeEnum";
 import {CHILDBIRTH_TYPE} from "@/utils/enum/ChildbirthTypeEnum";
 import * as shop_API from "@/api/ncs_shop";
+import {getDevicesByUuid} from "@/api/initialize"
+import myMapHtml from '@/views/customer/myMapHtml'
 const serverUrl = domain.serverUrl
 export default {
   name: 'CustomerManager',
-  components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr },
+  components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr, myMapHtml },
   filters: {
     unixDateFilter(val) {
       return unixToDate(val)
@@ -644,20 +649,20 @@ export default {
         true_name: [{ required: true, message: this.$t('customerManage.inputRemarks'), trigger: 'blur' }],
         relative_name: [{ required: true, message: this.$t('customerManage.inputRelativeName'), trigger: 'blur' }],
         mobile: [
-          { required: false, message: this.$t('member.inputMobile'), trigger: 'blur',
-            validator: (rule, value, callback) => {
-              // this.isCloud = false
-              if (this.isCloud === false) {
-                if (value === null || value === '') { // 手机号可为空
-                  callback()
-                }
-              // }
-              // if (!RegExp.mobile.test(value)) {
-              //   callback(new Error(this.$t('member.mobileInputMsg')))
-              // } else {
-                callback()
-              }
-            }
+          { required: this.isCloud, message: this.$t('member.inputMobile'), trigger: 'blur',
+            // validator: (rule, value, callback) => {
+            //   // this.isCloud = false
+            //   if (this.isCloud === false) {
+            //     if (value === null || value === '') { // 手机号可为空
+            //       callback()
+            //     }
+            //   // }
+            //   // if (!RegExp.mobile.test(value)) {
+            //   //   callback(new Error(this.$t('member.mobileInputMsg')))
+            //   // } else {
+            //     callback()
+            //   }
+            // }
           }
         ]
       },
@@ -718,7 +723,9 @@ export default {
       relativeNameTypeEnum: RELATIVE_NAME_TYPE.getValueList(),
       childbirthTypeEnum: CHILDBIRTH_TYPE.getValueList(),
       isChild: false,
-      shop: {}
+      shop: {},
+      boolDevice: false,
+      mapUrl: null
     }
   },
   computed: {
@@ -1104,7 +1111,9 @@ export default {
       return date
     },
     handleClick() {
-
+      if (this.activeName === 'footprint') {
+        this.$router.push({path:'/myMapHtml', query: {mapUrl: this.mapUrl}})
+      }
     },
     /** 生日选择变化,修改年龄字段 */
     birthdayChange(val) {
@@ -1258,6 +1267,7 @@ export default {
     },
 
     handleEdit(row) {
+      this.boolDevice = false
       this.relativeRules.mobile[0].required = this.isCloud
       this.formmodel = {
         ...row
@@ -1283,6 +1293,15 @@ export default {
       this.getQrCode()
       this.getRemarks()
       this.getRelatives()
+      if (this.isCloud) {
+        const _this = this
+        getDevicesByUuid(row.uuid).then(res => {
+          if (res) {
+            _this.boolDevice = true
+            _this.mapUrl = res
+          }
+        })
+      }
     },
     /** 出院 退床 **/
     handleOut(row) {

+ 3 - 3
src/views/customer/components/elderlyCareManager.vue

@@ -396,7 +396,7 @@
                 </el-tab-pane>
 
               <el-tab-pane v-if="formmodel.id && boolDevice" :label="this.$t('customerManage.footprint')" name="footprint">
-<!--                <my-map-html :map-url="mapUrl" style="width: 100%; height: 670px;"></my-map-html>-->
+                <my-map-html :map-url="mapUrl" style="width: 100%; height: 670px;"></my-map-html>
               </el-tab-pane>
 
             </el-tabs>
@@ -494,14 +494,14 @@
     import * as API_Clerk from '@/api/ncs_clerk'
     import * as API_NurseConfig from '@/api/ncs_nurse_config'
     import vitalSignLog from '@/views/vital-sign/log'
-    // import myMapHtml from '@/views/customer/myMapHtml'
+    import myMapHtml from '@/views/customer/myMapHtml'
     import myMap from '@/views/customer/myMap'
     import * as API_SystemConfig from '@/api/ncs_systemconfig'
     import { getDevicesByUuid } from '@/api/initialize'
     const serverUrl = domain.serverUrl
     export default {
         name: 'ElderlyCareManager',
-        components: {ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, myMap},
+        components: {ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, myMap, myMapHtml},
         filters: {
             unixDateFilter(val) {
                 return unixToDate(val)

+ 42 - 15
src/views/customer/components/patientManager.vue

@@ -307,7 +307,7 @@
                             <el-row>
                                 <el-col :span="12">
                                     <el-form-item :label="this.$t('customerManage.customerRelativeTrueName')" prop="true_name">
-                                        <el-input v-model="relativeFormModel.true_name" clearable :placeholder="请输入姓名"
+                                        <el-input v-model="relativeFormModel.true_name" clearable :placeholder="this.$t('customerManage.inputNamed')"
                                                   :maxlength="20"/>
                                     </el-form-item>
                                 </el-col>
@@ -415,6 +415,10 @@
                     </div>
                 </el-tab-pane>
 
+              <el-tab-pane v-if="formmodel.id && boolDevice" :label="this.$t('customerManage.footprint')" name="footprint">
+                <my-map-html :map-url="mapUrl" style="width: 100%; height: 670px;"></my-map-html>
+              </el-tab-pane>
+
             </el-tabs>
         </el-dialog>
         <!-- 用户信息 -->
@@ -510,10 +514,12 @@
     import {FRAME_TYPE} from "@/utils/enum/FrameTypeEnum";
     import * as API_SystemConfig from "@/api/ncs_systemconfig";
     import * as shop_API from "@/api/ncs_shop";
+    import myMapHtml from '@/views/customer/myMapHtml'
+    import {getDevicesByUuid} from "@/api/initialize";
     const serverUrl = domain.serverUrl
     export default {
         name: 'PatientManager',
-        components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr },
+        components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr, myMapHtml },
         filters: {
             unixDateFilter(val) {
                 return unixToDate(val)
@@ -600,18 +606,21 @@
                     relative_name: [{required: true, message: this.$t('customerManage.inputRelativeName'), trigger: 'blur'}],
                     mobile: [
                         {
-                            validator: (rule, value, callback) => {
-                                if (this.isCloud === false) {
-                                    if (value === null || value === '') { // 手机号可为空
-                                      callback()
-                                    }
-                                // }
-                                // if (!RegExp.mobile.test(value)) {
-                                //     callback(new Error(this.$t('member.mobileInputMsg')))
-                                // } else {
-                                    callback()
-                                }
-                            }
+                          required: this.isCloud
+                            // validator: (rule, value, callback) => {
+                            //     if (this.isCloud === false) {
+                            //         if (value === null || value === '') { // 手机号可为空
+                            //           callback()
+                            //         }
+                            //     // }
+                            //     // if (!RegExp.mobile.test(value)) {
+                            //     //     callback(new Error(this.$t('member.mobileInputMsg')))
+                            //     // } else {
+                            //         callback()
+                            //     } else {
+                            //
+                            //     }
+                            // }
                         }
                     ]
                 },
@@ -666,6 +675,8 @@
                 colour: this.$t('action.colour'),
                 deleted: this.$t('action.delete'),
                 qrCode: null,
+                boolDevice: false,
+                mapUrl: null
             }
         },
         computed: {
@@ -1104,7 +1115,9 @@
             }
           },
             handleClick() {
-
+              if (this.activeName === 'footprint') {
+                this.$router.push({path:'/myMapHtml', query: {mapUrl: this.mapUrl}})
+              }
             },
             /** 生日选择变化,修改年龄字段 */
             birthdayChange(val) {
@@ -1266,6 +1279,7 @@
             },
 
             handleEdit(row) {
+                this.boolDevice = false
                 this.relativeRules.mobile[0].required = this.isCloud
                 this.formmodel = {
                     ...row
@@ -1298,6 +1312,15 @@
                 this.getQrCode()
                 this.getRemarks()
                 this.getRelatives()
+              if (this.isCloud) {
+                const _this = this
+                getDevicesByUuid(row.uuid).then(res => {
+                  if (res) {
+                    _this.boolDevice = true
+                    _this.mapUrl = res
+                  }
+                })
+              }
             },
             /** 出院 退床 **/
             handleOut(row) {
@@ -1406,7 +1429,11 @@
             },
             /** 添加亲属 */
             addRelative() {
+              console.log('8888888888888888888888888888')
+              console.log(this.$refs['relativeForm'])
                 this.$refs['relativeForm'].validate(valid => {
+                  console.log('222222222222222')
+                  console.log(valid)
                     if (valid) {
                         this.relativeFormModel.relative_id = this.formmodel.member_id
                         API_User.addRelative(this.relativeFormModel).then(res => {

+ 0 - 2
src/views/dashboard/calling/index.vue

@@ -250,9 +250,7 @@ export default {
       this.$router.push({ name: path })
     },
     formatterFromName(row, column, cellValue) {
-      console.log(!row.outerior_action, row.relative_name, !row.outerior_action && row.relative_name === null)
       if (!row.outerior_action && row.relative_name === null) {
-        console.log('row===', row.id)
         let named = ''
         if (row.from_frame_full_name && row.from_member_name) {
           named = row.from_frame_full_name + row.from_member_name

+ 12 - 12
src/views/hospital/ledManager.vue

@@ -66,7 +66,7 @@ export default {
       rules: {},
       isOnlyTime: false,
       // addCustom: '',
-      hospital_id: this.$store.getters.partId
+      shop_id: this.$store.getters.partId
     }
   },
   async mounted() {
@@ -79,48 +79,48 @@ export default {
         text = this.formmodel.addCustom
       }
       const params = {}
-      params.hospital_id = this.hospital_id
+      params.shop_id = this.shop_id
       params.text = text
-      API_Led.updateDefaultProgramHospitalId(params).then(r => {
+      API_Led.updateDefaultProgramShopId(params).then(r => {
         this.$message.success(this.$t('action.saveSuccess'))
       })
     },
     powerOn() {
       const params = {}
-      params.hospital_id = this.hospital_id
+      params.shop_id = this.shop_id
       params.on_off = 0
-      API_Led.powerOnOffByHospitalId(params).then(r => {
+      API_Led.powerOnOffByShopId(params).then(r => {
         this.$message.success(this.$t('action.saveSuccess'))
       })
     },
     powerOff() {
       const params = {}
-      params.hospital_id = this.hospital_id
+      params.shop_id = this.shop_id
       params.on_off = 1
-      API_Led.powerOnOffByHospitalId(params).then(r => {
+      API_Led.powerOnOffByShopId(params).then(r => {
         this.$message.success(this.$t('action.saveSuccess'))
       })
     },
     powerRestart() {
       const params = {}
-      params.hospital_id = this.hospital_id
+      params.shop_id = this.shop_id
       params.on_off = 2
-      API_Led.powerOnOffByHospitalId(params).then(r => {
+      API_Led.powerOnOffByShopId(params).then(r => {
         this.$message.success(this.$t('action.saveSuccess'))
       })
     },
     timing() {
       const params = {}
-      params.hospital_id = this.hospital_id
+      params.shop_id = this.shop_id
       API_Led.timing(params).then(r => {
         this.$message.success(this.$t('action.saveSuccess'))
       })
     },
     deleteAllPrograms() {
       const params = {}
-      params.hospital_id = this.hospital_id
+      params.shop_id = this.shop_id
       params.text = null
-      API_Led.removeAllProgramByHospitalId(params).then(r => {
+      API_Led.removeAllProgramByShopId(params).then(r => {
         this.$message.success(this.$t('action.saveSuccess'))
       })
     }

+ 34 - 4
src/views/hospitalFrame/frameTreeView.vue

@@ -139,17 +139,17 @@
     <!---添加空间结构弹窗 -->
 
     <!---快速创建结构弹窗 -->
-    <el-dialog :title="this.$t('frameManage.quickCreateFrame')" :visible.sync="frameQuickCreateVisible" width="600px">
+    <el-dialog :title="this.$t('frameManage.quickCreateFrame')" :visible.sync="frameQuickCreateVisible" width="620px">
       <el-form ref="createFrameForm" :model="createFrameModel" :rules="createFrameRules" label-width="200px">
         <el-row>
-          <el-col :span="16">
+          <el-col :span="17">
             <!--前缀-->
             <el-form-item :label="this.$t('frameManage.prefix')" prop="prefix">
               <el-input v-model="createFrameModel.prefix" :placeholder="$t('frameManage.prefixExample')" maxlength="10" show-word-limit />
             </el-form-item>
           </el-col>
           <el-col :span="6">
-            <div class="el-form-item__label">
+            <div class="el-form-item__label" style="margin-left: 20px">
               {{ this.$t('frameManage.example') }}:{{ $t('frameManage.prefixExample') }}
             </div>
           </el-col>
@@ -207,6 +207,34 @@
           </el-col>
         </el-row>
 
+        <el-row>
+          <el-col :span="17">
+            <!--需要跳过的房间号-->
+            <el-form-item :label="this.$t('frameManage.skipRoomNo')" prop="skip_room_no">
+              <el-input v-model="createFrameModel.skip_room_no" :placeholder="$t('frameManage.skipMsg1')" clearable :maxlength="20"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <div class="el-form-item__label" style="margin-left: 20px">
+              {{ this.$t('frameManage.example') }}:{{ $t('frameManage.skipMsg2') }}
+            </div>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="17">
+            <!--需要跳过的床位号-->
+            <el-form-item :label="this.$t('frameManage.skipBedNo')" prop="skip_bed_no">
+              <el-input v-model="createFrameModel.skip_bed_no" :placeholder="$t('frameManage.skipMsg1')" clearable :maxlength="20"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <div class="el-form-item__label" style="margin-left: 20px">
+              {{ this.$t('frameManage.example') }}:{{ $t('frameManage.skipMsg2') }}
+            </div>
+          </el-col>
+        </el-row>
+
         <el-form-item>
           <el-button type="primary" class="save" @click="quickCreateSubmit()">{{ this.$t('action.yes') }}</el-button>
         </el-form-item>
@@ -267,7 +295,9 @@ export default {
         room_end_no: 2,
         beds_per_room: 4,
         room_num_bits: 2,
-        bed_num_bits: 2
+        bed_num_bits: 2,
+        skip_room_no: '',
+        skip_bed_no: ''
       },
       bed_num_demo: '01',
       room_num_demo: '01',

+ 61 - 3
src/views/ncs-485/index.vue

@@ -19,6 +19,12 @@
         <el-button :disabled="multipleSelection.length === 0" type="success" @click="sendAll">
           批量发送
         </el-button>
+        <el-button v-if="multipleSelection.length === 0" type="primary" @click="recoverList">
+          恢复勾选
+        </el-button>
+        <el-button v-else type="primary" @click="saveList">
+          保存勾选
+        </el-button>
         <el-switch v-model="boolOpen" active-text="打印具体消息" inactive-text="不打印具体消息" style="margin-left: 10px"></el-switch>
       </div>
       <div>
@@ -31,7 +37,7 @@
           <el-button slot="append" size="mini" icon="el-icon-search" @click="clickSearch"></el-button>
         </el-input>
       </div>
-      <el-table :data="deviceList" stripe border style="width: 100%" @selection-change="selectFun" height="520">
+      <el-table :data="deviceList" id="myTableId" stripe border style="width: 100%" ref="refTable" @selection-change="selectFun" height="520">
         <el-table-column type="selection" width="55"></el-table-column>
         <el-table-column prop="full_name" min-width="100" label="位置" align="center" />
         <el-table-column prop="name" label="设备名" min-width="130" align="center" />
@@ -148,8 +154,8 @@
 import { listByType } from '@/api/ncs_partInfo'
 import {get485DeviceAndFrame, getDeviceByType, update485s} from '@/api/ncs_device'
 import { unix2Date } from '@/utils/Foundation'
-import {changeRs485Debug} from "@/api/initialize";
-import * as API_Customer from "@/api/ncs_customer";
+import {changeRs485Debug} from "@/api/initialize"
+import Storage from '@/utils/storage'
 const DeviceUrl = domain.DeviceUrl
 export default {
   name: "index",
@@ -214,6 +220,11 @@ export default {
       }
       const time = (new Date()).valueOf()
       const item = this.deviceList[index]
+      //当点击"定位"按钮之后,实现屏幕滚动到这个id的位置,并且在屏幕的中间
+      let element = document.getElementById("table_td_bg_"+ item.id);
+      if (element) {
+        element.scrollIntoView({block:"center"})
+      }
       let active = {
         content: '设备:' + data.rs485mac  + '----' + data.rs485msg,
         timestamp: time,
@@ -283,6 +294,25 @@ export default {
         })
         _this.deviceList = res
         _this.allList = _this.MixinClone(res)
+        setTimeout(()=>{
+          //获取到存在 "userNameId"这个属性的对象下标
+          let refTabInsideData =  _this.$refs.refTable.data
+          //获取到表格的节点,获取到表格的所有子节点
+          let myTableId = document.getElementById("myTableId").childNodes
+          //拿到第3个表格内容结构的所有子节点  class = "el-table__body-wrapper is-scrolling-none"
+          let myTableIdChildNo3 =  myTableId[2].childNodes
+          //在拿到所有子节点中的第一个
+          let myTableIdChildNo3ChildNo1 = myTableIdChildNo3[0].childNodes
+          //再拿到结构为<tboby></tboby>的节点
+          let tbobyChildNo2 = myTableIdChildNo3ChildNo1[1]
+          //获取到结构为<tboby></tboby>的子节点
+          let kk = tbobyChildNo2.childNodes
+          kk.forEach((t, i) => {
+            if (i !== refTabInsideData.length) {
+              t.setAttribute('id','table_td_bg_' + refTabInsideData[i].id)
+            }
+          })
+        },1000)
       })
     },
     changeShop() {
@@ -398,6 +428,34 @@ export default {
           return false
         }
       })
+    },
+    recoverList() {
+      const data = Storage.getItem('rs485DeviceList')
+      if (data) {
+        let list = []
+        JSON.parse(data).forEach(row => {
+          const item = this.deviceList.find( t => row.id === t.id)
+          if (item) {
+            list.push(item)
+            this.$refs.refTable.toggleRowSelection(item)
+          }
+        })
+        this.multipleSelection = list
+        this.$message.success('已恢复')
+      } else {
+        this.$message.error('没有设备!')
+      }
+    },
+    saveList() {
+      if (this.multipleSelection.length === 0) {
+        this.$message.error('没有勾选的设备!')
+        return
+      }
+      const _this = this
+      setTimeout(()=>{
+        Storage.setItem('rs485DeviceList', JSON.stringify(_this.MixinClone(_this.multipleSelection)))
+      },700)
+      this.$message.success('已保存')
     }
   }
 }

+ 1 - 0
src/views/ncs-broadcast/index.vue

@@ -788,6 +788,7 @@ export default {
     },
     initAuditionWebSocket: function() {
       const stockbase = domain.mediaUrl.replace('http', 'ws')
+      console.log(stockbase + '/audition/' + this.$store.getters.partId)
       this.websock = new WebSocket(stockbase + '/audition/' + this.$store.getters.partId)
       this.websock.onopen = this.websocketonopen
       this.websock.onerror = this.websocketonerror

+ 356 - 0
src/views/ncs-channel/channelImHistory.vue

@@ -0,0 +1,356 @@
+<template>
+  <div class="app-container">
+    <ag-grid-layout
+        :table-height="tableHeight"
+        theme="ag-theme-alpine"
+        :column-defs="columnDefs"
+        :row-data="tableData"
+        :locale-text="localeText"
+        :grid-options="gridOptions"
+        :default-col-def="defaultColDef"
+        :animate-rows="true"
+        :row-selection="rowSelection"
+        row-height="50"
+        @filterChanged="filterModifed"
+        @sortChanged="gridSortChange"
+    >
+      <!--工具栏-->
+      <div slot="toolbar" class="inner-toolbar">
+        <div class="toolbar-search">
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
+        </div>
+        <div  class="toolbar-search"></div>
+        <div class="toolbar-btns">
+          <el-form label-width="120px">
+            <el-form-item>
+              <el-date-picker
+                  v-model="searchDateRange"
+                  type="daterange"
+                  align="right"
+                  unlink-panels
+                  value-format="yyyy/MM/dd"
+                  :range-separator="this.$t('action.to')"
+                  :start-placeholder="this.$t('action.startDate')"
+                  :end-placeholder="this.$t('action.endDate')"
+                  :picker-options="pickerOptions"
+                  :default-time="['00:00:00', '23:59:59']"
+                  @change="dateRangeChange"
+              />
+            </el-form-item>
+
+          </el-form>
+        </div>
+      </div>
+      <el-pagination
+          v-if="pageData"
+          slot="pagination"
+          :current-page="pageData.page_no"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="pageData.page_size"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="pageData.data_total"
+          @size-change="handlePageSizeChange"
+          @current-change="handlePageCurrentChange"
+      />
+    </ag-grid-layout>
+
+<!--    <el-dialog title="留言播放" :visible.sync="dialogVisible" :before-close="stop">-->
+<!--      <template>-->
+<!--        <audio-->
+<!--          :src="src"-->
+<!--          autoplay="autoplay"-->
+<!--          controls="controls"-->
+<!--          ref="audio"-->
+<!--          >-->
+<!--        </audio>-->
+<!--      </template>-->
+<!--    </el-dialog>-->
+  </div>
+</template>
+
+<script>
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter";
+import {AG_GRID_LOCALE_CN} from "@/utils/AgGridVueLocaleCn";
+import * as API_ChannelImHistory from "@/api/ncs_channel_im_history";
+import {unixToDate} from "@/utils/Foundation";
+
+const DeviceUrl = domain.DeviceUrl
+export default {
+  name: "channelImHistory",
+  components: { ButtonCellRender, RadioFilter, ListFilter},
+  data: function() {
+    return {
+      pickerOptions: {
+        shortcuts: [{
+          text: this.$t('action.lastWeek'),
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+            picker.$emit('pick', [start, end])
+          }
+        },{
+          text: this.$t('action.lastMonth'),
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+            picker.$emit('pick', [start, end])
+          }
+        }, {
+          text: this.$t('action.lastThreeMonths'),
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
+            picker.$emit('pick', [start, end])
+          }
+        }]
+      },
+      /** 表格数据 */
+      tableData: [],
+      pageData: [],
+      loading: false,
+      multipleSelection: [],
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+        fixedCondition: 'channel_id = ' + this.$route.params.id,
+        sort: 'id',
+        dir: 'desc'
+      },
+      searchDateRange: [],
+      columnDefs: null, // 新表格
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      rowSelection: null,
+      showViewer: false,
+      timer: '',
+      audio: new Audio(),
+      src: '',
+      // dialogVisible: false
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 130
+    }
+  },
+  beforeMount() {
+    this.gridOptions = {
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 50,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 200 },
+      { headerName: this.$t('channel.channelName'), field: 'channel_name', sortable: false, filter: false , width: 200},
+      { headerName: this.$t('channel.senderMemberName'), field: 'sender_member_name', sortable: false, filter: false , width: 200 },
+      { headerName: this.$t('channel.senderTime'), field: 'send_time', sortable: true, valueFormatter: this.formatterDate, filter: false , width: 200 },
+      { headerName: this.$t('channel.audioPath'), field: 'audio_path', sortable: false, filter: false , width: 300 },
+      {
+        headerName: this.$t('channel.play'), field: 'id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.playIm,
+            label: this.$t('channel.play'),
+            buttonType: 'primary',
+            buttonSize: 'mini'
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        width: 100,
+        resizable: false,
+        sortable: false
+      }
+    ]
+    this.defaultColDef = {
+      sortable: true,
+      resizable: true,
+      filter: true,
+      filterParams: {
+        debounceMs: 200,
+        newRowsAction: 'keep',
+      }
+    }
+    this.rowSelection = 'multiple'
+  },
+  mounted() {
+    // window.onresize = this.windowResize()
+    this.gridApi = this.gridOptions.api
+    this.getList()
+  },
+  methods: {
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.getList()
+    },
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.getList()
+    },
+    /** 加载通知列表 */
+    getList() {
+      this.loading = true
+      const param = this.MixinClone(this.params)
+      this.gridApi.showLoadingOverlay()
+      API_ChannelImHistory.getList(param).then(response => {
+        this.loading = false
+        this.tableData = response.data
+        this.pageData = {
+          page_no: response.page_no,
+          page_size: response.page_size,
+          data_total: response.data_total
+        }
+        this.$nextTick(() => {
+          const node = this.gridApi.getDisplayedRowAtIndex(0)
+          if (node !== null && node !== undefined) {
+            node.setSelected(true)
+          }
+        })
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    /** 处理搜索 */
+    handlerSearch(keywords) {
+      this.params.filerStr = keywords
+      this.getList()
+    },
+    /** 处理排序 */
+    tableSort(column) {
+      if (column.order !== null) {
+        this.params.sort = column.prop
+        this.params.dir = column.order === 'ascending' ? 'asc' : 'desc'
+      } else {
+        this.params.sort = null
+        this.params.dir = null
+      }
+      this.getList()
+    },
+    filterModifed(param) {
+      const model = param.api.getFilterModel()
+      // 连接状态不经过服务器过滤
+      delete model.online_state
+      this.params.filter = JSON.stringify(model)
+      this.getList()
+    },
+    gridSortChange(param) {
+      const columnState = param.columnApi.getColumnState()
+      // 排序状态
+      const sortState = columnState.filter(function(s) {
+        return s.sort != null
+      }).map(function(s) {
+        return {
+          colId: s.colId,
+          sort: s.sort,
+          sortIndex: s.sortIndex
+        }
+      }).sort(function(a, b) {
+        return a.sortIndex - b.sortIndex
+      })
+      if (sortState.length > 0) {
+        if (sortState.length === 1) {
+          this.params.sort = sortState[0].colId
+          this.params.dir = sortState[0].sort
+        } else {
+          let sortstring = ''
+          sortState.forEach(function(item) {
+            sortstring += item.colId + ' ' + item.sort + ','
+          })
+          this.params.sort = sortstring.substring(0, sortstring.length - 1)
+          this.params.dir = ' '
+        }
+      } else {
+        delete this.params.sort
+        delete this.params.dir
+      }
+      this.getList()
+    },
+    formatterDate(params) {
+      return unixToDate(params.value)
+    },
+    dateRangeChange(value) {
+      if (value && value.length > 0) {
+        this.params.start_date = value[0]
+        this.params.end_date = value[1]
+      } else {
+        delete this.params.start_date
+        delete this.params.end_date
+      }
+      this.params.page_no = 1
+      this.getList()
+    },
+    playIm(params) {
+      console.log(params.audio_path)
+      console.log(DeviceUrl + '/' + params.audio_path)
+      this.audio.src = DeviceUrl + '/' + params.audio_path
+      this.audio.play();
+
+      // this.src = DeviceUrl + '/' + params.audio_path
+      // this.play();
+    },
+    // play() {
+    //   this.dialogVisible = true
+    //   this.$refs.audio.play()
+    // },
+    // stop() {
+    //   this.dialogVisible = false
+    //   this.$refs.audio.pause()
+    //   this.$refs.audio.currentTime = 0
+    // }
+  }
+}
+</script>
+
+<style type="text/scss" scoped>
+.tablewen{
+  width:100%;
+  border-collapse:collapse;
+  border: 1px solid #a5b6c8;
+  margin-bottom: 30px;
+  line-height: 40px;
+}
+.tablewen td{
+  font-size: 14px;
+  -webkit-margin-before: 0.83em;
+  -webkit-margin-after: 0.83em;
+  -webkit-margin-start: 0px;
+  -webkit-margin-end: 0px;
+  font-weight: bold;
+}
+.tablewen td span{
+  font-size: 0.8em;
+  -webkit-margin-before: 0.83em;
+  -webkit-margin-after: 0.83em;
+  -webkit-margin-start: 0px;
+  -webkit-margin-end: 0px;
+  font-weight: bold;
+  color: #8c939d;
+  margin-left: 5px;
+}
+.tablewen .td1{
+  width:15%;
+}
+.tablewen .td2{
+  width:20%;
+}
+</style>

+ 104 - 45
src/views/ncs-channel/index.vue

@@ -89,10 +89,11 @@ import { unix2Date } from '@/utils/Foundation'
 import * as API_Clerk from '@/api/ncs_clerk'
 import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
 import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
+import ButtonCellRenderList from "@/components/AgGridCellRender/ButtonCellRenderList";
 
 export default {
   name: 'Index',
-  components: { ButtonCellRender, ListFilter, RadioFilter },
+  components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter },
   data() {
     return {
       tableData: [],
@@ -171,58 +172,113 @@ export default {
         width: 200,
         valueFormatter: this.unixDateFormatter
       },
-      {
-        headerName: this.$t('action.edit'), field: 'id',
-        cellRendererFramework: 'ButtonCellRender',
-        cellRendererParams: {
-          onClick: this.handEdit,
-          label: this.$t('action.edit'),
-          buttonType: 'primary',
-          buttonSize: 'mini'
-        },
-        filter: false,
-        pinned: 'right',
-        lockPinned: true,
-        width: 100,
-        resizable: false,
-        sortable: false
-      },
-
-      {
-        headerName: this.$t('channel.subscribeManage'), field: 'id',
-        cellRendererFramework: 'ButtonCellRender',
-        cellRendererParams: {
-          onClick: this.manageSubscribe,
-          label: this.$t('channel.subscribeManage'),
-          buttonType: 'success',
-          buttonSize: 'mini'
-        },
-        filter: false,
-        pinned: 'right',
-        lockPinned: true,
-        width: 100,
-        resizable: false,
-        sortable: false
-      },
-
-      {
-        headerName: this.$t('action.delete'), field: 'id',
-        cellRendererFramework: 'ButtonCellRender',
+      { headerName: this.$t('action.handle'), field: 'id',
+        cellRendererFramework: 'ButtonCellRenderList',
         cellRendererParams: param => {
           return {
-            onClick: this.deleteSingle,
-            label: this.$t('action.delete'),
-            buttonType: 'danger',
-            buttonSize: 'mini'
-          }
+            list: [
+              {
+                onClick: this.handleEdit,
+                label: this.$t('action.edit'),
+                buttonType: 'primary',
+                buttonSize: 'mini'
+              },
+              {
+                onClick: this.manageSubscribe,
+                label: this.$t('channel.subscribeManage'),
+                buttonType: 'warning',
+                buttonSize: 'mini',
+              },
+              {
+                onClick: this.channelImHistory,
+                label: this.$t('channel.channelImHistory'),
+                buttonType: 'success',
+                buttonSize: 'mini',
+              },
+              {
+                onClick: this.deleteSingle,
+                label: this.$t('action.delete'),
+                buttonType: 'danger',
+                buttonSize: 'mini',
+              }
+            ]}
         },
+        filter: false,
         pinned: 'right',
         lockPinned: true,
-        width: 100,
+        minWidth: this.$i18n.locale === 'zh' ? 310 : 340,
         resizable: false,
-        filter: false,
         sortable: false
       }
+      // {
+      //   headerName: this.$t('action.edit'), field: 'id',
+      //   cellRendererFramework: 'ButtonCellRender',
+      //   cellRendererParams: {
+      //     onClick: this.handEdit,
+      //     label: this.$t('action.edit'),
+      //     buttonType: 'primary',
+      //     buttonSize: 'mini'
+      //   },
+      //   filter: false,
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   width: 100,
+      //   resizable: false,
+      //   sortable: false
+      // },
+      //
+      // {
+      //   headerName: this.$t('channel.subscribeManage'), field: 'id',
+      //   cellRendererFramework: 'ButtonCellRender',
+      //   cellRendererParams: {
+      //     onClick: this.manageSubscribe,
+      //     label: this.$t('channel.subscribeManage'),
+      //     buttonType: 'success',
+      //     buttonSize: 'mini'
+      //   },
+      //   filter: false,
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   width: 100,
+      //   resizable: false,
+      //   sortable: false
+      // },
+      //
+      // {
+      //   headerName: "留言历史", field: 'id',
+      //   cellRendererFramework: 'ButtonCellRender',
+      //   cellRendererParams: {
+      //     onClick: this.channelImHistory,
+      //     label: "留言历史",
+      //     buttonType: 'success',
+      //     buttonSize: 'mini'
+      //   },
+      //   filter: false,
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   width: 100,
+      //   resizable: false,
+      //   sortable: false
+      // },
+      //
+      // {
+      //   headerName: this.$t('action.delete'), field: 'id',
+      //   cellRendererFramework: 'ButtonCellRender',
+      //   cellRendererParams: param => {
+      //     return {
+      //       onClick: this.deleteSingle,
+      //       label: this.$t('action.delete'),
+      //       buttonType: 'danger',
+      //       buttonSize: 'mini'
+      //     }
+      //   },
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   width: 100,
+      //   resizable: false,
+      //   filter: false,
+      //   sortable: false
+      // }
     ]
     this.defaultColDef = {
       sortable: true,
@@ -457,6 +513,9 @@ export default {
       this.subscribeTitle = row.channel_name + this.$t('channel.subscribeManage')
       this.formSubscribe = true
     },
+    channelImHistory(row) {
+      this.$router.push({ name: 'channelImHistory', params: { id: row.id, callback: this.getList() }})
+    },
     getEmployees() {
       const _this = this
       _this.nurses = []

+ 15 - 2
src/views/ncs-chars/index.vue

@@ -166,6 +166,7 @@ import CountTo from 'vue-count-to'
 import * as API_interaction from '@/api/ncs_interaction'
 import Storage from '@/utils/storage'
 import myInfo from '@/views/ncs-chars/info'
+import {TCP_TYPE} from "@/utils/enum/TcpTypeEnum";
 
 export default {
   name: 'Index',
@@ -224,6 +225,8 @@ export default {
         } else {
           _this.partTotal.count = res.count
           _this.partTotal.noCount = res.noCount
+          _this.btListNameToStr(res.btList)
+          _this.btListNameToStr(res.noBtList)
           _this.buildTable(res.btList, res.noBtList)
           _this.buildBtChart(res.btList, res.noBtList) // 饼图
           _this.buildChart(res.dataList, res.tilStr, res.xAxis, 'chart', this.$t('interaction.dataCensus'))
@@ -236,10 +239,12 @@ export default {
       this.dataList.forEach(item => {
         let count = 0
         let noCount = 0
+        // const data = btList.find(p => TCP_TYPE.getDescFromValue(p.name) === item)
         const data = btList.find(p => p.name === item)
         if (data) {
           count = data.value
         }
+        // const noData = noBtList.find(p => TCP_TYPE.getDescFromValue(p.name) === item)
         const noData = noBtList.find(p => p.name === item)
         if (noData) {
           noCount = noData.value
@@ -258,7 +263,7 @@ export default {
       if (dataList.length > 0) {
         dataList.forEach((item, index) => {
           const d = {
-            name: tilStr[index],
+            name: TCP_TYPE.getDescFromValue(tilStr[index]),
             type: 'line',
             stack: this.$t('interaction.total') + index,
             data: item,
@@ -284,7 +289,7 @@ export default {
         //   top: 'bottom'
         // },
         legend: {
-          data: tilStr
+          data: TCP_TYPE.getDescFromValue(tilStr)
         },
         grid: {
           left: '3%',
@@ -491,6 +496,8 @@ export default {
           return this.$t('tcpType.ENTRACEGUARD')
         case 'SOS':
           return this.$t('tcpType.SOS')
+        case 'PHONE':
+          return this.$t('tcpType.PHONE')
         default:
           return this.$t('tcpType.UNKNOWN')
       }
@@ -589,6 +596,12 @@ export default {
           return v[j]
         }
       }))
+    },
+    btListNameToStr(btList) {
+      console.log(btList)
+      btList = btList.forEach(p => p.name = TCP_TYPE.getDescFromValue(p.name))
+      // console.log(btList)
+      // return btList
     }
   }
 

+ 9 - 3
src/views/ncs-device/components/deviceManager.vue

@@ -912,7 +912,6 @@ export default {
     handleEdit(params) {
       this.getRoles({ page_size: 200, page_no: 1, fixedCondition: ' shop_id = -1', sort: ' role_id', dir: 'desc' })
       this.getDevices(params.part_id)
-      this.getSosDeviceSetting(params.id)
       this.deviceTypeChangeToFrameTypeChange(params.device_type)
       this.hasRoleId = params.device_type === DEVICE_TYPE.NURSE_WATCH
       this.hasAudioId = params.device_type === DEVICE_TYPE.SIMULATE_BED_DEVICE ||
@@ -920,9 +919,16 @@ export default {
                         params.device_type === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON ||
                         params.device_type === DEVICE_TYPE.SIMULATE_DOOR_LIGHT
       this.isVitalSigns = params.device_type === DEVICE_TYPE.VITAL_SIGNS_DEVICE
-      this.hasSosDeviceSettings = params.device_type === DEVICE_TYPE.ALARM_BODY_INDUCTIVE ||
+
+      if (params.device_type === DEVICE_TYPE.ALARM_BODY_INDUCTIVE ||
           params.device_type === DEVICE_TYPE.DOOR_LOCK ||
-          params.device_type === DEVICE_TYPE.ALARM_RESTRAINT_BAND
+          params.device_type === DEVICE_TYPE.ALARM_RESTRAINT_BAND) {
+        this.hasSosDeviceSettings = true
+        this.getSosDeviceSetting(params.id)
+      } else {
+        this.hasSosDeviceSettings = false
+      }
+
       this.isLedDevice = params.device_type === DEVICE_TYPE.LED_SCREEN
       this.deviceModel = {
         ...params

+ 167 - 5
src/views/ncs-interaction/index.vue

@@ -61,6 +61,62 @@
         @current-change="handlePageCurrentChange"
       />
     </ag-grid-layout>
+      <el-dialog :v-loading="this.loading" :title="this.$t('interaction.recordPlay')" :visible.sync="dialogVisible" :before-close="stop" width="70%">
+        <template>
+          <el-row v-if="this.streamingType">
+            <el-col :span="12">
+              <video
+                :src="this.srcStreaming1"
+                autoplay="autoplay"
+                controls="controls"
+                ref="video1"
+                style="width: 98%"
+              >
+              </video>
+            </el-col>
+
+            <el-col :span="12">
+              <video
+                :src="this.srcStreaming2"
+                autoplay="autoplay"
+                controls="controls"
+                ref="video2"
+                style="width: 98%"
+              >
+              </video>
+            </el-col>
+          </el-row>
+
+          <el-row v-else>
+
+            <el-col :span="12">
+              <audio
+                  :src="this.srcStreaming1"
+                  autoplay="autoplay"
+                  controls="controls"
+                  ref="audio1"
+                  style="width: 98%"
+              >
+              </audio>
+            </el-col>
+
+            <el-col :span="12">
+              <audio
+                  :src="this.srcStreaming2"
+                  autoplay="autoplay"
+                  controls="controls"
+                  ref="audio2"
+                  style="width: 98%"
+              >
+              </audio>
+            </el-col>
+          </el-row>
+
+          <div slot="footer" class="dialog-footer" style="text-align: center">
+            <el-button ref="play" type="primary" @click="onclick('onclick')"> {{ this.buttonStr }} </el-button>
+          </div>
+        </template>
+      </el-dialog>
 
   </div>
 </template>
@@ -69,12 +125,18 @@
 import * as API_interaction from '@/api/ncs_interaction'
 import { unixToDate } from '@/utils/Foundation'
 import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
-import { returnDeviceType } from '@/utils/device_type'
 import {DEVICE_TYPE} from "@/utils/enum/DeviceTypeEnum";
 import {TCP_TYPE} from "@/utils/enum/TcpTypeEnum";
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
+import RecordButtonCellRender from "@/components/AgGridCellRender/RecordButtonCellRender";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter";
+import * as API_Part from "@/api/ncs_partInfo";
+const DeviceUrl = domain.DeviceUrl
 
 export default {
   name: 'Index',
+  components: { ButtonCellRender, RadioFilter, ListFilter, RecordButtonCellRender },
   data() {
     return {
       pickerOptions: {
@@ -128,7 +190,16 @@ export default {
       tcpActionTransfer: [
         { key: 'TCP反馈', value: 'CALLBACK' }
       ],
-      queryResult: '-1'
+      queryResult: '-1',
+      srcStreaming1: '',
+      srcStreaming2: '',
+      stream1: '',
+      stream2: '',
+      beginSeconds: 0,
+      buttonStr: this.$t('action.play'),
+      dialogVisible: false,
+      streamingType: true,
+      recordDir: '',
     }
   },
   computed: {
@@ -138,6 +209,15 @@ export default {
   },
   beforeMount() {
     this.gridOptions = {
+      // onCellClicked: function (event) {
+      //   console.log(event)
+      //   if (event.data.action_type === TCP_TYPE.VOICE ||
+      //       event.data.action_type === TCP_TYPE.VIDEO ||
+      //       event.data.action_type === TCP_TYPE.PHONE
+      //   ) {
+      //     this.getStreaming(event.data);
+      //   }
+      // }
     }
     this.columnDefs = [
       {
@@ -154,10 +234,25 @@ export default {
       { headerName: this.$t('interaction.toMemberName'), field: 'toMemberName', sortable: false, valueFormatter: this.formatterToName, minWidth: 150 },
       { headerName: this.$t('interaction.actionType'), field: 'action_type', sortable: true, valueFormatter: this.formatterType, width: 100 },
       { headerName: this.$t('interaction.actionEnd'), field: 'action_end', sortable: true, cellRenderer: this.formatterResult, width: 100 },
-      { headerName: this.$t('interaction.data'), field: 'data', sortable: true, width: 120 },
+      { headerName: this.$t('interaction.data'), field: 'data',
+        cellRendererFramework: 'RecordButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.getStreaming,
+            icon: 'el-icon-caret-right',
+            buttonType: 'primary',
+            buttonSize: 'mini',
+            value: param.value,
+            show: param.data.action_type === TCP_TYPE.VOICE ||
+                param.data.action_type === TCP_TYPE.VIDEO
+          }
+        },
+        sortable: true,
+        width: 120
+      },
       { headerName: this.$t('interaction.createDate'), field: 'create_date', sortable: true, valueFormatter: this.formatterDate, width: 150 },
       { headerName: this.$t('interaction.fromDevice'), field: 'from_device_type', sortable: true, valueFormatter: this.formatterDeviceType, width: 120 },
-      { headerName: this.$t('interaction.toDevice'), field: 'to_device_type', sortable: true, valueFormatter: this.formatterDeviceType, width: 120 }
+      { headerName: this.$t('interaction.toDevice'), field: 'to_device_type', sortable: true, valueFormatter: this.formatterDeviceType, width: 120 },
     ]
     this.defaultColDef = {
       filter: false,
@@ -177,6 +272,7 @@ export default {
     window.onresize = this.windowResize
     this.gridApi = this.gridOptions.api
     this.getList()
+    // this.$refs.video2.addEventListener("pause", this.pause)
   },
   methods: {
     windowResize() {
@@ -439,7 +535,73 @@ export default {
           return v[j]
         }
       }))
-    }
+    },
+    getStreaming(params) {
+      this.loading = true
+
+      // const url = '/upload/rec/1.webm'
+      // const url2 = '/upload/rec/1.webm'
+      API_interaction.getStreaming(params.part_id, params.id).then(res => {
+        this.loading = false
+        if (res.length !== 0) {
+          if (res[0].endsWith("webm")) {
+            this.streamingType = true
+          } else if (resp[0].endsWith("opus")) {
+            this.streamingType = false
+          }
+
+          this.srcStreaming1 = DeviceUrl + res[0]
+          this.srcStreaming2 = DeviceUrl + res[1]
+          console.log(this.srcStreaming1)
+          console.log(this.srcStreaming2)
+          this.dialogVisible = true
+        } else {
+          this.$message(this.$t('action.noFile'))
+        }
+      }).catch(response => {
+        this.$message({
+          type: 'info',
+          message: response.message
+        })
+      })
+    },
+    onclick() {
+      if (this.buttonStr === this.$t('action.play')) {
+        this.buttonStr = this.$t('action.pause')
+
+        // const time = this.$refs.video1.duration - this.$refs.video2.duration  // 总时长差
+        if (this.streamingType) {
+          this.$refs.video1.play()
+          this.$refs.video2.play()
+        } else {
+          this.$refs.audio1.play()
+          this.$refs.audio2.play()
+        }
+      } else if (this.buttonStr === this.$t('action.pause')) {
+        this.buttonStr = this.$t('action.play')
+        if (this.streamingType) {
+          this.$refs.video1.pause()
+          this.$refs.video2.pause()
+        } else {
+          this.$refs.audio1.pause()
+          this.$refs.audio2.pause()
+        }
+      }
+    },
+    stop() {
+      if (this.streamingType) {
+        this.$refs.video1.currentTime = 0
+        this.$refs.video2.currentTime = 0
+        this.$refs.video1.pause()
+        this.$refs.video2.pause()
+      } else {
+        this.$refs.audio1.currentTime = 0
+        this.$refs.audio2.currentTime = 0
+        this.$refs.audio1.pause()
+        this.$refs.audio2.pause()
+      }
+      this.dialogVisible = false
+    },
   }
 }
 </script>

+ 133 - 0
src/views/ncs-led/ledManager.vue

@@ -0,0 +1,133 @@
+<template>
+  <div>
+    <el-card style="margin: 15px">
+      <el-form ref="editform" :rules="rules" label-width="140px" :model="formmodel">
+        <fieldset>
+          <legend>{{ this.$t('tab.ledDevice') }}</legend>
+
+          <el-row>
+            <el-form-item :label="this.$t('deviceManage.ledUpdateDefaultProgram')">
+              <el-radio v-model="isOnlyTime" :label="false">{{ this.$t('deviceManage.ledOnlyTime') }}</el-radio>
+              <el-radio v-model="isOnlyTime" :label="true">{{ this.$t('deviceManage.ledAddCustom') }}</el-radio>
+            </el-form-item>
+          </el-row>
+
+          <el-row v-if="isOnlyTime">
+<!--          <el-row>-->
+            <el-col :span="18">
+              <el-form-item :label="this.$t('deviceManage.ledAddCustom')">
+                <el-input v-model="formmodel.addCustom" :maxlength="50" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row>
+            <el-form-item>
+              <el-col :span="4">
+                <el-button type="primary" @click="timing">{{ this.$t('deviceManage.ledTiming') }}</el-button>
+              </el-col>
+
+              <el-col :span="4">
+                <el-button type="primary" @click="updateDefaultProgram">{{ this.$t('deviceManage.ledUpdateDefaultProgram') }}</el-button>
+              </el-col>
+
+              <el-col :span="4">
+                <el-button type="primary" @click="deleteAllPrograms">{{ this.$t('deviceManage.ledRemoveAllProgram') }}</el-button>
+              </el-col>
+
+              <el-col :span="4">
+                <el-button type="primary" @click="powerOn">{{ this.$t('deviceManage.ledPowerOn') }}</el-button>
+              </el-col>
+
+              <el-col :span="4">
+                <el-button type="primary" @click="powerOff">{{ this.$t('deviceManage.ledPowerOff') }}</el-button>
+              </el-col>
+
+              <el-col :span="4">
+                <el-button type="primary" @click="powerRestart">{{ this.$t('deviceManage.ledRestart') }}</el-button>
+              </el-col>
+            </el-form-item>
+          </el-row>
+        </fieldset>
+      </el-form>
+    </el-card>
+  </div>
+</template>
+
+<script>
+
+import * as API_Led from '@/api/ncs_led'
+export default {
+  name: "ledManager",
+
+  data() {
+    return {
+      formmodel: {},
+      rules: {},
+      isOnlyTime: false,
+      // addCustom: '',
+      shop_id: this.$store.getters.partId
+    }
+  },
+  async mounted() {
+    this.isOnlyTime === false
+  },
+  methods: {
+    updateDefaultProgram() {
+      let text;
+      if (this.isOnlyTime) {
+        text = this.formmodel.addCustom
+      }
+      const params = {}
+      params.shop_id = this.shop_id
+      params.text = text
+      API_Led.updateDefaultProgramShopId(params).then(r => {
+        this.$message.success(this.$t('action.saveSuccess'))
+      })
+    },
+    powerOn() {
+      const params = {}
+      params.shop_id = this.shop_id
+      params.on_off = 0
+      API_Led.powerOnOffByShopId(params).then(r => {
+        this.$message.success(this.$t('action.saveSuccess'))
+      })
+    },
+    powerOff() {
+      const params = {}
+      params.shop_id = this.shop_id
+      params.on_off = 1
+      API_Led.powerOnOffByShopId(params).then(r => {
+        this.$message.success(this.$t('action.saveSuccess'))
+      })
+    },
+    powerRestart() {
+      const params = {}
+      params.shop_id = this.shop_id
+      params.on_off = 2
+      API_Led.powerOnOffByShopId(params).then(r => {
+        this.$message.success(this.$t('action.saveSuccess'))
+      })
+    },
+    timing() {
+      const params = {}
+      params.shop_id = this.shop_id
+      API_Led.timing(params).then(r => {
+        this.$message.success(this.$t('action.saveSuccess'))
+      })
+    },
+    deleteAllPrograms() {
+      const params = {}
+      params.shop_id = this.shop_id
+      params.text = null
+      API_Led.removeAllProgramByShopId(params).then(r => {
+        this.$message.success(this.$t('action.saveSuccess'))
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 22 - 0
src/views/ncs-orginazition/components/partInfoEdit.vue

@@ -306,6 +306,25 @@
                 <el-checkbox v-model="formmodel.two_color_door_light_valid" :true-label="1" :false-label="0">{{ this.$t('partInfo.support') }}</el-checkbox>
               </el-form-item>
             </el-col>
+
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.customerNameHidden')" prop="customer_name_hidden">
+                <el-checkbox v-model="formmodel.customer_name_hidden" :true-label="1" :false-label="0">{{ this.$t('partInfo.hidden') }}</el-checkbox>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+
+          <el-row>
+            <el-form-item :label="this.$t('partInfo.channelImHistoryStoreDays')" prop="channel_im_history_store_days">
+              <el-input-number v-model="formmodel.channel_im_history_store_days" :min="1" :max="1000" :label="this.$t('partInfo.channelImHistoryStoreDays')" />
+            </el-form-item>
+
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.recordEnabled')" prop="record_enabled">
+                <el-checkbox v-model="formmodel.record_enabled" :true-label="1" :false-label="0">{{ this.$t('partInfo.recordAble') }}</el-checkbox>
+              </el-form-item>
+            </el-col>
           </el-row>
 
 
@@ -624,6 +643,9 @@ export default {
                 customize_role_call_third: 0,
                 customize_role_call_fourth: 0,
                 customize_role_call_fifth: 0,
+                customer_name_hidden: 0,
+                channel_im_history_store_days: 30,
+                record_enabled: false,
                 auto_accept: 0,
                 door_nurse_title: '呼叫护士',
                 door_nurse_valid: 1,

+ 30 - 25
src/views/ncs-orginazition/device-frame.vue

@@ -2,12 +2,12 @@
   <el-container style="height:850px; border: 1px solid #eee">
     <el-aside width="25%" style="background-color: rgb(255,255,255);border: 1px solid #eee">
       <div>
-        <el-input v-model="searchDeviceStr" placeholder="输入搜索" clearable @change="clickSearch">
-          <el-select v-model="frameType" slot="prepend" placeholder="请选择设备位置级别" @change="changeFrameType">
-            <el-option label="全部" value="all"></el-option>
-            <el-option label="科室" value="part"></el-option>
-            <el-option label="房间" value="room"></el-option>
-            <el-option label="床位" value="bed"></el-option>
+        <el-input v-model="searchDeviceStr" :placeholder="$t('action.search')" clearable @change="clickSearch">
+          <el-select v-model="frameType" slot="prepend" :placeholder="$t('deviceManage.deviceLocationLevel')" @change="changeFrameType">
+            <el-option :label="$t('action.all')" value="all"></el-option>
+            <el-option :label="$t('frameManage.part')" value="part"></el-option>
+            <el-option :label="$t('frameManage.room2')" value="room"></el-option>
+            <el-option :label="$t('frameManage.bed2')" value="bed"></el-option>
           </el-select>
           <el-button slot="append" size="mini" icon="el-icon-search" @click="clickSearch"></el-button>
         </el-input>
@@ -22,13 +22,14 @@
     <el-container>
       <el-header style="font-size: 12px; margin-top: 10px;">
         <div style="text-align: left; float: left">
-          <el-button type="success" @click="onekeySave" :loading="isSave">一键分配</el-button>
-          <el-button type="danger" plain @click="onekeyDel">一键重置</el-button>
+          <el-button type="success" @click="onekeySave" :loading="isSave">{{ $t('deviceManage.assignment') }}</el-button>
+          <el-button type="danger" plain @click="onekeyDel">{{ $t('deviceManage.reset') }}</el-button>
         </div>
         <div style="text-align: right">
-          <el-switch v-model="openType" active-text="折叠显示" inactive-text="卡片显示" style="margin-right: 20px;"></el-switch>
-          <el-button type="success" icon="el-icon-check" :loading="isSave" :disabled="needUpdateList.length === 0" @click="saveUpdate">保存</el-button>
-          <el-button icon="el-icon-close" :disabled="needUpdateList.length === 0" @click="canle">取消</el-button>
+          <el-switch v-model="openType" :active-text="$t('deviceManage.collapse')" :inactive-text="$t('deviceManage.card')" style="margin-right: 20px;"></el-switch>
+          <el-button type="success" icon="el-icon-check" :loading="isSave" :disabled="needUpdateList.length === 0" @click="saveUpdate">
+            {{ $t('action.save') }}</el-button>
+          <el-button icon="el-icon-close" :disabled="needUpdateList.length === 0" @click="canle">{{ $t('action.cancel') }}</el-button>
         </div>
       </el-header>
 
@@ -38,7 +39,7 @@
           <el-col :span="24">
             <el-card class="box-card" shadow="hover" :body-style="{ padding: '0px', margin: '0px' }">
               <div slot="header" class="clearfix">
-                <span>{{ framesAndDevices.full_name }}-{{ framesAndDevices.device_size }}台设备</span>
+                <span>{{ framesAndDevices.full_name }}-{{ framesAndDevices.device_size }}{{ $t('deviceManage.devices') }}</span>
                 <!--                <el-button style="float: right; padding: 3px 0" type="text">操作按钮</el-button>-->
               </div>
               <div :class="boolPart ? 'mybg' : ''" style="width: 100%; height: 100%; padding: 15px 0px 10px 0px; min-height: 80px;">
@@ -67,7 +68,8 @@
               <div slot="title" style="width: 100%;min-height: 50px;">
                 <div style="font-size: 15px;float: left;width: 10%;" :class="boolRoom ? 'mybg' : ''">{{ item.full_name }}</div>
                 <div :class="boolRoom ? 'mybg' : ''"  style="margin: 0;float: left;width: 85%;">
-                  <div v-if="item.device_dos.length === 0" style="float: left;height: 100%"><el-tag effect="plain" type="info">房间无设备</el-tag></div>
+                  <div v-if="item.device_dos.length === 0" style="float: left;height: 100%"><el-tag effect="plain" type="info">
+                    {{ $t('deviceManage.roomNoDevice') }}</el-tag></div>
                   <draggable class="selected-list" v-model="item.device_dos" tag="div" :options="dragOptions" :disabled="boolRoom" @start="roomMove" @end="onEnd" @remove="otherRemove">
                     <el-tag v-for="(t, i) in item.device_dos" :key="i" :type="getColor(i)" style="margin-bottom: 5px;"> {{ t.name }}</el-tag>
                   </draggable>
@@ -78,7 +80,8 @@
                   <div class="clearfix" :class="boolBed ? 'mybg' : ''" style="margin: 0;padding: 15px 0px 10px 0px">
                     <div style="font-size: 15px;float: left;width: 10%;margin-left: 5px;">{{ t.full_name }}</div>
                     <div style="margin: 0;float: left;width: 85%;">
-                      <div v-if="t.device_dos.length === 0" style="float: left;height: 100%"><el-tag effect="plain" type="info">床位无设备</el-tag></div>
+                      <div v-if="t.device_dos.length === 0" style="float: left;height: 100%"><el-tag effect="plain" type="info">
+                        {{ $t('deviceManage.bedNoDevice') }}</el-tag></div>
                       <draggable class="selected-list" tag="div" v-model="t.device_dos" :options="dragOptions" :disabled="boolBed" style="height: 100%" @start="bedMove" @end="onEnd" @remove="otherRemove">
                         <el-tag v-for="(tt, ii) in t.device_dos" :key="ii" :type="getColor(ii)"> {{ tt.name }}</el-tag>
                       </draggable>
@@ -96,7 +99,8 @@
               <div slot="header" :class="boolRoom ? 'mybg' : ''" class="clearfix" style="width: 100%;min-height: 40px;">
                 <div style="font-size: 15px;float: left;width: 10%;margin-top: 5px;">{{ item.full_name }}</div>
                 <div style="margin: 0;float: left;width: 85%;">
-                  <div v-if="item.device_dos.length === 0" style="float: left;height: 100%"><el-tag effect="plain" type="info">房间无设备</el-tag></div>
+                  <div v-if="item.device_dos.length === 0" style="float: left;height: 100%"><el-tag effect="plain" type="info">
+                    {{ $t('deviceManage.roomNoDevice') }}</el-tag></div>
                   <draggable class="selected-list" v-model="item.device_dos" tag="div" :options="dragOptions" :disabled="boolRoom" @start="roomMove" @end="onEnd" @remove="otherRemove">
                     <el-tag v-for="(t, i) in item.device_dos" :key="i" :type="getColor(i)" style="margin-bottom: 5px;"> {{ t.name }}</el-tag>
                   </draggable>
@@ -109,7 +113,8 @@
                   <div class="clearfix" :class="boolBed ? 'mybg' : ''" style="margin: 0;padding: 15px 0 10px 0;min-height: 40px">
                     <div style="font-size: 15px;float: left;width: 10%;margin: 5px">{{ t.full_name }}</div>
                     <div style="margin: 0;float: left;width: 85%;">
-                      <div v-if="t.device_dos.length === 0" style="float: left;height: 100%"><el-tag effect="plain" type="info">床位无设备</el-tag></div>
+                      <div v-if="t.device_dos.length === 0" style="float: left;height: 100%"><el-tag effect="plain" type="info">
+                        {{ $t('deviceManage.bedNoDevice') }}</el-tag></div>
                       <draggable class="selected-list" tag="div" v-model="t.device_dos" :options="dragOptions" :disabled="boolBed" style="height: 100%" @start="bedMove" @end="onEnd" @remove="otherRemove">
                         <el-tag v-for="(tt, ii) in t.device_dos" :key="ii" :type="getColor(ii)"> {{ tt.name }}</el-tag>
                       </draggable>
@@ -390,7 +395,7 @@ export default {
         this.isSave = false
         this.API_getDeviceList()
         this.API_getFrameAndDevice()
-        this.$message.success('保存成功!')
+        this.$message.success(this.$t('action.saveSuccess'))
       })
     },
     // 取消
@@ -406,7 +411,7 @@ export default {
       this.isSave = true
       if (this.deviceList.length === 0) {
         this.isSave = false
-        this.$message.info('没有空余分配的设备!')
+        this.$message.info(this.$t('deviceManage.assignmentMsg'))
         return
       }
       this.canle()
@@ -430,7 +435,7 @@ export default {
       // }
       if (this.framesAndDevices.device_size > this.framesAndDevices.device_dos.length) {
         this.isSave = false
-        this.$message.info('房间及床位有设备,只能自动分配科室级设备!')
+        this.$message.info(this.$t('deviceManage.assignmentMsg2'))
           // let item
           // while(i--){
           //   item = this.deviceList[i]
@@ -443,7 +448,7 @@ export default {
           // }
           return
       }
-      this.$message.info('开始自动分配!')
+      this.$message.info(this.$t('deviceManage.assignmentMsg3'))
       const roomList = this.returnRoomList()
       const groupBy = (arr, func) =>
           arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
@@ -479,23 +484,23 @@ export default {
       })
       this.isSave = false
       this.changeDeviceList = this.deviceList
-      this.$alert('自动分配已完成,全级别设备需手动分配,分配完成后请点击【保存】!', '提示', {
-        confirmButtonText: '确定',
+      this.$alert(this.$t('deviceManage.assignmentMsg4'), this.$t('action.prompt'), {
+        confirmButtonText: this.$t('action.yes'),
         callback: action => {
-          console.log('确定')
+          console.log(this.$t('action.yes'))
         }
       })
     },
     // 一键重置
     onekeyDel() {
       const _this = this
-      this.$confirm('确定要重置所有设备吗?', this.$t('action.tips'), {
+      this.$confirm(this.$t('deviceManage.resetMsg'), this.$t('action.tips'), {
         confirmButtonText: this.$t('action.yes'),
         cancelButtonText: this.$t('action.cancel'),
         type: 'warning'
       }).then(() => {
         delAllDeviceFrame(_this.$route.params.id, _this.$route.params.parent_id).then(res => {
-          _this.$message.success('已成功重置!')
+          _this.$message.success(this.$t('deviceManage.resetMsg2'))
           _this.canle()
           _this.API_getDeviceList()
           _this.API_getFrameAndDevice()

+ 1 - 1
src/views/ncs-orginazition/index.vue

@@ -239,7 +239,7 @@ export default {
         filter: false,
         pinned: 'right',
         lockPinned: true,
-        minWidth: 230,
+        minWidth: this.$i18n.locale === 'zh' ? 230 : 280,
         resizable: false,
         sortable: false },
 

+ 1 - 1
src/views/ncs-sos-device-setting/sos_device_setting.vue

@@ -17,7 +17,7 @@
       <!--工具栏-->
       <div slot="toolbar" class="inner-toolbar">
         <div class="toolbar-search">
-          <en-table-search :placeholder="this.$t('deviceManage.keywords')" @search="handlerSearch" />
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
         </div>
       </div>
       <el-pagination