Prechádzať zdrojové kódy

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

* 'master' of http://git.wdklian.com/allen/ncs_ui:
  485调试优化
  增加433报警器,修复新增亲属会导致用户年龄变更的问题,
  增加485调试功能
  开发出所时间、分娩方式、亲属出生日期,修改病人管理、用户管理的操作配置文件
  增加设备类型
  1、优化地图足迹展示; 2、增加同步语音转换盒功能
  增加护理门灯控制,增加事件转发功能开关
  1、用户地图足迹; 2、其他优化
  用户位置选点及查看所有用户位置分布
  增加tcp的枚举,修复设备类别查询错误的问题,修复交互记录类别查询错误的问题,增加医生主机上传,增加呼叫护士、增援按钮的标题设置
  修改多语言文件冲突的地方
  完成呼叫系统多语言

# Conflicts:
#	public/domain.js
wuyunfeng 3 rokov pred
rodič
commit
56b039e761
52 zmenil súbory, kde vykonal 2774 pridanie a 1005 odobranie
  1. 0 3
      languages/en.js
  2. 227 7
      languages/zh-CN.js
  3. 1 0
      package.json
  4. 4 3
      public/domain.js
  5. 15 0
      src/api/initialize.js
  6. 7 0
      src/api/ncs_customer.js
  7. 8 0
      src/api/ncs_device.js
  8. 10 0
      src/api/ncs_partInfo.js
  9. 15 0
      src/api/user.js
  10. 5 5
      src/components/YearMonthPicker/src/main.vue
  11. 6 0
      src/main.js
  12. 40 0
      src/router/index.js
  13. 9 0
      src/utils/enum/ChildbirthTypeEnum.js
  14. 5 1
      src/utils/enum/DeviceTypeEnum.js
  15. 14 0
      src/utils/enum/RelativeNameTypeEnum
  16. 22 0
      src/utils/enum/TcpTypeEnum.js
  17. 12 0
      src/utils/enum/VitalSignsDeviceEnum.js
  18. 5 4
      src/utils/mixin.js
  19. 0 1
      src/utils/request.js
  20. 43 39
      src/views/calling-board/index.vue
  21. 32 32
      src/views/calling-ncError/index.vue
  22. 2 2
      src/views/calling-setting/index.vue
  23. 81 0
      src/views/customer/allMap.vue
  24. 99 29
      src/views/customer/components/customerManager.vue
  25. 188 93
      src/views/customer/components/elderlyCareManager.vue
  26. 138 82
      src/views/customer/components/patientManager.vue
  27. 2 2
      src/views/customer/customerEdit.vue
  28. 91 0
      src/views/customer/myMap.vue
  29. 31 0
      src/views/customer/myMapHtml.vue
  30. 8 8
      src/views/entrace-guard/index.vue
  31. 62 62
      src/views/hospital/clerkManager.vue
  32. 302 243
      src/views/hospital/ncs_customer/customerManager.vue
  33. 142 120
      src/views/hospital/ncs_device/deviceManager.vue
  34. 2 2
      src/views/hospitalFrame/hospitalFrame.vue
  35. 239 0
      src/views/ncs-485/index.vue
  36. 10 10
      src/views/ncs-auth/compontents/roleEdit.vue
  37. 10 10
      src/views/ncs-auth/superadmin/defaultRoleManager.vue
  38. 2 2
      src/views/ncs-broadcast/index.vue
  39. 51 51
      src/views/ncs-chars/index.vue
  40. 52 24
      src/views/ncs-device/components/deviceManager.vue
  41. 20 20
      src/views/ncs-device/nurse_watch.vue
  42. 518 0
      src/views/ncs-device/user_watch.vue
  43. 3 3
      src/views/ncs-device/watch_location.vue
  44. 9 24
      src/views/ncs-interaction/index.vue
  45. 23 19
      src/views/ncs-menu/menuManager.vue
  46. 15 15
      src/views/ncs-orginazition/components/AppVersionManager.vue
  47. 112 12
      src/views/ncs-orginazition/components/partInfoEdit.vue
  48. 34 34
      src/views/ncs-orginazition/index.vue
  49. 18 13
      src/views/ncs-orginazition/partInfoSetting.vue
  50. 1 1
      src/views/ncs-remark/index.vue
  51. 22 22
      src/views/ncs-system-config/index.vue
  52. 7 7
      src/views/vital-sign/log.vue

+ 0 - 3
languages/en.js

@@ -96,8 +96,5 @@ module.exports = {
     clerkManage: 'clerk manage',
     memberManage: 'member manage',
     mobileDeviceManage: 'mobile device manage'
-  },
-  error: {
-    fromError: '表单填写有误,请检查!'
   }
 }

+ 227 - 7
languages/zh-CN.js

@@ -1,3 +1,4 @@
+const i18n = require('@/utils/i18n')
 module.exports = {
   action: {
     home: '首页',
@@ -7,6 +8,8 @@ module.exports = {
     delete: '删除',
     logout: '退出登录',
     waring: '警告',
+    systemPrompt: '系统提示',
+    prompt: '提示',
     yes: '确定',
     cancel: '取消',
     back: '返回',
@@ -14,6 +17,8 @@ module.exports = {
     details: '详情',
     sort: '排序',
     submit: '提交',
+    settings: '设置',
+    setUp: '设定',
     systemCreate: '系统创建',
     cancelHandle: '取消操作!',
     handleSuccess: '操作成功',
@@ -27,10 +32,15 @@ module.exports = {
     allDeleteSuccess: '清空成功!',
     cancelDelete: '已取消删除',
     pleaseChoiceDelete: '请先勾选需要删除的数据',
+    noChoice: '没有选择任何记录!',
     fromError: '表单填写有误,请检查!',
+    notSpace: ',不能以空格开头',
     editSuccess: '修改成功!',
     addSuccess: '新增成功!',
+    addSuccess2: '添加成功!',
     createSuccess: '创建成功!',
+    settingsSuccess: '设置成功!',
+    setUpSuccess: '设定成功!',
     createTime: '创建时间',
     updateTime: '更新时间',
     save: '保存',
@@ -48,8 +58,12 @@ module.exports = {
     alias: '别名',
     tips: '提示',
     time: '小时',
+    time2: '时',
     minute: '分钟',
+    minute2: '分',
     second: '秒',
+    millisecond: '毫秒',
+    oneSecond: '1秒内',
     Monday: '周一',
     Tuesday: '周二',
     Wednesday: '周三',
@@ -64,10 +78,18 @@ module.exports = {
     colour: '颜色',
     searchDateRange: '搜索时间段',
     to: '至',
+    index: '序号',
+    null: '无',
+    choiceData: '选择日期时间',
     startDate: '开始日期',
     endDate: '结束日期',
     startTime: '开始时间',
     endTime: '结束时间',
+    daily: '按天',
+    monthly: '按月',
+    yearly: '按年',
+    choiceMonth: '选择月份',
+    choiceHYear: '选择年份',
     lastWeek: '最近一周',
     lastMonth: '最近一个月',
     lastThreeMonths: '最近三个月',
@@ -86,16 +108,26 @@ module.exports = {
     uploaderImgMsg2: '请上传宽高比为1:1的图片',
     uploaderImgMsg3: '图片高度必须在100~500之间!',
     uploadFile: '上传文件',
+    uploadAPK: 'APK文件上传',
     uploadFileMsg: '将文件拖到此处,或',
     uploadFileMsg2: '点击上传',
     uploadFileMsg3: '只能上传mp3文件',
     uploadFileMsg4: '上传附件大小不能超过 5MB!',
+    uploadFileMsg5: '只能上传APK文件',
     uploadFileName: '文件名称',
     uploadFileNameMsg: '文件名称不能为空',
     uploadFileUrl: '文件路径',
     uploadFileUrlMsg: '文件路径不能为空,请上传文件',
+    uploadFileUrlMsg2: '请上传APK文件',
     uploadFileAuthor: '上传者',
-    uploadFileDate: '上传日期'
+    uploadFileDate: '上传日期',
+    uploadVersionNo: '版本数字',
+    inputUploadVersionNo: '请输入版本数字',
+    uploadVersionNoMsg: '版本数字不能为空',
+    uploadVersionCode: '版本信息',
+    inputUploadVersionCode: '请输入版本信息',
+    uploadVersionCodeMsg: '版本信息不能为空',
+    initialing: '正在初始化,请稍后...'
   },
   member: {
     face: '头像',
@@ -110,6 +142,7 @@ module.exports = {
     password: '密码',
     inputPassword: '请输入密码!',
     passwordInputMsg: '密码格式有误,密码只能包含字母数字和!#$%^&*.~,字符,长度为6-20位',
+    name: '姓名',
     nickname: '真实姓名',
     inputNickname: '请输入真实姓名',
     nicknameInputMsg: '长度在 2 到 20 个字符',
@@ -123,6 +156,8 @@ module.exports = {
     IDCard: '身份证号',
     birthday: '生日',
     choiceBirthday: '选择日期',
+    birthday2: '出生日期',
+    choiceBirthday2: '选择出生日期',
     address: '详细地址',
     addressInputMsg: '最长50个字符',
     homeAddress: '家庭住址',
@@ -184,6 +219,9 @@ module.exports = {
     deviceId: '设备id',
     deviceType: '设备类型',
     choiceDeviceType: '请选择设备类型',
+    deviceTypeMsg: '设备类型必须选择',
+    signType: '体征设备类型',
+    choiceSignType: '请选择体征设备类型',
     deviceName: '设备别名',
     inputDeviceName: '请输入设备别名',
     status: '设备状态',
@@ -243,6 +281,7 @@ module.exports = {
     ledVoice: '语音播放',
     ledVoiceStatus: '启用语音',
     ledFontSize: '字体大小',
+    hostDeviceList: '护士主机列表',
     webSocketSuccess: 'WebSocket连接成功',
     webSocketError: 'WebSocket连接发生错误'
   },
@@ -251,7 +290,10 @@ module.exports = {
     role: '角色',
     choiceRole: '请选择角色',
     clerkList: '小组成员',
-    admin: '机构负责人'
+    admin: '机构负责人',
+    shop: '所负责机构',
+    choiceShop: '选择机构',
+    shopMsg: '请选择机构'
   },
   customerManage: {
     customerAdd: '入住登记',
@@ -274,6 +316,7 @@ module.exports = {
     day: '天',
     inDate: '入住日期',
     outDate: '离开时间',
+    outDate2: '出所时间',
     choiceDate: '选择日期',
     to: '至',
     today: '至今',
@@ -293,8 +336,10 @@ module.exports = {
     choiceFrame: '请选择床位',
     illnessDesc: '用户情况简述',
     illnessDesc2: '用户简介',
+    illnessDesc3: '分娩方式',
     patientIllnessDesc: '病况描述',
     inputIllnessDesc: '请输入文本内容,长度2~50',
+    choiceIllnessDesc: '请选择分娩方式',
     advice: '医嘱',
     inputAdvice: '请输入文本内容,长度2~50',
     doctor: '责任医生',
@@ -305,12 +350,14 @@ module.exports = {
     choiceNurse: '请选择护士',
     worker: '责任护工',
     choiceWorker: '请选择护工',
+    choiceUser: '请选择用户',
     customerRelative: '用户亲属',
     sureDeleteRelative: '你确定要删除此病人亲属信息?',
     customerRelativeTrueName: '亲属姓名',
     inputCustomerRelativeTrueName: '请输入亲属姓名',
     relativeName: '关系',
     inputRelativeName: '请输入亲属关系 如:朋友',
+    choiceRelativeName: '请选择亲属关系',
     vital: '体征',
     remark: '备注',
     remarks: '备注内容:',
@@ -334,7 +381,15 @@ module.exports = {
     message: '的信息',
     customerStatus: '当前状态',
     customerStatusTrue: '入住中',
-    customerStatusFalse: '已离开'
+    customerStatusFalse: '已离开',
+    footprint: '足迹'
+  },
+  vital: {
+    customerVital: '用户体征日志',
+    paramName: '体征参数',
+    value: '体征值',
+    logTime: '测量时间',
+    company: '单位'
   },
   watch: {
     deviceKeywords: '请输入设备别名或设备标识码',
@@ -398,12 +453,32 @@ module.exports = {
     toMemberName: '接收方',
     actionType: '交互类型',
     actionEnd: '交互结果',
+    actionTime: '交互次数',
     success: '成功',
+    successInteraction: '已响应交互',
+    unSuccessInteraction: '未完成交互',
+    unSuccessTime: '未完成次数',
+    failedInteraction: '未正常挂断交互',
     notOperated: '未响应',
     data: '交互数据',
     createDate: '交互时间',
     fromDevice: '发起设备',
-    toDevice: '接收设备'
+    toDevice: '接收设备',
+    interactionRecord: '交互记录',
+    all: '全部',
+    customerAndClerk: '客户与员工',
+    clerkAndClerk: '同事与同事',
+    selectData: '查询周期:',
+    customerCensus: '用户交互统计',
+    clerkCensus: '员工交互统计',
+    dataCensus: '时间段交互统计',
+    unSuccessCensus: '未完成交互统计',
+    interactionCensus: '交互记录统计',
+    quantityCensus: '数量统计',
+    avgResponseNum: '平均响应时间',
+    MinNum: '最小响应时间',
+    MaxNum: '最大响应时间',
+    total: '总量'
   },
   frameGroup: {
     frameGroupAdd: '新建区域',
@@ -482,22 +557,107 @@ module.exports = {
     colorRgb: '颜色标识',
     basic: '基本护理信息'
   },
+  board: {
+    boardSet: '设置看板',
+    statusTime: '屏停留时长',
+    statusTimeSet: '设置停留时长',
+    statusTimeSetMsg: '时长必须每项都设置!',
+    the: '第',
+    screen: '屏',
+    screenFirst: '第1屏',
+    screenFirstSet: '第1屏停留时长',
+    screenSecond: '第2屏',
+    screenSecondSet: '第2屏停留时长',
+    screenFixedSet: '设置固定屏显示',
+    noFixed: '不固定',
+    name: '别名',
+    ethMac: 'mac地址',
+    partId: '科室ID',
+    setUpThisPart: '设定到本科室',
+    webSocketSuccess: '服务正常,可自动发现新看板'
+  },
+  guard: {
+    shotPicture: '拍照',
+    openDoor: '开锁',
+    lockDoor: '锁门',
+    addVisit: '下发人证基本信息',
+    addUser: '添加人员'
+  },
+  error: {
+    errorClear: '清空日志',
+    errorDetails: '错误详情',
+    device: '设备:',
+    ethMac: '标识码',
+    deviceFrame: '设备位置:',
+    deviceFrame2: '设备位置',
+    className: '类名:',
+    className2: '类名',
+    methodName: '方法名:',
+    methodName2: '方法名',
+    exceptionName: '异常类型:',
+    errorTime: '错误时间:',
+    errorTime2: '错误时间',
+    errorMsg: '错误信息:',
+    detailsError: '详细错误:'
+  },
+  systemConfig: {
+    add: '新增参数配置',
+    groupName: '分组名称',
+    inputGroupName: '请输入分组名称',
+    keyCode: '引用代码',
+    keyCodeMsg: '引用代码不能为空',
+    inputKeyCode: '请输入引用代码',
+    keyName: '配置名称',
+    inputKeyName: '请输入配置名称',
+    keyVal: '配置值',
+    keyValMsg: '配置值不能为空',
+    inputKeyVal: '请输入配置值',
+    description: '参数说明',
+    inputDescription: '请输入参数说明'
+  },
+  menu: {
+    add: '增加',
+    addMsg: '菜单最多添加三级',
+    addFirst: '添加顶级菜单',
+    menuEdit: '编辑菜单',
+    menuAdd: '添加菜单',
+    title: '菜单标题',
+    inputTitle: '请输入菜单标题!',
+    titleMsg: '长度在 2 到 6 个字符',
+    identifier: '菜单标识',
+    inputIdentifier: '请输入菜单标识!',
+    identifierMsg: '长度在 1 到 50 个字符',
+    authRegular: '菜单权限',
+    inputAuthRegular: '请输入菜单权限!',
+    authRegularMsg: '长度在 1 到 50 个字符',
+    MenuDeleteMsg: '确定要删除这个菜单吗?如果有子菜单,子菜单也会被一并删除!'
+  },
   partInfo: {
     partInfo: '系统设置',
     baseInfo: '基本信息',
     shopName: '组织简称',
+    shopNameMsg: '组织简称必须填写',
     inputShopName: '输入组织简称',
     shopFullName: '组织全称',
+    shopFullNameMsg: '组织全称必须填写',
     inputShopFullName: '输入组织全称',
     hisCode: 'HIS系统标识',
     inputHisCode: '请输入HIS系统标识',
     shopType: '组织类型',
+    shopTypeMsg: '组织类型必须选择',
     choiceShopType: '请选择组织类型',
     hospital: '医院',
     part: '科室',
+    shop: '机构',
     organization: '组织',
     shopMemberName: '管理员账号',
+    shopMemberNameMsg: '管理员账号必须填写',
     inputShopMemberName: '请输入管理员账号',
+    shopMemberPassword: '管理员密码',
+    shopMemberPasswordMsg: '管理员密码必须填写',
+    inputShopMemberPassword: '请输入管理员密码',
+    shopParentName: '上级组织简称',
+    shopParentFullName: '上级组织全称',
     shopParentId: '所属组织',
     choiceShopParentId: '请选择上级组织',
     dayInfo: '白天参数设置',
@@ -523,6 +683,8 @@ module.exports = {
     nurseKeyVal: '护士主机转接时长',
     autoAccept: '分机开启自动接听',
     openAutoAccept: '开启自动接听',
+    eventForward: '事件转发功能',
+    openEventForward: '开启事件转发',
     communicationModeBed: '分机通讯方式',
     communicationModeNurse: '护士主机通讯方式',
     communicationModeMobile: '移动设备通讯方式',
@@ -533,6 +695,8 @@ module.exports = {
     customizeRoleCallSecond: '自定义呼叫角色2',
     doctorTitle: '模拟分机医生标题',
     nurseTitle: '模拟分机护士标题',
+    doorNurseTitle: '门口机呼叫护士标题',
+    doorNursingTitle: '门口机进入护理标题',
     display: '显示',
     onDisplay: '不显示',
     upSeconds: '腕表上传定位间隔',
@@ -541,10 +705,40 @@ module.exports = {
     initialize485Device: '初始化485设备',
     addTestMemberList: '批量添加测试用户',
     devicesRef: '设备批量刷新',
+    bindDevice: '绑定语音转换盒',
+    sureBindDevice: '确定需要绑定语音转换盒吗?',
     sureAddTestMemberList: '确定需要批量增加测试用户吗?',
     startAdd: '开始创建',
     sureDevicesRef: '确定需要批量刷新设备吗?',
-    boardShowEmptyBed: '看板显示空床'
+    partInfoSetting: '科室信息设置',
+    nurse: '护士主机APP更新',
+    vnurse: '护士主机可视版',
+    znurse: '总控护士主机APP更新',
+    doctor: '医生主机',
+    door: '门口机APP更新',
+    vdoor: '门口机可视版',
+    sickbed: '5寸床位分机APP',
+    sevensickbed: '7寸床位分机APP',
+    vsickbed: '床位分机可视版',
+    mobiledevice: '移动设备',
+    vistitation: '探视机',
+    transferDevice: '转换盒',
+    organizationAdd: '新建组织',
+    boardShowEmptyBed: '看板显示空床',
+    nursingColorRgb: '护理门灯颜色'
+  },
+  role: {
+    roleName: '角色名称',
+    roleNameMsg: '长度在 1 到 10 个字符',
+    inputRoleName: '请输入角色名称!',
+    roleDescribe: '角色描述',
+    roleDescribeMsg: '最多200字',
+    permission: '角色权限',
+    roleAdd: '新建角色',
+    roleEvent: '角色事件',
+    roleDelete: '删除角色',
+    roleEdit: '编辑角色事件',
+    onChoiceRole: '没有选中任何角色!'
   },
   tab: {
     home: '首页',
@@ -555,6 +749,7 @@ module.exports = {
     customerManage: '用户管理',
     customerQrCode: '用户二维码',
     mobileDeviceManage: '移动设备',
+    userLocationManage: '用户位置',
     sosDeviceSettingManage: '报警设备',
     channelManage: '对讲频道',
     remarkManage: '便签管理',
@@ -578,7 +773,8 @@ module.exports = {
     shopSetting: '系统设置',
     menuManage: '菜单管理',
     organization: '组织机构',
-    roleManage: '角色管理'
+    roleManage: '角色管理',
+    debugging485: '485调试'
   },
   deviceType: {
     NURSE_HOST: '护士主机',
@@ -608,7 +804,18 @@ module.exports = {
     ALARM_HOUSEHOLD_GAS: '家用燃起报警器',
     ALARM_HOUSEHOLD_SMOKE: '家用烟雾报警器',
     ALARM_BUTTON_SOS: '一键报警器',
-    DOOR_LOCK: '门磁传感器'
+    VITAL_SIGNS_DEVICE: '体征设备',
+    ALARM_RESTRAINT_BAND: '约束带报警器',
+    DOOR_LOCK: '门磁传感器',
+    EMERGENCY_GATEWAY: '报警网关',
+    ALARM_433BUTTON: '433报警器'
+  },
+  vitalSignsDeviceType: {
+    BLOOD_SUGAR: '血糖仪',
+    BLOOD_OXYGEN: '血氧仪',
+    BLOOD_PRESSURE: '血压计',
+    TEMPERATURE: '体温枪',
+    SHADOW_OF_GUARDIAN: '守护之影'
   },
   sosDeviceSettingType: {
     NOT_START: '不启动',
@@ -632,5 +839,18 @@ module.exports = {
     CHANNELIM: '频道留言',
     LOCATION: '定位',
     UNKNOWN: '未知'
+  },
+  relativeNameType: {
+    CHILDREN: '孩子',
+    HUSBAND: '丈夫',
+    WIFE: '妻子',
+    FATHER: '父亲',
+    MOTHER: '母亲',
+    RELATIVE: '亲属',
+    FRIEND: '朋友'
+  },
+  childbirthType: {
+    SPONTANEOUS_LABOR: '顺产',
+    CAESAREAN_BIRTH: '剖腹产'
   }
 }

+ 1 - 0
package.json

@@ -45,6 +45,7 @@
     "tui-editor": "1.3.3",
     "vcolorpicker": "^1.0.3",
     "vue": "2.6.10",
+    "vue-baidu-map": "^0.21.22",
     "vue-class-component": "^7.2.6",
     "vue-count-to": "^1.0.13",
     "vue-draggable-resizable": "^2.3.0",

+ 4 - 3
public/domain.js

@@ -1,7 +1,8 @@
 const domain = {
-  serverUrl: 'http://localhost:8005',
-  DeviceUrl: 'http://localhost:8006',
+  serverUrl: 'http://8.129.220.143:8005',
+  DeviceUrl: 'http://8.129.220.143:8006',
+  OnlineSystemUrl: 'http://api.base.wdklian.com',
   apiMode: 'dev',
-  uiVersion: 1 // 1 医院版,2 月子中心版,3养老院版
+  uiVersion: 3 // 1 医院版,2 月子中心版,3养老院版
 }
 

+ 15 - 0
src/api/initialize.js

@@ -1,4 +1,5 @@
 import request from '@/utils/request'
+const OnlineSystemUrl = domain.OnlineSystemUrl
 
 export function initData() {
   return request({
@@ -17,4 +18,18 @@ export function initDeviceList(partId) {
     url: `/initialize/init_device_list/${partId}`,
     method: 'GET'
   })
+}
+
+export function getDevicesByUuid(id) {
+  return request({
+    url: OnlineSystemUrl + `/ncs_sync/get_device_by_uuid/${id}`,
+    method: 'GET'
+  })
+}
+
+export function bindDeviceTransAudio() {
+  return request({
+    url: `/initialize/bind_device_trans_audio`,
+    method: 'GET'
+  })
 }

+ 7 - 0
src/api/ncs_customer.js

@@ -67,4 +67,11 @@ export function saveListByCustomer(partId) {
     method: 'GET',
     loading: true
   })
+}
+export function getListByPartId(partId) {
+  return request({
+    url: `/ncs/customer/getListByPartId/${partId}`,
+    method: 'GET',
+    loading: true
+  })
 }

+ 8 - 0
src/api/ncs_device.js

@@ -186,3 +186,11 @@ export function getManageHostDeviceByHospitalId(hospitalId) {
   })
 }
 
+export function get485DeviceAndFrame(partId, tid) {
+  return request({
+    url: `/ncs/device/get_485_device_and_frame/${partId}/${tid}`,
+    method: 'GET',
+    loading: false
+  })
+}
+

+ 10 - 0
src/api/ncs_partInfo.js

@@ -68,3 +68,13 @@ export function editPartSetting(params, partid) {
     data: params
   })
 }
+
+export function editShopMember(params) {
+  params.member_password = md5(params.member_password)
+  return request({
+    url: '/mgr/partinfo/edit_shop_member',
+    method: 'POST',
+    loading: true,
+    data: params
+  })
+}

+ 15 - 0
src/api/user.js

@@ -61,6 +61,14 @@ export function add(params) {
   })
 }
 
+export function addRelative(params) {
+  return request({
+    url: '/Mgr/member/add_relative',
+    method: 'POST',
+    data: params
+  })
+}
+
 export function remove(params) {
   const ids = params.toString()
   return request({
@@ -71,6 +79,13 @@ export function remove(params) {
   })
 }
 
+export function getUnionId(memberId) {
+  return request({
+    url: `/Mgr/member/get_union_id/${memberId}`,
+    method: 'GET'
+  })
+}
+
 /**
  * 获取用户角色权限
  * @param role_id

+ 5 - 5
src/components/YearMonthPicker/src/main.vue

@@ -1,9 +1,9 @@
 <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 v-if="optional" v-model="date_type" :disabled="disabled" :placeholder="this.$t('action.choice')" style="width: 100px">
+      <el-option :label="this.$t('action.monthly')" value="month" />
+      <el-option :label="this.$t('action.yearly')" value="year" />
+      <el-option v-if="boolDay" :label="this.$t('action.daily')" value="date" />
     </el-select>
     <el-date-picker
       v-model="date_val"
@@ -13,7 +13,7 @@
       :clearable="clearable"
       :type="date_type"
       :value-format="date_type === 'year' ? 'yyyy' : date_type === 'month' ? 'yyyy-MM' : 'yyyy-MM-dd'"
-      :placeholder="date_type === 'month' ? '选择月份' : '选择年份'"
+      :placeholder="date_type === 'month' ? this.$t('action.choiceMonth') : this.$t('action.choiceHYear')"
       :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
       @change="handleDateChange" />
   </div>

+ 6 - 0
src/main.js

@@ -30,6 +30,7 @@ import vcolorpicker from 'vcolorpicker'
 import scroll from 'vue-seamless-scroll/src'
 
 import i18n from './utils/i18n'
+import BaiduMap from 'vue-baidu-map'
 /**
  * If you don't want to use mock-server
  * you want to use MockJs for mock api
@@ -64,6 +65,11 @@ Object.keys(filters).forEach(key => {
   Vue.filter(key, filters[key])
 })
 
+Vue.use(BaiduMap, {
+  /* Visit http://lbsyun.baidu.com/apiconsole/key for details about app key. */
+  ak: 'npNSlyyrVBUm37EUSHHGDgfZ44sunSp2'
+})
+
 Vue.config.productionTip = false
 
 new Vue({

+ 40 - 0
src/router/index.js

@@ -169,6 +169,13 @@ export const partRoutes = [
         component: () => uiVersion === 1 ? import('@/views/customer/patientManagement') : uiVersion === 2 ? import('@/views/customer/customerManagement') : import('@/views/customer/elderlyCareManagement'),
         name: uiVersion === 1 ? 'patientManagement' : uiVersion === 2 ? 'customerManager' : 'elderlyCareManager',
         meta: { title: uiVersion === 1 ? i18n.t('tab.patientManage') : i18n.t('tab.customerManage'), icon: 'el-icon-s-custom', noCache: true }
+      },
+      {
+        path: '/allMap',
+        component: () => import('@/views/customer/allMap'),
+        name: 'allMap',
+        meta: { title: '用户分布', icon: 'area', noCache: true },
+        hidden: true
       }
     ]
   },
@@ -196,6 +203,27 @@ export const partRoutes = [
         component: () => import('@/views/ncs-device/nurse_watch'),
         name: 'nurse_watch',
         meta: { title: i18n.t('tab.mobileDeviceManage'), icon: 'el-icon-watch', noCache: true }
+      },
+      {
+        path: '/myMapHtml',
+        component: () => import('@/views/customer/myMapHtml'),
+        name: 'myMapHtml',
+        meta: { title: i18n.t('customerManage.footprint'), icon: 'area', noCache: true },
+        hidden: true
+      }
+    ],
+    hidden: uiVersion === 1
+  },
+  {
+    path: '/ncs-user-watch',
+    component: Layout,
+    redirect: '/ncs-device/user_watch',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/ncs-device/user_watch'),
+        name: 'user_watch',
+        meta: { title: i18n.t('tab.userLocationManage'), icon: 'el-icon-watch', noCache: true }
       }
     ],
     hidden: uiVersion === 1
@@ -600,6 +628,18 @@ export const adminRoutes = [
       }
     ]
   },
+  {
+    path: '/ncs-485',
+    component: Layout,
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/ncs-485/index'),
+        name: 'rolemanager',
+        meta: { title: i18n.t('tab.debugging485'), icon: 'authen', noCache: true }
+      }
+    ]
+  },
 
   { path: '*', redirect: '/404', hidden: true }
 ]

+ 9 - 0
src/utils/enum/ChildbirthTypeEnum.js

@@ -0,0 +1,9 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+
+export const CHILDBIRTH_TYPE = createEnum(
+  {
+    SPONTANEOUS_LABOR: ['顺产', i18n.t('childbirthType.SPONTANEOUS_LABOR')],
+    CAESAREAN_BIRTH: ['剖腹产', i18n.t('childbirthType.CAESAREAN_BIRTH')]
+  }
+)

+ 5 - 1
src/utils/enum/DeviceTypeEnum.js

@@ -30,6 +30,10 @@ export const DEVICE_TYPE = createEnum(
     ALARM_HOUSEHOLD_GAS: [25, i18n.t('deviceType.ALARM_HOUSEHOLD_GAS')],
     ALARM_HOUSEHOLD_SMOKE: [26, i18n.t('deviceType.ALARM_HOUSEHOLD_SMOKE')],
     ALARM_BUTTON_SOS: [27, i18n.t('deviceType.ALARM_BUTTON_SOS')],
-    DOOR_LOCK: [30, i18n.t('deviceType.DOOR_LOCK')]
+    VITAL_SIGNS_DEVICE: [28, i18n.t('deviceType.VITAL_SIGNS_DEVICE')],
+    ALARM_RESTRAINT_BAND: [29, i18n.t('deviceType.ALARM_RESTRAINT_BAND')],
+    DOOR_LOCK: [30, i18n.t('deviceType.DOOR_LOCK')],
+    EMERGENCY_GATEWAY: [31, i18n.t('deviceType.EMERGENCY_GATEWAY')],
+    ALARM_433BUTTON: [32, i18n.t('deviceType.ALARM_433BUTTON')]
   }
 )

+ 14 - 0
src/utils/enum/RelativeNameTypeEnum

@@ -0,0 +1,14 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+
+export const RELATIVE_NAME_TYPE = createEnum(
+    {
+        CHILDREN: [ '孩子', i18n.t('relativeNameType.CHILDREN') ],
+        HUSBAND: [ '丈夫', i18n.t('relativeNameType.HUSBAND') ],
+        WIFE: [ '妻子', i18n.t('relativeNameType.WIFE') ],
+        FATHER: [ '父亲', i18n.t('relativeNameType.FATHER') ],
+        MOTHER: [ '母亲', i18n.t('relativeNameType.MOTHER') ],
+        RELATIVE: [ '亲属', i18n.t('relativeNameType.RELATIVE') ],
+        FRIEND: [ '朋友', i18n.t('relativeNameType.FRIEND') ],
+    }
+)

+ 22 - 0
src/utils/enum/TcpTypeEnum.js

@@ -0,0 +1,22 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+
+export const TCP_TYPE = createEnum(
+  {
+    CALLBACK: ['CALLBACK', i18n.t('tcpType.CALLBACK')],
+    SOS: ['SOS', i18n.t('tcpType.SOS')],
+    VOICE: ['VOICE', i18n.t('tcpType.VOICE')],
+    VIDEO: ['VIDEO', i18n.t('tcpType.VIDEO')],
+    IM: ['IM', i18n.t('tcpType.IM')],
+    DEVICE: ['DEVICE', i18n.t('tcpType.DEVICE')],
+    REINFORCE: ['REINFORCE', i18n.t('tcpType.REINFORCE')],
+    DATA: ['DATA', i18n.t('tcpType.DATA')],
+    EVENT: ['EVENT', i18n.t('tcpType.EVENT')],
+    SIDE: ['SIDE', i18n.t('tcpType.SIDE')],
+    BROADCAST: ['BROADCAST', i18n.t('tcpType.BROADCAST')],
+    TIME: ['TIME', i18n.t('tcpType.TIME')],
+    ENTRACEGUARD: ['ENTRACEGUARD', i18n.t('tcpType.ENTRACEGUARD')],
+    CHANNELIM: ['CHANNELIM', i18n.t('tcpType.CHANNELIM')],
+    LOCATION: ['LOCATION', i18n.t('tcpType.LOCATION')]
+  }
+)

+ 12 - 0
src/utils/enum/VitalSignsDeviceEnum.js

@@ -0,0 +1,12 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+
+export const VITAL_SIGNS_DEVICE_TYPE = createEnum(
+  {
+    BLOOD_SUGAR: [3, i18n.t('vitalSignsDeviceType.BLOOD_SUGAR')],
+    BLOOD_OXYGEN: [5, i18n.t('vitalSignsDeviceType.BLOOD_OXYGEN')],
+    BLOOD_PRESSURE: [6, i18n.t('vitalSignsDeviceType.BLOOD_PRESSURE')],
+    TEMPERATURE: [7, i18n.t('vitalSignsDeviceType.TEMPERATURE')],
+    SHADOW_OF_GUARDIAN: [8, i18n.t('vitalSignsDeviceType.SHADOW_OF_GUARDIAN')]
+  }
+)

+ 5 - 4
src/utils/mixin.js

@@ -5,12 +5,13 @@
 import Vue from 'vue'
 import * as Foundation from './Foundation'
 import * as XLSX from 'xlsx'
+import i18n from '@/utils/i18n'
 
 export default {
   data() {
     return {
       MixinPickerShortcuts: [{
-        text: '最近一周',
+        text: i18n.t('action.lastWeek'),
         onClick(picker) {
           const end = new Date()
           const start = new Date()
@@ -18,7 +19,7 @@ export default {
           picker.$emit('pick', [start, end])
         }
       }, {
-        text: '最近一个月',
+        text: i18n.t('action.lastMonth'),
         onClick(picker) {
           const end = new Date()
           const start = new Date()
@@ -26,7 +27,7 @@ export default {
           picker.$emit('pick', [start, end])
         }
       }, {
-        text: '最近三个月',
+        text: i18n.t('action.lastThreeMonths'),
         onClick(picker) {
           const end = new Date()
           const start = new Date()
@@ -76,7 +77,7 @@ export default {
     },
     /** 用于判断表单是否为空 */
     MixinRequired(message, trigger) {
-      return { required: true, pattern: /^\S.*$/gi, message: message + ',不能以空格开头', trigger: trigger || 'blur' }
+      return { required: true, pattern: /^\S.*$/gi, message: message + i18n.t('action.notSpace'), trigger: trigger || 'blur' }
     },
     /** 格式化金钱 */
     MixinFormatPrice(row, column, cellValue, index) {

+ 0 - 1
src/utils/request.js

@@ -163,7 +163,6 @@ const closeLoading = (target) => {
 }
 
 export default function request(options) {
-  console.log(options.url.toLocaleLowerCase())
   // 如果是请求【刷新token、登录、退出】不需要检查token,直接请求。
   if (/mgr\/refresh_token|mgr\/login|mgr\/logout|care/.test(options.url.toLocaleLowerCase())) {
     return service(options)

+ 43 - 39
src/views/calling-board/index.vue

@@ -47,12 +47,12 @@
     <!--      <div slot="toolbar" class="inner-toolbar" />-->
     <!--      &lt;!&ndash;表头&ndash;&gt;-->
     <!--      <template slot="table-columns">-->
-    <!--        <el-table-column prop="id" sortable="custom" label="识别码" width="200" align="center" />-->
-    <!--        <el-table-column prop="device_name" sortable="custom" label="别名" width="200" align="center" />-->
-    <!--        <el-table-column prop="device_wifi_mac" sortable="custom" label="mac地址" width="200" align="center" />-->
-    <!--        <el-table-column prop="device_eth_ip" sortable="custom" label="IP地址" width="200" align="center" />-->
-    <!--        <el-table-column prop="partid" sortable="custom" label="科室ID" width="200" align="center" />-->
-    <!--        <el-table-column label="操作" align="center">-->
+    <!--        <el-table-column prop="id" sortable="custom" :label="识别码" width="200" align="center" />-->
+    <!--        <el-table-column prop="device_name" sortable="custom" :label="别名" width="200" align="center" />-->
+    <!--        <el-table-column prop="device_wifi_mac" sortable="custom" :label="mac地址" width="200" align="center" />-->
+    <!--        <el-table-column prop="device_eth_ip" sortable="custom" :label="IP地址" width="200" align="center" />-->
+    <!--        <el-table-column prop="partid" sortable="custom" :label="科室ID" width="200" align="center" />-->
+    <!--        <el-table-column :label="操作" align="center">-->
     <!--          <template slot-scope="scope">-->
     <!--            <el-button type="primary" size="mini" @click="setPartBoard(scope.row)">设定</el-button>-->
     <!--            <el-button type="primary" size="mini" @click="setBoard(scope.row)">设置</el-button>-->
@@ -75,42 +75,42 @@
     <!--      />-->
     <!--    </en-table-layout>-->
 
-    <el-dialog title="设置看板" :visible.sync="formshow" width="50%">
+    <el-dialog :title="this.$t('board.boardSet')" :visible.sync="formshow" width="50%">
       <el-form ref="editform" v-model="boardConfig" label-width="120px">
         <fieldset>
-          <legend>设置停留时长</legend>
-          <el-form-item label="第1屏">
-            <el-input v-model="boardConfig.staySeconds[0]" clearable placeholder="第1屏停留时长" type="number">
-              <template slot="append"></template>
+          <legend>{{ this.$t('board.statusTime') }}</legend>
+          <el-form-item :label="this.$t('board.screenFirst')">
+            <el-input v-model="boardConfig.staySeconds[0]" clearable :placeholder="this.$t('board.screenFirstSet')" type="number">
+              <template slot="append">{{ second }}</template>
             </el-input>
 
           </el-form-item>
-          <el-form-item label="第2屏">
-            <el-input v-model="boardConfig.staySeconds[1]" clearable placeholder="第2屏停留时长" type="number">
-              <template slot="append"></template>
+          <el-form-item :label="this.$t('board.screenSecond')">
+            <el-input v-model="boardConfig.staySeconds[1]" clearable :placeholder="this.$t('board.screenSecondSet')" type="number">
+              <template slot="append">{{ second }}</template>
             </el-input>
           </el-form-item>
-          <el-form-item v-for="(item,index) in boardTitles" :key="index" :label="'第'+(index+3)+'屏'">
-            <el-input v-model="boardConfig.staySeconds[index+2]" clearable :placeholder="'第'+(index+3)+'屏停留时长'" type="number">
-              <template slot="append"></template>
+          <el-form-item v-for="(item,index) in boardTitles" :key="index" :label="labelStr(index)">
+            <el-input v-model="boardConfig.staySeconds[index+2]" clearable :placeholder="labelStr(index)" type="number">
+              <template slot="append">{{ second }}</template>
             </el-input>
           </el-form-item>
         </fieldset>
         <fieldset class="margin-top-sm">
-          <legend>设置固定屏显示</legend>
+          <legend>{{ this.$t('board.screenFixedSet') }}</legend>
           <el-form-item label-width="80">
             <el-radio-group v-model="boardConfig.stayIndex">
-              <el-radio :label="0">不固定</el-radio>
-              <el-radio :label="1">第1屏</el-radio>
-              <el-radio :label="2">第2屏</el-radio>
-              <el-radio v-for="(item,index) in boardTitles" :key="index" :label="(index+3)">第{{ index+3 }}屏</el-radio>
+              <el-radio :label="0">{{ this.$t('board.noFixed') }}</el-radio>
+              <el-radio :label="1">{{ this.$t('board.screenFirst') }}</el-radio>
+              <el-radio :label="2">{{ this.$t('board.screenSecond') }}</el-radio>
+              <el-radio v-for="(item,index) in boardTitles" :key="index" :label="(index+3)" > {{ labelStr(index) }}</el-radio>
             </el-radio-group>
           </el-form-item>
         </fieldset>
       </el-form>
       <div slot="footer" class="dialog-footer">
-        <el-button @click="formshow = false">取 消</el-button>
-        <el-button type="primary" @click="updateBoard()">确 定</el-button>
+        <el-button @click="formshow = false">{{ this.$t('action.cancel') }}</el-button>
+        <el-button type="primary" @click="updateBoard()">{{ this.$t('action.yes') }}</el-button>
       </div>
     </el-dialog>
   </div>
@@ -153,6 +153,7 @@ export default {
       filterState: null,
       rowSelection: null,
       frameworkComponents: null,
+      second: this.$t('action.second'),
 
       websock: null,
       boardObj: {},
@@ -165,7 +166,7 @@ export default {
       formshow: false,
       rules: {
         device_type: [
-          { required: true, message: '设备类型必须选择', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.deviceTypeMsg'), trigger: 'blur' }
         ]
       }
     }
@@ -191,21 +192,21 @@ export default {
       },
       { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 130 },
       {
-        headerName: '别名', field: 'name', sortable: true, filter: 'agTextColumnFilter', width: 150
+        headerName: this.$t('board.name'), field: 'name', sortable: true, filter: 'agTextColumnFilter', width: 150
       },
       {
-        headerName: 'mac地址', field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter', flex: 1
+        headerName: this.$t('board.ethMac'), field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter', flex: 1
       },
       {
-        headerName: '科室ID', field: 'part_id', sortable: true, filter: 'agNumberColumnFilter', width: 150
+        headerName: this.$t('board.partId'), field: 'part_id', sortable: true, filter: 'agNumberColumnFilter', width: 150
 
       },
       {
-        headerName: '设定', field: 'id',
+        headerName: this.$t('action.setUp'), field: 'id',
         cellRendererFramework: 'ButtonCellRender',
         cellRendererParams: {
           onClick: this.handEdit,
-          label: '设定到本科室',
+          label: this.$t('board.setUpThisPart'),
           buttonType: 'primary',
           buttonSize: 'mini'
         },
@@ -217,11 +218,11 @@ export default {
         sortable: false
       },
       {
-        headerName: '设置', field: 'id',
+        headerName: this.$t('action.settings'), field: 'id',
         cellRendererFramework: 'ButtonCellRender',
         cellRendererParams: {
           onClick: this.setBoard,
-          label: '设置看板',
+          label: this.$t('board.boardSet'),
           buttonType: 'primary',
           buttonSize: 'mini'
         },
@@ -440,13 +441,13 @@ export default {
 
     updateBoard() {
       if (this.boardConfig.staySeconds.length !== this.boardTitles.length + 2) {
-        this.$message.success('时长必须每项都设置!')
+        this.$message.success(this.$t('board.statusTimeSetMsg'))
         return false
       }
       this.boardConfig.staySeconds = this.boardConfig.staySeconds.map(p => Number(p))
       this.boardObj.config = JSON.stringify(this.boardConfig)
       API_Device.update(this.boardObj.id, this.boardObj).then(() => {
-        this.$message.success('设置成功!')
+        this.$message.success(this.$t('action.settingsSuccess'))
         this.getList()
         this.formshow = false
       }).catch(response => {
@@ -462,7 +463,7 @@ export default {
       row.part_id = this.$store.getters.partId
       row.frame_id = this.treeData[0].id
       API_Device.update(row.id, row).then(res => {
-        this.$message.success('设定成功!')
+        this.$message.success(this.$t('action.setUpSuccess'))
         this.gridApi.redrawRows()
       }).catch(response => {
         this.getList()
@@ -486,18 +487,21 @@ export default {
       this.websock.onclose = this.websocketclose
     },
     websocketonopen: function() {
-      this.$message.success('服务正常,可自动发现新看板')
-      console.log('WebSocket连接成功')
+      this.$message.success(this.$t('board.webSocketSuccess'))
+      console.log(this.$t('deviceManage.webSocketSuccess'))
     },
     websocketonerror: function(e) {
-      console.log('WebSocket连接发生错误')
+      console.log(this.$t('deviceManage.webSocketError'))
     },
     websocketonmessage: function(e) {
       this.getList()
     },
     websocketclose: function(e) {
       console.log('connection closed (' + e.code + ')')
-    }
+    },
+    labelStr(index) {
+      return this.$t('board.the') + (index + 3) + this.$t('board.screen')
+    },
   }
 }
 </script>

+ 32 - 32
src/views/calling-ncError/index.vue

@@ -20,7 +20,7 @@
 <!--          <en-table-search placeholder="请输入搜索关键字" @search="handlerSearch" />-->
 <!--        </div>-->
         <div class="toolbar-btns">
-          <el-button type="danger" size="mini" @click="clearError">清空日志</el-button>
+          <el-button type="danger" size="mini" @click="clearError">{{ this.$t('error.errorClear') }}</el-button>
         </div>
       </div>
       <el-pagination
@@ -36,34 +36,34 @@
       />
     </ag-grid-layout>
 
-    <el-dialog :visible.sync="shopVisible" title="错误详情" class="customer-dialog">
+    <el-dialog :visible.sync="shopVisible" :title="this.$t('error.errorDetails')" class="customer-dialog">
       <div>
         <table border="1" class="tablewen">
           <tr>
-            <td>设备:</td>
+            <td>{{ this.$t('error.device') }}</td>
             <td><span>{{ deviceTypeGetter({ data: selectedRow }) }} {{ selectedRow.eth_mac }}</span></td>
-            <td>设备位置:</td>
+            <td>{{ this.$t('error.deviceFrame') }}</td>
             <td>
               <span>{{ selectedRow.full_name }}</span>
             </td>
           </tr>
           <tr>
-            <td>类名:</td>
+            <td>{{ this.$t('error.className') }}</td>
             <td><span>{{ selectedRow.class_name }}</span></td>
-            <td>方法名:</td>
+            <td>{{ this.$t('error.methodName') }}</td>
             <td><span>{{ selectedRow.method_name }}</span></td>
           </tr>
           <tr>
-            <td>异常类型:</td>
+            <td>{{ this.$t('error.exceptionName') }}</td>
             <td><span>{{ selectedRow.exception_name }}</span></td>
-            <td>错误时间:</td>
+            <td>{{ this.$t('error.errorTime') }}</td>
             <td><span>{{ dateValueFormatter({ value: selectedRow.create_time }) }}</span></td>
           </tr>
         </table>
-        <div class="td1">错误信息:</div>
+        <div class="td1">{{ this.$t('error.errorMsg') }}</div>
         <div class="td2">{{ selectedRow.err_msg }}</div>
       </div>
-      <div class="td1">详细错误:</div>
+      <div class="td1">{{ this.$t('error.detailsError') }}</div>
       <el-scrollbar>
         <div style="height: 500px;padding:15px" v-html="selectedRow.stack_trace" />
       </el-scrollbar>
@@ -107,23 +107,23 @@ export default {
       selectedRow: {},
       /** 设备类型转换数组 **/
       deviceTypeTransfer: [
-        { key: '护士主机', value: 1 },
-        { key: '医生主机', value: 2 },
-        { key: '门口机', value: 3 },
-        { key: '床位分机', value: 4 },
-        { key: 'LCD走廊屏', value: 5 },
-        { key: 'LED点阵屏', value: 6 },
-        { key: '移动设备', value: 7 },
+        { key: this.$t('deviceType.NURSE_HOST'), value: 1 },
+        { key: this.$t('deviceType.DOCTOR_HOST'), value: 2 },
+        { key: this.$t('deviceType.DOOR_DEVICE'), value: 3 },
+        { key: this.$t('deviceType.DIGIT_BED_DEVICE'), value: 4 },
+        { key: this.$t('deviceType.LCD_SCREEN'), value: 5 },
+        { key: this.$t('deviceType.LED_SCREEN'), value: 6 },
+        { key: this.$t('deviceType.NURSE_WATCH'), value: 7 },
         // { key: '护工腕表', value: 8 },
-        { key: '病人腕表', value: 9 },
-        { key: '手机App', value: 10 },
-        { key: '总线转换盒', value: 11 },
-        { key: '模拟分机', value: 12 },
-        { key: '模拟紧急按钮', value: 13 },
-        { key: '模拟门灯', value: 14 },
-        { key: '遥控器', value: 15 },
-        { key: '信标', value: 16 },
-        { key: '看板', value: 17 }
+        { key: this.$t('deviceType.USER_WATCH'), value: 9 },
+        { key: this.$t('deviceType.CELL_PHONE'), value: 10 },
+        { key: this.$t('deviceType.TRANSFER_DEVICE'), value: 11 },
+        { key: this.$t('deviceType.SIMULATE_BED_DEVICE'), value: 12 },
+        { key: this.$t('deviceType.SIMULATE_EMERGENCY_BUTTON'), value: 13 },
+        { key: this.$t('deviceType.SIMULATE_DOOR_LIGHT'), value: 14 },
+        { key: this.$t('deviceType.REMOTE_CONTROL'), value: 15 },
+        { key: this.$t('deviceType.BEACON'), value: 16 },
+        { key: this.$t('deviceType.INFORMATION_BOARD'), value: 17 }
       ]
     }
   },
@@ -146,25 +146,25 @@ export default {
         resizable: false,
         valueGetter: this.hashValueGetter
       },
-      { headerName: '标识码', field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter', flex: 1 },
-      { headerName: '设备', field: 'device_type', sortable: true, filterFramework: 'ListFilter', flex: 1,
+      { headerName: this.$t('error.ethMac'), field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter', flex: 1 },
+      { headerName: this.$t('error.device'), field: 'device_type', sortable: true, filterFramework: 'ListFilter', flex: 1,
         filterParams: {
           listData: this.deviceTypeTransfer
         },
         valueGetter: this.deviceTypeGetter
       },
-      { headerName: '设备位置', field: 'full_name', sortable: true, filter: 'agTextColumnFilter', flex: 1 },
-      { headerName: '类名', field: 'class_name', sortable: true, filter: 'agTextColumnFilter', filterParams: {
+      { headerName: this.$t('error.deviceFrame2'), field: 'full_name', sortable: true, filter: 'agTextColumnFilter', flex: 1 },
+      { headerName: this.$t('error.className2'), field: 'class_name', sortable: true, filter: 'agTextColumnFilter', filterParams: {
         debounceMs: 200,
         newRowsAction: 'keep'
       }, flex: 2 },
-      { headerName: '方法名', field: 'method_name', sortable: true, filter: true, filterParams: {
+      { headerName: this.$t('error.methodName2'), field: 'method_name', sortable: true, filter: true, filterParams: {
         debounceMs: 200,
         newRowsAction: 'keep'
       }},
       // { headerName: '异常类型', field: 'exception_name', sortable: true, filter: true, flex: 1 },
       // { headerName: '错误信息', field: 'err_msg', sortable: true, filter: true, flex: 1 },
-      { headerName: '错误时间', field: 'create_time',
+      { headerName: this.$t('error.errorTime2'), field: 'create_time',
         valueFormatter: this.dateValueFormatter,
         filterParams: {
           comparator: (filterLocalDateAtMidnight, cellValue) => {

+ 2 - 2
src/views/calling-setting/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="tab-container">
     <el-tabs v-model="activeName" style="margin:15px;" type="border-card">
-      <el-tab-pane   label="系统设置" name="systemSetting">
+      <el-tab-pane   :label="this.$t('partInfo.partInfo')" name="systemSetting">
         <keep-alive>
            <part-info-edit :part-id="partid"></part-info-edit>
 <!--          <speech-setting v-if="index===1"></speech-setting>-->
@@ -19,7 +19,7 @@ export default {
   data() {
     return {
       tabMapOptions: [
-        { label: '系统设置', key: 'systemSetting' }
+        { label: this.$t('partInfo.partInfo'), key: 'systemSetting' }
 
       ],
       activeName: 'systemSetting',

+ 81 - 0
src/views/customer/allMap.vue

@@ -0,0 +1,81 @@
+<template>
+  <div style="height: 1000px">
+    <baidu-map :center="center" :zoom="zoom" scroll-wheel-zoom @ready="handler">
+      <bm-view class="map"></bm-view>
+      <bm-control :offset="{width: '10px', height: '10px'}">
+        <bm-auto-complete v-model="keyword" :sugStyle="{zIndex: 1}">
+          <input v-model="keyword" placeholder="请输入地名关键字" style="width: 300px;margin-left: 20px;margin-top: 20px;">
+        </bm-auto-complete>
+      </bm-control>
+      <bm-local-search :keyword="keyword" :auto-viewport="true" :location="location" :panel="false"></bm-local-search>
+      <bm-marker v-for="marker of markers" :position="{lng: marker.lng, lat: marker.lat}" :dragging="true" animation="BMAP_ANIMATION_BOUNCE" clicking></bm-marker>
+      <bm-geolocation anchor="BMAP_ANCHOR_BOTTOM_RIGHT" :showAddressBar="true" :autoLocation="true"></bm-geolocation>
+    </baidu-map>
+  </div>
+</template>
+
+<script>
+
+import { getListByPartId } from '@/api/ncs_customer'
+
+export default {
+name: "allMap",
+  data() {
+    return {
+      center: {lng: 0, lat: 0},
+      zoom: 5,
+      myCenter: {
+        lng: 116.404,
+        lat: 39.915
+      },
+      isShow: false,
+      location: '',
+      keyword: '',
+      markers: [],
+    }
+  },
+  computed: {
+    tableHeight() {
+      return  this.mainAreaHeight - 130
+    },
+  },
+  mounted() {
+    window.onresize = this.windowResize()
+  },
+  methods: {
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    handler ({BMap, map}) {
+      this.zoom = 7
+      this.getList()
+    },
+    getList() {
+      const _this = this
+      this.markers = []
+      let i = 0
+      getListByPartId(this.$store.getters.partId).then(res =>{
+        if (res) {
+          res.forEach(item => {
+            if (item.lng_lat) {
+              const position = {lng: item.lng_lat.split(',')[0], lat: item.lng_lat.split(',')[1]}
+              if (i === 0) {
+                _this.center = position
+              }
+              ++ i
+              _this.markers.push(position)
+            }
+          })
+        }
+      })
+    },
+  }
+}
+</script>
+
+<style scoped>
+.map {
+  width: 100%;
+  height: 1000px;
+}
+</style>

+ 99 - 29
src/views/customer/components/customerManager.vue

@@ -43,7 +43,7 @@
     <el-dialog :visible.sync="customerFormVisible" :title="this.$t('customerManage.customerInfo')" class="customer-dialog">
       <el-tabs v-model="activeName" type="border-card" tab-position="bottom" width="50%" @tab-click="handleClick">
         <el-tab-pane :label="this.$t('customerManage.baseInfo')" name="customerBaseInfo">
-          <div >
+          <div>
             <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="120px">
               <el-row>
                 <el-col :span="12">
@@ -98,11 +98,14 @@
                       :editable="false"
                       value-format="timestamp"
                       :placeholder="this.$t('member.choiceBirthday')"
-                      :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+                      :picker-options="{ disabledDate(time) { return time.getTime() > Date.now() }}"
                       @change="birthdayChange"
                     />
                   </el-form-item>
                 </el-col>
+              </el-row>
+
+              <el-row>
                 <el-col :span="12">
                   <el-form-item :label="this.$t('customerManage.inDate')" prop="in_date">
                     <el-date-picker
@@ -112,11 +115,26 @@
                       value-format="timestamp"
                       :default-value="new Date()"
                       :placeholder="this.$t('customerManage.choiceDate')"
-                      :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+                      :picker-options="{ disabledDate(time) { return time.getTime() > Date.now() }}"
+                    />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item :label="this.$t('customerManage.outDate2')" prop="out_date">
+                    <el-date-picker
+                      v-model="formmodel.out_date"
+                      type="date"
+                      :editable="false"
+                      value-format="timestamp"
+                      :default-value="new Date()"
+                      :placeholder="this.$t('customerManage.choiceDate')"
+                      :picker-options="{ disabledDate(time) { return time.getTime() <= formmodel.in_date }}"
                     />
                   </el-form-item>
                 </el-col>
+              </el-row>
 
+              <el-row>
                 <el-col :span="12">
                   <el-form-item :label="this.$t('customerManage.idType')">
                     <el-radio v-model="formmodel.id_type" label="身份证">{{ this.$t('customerManage.idCard') }}</el-radio>
@@ -148,15 +166,18 @@
                       </el-form-item>
                     </el-col>
                   </el-row>
-                  <el-form-item :label="this.$t('customerManage.illnessDesc')">
-                    <el-input
-                      v-model="formmodel.illness_desc"
-                      type="textarea"
-                      :autosize="{ minRows: 2, maxRows: 4}"
-                      :minlength="2"
-                      :maxlength="50"
-                      :placeholder="this.$t('customerManage.inputIllnessDesc')"
-                    />
+                  <el-form-item :label="this.$t('customerManage.illnessDesc3')">
+<!--                    <el-input-->
+<!--                      v-model="formmodel.illness_desc"-->
+<!--                      type="textarea"-->
+<!--                      :autosize="{ minRows: 2, maxRows: 4}"-->
+<!--                      :minlength="2"-->
+<!--                      :maxlength="50"-->
+<!--                      :placeholder="this.$t('customerManage.inputIllnessDesc')"-->
+<!--                    />-->
+                    <el-select v-model="formmodel.illness_desc" :placeholder="this.$t('customerManage.choiceIllnessDesc')" clearable>
+                      <el-option v-for="(item, index) in Object.keys(childbirthTypeEnum)" :key="index" :label="childbirthTypeEnum[item]" :value="item" />
+                    </el-select>
                   </el-form-item>
                 </el-col>
                 <el-col :span="8">
@@ -212,16 +233,16 @@
 
               </el-row>
 
-<!--              <el-row>-->
-<!--                <el-col :span="24" :offset="8">-->
-<!--                  <vue-qr-->
-<!--                      v-if="formmodel.member_id"-->
-<!--                      :text="qrCode(formmodel.member_id)"-->
-<!--                      :size="150"-->
-<!--                      :correctLevel="0"-->
-<!--                  ></vue-qr>-->
-<!--                </el-col>-->
-<!--              </el-row>-->
+              <el-row>
+                <el-col :span="24" :offset="8">
+                  <vue-qr
+                      v-if="formmodel.member_id && qrCode"
+                      :text="qrCode"
+                      :size="150"
+                      :correctLevel="0"
+                  ></vue-qr>
+                </el-col>
+              </el-row>
 
               <el-form-item>
                 <el-button type="primary" :disabled="isDisabled" class="save" @click="handlerSubmit('editForm')">{{ this.$t('action.save') }}</el-button>
@@ -253,6 +274,7 @@
                   prop="relative_name"
                   :label="this.$t('customerManage.relativeName')"
                   width="180"
+                  :formatter="formatterRelativeName"
               />
               <el-table-column
                   prop="mobile"
@@ -277,8 +299,11 @@
                 </el-col>
                 <el-col :span="12">
                   <el-form-item :label="this.$t('customerManage.relativeName')" prop="relative_name">
-                    <el-input v-model="relativeFormModel.relative_name" clearable
-                              :placeholder="this.$t('customerManage.inputRelativeName')" :maxlength="20" />
+<!--                    <el-input v-model="relativeFormModel.relative_name" clearable-->
+<!--                              :placeholder="this.$t('customerManage.inputRelativeName')" :maxlength="20" />-->
+                    <el-select v-model="relativeFormModel.relative_name" :placeholder="this.$t('customerManage.choiceRelativeName')" clearable  @change="relativeNameChange">
+                      <el-option v-for="(item, index) in Object.keys(relativeNameTypeEnum)" :key="index" :label="relativeNameTypeEnum[item]" :value="item" />
+                    </el-select>
                   </el-form-item>
                 </el-col>
               </el-row>
@@ -295,6 +320,19 @@
                     <el-input v-model="relativeFormModel.mobile" clearable :placeholder="this.$t('member.inputMobile')" :maxlength="20" />
                   </el-form-item>
                 </el-col>
+                <el-col :span="12">
+                  <el-form-item v-if="isChild"
+                      :label="this.$t('member.birthday2')" prop="birthday">
+                    <el-date-picker
+                        v-model="relativeFormModel.birthday"
+                        type="date"
+                        :editable="false"
+                        value-format="timestamp"
+                        :placeholder="this.$t('member.choiceBirthday2')"
+                        :picker-options="{ disabledDate(time) { return time.getTime() > Date.now() }}"
+                    />
+                  </el-form-item>
+                </el-col>
               </el-row>
               <el-form-item>
                 <el-button type="primary" @click="addRelative">{{ this.$t('action.add') }}</el-button>
@@ -336,7 +374,7 @@
               <el-form ref="remarkForm" :model="remarkFormModel" :rules="remarkRules" label-width="100px" style="margin-right: 10px">
                 <el-row>
                   <el-col :span="16">
-                    <el-form-item :label="this.$t('customerManage.content')" prop="content">
+                    <el-form-item :label="this.$t('action.content')" prop="content">
                       <el-input
                         v-model="remarkFormModel.content"
                         type="textarea"
@@ -504,6 +542,8 @@ import { FRAME_TYPE } from '@/utils/enum/FrameTypeEnum'
 import vitalSignLog from '@/views/vital-sign/log'
 import vueQr from 'vue-qr'
 import * as API_SystemConfig from '@/api/ncs_systemconfig'
+import {RELATIVE_NAME_TYPE} from "@/utils/enum/RelativeNameTypeEnum";
+import {CHILDBIRTH_TYPE} from "@/utils/enum/ChildbirthTypeEnum";
 const serverUrl = domain.serverUrl
 export default {
   name: 'CustomerManager',
@@ -565,6 +605,7 @@ export default {
       customerRemarks: this.$t('customerManage.remarks'),
       customerRemarkTime: this.$t('customerManage.remarkTime'),
       customerRemarkName: this.$t('customerManage.remarkName'),
+      deleted: this.$t('action.delete'),
       remarkParams: {
         page_size: 100,
         page_no: 1,
@@ -671,7 +712,10 @@ export default {
         { key: this.$t('customerManage.customerStatusFalse'), value: 1, color: 'red' }
       ],
       detailsVisible: false,
-      deleted: this.$t('action.delete')
+      qrCode: null,
+      relativeNameTypeEnum: RELATIVE_NAME_TYPE.getValueList(),
+      childbirthTypeEnum: CHILDBIRTH_TYPE.getValueList(),
+      isChild: false,
     }
   },
   computed: {
@@ -988,6 +1032,7 @@ export default {
         id_type: '身份证',
         age_unit: '岁',
         in_date: (new Date()).valueOf(),
+        out_date: (new Date()).valueOf(),
         mobile: '',
         part_id: this.$store.getters.partId
       }
@@ -1137,6 +1182,9 @@ export default {
           if (this.formmodel.in_date) {
             this.$set(this.formmodel, 'in_date', this.formmodel.in_date / 1000) // 将毫秒数转换成秒
           }
+          if (this.formmodel.out_date) {
+            this.$set(this.formmodel, 'out_date', this.formmodel.out_date / 1000) // 将毫秒数转换成秒
+          }
           if (this.formmodel.birthday) {
             this.$set(this.formmodel, 'birthday', this.formmodel.birthday / 1000) // 将毫秒数转换成秒
           }
@@ -1212,10 +1260,14 @@ export default {
       if (this.formmodel.in_date) {
         this.$set(this.formmodel, 'in_date', this.formmodel.in_date * 1000)
       }
+      if (this.formmodel.out_date) {
+        this.$set(this.formmodel, 'out_date', this.formmodel.out_date * 1000)
+      }
       if (this.formmodel.birthday) {
         this.$set(this.formmodel, 'birthday', this.formmodel.birthday * 1000)
       }
       this.customerFormVisible = true
+      this.getQrCode()
       this.getRemarks()
       this.getRelatives()
     },
@@ -1330,7 +1382,10 @@ export default {
       this.$refs['relativeForm'].validate(valid => {
         if (valid) {
           this.relativeFormModel.relative_id = this.formmodel.member_id
-          API_User.add(this.relativeFormModel).then(res => {
+          if (this.relativeFormModel.birthday) {
+            this.$set(this.relativeFormModel, 'birthday', this.relativeFormModel.birthday / 1000) // 将毫秒数转换成秒
+          }
+          API_User.addRelative(this.relativeFormModel).then(res => {
             this.relativeFormModel = {
               sex: 0,
               true_name: null,
@@ -1380,6 +1435,19 @@ export default {
         return this.$t('member.unknown')
       }
     },
+    formatterRelativeName(row) {
+      return RELATIVE_NAME_TYPE.getDescFromValue(row.relative_name) ? RELATIVE_NAME_TYPE.getDescFromValue(row.relative_name) : row.relative_name
+    },
+    relativeNameChange(val) {
+      if (val === RELATIVE_NAME_TYPE.CHILDREN) {
+        this.relativeRules.mobile[0].required = false
+        this.relativeRules.mobile[0].validator = (rule, value, callback) => { callback() }
+        this.isChild = true
+      } else {
+        this.relativeRules.mobile[0].required = true
+        this.isChild = false
+      }
+    },
     /** 信息变化后操作,如床位状态改变,传入的空间结构变化了 **/
     infoChanged() {
       this.getEmptyBeds().then(() => {
@@ -1410,8 +1478,10 @@ export default {
     async deleteMembers(ids) {
       API_User.remove(ids)
     },
-    qrCode(member_id){
-      return 'http://m.wdklian.com/care/apk/care.user?type=USER_LOGIN&uid=' + member_id
+    getQrCode(){
+      API_User.getUnionId(this.formmodel.member_id).then(r => {
+        this.qrCode = 'http://m.wdklian.com/care/apk/care.user?type=USER_LOGIN&uid=' +  r
+      })
     },
     getCloud() {
       API_SystemConfig.cloud().then(r => {

+ 188 - 93
src/views/customer/components/elderlyCareManager.vue

@@ -22,6 +22,7 @@
                     <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch"/>
                 </div>
                 <div class="toolbar-btns">
+                    <el-button type="s" size="mini" @click="goPage">用户分布</el-button>
                     <el-button type="primary" size="mini" :disabled="!isEmptyFrame" @click="handleAdd">{{ this.$t('customerManage.customerAdd2') }}</el-button>
                     <el-button type="danger" size="mini" @click="batchDelete">{{ this.$t('action.deleteList') }}</el-button>
                 </div>
@@ -40,10 +41,10 @@
         </ag-grid-layout>
 
         <!-- 用户信息 -->
-        <el-dialog :visible.sync="customerFormVisible" :title="this.$t('customerManage.customerInfo')" class="customer-dialog">
+        <el-dialog :visible.sync="customerFormVisible" :title="this.$t('customerManage.customerInfo')" class="customer-dialog" width="70%">
             <el-tabs v-model="activeName" type="border-card" tab-position="bottom" width="50%" @tab-click="handleClick">
                 <el-tab-pane :label="this.$t('customerManage.baseInfo')" name="customerBaseInfo">
-                    <div style="height: 590px">
+                    <div>
                         <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="120px">
                             <el-row>
                                 <el-col :span="12">
@@ -181,7 +182,6 @@
                                     </el-form-item>
                                 </el-col>
                             </el-row>
-
                             <el-row>
                                 <el-col :span="8">
                                     <el-form-item :label="this.$t('customerManage.doctor')">
@@ -210,6 +210,11 @@
                                         </el-select>
                                     </el-form-item>
                                 </el-col>
+                                <el-col :span="8">
+                                  <el-form-item label="坐标">
+                                    <el-button @click="clickLngLat">{{ formmodel.lng_lat ? formmodel.lng_lat : '选择坐标'}}</el-button>
+                                  </el-form-item>
+                                </el-col>
                             </el-row>
 
 <!--                            <el-row v-if="nurseconfigSelection.length > 0">-->
@@ -282,7 +287,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="请输入姓名"
                                                   :maxlength="20"/>
                                     </el-form-item>
                                 </el-col>
@@ -390,6 +395,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>
         <!-- 用户信息 -->
@@ -459,6 +468,11 @@
             </el-form>
         </el-dialog>
         <!-- 用户换床-->
+
+      <!--    选择坐标-->
+      <el-dialog title="选择坐标" :visible.sync="locationShow" width="70%">
+        <my-map :customer-id="formmodel.id" :dialog-show="locationShow" :lng-lat="formmodel.lng_lat" @childFn="setVal"></my-map>
+      </el-dialog>
     </div>
 
 </template>
@@ -467,6 +481,7 @@
     // 养老院版,有责任医生(监护人),责任护工选项 无护理参数
     import {AG_GRID_LOCALE_CN} from '@/utils/AgGridVueLocaleCn'
     import ButtonCellRender from '@/components/AgGridCellRender/ButtonCellRender'
+    import ButtonCellRenderList from '@/components/AgGridCellRender/ButtonCellRenderList'
     import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
     import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
     import * as API_Customer from '@/api/ncs_customer'
@@ -479,10 +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 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: {ButtonCellRender, ListFilter, RadioFilter, vitalSignLog},
+        components: {ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, myMap},
         filters: {
             unixDateFilter(val) {
                 return unixToDate(val)
@@ -564,18 +583,21 @@
                     true_name: [{required: true, message: this.$t('customerManage.inputRemarks'), trigger: 'blur'}],
                     relative_name: [{required: true, message: this.$t('customerManage.inputRelativeName'), trigger: 'blur'}],
                     mobile: [
-                        {
-                            validator: (rule, value, callback) => {
-                                if (value === null || value === '') { // 手机号可为空
-                                    callback()
-                                }
-                                if (!RegExp.mobile.test(value)) {
-                                    callback(new Error(this.$t('member.mobileInputMsg')))
-                                } else {
-                                    callback()
-                                }
+                      { 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()
+                          }
                         }
+                      }
                     ]
                 },
                 /** 换床 */
@@ -627,7 +649,11 @@
                 customerRemarks: this.$t('customerManage.remarks'),
                 customerRemarkTime: this.$t('customerManage.remarkTime'),
                 customerRemarkName: this.$t('customerManage.remarkName'),
-                deleted: this.$t('action.delete')
+                deleted: this.$t('action.delete'),
+              locationShow: false,
+              isCloud: false,
+              boolDevice: false,
+              mapUrl: null
             }
         },
         computed: {
@@ -699,12 +725,12 @@
                 {
                     headerName: this.$t('customerManage.ageUnit'), field: 'age_unit', sortable: true, filter: 'agTextColumnFilter', width: 130
                 },
-                {headerName: this.$t('customerManage.cardNo'), field: 'card_no', sortable: true, filter: 'agTextColumnFilter'},
-                {headerName: this.$t('customerManage.idType'), field: 'id_type', sortable: true, filter: 'agTextColumnFilter'},
-                {headerName: this.$t('customerManage.idNo'), field: 'id_no', sortable: true, filter: 'agNumberColumnFilter', width: 160},
-                {headerName: this.$t('customerManage.frame'), field: 'full_name', sortable: true, filter: 'agTextColumnFilter'},
-                {headerName: this.$t('member.mobile'), field: 'mobile', sortable: true, filter: 'agTextColumnFilter'},
-                {headerName: this.$t('member.homeAddress'), field: 'address', sortable: true, filter: 'agTextColumnFilter', width: 260},
+                {   headerName: this.$t('customerManage.cardNo'), field: 'card_no', sortable: true, filter: 'agTextColumnFilter' },
+                {   headerName: this.$t('customerManage.idType'), field: 'id_type', sortable: true, filter: 'agTextColumnFilter' },
+                {   headerName: this.$t('customerManage.idNo'), field: 'id_no', sortable: true, filter: 'agNumberColumnFilter', width: 160 },
+                {   headerName: this.$t('customerManage.frame'), field: 'full_name', sortable: true, filter: 'agTextColumnFilter' },
+                {   headerName: this.$t('member.mobile'), field: 'mobile', sortable: true, filter: 'agTextColumnFilter'},
+                {   headerName: this.$t('member.homeAddress'), field: 'address', sortable: true, filter: 'agTextColumnFilter', width: 260 },
 
                 {
                     headerName: this.$t('customerManage.inDate'),
@@ -732,79 +758,118 @@
                         }
                     }
                 },
-                {
-                    headerName: this.$t('action.edit'), field: 'id',
-                    cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: {
+              { headerName: this.$t('action.handle'), field: 'id',
+                cellRendererFramework: 'ButtonCellRenderList',
+                cellRendererParams: param => {
+                  return {
+                    list: [
+                      {
                         onClick: this.handleEdit,
                         label: this.$t('action.edit'),
                         buttonType: 'primary',
                         buttonSize: 'mini'
-                    },
-                    filter: false,
-                    pinned: 'right',
-                    lockPinned: true,
-                    width: 80,
-                    resizable: false,
-                    sortable: false
-                },
-                {
-                    headerName: this.$t('customerManage.outBed2'), field: 'id',
-                    cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: param => {
-                        return {
-                            onClick: this.handleOut,
-                            label: this.$t('customerManage.outBed3'),
-                            buttonType: 'warning',
-                            buttonSize: 'mini',
-                            disabled: param.data['status'] !== 0
-                        }
-                    },
-                    filter: false,
-                    pinned: 'right',
-                    lockPinned: true,
-                    width: 100,
-                    resizable: false,
-                    sortable: false
+                      },
+                      {
+                        onClick: this.handleOut,
+                        label: this.$t('customerManage.outBed2'),
+                        buttonType: 'warning',
+                        buttonSize: 'mini',
+                        disabled: param.data['status'] !== 0
+                      },
+                      {
+                        onClick: this.handleChangeBed,
+                        label: this.$t('customerManage.changeBed2'),
+                        buttonType: 'success',
+                        buttonSize: 'mini',
+                        disabled: param.data['status'] !== 0
+                      },{
+                        onClick: this.deleteSingle,
+                        label: this.$t('action.delete'),
+                        buttonType: 'danger',
+                        buttonSize: 'mini',
+                        disabled: param.data['member_name'] === 'superadmin'
+                      }
+                    ]}
                 },
-                {
-                    headerName: this.$t('customerManage.changeBed2'), field: 'id',
-                    cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: param => {
-                        return {
-                            onClick: this.handleChangeBed,
-                            label: this.$t('customerManage.changeBed3'),
-                            buttonType: 'success',
-                            buttonSize: 'mini',
-                            disabled: param.data['status'] !== 0
-                        }
-                    },
-                    filter: false,
-                    pinned: 'right',
-                    lockPinned: true,
-                    width: 100,
-                    resizable: false,
-                    sortable: false
-                },
-                {
-                    headerName: this.$t('action.delete'), field: 'shop_id',
-                    cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: param => {
-                        return {
-                            onClick: this.deleteSingle,
-                            label: this.$t('action.delete'),
-                            buttonType: 'danger',
-                            buttonSize: 'mini',
-                            disabled: param.data['member_name'] === 'superadmin'
-                        }
-                    },
-                    pinned: 'right',
-                    lockPinned: true,
-                    width: 80,
-                    resizable: false,
-                    filter: false,
-                    sortable: false
-                }
+                filter: false,
+                pinned: 'right',
+                lockPinned: true,
+                minWidth: 305,
+                resizable: false,
+                sortable: false },
+                // {
+                //     headerName: this.$t('action.edit'), field: 'id',
+                //     cellRendererFramework: 'ButtonCellRender',
+                //     cellRendererParams: {
+                //         onClick: this.handleEdit,
+                //         label: this.$t('action.edit'),
+                //         buttonType: 'primary',
+                //         buttonSize: 'mini'
+                //     },
+                //     filter: false,
+                //     pinned: 'right',
+                //     lockPinned: true,
+                //     width: 80,
+                //     resizable: false,
+                //     sortable: false
+                // },
+                // {
+                //     headerName: this.$t('customerManage.outBed2'), field: 'id',
+                //     cellRendererFramework: 'ButtonCellRender',
+                //     cellRendererParams: param => {
+                //         return {
+                //             onClick: this.handleOut,
+                //             label: this.$t('customerManage.outBed3'),
+                //             buttonType: 'warning',
+                //             buttonSize: 'mini',
+                //             disabled: param.data['status'] !== 0
+                //         }
+                //     },
+                //     filter: false,
+                //     pinned: 'right',
+                //     lockPinned: true,
+                //     width: 100,
+                //     resizable: false,
+                //     sortable: false
+                // },
+                // {
+                //     headerName: this.$t('customerManage.changeBed2'), field: 'id',
+                //     cellRendererFramework: 'ButtonCellRender',
+                //     cellRendererParams: param => {
+                //         return {
+                //             onClick: this.handleChangeBed,
+                //             label: this.$t('customerManage.changeBed3'),
+                //             buttonType: 'success',
+                //             buttonSize: 'mini',
+                //             disabled: param.data['status'] !== 0
+                //         }
+                //     },
+                //     filter: false,
+                //     pinned: 'right',
+                //     lockPinned: true,
+                //     width: 100,
+                //     resizable: false,
+                //     sortable: false
+                // },
+                // {
+                //     headerName: this.$t('action.delete'), field: 'shop_id',
+                //     cellRendererFramework: 'ButtonCellRender',
+                //     cellRendererParams: param => {
+                //         return {
+                //             onClick: this.deleteSingle,
+                //             label: this.$t('action.delete'),
+                //             buttonType: 'danger',
+                //             buttonSize: 'mini',
+                //             disabled: param.data['member_name'] === 'superadmin'
+                //         }
+                //     },
+                //     pinned: 'right',
+                //     lockPinned: true,
+                //     width: 80,
+                //     resizable: false,
+                //     filter: false,
+                //     sortable: false
+                // }
             ]
             this.defaultColDef = {
                 // filter: 'agTextColumnFilter',
@@ -837,6 +902,7 @@
             this.getEmployees()
             // 加载护理参数设置项
             this.getNurseConfigs()
+            this.getCloud() // 是否开启同步线上
             // var column = this.gridColumnApi.getColumn('id')
             // const _this = this
             // column.addEventListener('sortChanged', function(event) {
@@ -991,7 +1057,9 @@
                 return unix2Date(param.value * 1000)
             },
             handleClick() {
-
+              if (this.activeName === 'footprint') {
+                this.$router.push({path:'/myMapHtml', query: {mapUrl: this.mapUrl}})
+              }
             },
             /** 生日选择变化,修改年龄字段 */
             birthdayChange(val) {
@@ -1152,6 +1220,9 @@
             },
 
             handleEdit(row) {
+                this.activeName = 'customerBaseInfo'
+                this.boolDevice = false
+                this.relativeRules.mobile[0].required = this.isCloud
                 this.formmodel = {
                     ...row
                 }
@@ -1182,6 +1253,15 @@
                 this.handNusreColor()
                 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) {
@@ -1293,7 +1373,7 @@
                 this.$refs['relativeForm'].validate(valid => {
                     if (valid) {
                         this.relativeFormModel.relative_id = this.formmodel.member_id
-                        API_User.add(this.relativeFormModel).then(res => {
+                        API_User.addRelative(this.relativeFormModel).then(res => {
                             this.relativeFormModel = {
                                 sex: 0,
                                 true_name: null,
@@ -1456,7 +1536,22 @@
             },
             async deleteMembers(ids) {
                 API_User.remove(ids)
-            }
+            },
+          clickLngLat() {
+            this.locationShow = true
+          },
+          setVal(val) {
+            this.formmodel.lng_lat = val
+            this.locationShow = false
+          },
+          goPage() {
+            this.$router.push({path:'/allMap'})
+          },
+          getCloud() {
+            API_SystemConfig.cloud().then(r => {
+              this.isCloud = r
+            })
+          }
         }
     }
 </script>

+ 138 - 82
src/views/customer/components/patientManager.vue

@@ -43,7 +43,7 @@
         <el-dialog :visible.sync="customerFormVisible" :title="this.$t('customerManage.customerInfo')" class="customer-dialog">
             <el-tabs v-model="activeName" type="border-card" tab-position="bottom" width="50%" @tab-click="handleClick">
                 <el-tab-pane :label="this.$t('customerManage.baseInfo')" name="customerBaseInfo">
-                    <div style="height: 720px">
+                    <div>
                         <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="120px">
                             <el-row>
                                 <el-col :span="12">
@@ -245,8 +245,8 @@
                             <el-row>
                               <el-col :span="24" :offset="8">
                                 <vue-qr
-                                    v-if="formmodel.member_id"
-                                    :text="qrCode(formmodel.member_id)"
+                                    v-if="formmodel.member_id && qrCode"
+                                    :text="qrCode"
                                     :size="150"
                                     :correctLevel="0"
                                 ></vue-qr>
@@ -492,6 +492,7 @@
     // 医院版,有责任医生,责任护士,责任护工选项 有护理项参数
     import {AG_GRID_LOCALE_CN} from '@/utils/AgGridVueLocaleCn'
     import ButtonCellRender from '@/components/AgGridCellRender/ButtonCellRender'
+    import ButtonCellRenderList from '@/components/AgGridCellRender/ButtonCellRenderList'
     import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
     import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
     import * as API_Customer from '@/api/ncs_customer'
@@ -507,10 +508,11 @@
     import vueQr from "vue-qr";
     import avator from "@/assets/avatar.jpeg";
     import {FRAME_TYPE} from "@/utils/enum/FrameTypeEnum";
+    import * as API_SystemConfig from "@/api/ncs_systemconfig";
     const serverUrl = domain.serverUrl
     export default {
         name: 'PatientManager',
-        components: {ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr },
+        components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr },
         filters: {
             unixDateFilter(val) {
                 return unixToDate(val)
@@ -537,6 +539,7 @@
                 filterState: null,
                 rowSelection: null,
                 frameworkComponents: null,
+                isCloud: false,
                 /** 列表参数 */
                 params: {
                     page_size: 20,
@@ -597,8 +600,10 @@
                     mobile: [
                         {
                             validator: (rule, value, callback) => {
-                                if (value === null || value === '') { // 手机号可为空
-                                    callback()
+                                if (this.isCloud === false) {
+                                    if (value === null || value === '') { // 手机号可为空
+                                      callback()
+                                    }
                                 }
                                 if (!RegExp.mobile.test(value)) {
                                     callback(new Error(this.$t('member.mobileInputMsg')))
@@ -657,7 +662,8 @@
                 ],
                 choice: this.$t('action.choice'),
                 colour: this.$t('action.colour'),
-                deleted: this.$t('action.delete')
+                deleted: this.$t('action.delete'),
+                qrCode: null,
             }
         },
         computed: {
@@ -704,9 +710,9 @@
                     resizable: false,
                     valueGetter: this.hashValueGetter
                 },
-                {headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 100},
-                {headerName: this.$t('customerManage.named'), field: 'named', sortable: true, filter: 'agTextColumnFilter', width: 160},
-                {headerName: this.$t('customerManage.nickname'), field: 'nickname', sortable: true, filter: 'agTextColumnFilter', width: 130},
+                {   headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 100},
+                {   headerName: this.$t('customerManage.named'), field: 'named', sortable: true, filter: 'agTextColumnFilter', width: 160},
+                {   headerName: this.$t('customerManage.nickname'), field: 'nickname', sortable: true, filter: 'agTextColumnFilter', width: 130},
                 {
                     headerName: this.$t('customerManage.customerStatus'), field: 'status', sortable: true, filterFramework: 'RadioFilter', width: 130,
                     filterParams: {
@@ -777,79 +783,118 @@
                         }
                     }
                 },
-                {
-                    headerName: this.$t('action.edit'), field: 'id',
-                    cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: {
+                // {
+                //     headerName: this.$t('action.edit'), field: 'id',
+                //     cellRendererFramework: 'ButtonCellRender',
+                //     cellRendererParams: {
+                //         onClick: this.handleEdit,
+                //         label: this.$t('action.edit'),
+                //         buttonType: 'primary',
+                //         buttonSize: 'mini'
+                //     },
+                //     filter: false,
+                //     pinned: 'right',
+                //     lockPinned: true,
+                //     width: 80,
+                //     resizable: false,
+                //     sortable: false
+                // },
+                // {
+                //     headerName: this.$t('customerManage.outBed'), field: 'id',
+                //     cellRendererFramework: 'ButtonCellRender',
+                //     cellRendererParams: param => {
+                //         return {
+                //             onClick: this.handleOut,
+                //             label: this.$t('customerManage.outBed'),
+                //             buttonType: 'warning',
+                //             buttonSize: 'mini',
+                //             disabled: param.data['status'] !== 0
+                //         }
+                //     },
+                //     filter: false,
+                //     pinned: 'right',
+                //     lockPinned: true,
+                //     width: 80,
+                //     resizable: false,
+                //     sortable: false
+                // },
+                // {
+                //     headerName: this.$t('customerManage.changeBed'), field: 'id',
+                //     cellRendererFramework: 'ButtonCellRender',
+                //     cellRendererParams: param => {
+                //         return {
+                //             onClick: this.handleChangeBed,
+                //             label: this.$t('customerManage.changeBed'),
+                //             buttonType: 'success',
+                //             buttonSize: 'mini',
+                //             disabled: param.data['status'] !== 0
+                //         }
+                //     },
+                //     filter: false,
+                //     pinned: 'right',
+                //     lockPinned: true,
+                //     width: 80,
+                //     resizable: false,
+                //     sortable: false
+                // },
+                // {
+                //     headerName: this.$t('action.delete'), field: 'shop_id',
+                //     cellRendererFramework: 'ButtonCellRender',
+                //     cellRendererParams: param => {
+                //         return {
+                //             onClick: this.deleteSingle,
+                //             label: this.$t('action.delete'),
+                //             buttonType: 'danger',
+                //             buttonSize: 'mini',
+                //             disabled: param.data['member_name'] === 'superadmin'
+                //         }
+                //     },
+                //     pinned: 'right',
+                //     lockPinned: true,
+                //     width: 80,
+                //     resizable: false,
+                //     filter: false,
+                //     sortable: false
+                // }
+              { headerName: this.$t('action.handle'), field: 'id',
+                cellRendererFramework: 'ButtonCellRenderList',
+                cellRendererParams: param => {
+                  return {
+                    list: [
+                      {
                         onClick: this.handleEdit,
                         label: this.$t('action.edit'),
                         buttonType: 'primary',
                         buttonSize: 'mini'
-                    },
-                    filter: false,
-                    pinned: 'right',
-                    lockPinned: true,
-                    width: 80,
-                    resizable: false,
-                    sortable: false
-                },
-                {
-                    headerName: this.$t('customerManage.outBed'), field: 'id',
-                    cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: param => {
-                        return {
-                            onClick: this.handleOut,
-                            label: this.$t('customerManage.outBed'),
-                            buttonType: 'warning',
-                            buttonSize: 'mini',
-                            disabled: param.data['status'] !== 0
-                        }
-                    },
-                    filter: false,
-                    pinned: 'right',
-                    lockPinned: true,
-                    width: 80,
-                    resizable: false,
-                    sortable: false
-                },
-                {
-                    headerName: this.$t('customerManage.changeBed'), field: 'id',
-                    cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: param => {
-                        return {
-                            onClick: this.handleChangeBed,
-                            label: this.$t('customerManage.changeBed'),
-                            buttonType: 'success',
-                            buttonSize: 'mini',
-                            disabled: param.data['status'] !== 0
-                        }
-                    },
-                    filter: false,
-                    pinned: 'right',
-                    lockPinned: true,
-                    width: 80,
-                    resizable: false,
-                    sortable: false
+                      },
+                      {
+                        onClick: this.handleOut,
+                        label: this.$t('customerManage.outBed'),
+                        buttonType: 'warning',
+                        buttonSize: 'mini',
+                        disabled: param.data['status'] !== 0
+                      },
+                      {
+                        onClick: this.handleChangeBed,
+                        label: this.$t('customerManage.changeBed'),
+                        buttonType: 'success',
+                        buttonSize: 'mini',
+                        disabled: param.data['status'] !== 0
+                      },{
+                        onClick: this.deleteSingle,
+                        label: this.$t('action.delete'),
+                        buttonType: 'danger',
+                        buttonSize: 'mini',
+                        disabled: param.data['member_name'] === 'superadmin'
+                      }
+                    ]}
                 },
-                {
-                    headerName: this.$t('action.delete'), field: 'shop_id',
-                    cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: param => {
-                        return {
-                            onClick: this.deleteSingle,
-                            label: this.$t('action.delete'),
-                            buttonType: 'danger',
-                            buttonSize: 'mini',
-                            disabled: param.data['member_name'] === 'superadmin'
-                        }
-                    },
-                    pinned: 'right',
-                    lockPinned: true,
-                    width: 80,
-                    resizable: false,
-                    filter: false,
-                    sortable: false
-                }
+                filter: false,
+                pinned: 'right',
+                lockPinned: true,
+                minWidth: 260,
+                resizable: false,
+                sortable: false },
             ]
             this.defaultColDef = {
                 // filter: 'agTextColumnFilter',
@@ -878,6 +923,8 @@
             })
             this.getEmptyBeds()
 
+            this.getCloud()
+
             // 加载医护人员选择项
             this.getEmployees()
             // 加载护理参数设置项
@@ -1197,6 +1244,7 @@
             },
 
             handleEdit(row) {
+                this.relativeRules.mobile[0].required = this.isCloud
                 this.formmodel = {
                     ...row
                 }
@@ -1225,6 +1273,7 @@
                 }
                 this.customerFormVisible = true
                 this.handNusreColor()
+                this.getQrCode()
                 this.getRemarks()
                 this.getRelatives()
             },
@@ -1338,7 +1387,7 @@
                 this.$refs['relativeForm'].validate(valid => {
                     if (valid) {
                         this.relativeFormModel.relative_id = this.formmodel.member_id
-                        API_User.add(this.relativeFormModel).then(res => {
+                        API_User.addRelative(this.relativeFormModel).then(res => {
                             this.relativeFormModel = {
                                 sex: 0,
                                 true_name: null,
@@ -1502,9 +1551,16 @@
             async deleteMembers(ids) {
                 API_User.remove(ids)
             },
-            qrCode(member_id){
-              return 'http://m.wdklian.com/care/apk/care.user?type=USER_LOGIN&uid=' + member_id
-            }
+          getQrCode() {
+            API_User.getUnionId(this.formmodel.member_id).then(r => {
+              this.qrCode = 'http://m.wdklian.com/care/apk/care.user?type=USER_LOGIN&uid=' + r
+            })
+          },
+          getCloud() {
+            API_SystemConfig.cloud().then(r => {
+              this.isCloud = r
+            })
+          }
         }
     }
 </script>

+ 2 - 2
src/views/customer/customerEdit.vue

@@ -430,7 +430,7 @@ export default {
             this.formmodel.frame_id = this.frameId
             this.formmodel.list = this.nurseConfigDtos
             customer_API.addAll(this.formmodel).then(res => {
-              this.$message.success('添加成功!')
+              this.$message.success(this.$t('action.addSuccess2'))
               this.clearForm()
               this.$emit('saved')
             }).catch(e => {
@@ -550,7 +550,7 @@ export default {
       }
       const _this = this
       remark_API.save(data).then(res => {
-        _this.$message.success('添加成功!')
+        _this.$message.success(this.$t('action.addSuccess2'))
         _this.getRemarks()
         _this.quxiao()
       })

+ 91 - 0
src/views/customer/myMap.vue

@@ -0,0 +1,91 @@
+<template>
+  <div>
+<!--    <label>关键词:<input v-model="keyword"></label>-->
+<!--    <label>地区:<input v-model="location"></label>-->
+    <baidu-map v-if="dialogShow" :center="center" :zoom="zoom" scroll-wheel-zoom @ready="handler" @click="clickMap">
+      <bm-view class="map"></bm-view>
+      <bm-control :offset="{width: '10px', height: '10px'}">
+        <bm-auto-complete v-model="keyword" :sugStyle="{zIndex: 1}">
+          <input v-model="keyword" placeholder="请输入地名关键字" style="width: 300px;margin-left: 20px;margin-top: 20px;">
+<!--          <search-field placeholder="请输入地名关键字"></search-field> &lt;!&ndash; 这里指代一个自定义搜索框组件 &ndash;&gt;-->
+        </bm-auto-complete>
+      </bm-control>
+      <bm-local-search :keyword="keyword" :auto-viewport="true" :location="location" :panel="false"></bm-local-search>
+      <bm-marker v-if="isShow" :position="myCenter" :dragging="true" animation="BMAP_ANIMATION_BOUNCE" clicking></bm-marker>
+<!--      <bm-city-list anchor="BMAP_ANCHOR_TOP_LEFT"></bm-city-list>-->
+      <bm-geolocation anchor="BMAP_ANCHOR_BOTTOM_RIGHT" :showAddressBar="true" :autoLocation="true"></bm-geolocation>
+    </baidu-map>
+  </div>
+</template>
+
+<script>
+import * as API_User from "@/api/user";
+
+export default {
+name: "wyMap",
+  data() {
+    return {
+      center: {lng: 0, lat: 0},
+      zoom: 3,
+      myCenter: {
+        lng: 116.404,
+        lat: 39.915
+      },
+      isShow: false,
+      location: '',
+      keyword: ''
+    }
+  },
+  props: {
+    dialogShow: {
+      type: Boolean,
+      default: false
+    },
+    lngLat: {
+      type: String,
+      default: ''
+    }
+  },
+  methods: {
+    handler ({BMap, map}) {
+      const _this = this
+      setTimeout(()=>{
+        if (_this.lngLat) {
+          _this.center.lng = _this.lngLat.split(',')[0]
+          _this.center.lat = _this.lngLat.split(',')[1]
+          _this.myCenter = _this.center
+          _this.isShow = true
+        } else {
+          _this.center.lng = 116.404
+          _this.center.lat = 39.915
+        }
+        console.log(_this.center.lng, _this.center.lat)
+        _this.zoom = 15
+      },500)
+
+    },
+    clickMap(e) {
+      console.log('点击的经纬度:' + e.Bg.lng + ', ' + e.Bg.lat)
+      this.myCenter.lng = e.Bg.lng
+      this.myCenter.lat = e.Bg.lat
+      this.isShow = true
+      let _this = this
+      this.$confirm('确定要选择这个地方吗', this.$t('action.waring'), {
+        confirmButtonText: this.$t('action.yes'),
+        cancelButtonText: this.$t('action.cancel'),
+        type: 'warning'
+      }).then(() => {
+        const lngLat = e.Bg.lng + ',' + e.Bg.lat
+        _this.$emit('childFn', lngLat);
+      })
+    },
+  }
+}
+</script>
+
+<style scoped>
+.map {
+  width: 100%;
+  height: 600px;
+}
+</style>

+ 31 - 0
src/views/customer/myMapHtml.vue

@@ -0,0 +1,31 @@
+<template>
+  <div style="width: 100%; height: 800px">
+    <iframe v-bind:src="mapUrl" frameborder="0" style="width: 100%; height: 100%"></iframe>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "myMapHtml",
+  // props: {
+  //   mapUrl: {
+  //     type: String,
+  //     default: ''
+  //   }
+  // },
+  data() {
+    return {
+      mapUrl: null
+    }
+  },
+  created() {
+  },
+  mounted() {
+    this.mapUrl = this.$route.query.mapUrl
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 8 - 8
src/views/entrace-guard/index.vue

@@ -1,10 +1,10 @@
 <template>
   <div>
-    <el-button @click="shotPicture">拍照</el-button>
-      <el-button @click="openDoor">开锁</el-button>
-      <el-button @click="lockDoor">锁门</el-button>
-      <el-button @click="addVisit">下发人证基本信息</el-button>
-      <el-button @click="addUser">添加人员</el-button>
+    <el-button @click="shotPicture">{{ this.$t('guard.shotPicture') }}</el-button>
+      <el-button @click="openDoor">{{ this.$t('guard.openDoor') }}</el-button>
+      <el-button @click="lockDoor">{{ this.$t('guard.lockDoor') }}</el-button>
+      <el-button @click="addVisit">{{ this.$t('guard.addVisit') }}</el-button>
+      <el-button @click="addUser">{{ this.$t('guard.addUser') }}</el-button>
   </div>
 </template>
 
@@ -31,12 +31,12 @@ export default {
       this.websock.onclose = this.websocketclose
     },
     websocketonopen: function() {
-      this.$message.success('服务正常,可自动发现新看板')
+      this.$message.success(this.$t('board.webSocketSuccess'))
       this.websock.send(JSON.stringify({ 'cmd': 'web_clinet', 'id': this.$store.getters.uuid }))
-      console.log('WebSocket连接成功')
+      console.log(this.$t('deviceManage.webSocketSuccess'))
     },
     websocketonerror: function(e) {
-      console.log('WebSocket连接发生错误')
+      console.log(this.$t('deviceManage.webSocketError'))
     },
     websocketonmessage: function(e) {
       console.log(e)

+ 62 - 62
src/views/hospital/clerkManager.vue

@@ -19,7 +19,7 @@
           <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
         </div>
         <div class="toolbar-btns">
-          <el-button type="primary" @click="handleAddMember">新增</el-button>
+          <el-button type="primary" @click="handleAddMember">{{ this.$t('action.add') }}</el-button>
           <!-- <el-button type="danger" @click="batchDelete">禁用</el-button>-->
         </div>
       </div>
@@ -37,7 +37,7 @@
     </ag-grid-layout>
     <!--添加会员 dialog-->
     <el-dialog
-      title="编辑成员信息"
+      :title="this.$t('clerkManage.clerkEdit')"
       :visible.sync="dialogAddMemberVisible"
       width="60%"
       :close-on-click-modal="false"
@@ -46,7 +46,7 @@
       <el-form ref="addMemberForm" :model="addMemberForm" :rules="addMemberRules" label-width="110px" class="formwrap">
         <el-row>
           <el-col :span="12">
-            <el-form-item label="头像">
+            <el-form-item :label="this.$t('member.face')">
               <el-upload
                 class="avatar-uploader"
                 :action="`${uploadurl}?scene=avatar`"
@@ -60,10 +60,10 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="登录名" prop="uname">
+            <el-form-item :label="this.$t('member.uname')" prop="uname">
               <el-input v-model="addMemberForm.uname" :maxlength="20" />
             </el-form-item>
-            <el-form-item label="密码" prop="password">
+            <el-form-item :label="this.$t('member.password')" prop="password">
               <el-input v-model="addMemberForm.password" :type="pwdType" :maxlength="20" />
               <span class="show-pwd" @click="pwdType = pwdType === 'password' ? 'text' : 'password'">
                 <svg-icon :icon-class="pwdType === 'password' ? 'eye' : 'eye-open'" />
@@ -74,12 +74,12 @@
 
         <el-row>
           <el-col :span="12">
-            <el-form-item label="真实姓名" prop="nickname">
+            <el-form-item :label="this.$t('member.nickname')" prop="nickname">
               <el-input v-model="addMemberForm.nickname" :maxlength="20" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="手机号码" prop="mobile">
+            <el-form-item :label="this.$t('member.mobile')" prop="mobile">
               <el-input v-model.number="addMemberForm.mobile" :maxlength="11" />
             </el-form-item>
           </el-col>
@@ -87,14 +87,14 @@
 
         <el-row>
           <el-col :span="12">
-            <el-form-item label="性别" class="form-item-sex">
-              <el-radio v-model="addMemberForm.sex" :label="1"></el-radio>
-              <el-radio v-model="addMemberForm.sex" :label="0"></el-radio>
+            <el-form-item :label="this.$t('member.sex')" class="form-item-sex">
+              <el-radio v-model="addMemberForm.sex" :label="1">{{ this.$t('member.man') }}</el-radio>
+              <el-radio v-model="addMemberForm.sex" :label="0">{{ this.$t('member.woman') }}</el-radio>
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <!--固定电话-->
-            <el-form-item label="身份证号">
+            <el-form-item :label="this.$t('member.IDCard')">
               <el-input v-model="addMemberForm.midentity" :maxlength="20" />
             </el-form-item>
           </el-col>
@@ -105,24 +105,24 @@
         <el-row>
           <el-col :span="12">
             <!--生日-->
-            <el-form-item label="生日" prop="birthday">
+            <el-form-item :label="this.$t('member.birthday')" prop="birthday">
               <el-date-picker
-                v-model="addMemberForm.birthday"
-                type="date"
-                :editable="false"
-                value-format="timestamp"
-                placeholder="选择生日"
-                :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+                  v-model="addMemberForm.birthday"
+                  type="date"
+                  :editable="false"
+                  value-format="timestamp"
+                  :placeholder="this.$t('member.choiceBirthday')"
+                  :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
               />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="角色" prop="role_id">
+            <el-form-item :label="this.$t('clerkManage.role')" prop="role_id">
               <el-select
-                v-model="addMemberForm.role_id"
-                placeholder="请选择角色"
-                :disabled="roleTypeDisabled"
-                clearable
+                  v-model="addMemberForm.role_id"
+                  :placeholder="this.$t('clerkManage.choiceRole')"
+                  :disabled="roleTypeDisabled"
+                  clearable
               >
 
                 <el-option
@@ -138,15 +138,15 @@
         <el-row>
           <el-col :span="24">
             <!--详细地址-->
-            <el-form-item label="详细地址" prop="address">
+            <el-form-item :label="this.$t('member.address')" prop="address">
               <el-input v-model="addMemberForm.address" :maxlength="50" />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
           <el-col :span="12">
-            <el-form-item label="所负责机构" prop="shop_id">
-              <el-select v-model="addMemberForm.shop_id" placeholder="选择机构" :disabled="shopDisabled" clearable>
+            <el-form-item :label="this.$t('clerkManage.shop')" prop="shop_id">
+              <el-select v-model="addMemberForm.shop_id" :placeholder="this.$t('clerkManage.choiceShop')" :disabled="shopDisabled" clearable>
                 <el-option v-for="(item, index) in shopOptions" :key="index" :label="item.shop_name" :value="item.shop_id" />
               </el-select>
             </el-form-item>
@@ -154,7 +154,7 @@
         </el-row>
         <el-row v-if="nurseList.length > 0">
           <el-col :span="24">
-            <el-form-item label="小组成员">
+            <el-form-item :label="this.$t('clerkManage.clerkList')">
               <div class="text item">
                 <el-row>
                   <el-checkbox-group v-model="newCheckList">
@@ -182,14 +182,14 @@
         <!--        <el-row>-->
         <!--          <el-col :span="12">-->
         <!--            &lt;!&ndash;地区&ndash;&gt;-->
-        <!--            <el-form-item label="地区" prop="region" class="form-item-region">-->
+        <!--            <el-form-item :label="地区" prop="region" class="form-item-region">-->
         <!--              <en-region-picker :api="MixinRegionApi" @changed="(object) => { addMemberForm.region = object.last_id }"/>-->
         <!--            </el-form-item>-->
         <!--          </el-col>-->
         <!--          <el-col :span="12">-->
 
         <!--            &lt;!&ndash;邮箱&ndash;&gt;-->
-        <!--            <el-form-item label="邮箱" prop="email">-->
+        <!--            <el-form-item :label="邮箱" prop="email">-->
         <!--              <el-input v-model="addMemberForm.email"></el-input>-->
         <!--            </el-form-item>-->
         <!--          </el-col>-->
@@ -197,8 +197,8 @@
 
       </el-form>
       <div slot="footer" class="dialog-footer">
-        <el-button @click="dialogAddMemberVisible = false">取 消</el-button>
-        <el-button type="primary" @click="submitAddMemberForm('addMemberForm')">确 定</el-button>
+        <el-button @click="dialogAddMemberVisible = false">{{ this.$t('action.cancel') }}</el-button>
+        <el-button type="primary" @click="submitAddMemberForm('addMemberForm')">{{ this.$t('action.yes') }}</el-button>
       </div>
     </el-dialog>
 
@@ -265,15 +265,15 @@ export default {
       /** 添加会员 表单规则 */
       addMemberRules: {
         uname: [
-          this.MixinRequired('请输入用户名'),
-          { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
+          this.MixinRequired(this.$t('member.inputUname')),
+          { min: 2, max: 20, message: this.$t('member.unameInputMsg'), trigger: 'blur' }
         ],
         password: [
-          this.MixinRequired('请输入密码!'),
+          this.MixinRequired(this.$t('member.inputPassword')),
           {
             validator: (rule, value, callback) => {
               if (!RegExp.password.test(value)) {
-                callback(new Error('密码格式有误,密码只能包含字母数字和!#$%^&*.~,字符,长度为6-20位'))
+                callback(new Error(this.$t('member.passwordInputMsg')))
               } else {
                 callback()
               }
@@ -282,16 +282,16 @@ export default {
           }
         ],
         nickname: [
-          this.MixinRequired('请输入真实姓名'),
-          { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
+          this.MixinRequired(this.$t('member.inputNickname')),
+          { min: 2, max: 20, message: this.$t('member.nicknameInputMsg'), trigger: 'blur' }
         ],
-        role_id: [this.MixinRequired('请选择角色')],
+        role_id: [this.MixinRequired(this.$t('clerkManage.choiceRole'))],
         mobile: [
-          this.MixinRequired('请输入手机号码!'),
+          this.MixinRequired(this.$t('member.inputMobile')),
           {
             validator: (rule, value, callback) => {
               if (!RegExp.mobile.test(value)) {
-                callback(new Error('手机格式格式有误'))
+                callback(new Error(this.$t('member.mobileInputMsg')))
               } else {
                 callback()
               }
@@ -300,10 +300,10 @@ export default {
           }
         ],
         address: [
-          { max: 50, message: '最长50个字符', trigger: 'blur' }
+          { max: 50, message: this.$t('member.addressInputMsg'), trigger: 'blur' }
         ],
         shop_id: [
-          { required: true, message: '请选择机构', trigger: 'blur' }
+          { required: true, message: this.$t('clerkManage.shopMsg'), trigger: 'blur' }
         ]
       },
       pwdType: 'password',
@@ -317,8 +317,8 @@ export default {
       rowSelection: null,
       showViewer: false,
       sexTransfer: [
-        { key: '男', value: 1 },
-        { key: '女', value: 0 }
+        { key: this.$t('member.man'), value: 1 },
+        { key: this.$t('member.woman'), value: 0 }
       ],
       roleId: null,
       roleZzId: null,
@@ -359,7 +359,7 @@ export default {
         resizable: false,
         valueGetter: this.hashValueGetter
       },
-      { headerName: '头像', field: 'face', sortable: true, filter: false, width: 70,
+      { headerName: this.$t('member.face'), field: 'face', sortable: true, filter: false, width: 70,
         cellRendererFramework: 'AgGridImg',
         cellRendererParams: param => {
           return {
@@ -368,16 +368,16 @@ export default {
           }
         }
       },
-      { headerName: '登录名', field: 'uname', sortable: true, filter: true, minWidth: 170 },
-      { headerName: '真实名字', field: 'clerk_name', sortable: true, filter: true, minWidth: 120 },
-      { headerName: '性别', field: 'sex', sortable: true, valueFormatter: this.formatterSex, width: 100, filterFramework: 'RadioFilter',
+      { headerName: this.$t('member.uname'), field: 'uname', sortable: true, filter: true, minWidth: 170 },
+      { headerName: this.$t('member.nickname'), field: 'clerk_name', sortable: true, filter: true, minWidth: 120 },
+      { headerName: this.$t('member.sex'), field: 'sex', sortable: true, valueFormatter: this.formatterSex, width: 100, filterFramework: 'RadioFilter',
         filterParams: {
           listData: this.sexTransfer
         }
       },
-      { headerName: '手机', field: 'mobile', sortable: true, filter: true, minWidth: 170 },
-      { headerName: '角色', field: 'role_name', sortable: true, filter: false, valueFormatter: this.formatterRole, width: 120 },
-      { headerName: '操作', field: 'id',
+      { headerName: this.$t('member.mobile'), field: 'mobile', sortable: true, filter: true, minWidth: 170 },
+      { headerName: this.$t('clerkManage.role'), field: 'role_name', sortable: true, filter: false, valueFormatter: this.formatterRole, width: 120 },
+      { headerName: this.$t('action.handle'), field: 'id',
         cellRendererFramework: 'ButtonCellRender',
         cellRendererParams: param => {
           return {
@@ -460,7 +460,7 @@ export default {
     },
     /** 单条数据删除处理 */
     handlerDelete(ids) {
-      this.$confirm('你确定要禁用此用户?', this.$t('action.waring'), {
+      this.$confirm(this.$t('member.disableClerk'), this.$t('action.waring'), {
         confirmButtonText: this.$t('action.yes'),
         cancelButtonText: this.$t('action.cancel'),
         type: 'warning'
@@ -470,7 +470,7 @@ export default {
             this.GET_MemberList()
             this.$message({
               type: 'success',
-              message: '已禁用!'
+              message: this.$t('member.disabled')
             })
           }
         ).catch(response => {
@@ -482,7 +482,7 @@ export default {
       }).catch((response) => {
         this.$message({
           type: 'info',
-          message: '已取消禁用'
+          message: this.$t('member.disableCancel')
         })
       })
     },
@@ -503,7 +503,7 @@ export default {
     /** 批量数据删除处理(删除选中的行) */
     batchDelete: function() {
       if (this.multipleSelection.length === 0) {
-        this.$alert('没有选择任何记录!', '系统提示', {
+        this.$alert(this.$t('action.noChoice'), this.$t('action.systemPrompt'), {
           confirmButtonText: this.$t('action.yes'),
           callback: action => {
           }
@@ -518,11 +518,11 @@ export default {
     },
     /** 性别格式化 */
     formatterSex(row) {
-      return row.data.sex === 1 ? '男' : row.data.sex === 0 ? '女' : '未知'
+      return row.data.sex === 1 ? this.$t('action.man') : row.data.sex === 0 ? this.$t('action.woman') : this.$t('action.unknown')
     },
     formatterRole(row) {
       if (row.data.founder === 1) {
-        return '机构负责人'
+        return this.$t('clerkManage.admin')
       } else {
         return row.data.role_name
       }
@@ -667,11 +667,11 @@ export default {
         const isLt2M = file.size / 1024 / 1024 < 2
 
         if (!isImg) {
-          this.$message.error('上传头像图片只能是 JPG、PNG、GIF 格式!')
+          this.$message.error(this.$t('member.faceImg'))
           reject()
         }
         if (!isLt2M) {
-          this.$message.error('上传头像图片大小不能超过 2MB!')
+          this.$message.error(this.$t('member.faceSize'))
           reject()
         }
 
@@ -682,15 +682,15 @@ export default {
             const width = image.width
             const height = image.height
             if (width > 500 || width < 100) {
-              this.$message.error('图片宽度必须在100~500之间,宽高比为1:1!')
+              this.$message.error(this.$t('member.faceError1'))
               reject()
             }
             if (width !== height) {
-              this.$message.error('请上传宽高比为1:1的图片')
+              this.$message.error(this.$t('member.faceError2'))
               reject()
             }
             if (height > 500 || height < 100) {
-              this.$message.error('图片高度必须在100~500之间!')
+              this.$message.error(this.$t('member.faceError3'))
               reject()
             }
             resolve()

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 302 - 243
src/views/hospital/ncs_customer/customerManager.vue


+ 142 - 120
src/views/hospital/ncs_device/deviceManager.vue

@@ -20,7 +20,7 @@
           <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
         </div>
         <div class="toolbar-btns">
-          <el-button type="primary" size="mini" @click="handleAdd">新增设备</el-button>
+          <el-button type="primary" size="mini" @click="handleAdd">{{ this.$t('deviceManage.deviceAdd') }}</el-button>
         </div>
       </div>
       <el-pagination
@@ -41,112 +41,112 @@
       <el-form ref="deviceEditForm" :rules="deviceRules" label-width="120px" :model="deviceModel">
         <el-row>
           <el-col :span="12">
-            <el-form-item label="设备类型" prop="device_type">
-              <el-select v-model="deviceModel.device_type" placeholder="请选择设备类型" :disabled="deviceTypeDisabled" clearable @change="deviceTypeChange">
+            <el-form-item :label="this.$t('deviceManage.deviceType')" prop="device_type">
+              <el-select v-model="deviceModel.device_type" :placeholder="this.$t('deviceManage.choiceDeviceType')" :disabled="deviceTypeDisabled" clearable @change="deviceTypeChange">
                 <el-option v-for="(item,index) in deviceTypeTransfer" :key="index" :label="item.key" :value="item.value" />
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="设备别名" prop="name">
-              <el-input v-model="deviceModel.name" clearable :maxlength="20" placeholder="请输入设备别名" />
+            <el-form-item :label="this.$t('deviceManage.deviceName')" prop="name">
+              <el-input v-model="deviceModel.name" clearable :maxlength="20" :placeholder="this.$t('deviceManage.inputDeviceName')" />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
           <el-col :span="12">
-            <el-form-item label="出厂编号" prop="code">
-              <el-input v-model="deviceModel.code" clearable placeholder="请输入出厂编号" />
+            <el-form-item :label="this.$t('deviceManage.code')" prop="code">
+              <el-input v-model="deviceModel.code" clearable :placeholder="this.$t('deviceManage.inputCode')" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="设备型号" prop="model">
-              <el-input v-model="deviceModel.model" clearable placeholder="请输入设备型号" />
+            <el-form-item :label="this.$t('deviceManage.model')" prop="model">
+              <el-input v-model="deviceModel.model" clearable :placeholder="this.$t('deviceManage.inputModel')" />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
           <el-col :span="12">
-            <el-form-item label="有线物理地址" prop="eth_mac">
-              <el-input v-model="deviceModel.eth_mac" clearable placeholder="请输入物理MAC地址" />
+            <el-form-item :label="this.$t('deviceManage.ethMac')" prop="eth_mac">
+              <el-input v-model="deviceModel.eth_mac" clearable :placeholder="this.$t('deviceManage.inputEthMac')" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="有线IP地址" prop="eth_ip">
-              <el-input v-model="deviceModel.eth_ip" clearable placeholder="请输入IP地址" />
+            <el-form-item :label="this.$t('deviceManage.ethIp')" prop="eth_ip">
+              <el-input v-model="deviceModel.eth_ip" clearable :placeholder="this.$t('deviceManage.inputEthIp')" />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
           <el-col :span="12">
-            <el-form-item label="WIFI物理地址" prop="wifi_mac">
-              <el-input v-model="deviceModel.wifi_mac" clearable placeholder="请输入WIFI MAC地址" readonly />
+            <el-form-item :label="this.$t('deviceManage.wifiMac')" prop="wifi_mac">
+              <el-input v-model="deviceModel.wifi_mac" clearable :placeholder="this.$t('deviceManage.inputWifiMac')" readonly />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="WIFIIP地址" prop="wifi_ip">
-              <el-input v-model="deviceModel.wifi_ip" clearable placeholder="请输入WIFI IP地址" readonly />
+            <el-form-item :label="this.$t('deviceManage.wifiIp')" prop="wifi_ip">
+              <el-input v-model="deviceModel.wifi_ip" clearable :placeholder="this.$t('deviceManage.inputWifiIp')" readonly />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
           <el-col :span="12">
-            <el-form-item label="软件版本" prop="soft_ver">
-              <el-input v-model="deviceModel.soft_ver" clearable placeholder="请输入软件版本号" />
+            <el-form-item :label="this.$t('deviceManage.softVer')" prop="soft_ver">
+              <el-input v-model="deviceModel.soft_ver" clearable :placeholder="this.$t('deviceManage.inputSoftVer')" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="硬件版本" prop="hard_ver">
-              <el-input v-model="deviceModel.hard_ver" clearable placeholder="请输入硬件版本号" />
+            <el-form-item :label="this.$t('deviceManage.hardVer')" prop="hard_ver">
+              <el-input v-model="deviceModel.hard_ver" clearable :placeholder="this.$t('deviceManage.inputHardVer')" />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
           <el-col :span="12">
-            <el-form-item label="WIFI热点">
-              <el-input v-model="deviceModel.wifi_hostname" :readonly="true" clearable placeholder="请输入WIFI热点名称" />
+            <el-form-item :label="this.$t('deviceManage.wifiHostname')">
+              <el-input v-model="deviceModel.wifi_hostname" :readonly="true" clearable :placeholder="this.$t('deviceManage.inputWifiHostname')" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="WIFI密码">
-              <el-input v-model="deviceModel.wifi_password" :readonly="true" clearable placeholder="请输入WIFI热点密码" />
+            <el-form-item :label="this.$t('deviceManage.wifiPassword')">
+              <el-input v-model="deviceModel.wifi_password" :readonly="true" clearable :placeholder="this.$t('deviceManage.inputPassword')" />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
 <!--          <el-col :span="12">-->
-<!--            <el-form-item label="设备位置">-->
+<!--            <el-form-item :label="设备位置">-->
 <!--              <span>{{ deviceModel.full_name }}</span>-->
 <!--            </el-form-item>-->
 <!--          </el-col>-->
           <el-col :span="12">
-            <el-form-item label="设备位置" prop="frame_id">
-              <el-select v-model="deviceModel.frame_id" filterable :disabled="frameSelectabled" placeholder="请选择安装位置">
+            <el-form-item :label="this.$t('deviceManage.frameName')" prop="frame_id">
+              <el-select v-model="deviceModel.frame_id" filterable :disabled="frameSelectabled" :placeholder="this.$t('deviceManage.choiceFrameName')">
                 <el-option v-for="(item,index) in typeFrames" :key="index" :label="item.full_name" :value="item.id" />
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="设备电话号码">
-              <el-input v-model="deviceModel.phone_number" clearable placeholder="请输入设备电话号码" />
+            <el-form-item :label="this.$t('deviceManage.phoneNumber')">
+              <el-input v-model="deviceModel.phone_number" clearable :placeholder="this.$t('deviceManage.inputPhoneNumber')" />
             </el-form-item>
           </el-col>
         </el-row>
 
         <el-row>
           <el-col :span="12">
-            <el-form-item label="设备优先级">
+            <el-form-item :label="this.$t('deviceManage.priority')">
               <el-input-number v-model="deviceModel.priority" controls-position="right" :min="1" :max="99" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="后备设备ID">
+            <el-form-item :label="this.$t('deviceManage.backupId')">
               <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-form-item :label="this.$t('deviceManage.deviceStatus')">
+              <el-checkbox v-model="deviceModel.status" :true-label="1" :false-label="0">{{ this.$t('deviceManage.choiceDeviceStatus') }}</el-checkbox>
               <!--              <el-radio v-model="formmodel.status" :label="1">启用</el-radio>-->
               <!--              <el-radio v-model="formmodel.status" :label="0">不启用</el-radio>-->
             </el-form-item>
@@ -154,8 +154,8 @@
         </el-row>
         <el-row v-if="hasRoleId">
           <el-col :span="12">
-            <el-form-item label="适用角色" prop="role_id">
-              <el-select v-model="deviceModel.role_id" placeholder="适用角色" clearable>
+            <el-form-item :label="this.$t('deviceManage.roleName')" prop="role_id">
+              <el-select v-model="deviceModel.role_id" :placeholder="this.$t('deviceManage.roleName')" clearable>
                 <el-option v-for="item in rolesOptions" :key="item.role_id" :label="item.role_name" :value="item.role_id" />
               </el-select>
             </el-form-item>
@@ -163,15 +163,15 @@
         </el-row>
         <el-row v-if="hasAudioId">
           <el-col :span="12">
-            <el-form-item label="上属总线转换盒" prop="trans_audio_id">
-              <el-select v-model="deviceModel.trans_audio_id" placeholder="上属总线转换盒" clearable>
+            <el-form-item :label="this.$t('deviceManage.transAudio')" prop="trans_audio_id">
+              <el-select v-model="deviceModel.trans_audio_id" :placeholder="this.$t('deviceManage.transAudio')" clearable>
                 <el-option v-for="item in audioOptions" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="上属485转换盒" prop="trans_rs485_id">
-              <el-select v-model="deviceModel.trans_rs485_id" placeholder="上属485转换盒" clearable>
+            <el-form-item :label="this.$t('deviceManage.transRs485')" prop="trans_rs485_id">
+              <el-select v-model="deviceModel.trans_rs485_id" :placeholder="this.$t('deviceManage.transRs485')" clearable>
                 <el-option v-for="item in rs485Options" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
@@ -179,15 +179,24 @@
         </el-row>
         <el-row v-if="hasAudioId">
           <el-col :span="12">
-            <el-form-item label="485地址" prop="sip_id">
-              <el-input v-model="deviceModel.sip_id" clearable placeholder="请输入485地址" />
+            <el-form-item :label="this.$t('deviceManage.re485SipId')" prop="sip_id">
+              <el-input v-model="deviceModel.sip_id" clearable :placeholder="this.$t('deviceManage.inputRe485SipId')" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row v-if="isVitalSigns">
+          <el-col :span="12">
+            <el-form-item :label="this.$t('deviceManage.signType')" prop="sign_type">
+              <el-select v-model="deviceModel.sign_type" :placeholder="this.$t('deviceManage.choiceSignType')" clearable>
+                <el-option v-for="(item, index) in Object.keys(vitalSignsDeviceEnum)" :key="index" :label="vitalSignsDeviceEnum[item]" :value="parseInt(item)" />
+              </el-select>
             </el-form-item>
           </el-col>
         </el-row>
         <el-row v-if="hasSosDeviceSettings">
           <el-col :span="12">
-            <el-form-item label="报警设备模式" prop="type">
-              <el-select v-model="sosDeviceSetting.type" placeholder="报警设备模式" clearable>
+            <el-form-item :label="this.$t('deviceManage.sosDeviceSettingType')" prop="type">
+              <el-select v-model="sosDeviceSetting.type" :placeholder="this.$t('deviceManage.sosDeviceSettingType')" clearable>
                 <el-option v-for="item in sosDeviceSettingsTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
               </el-select>
             </el-form-item>
@@ -195,38 +204,36 @@
         </el-row>
         <el-row v-if="sosDeviceSetting.type === 2">
           <el-col :span="12">
-            <el-form-item label="报警时间" prop="setting_time">
+            <el-form-item :label="this.$t('deviceManage.sosDeviceSettingTime')" prop="setting_time">
               <el-input-number v-model="sosDeviceSetting.setting_time" controls-position="right" :min="0" :max="60" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="报警时间单位" prop="unit">
+            <el-form-item :label="this.$t('deviceManage.sosDeviceSettingUnit')" prop="unit">
               <el-radio-group v-model="sosDeviceSetting.unit" size="mini" prop="unit">
-                <el-radio label="小时">小时</el-radio>
-                <el-radio label="分钟">分钟</el-radio>
-                <el-radio label="秒">秒</el-radio>
+                <el-radio :label="this.$t('action.time')">{{ this.$t('action.time') }}</el-radio>
+                <el-radio :label="this.$t('action.minute')">{{ this.$t('action.minute') }}</el-radio>
+                <el-radio :label="this.$t('action.second')">{{ this.$t('action.second') }}</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
         </el-row>
         <el-row v-if="isLedDevice">
           <el-col :span="12">
-            <el-form-item label="点阵屏规格" prop="led_resolution_ratio">
-              <el-input v-model="deviceModel.led_resolution_ratio" clearable placeholder="点阵屏规格" />
+            <el-form-item :label="this.$t('deviceManage.ledResolutionRatio')" prop="led_resolution_ratio">
+              <el-input v-model="deviceModel.led_resolution_ratio" clearable :placeholder="点阵屏规格" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="语音播放" prop="led_voice">
-              <el-radio-group v-model="deviceModel.led_voice" size="mini" prop="unit">
-                <el-radio :label=1>开启语音</el-radio>
-                <el-radio :label=0>关闭语音</el-radio>
-              </el-radio-group>
+            <el-form-item :label="this.$t('deviceManage.ledVoice')" prop="led_voice">
+              <el-checkbox v-model="deviceModel.led_voice" :true-label="1" :false-label="0">
+                {{ this.$t('deviceManage.ledVoiceStatus') }}</el-checkbox>
             </el-form-item>
           </el-col>
         </el-row>
         <el-row v-if="isLedDevice">
           <el-col :span="12">
-            <el-form-item label="字体大小" prop="led_font_size">
+            <el-form-item :label="this.$t('deviceManage.ledFontSize')" prop="led_font_size">
               <el-input-number v-model="deviceModel.led_font_size" controls-position="right" :min="0" :max="60" />
             </el-form-item>
           </el-col>
@@ -234,7 +241,7 @@
 
         <el-row v-if="groupHostDevices.length > 0">
           <el-col :span="24">
-            <el-form-item label="护士主机列表">
+            <el-form-item :label="this.$t('deviceManage.hostDeviceList')">
               <div class="text item">
                 <el-row>
                   <el-checkbox-group v-model="newCheckList">
@@ -259,7 +266,7 @@
         </el-row>
       </el-form>
       <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="handlerFormSubmit('deviceEditForm')">确 定</el-button>
+        <el-button type="primary" @click="handlerFormSubmit('deviceEditForm')">{{ this.$t('action.yes') }}</el-button>
       </div>
     </el-dialog>
     <!-- 设备编辑弹窗 -->
@@ -314,38 +321,41 @@ export default {
       },
       /** device 弹窗 **/
       deviceDialogVisible: false,
-      deviceEditTitle: '添加设备',
+      deviceEditTitle: this.$t('deviceManage.deviceAdd'),
       deviceModel: {},
       deviceTypeDisabled: false,
       deviceRules: {
         name: [
-          this.MixinRequired('请输入设备别名!')
+          this.MixinRequired(this.$t('deviceManage.inputDeviceName'))
         ],
         device_type: [
-          { required: true, message: '请选择设备类型', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.choiceDeviceType'), trigger: 'blur' }
         ],
         code: [
-          { required: true, message: '请输入设备编码', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.inputCode'), trigger: 'blur' }
         ],
         model: [
-          { required: true, message: '请输入设备型号', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.inputModel'), trigger: 'blur' }
         ],
         eth_mac: [
-          { required: true, message: '请输入设备MAC地址', trigger: 'blur' },
+          { required: true, message: this.$t('deviceManage.inputEthMac'), trigger: 'blur' },
           // { pattern: /^([0-9A-Fa-f]{2}:?){6}/gi, message: '请输入正确的MAC地址', trigger: 'blur' }
-          { pattern: null, message: '请输入正确的MAC地址', trigger: 'blur' }
+          { pattern: null, message: this.$t('deviceManage.inputTrueEthMac'), trigger: 'blur' }
         ],
         frame_id: [
-          { required: Object.keys(this.frame).length === 0, message: '请选安装位置!', trigger: 'blur' } // 没有传入frame 属性,必须选择安装位置
+          { required: Object.keys(this.frame).length === 0, message: this.$t('deviceManage.choiceFrameName'), trigger: 'blur' } // 没有传入frame 属性,必须选择安装位置
         ],
         phone_number: [
-          { required: true, message: '请输入设备电话号码', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.phoneNumber'), trigger: 'blur' }
         ],
         role_id: [
-          { required: true, message: '请选择适用人', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.choiceRoleName'), trigger: 'blur' }
         ],
         trans_audio_id: [
-          { required: true, message: '请选择总线转换盒', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.choiceTransAudio'), trigger: 'blur' }
+        ],
+        sign_type: [
+          { required: true, message: this.$t('deviceManage.choiceSignType'), trigger: 'blur' }
         ],
         // trans_rs485_id: [
         //   { required: true, message: '请选择485转换盒', trigger: 'blur' }
@@ -354,49 +364,55 @@ export default {
         //   { required: true, message: '请输入485地址', trigger: 'blur' }
         // ]
         led_resolution_ratio: [
-          { required: true, message: '点阵屏规格', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.ledResolutionRatio'), trigger: 'blur' }
         ],
         led_voice: [
-          { required: true, message: '点阵屏语音播放', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.ledVoice'), trigger: 'blur' }
         ],
         led_font_size: [
-          { required: true, message: '点阵屏字体大小', trigger: 'blur' }
+          { required: true, message: this.$t('deviceManage.ledFontSize'), trigger: 'blur' }
         ],
       },
       partFrames: [],
       typeFrames: [],
       /** 设备类型转换数组 **/
       deviceTypeTransfer: [
-        { key: '护士主机', value: 1 },
-        { key: '医生主机', value: 2 },
-        { key: '门口机', value: 3 },
-        { key: '床位分机', value: 4 },
-        { key: 'LCD走廊屏', value: 5 },
-        { key: 'LED点阵屏', value: 6 },
-        { key: '移动设备', value: 7 },
+        { key: this.$t('deviceType.NURSE_HOST'), value: 1 },
+        { key: this.$t('deviceType.DOCTOR_HOST'), value: 2 },
+        { key: this.$t('deviceType.DOOR_DEVICE'), value: 3 },
+        { key: this.$t('deviceType.DIGIT_BED_DEVICE'), value: 4 },
+        { key: this.$t('deviceType.LCD_SCREEN'), value: 5 },
+        { key: this.$t('deviceType.LED_SCREEN'), value: 6 },
+        { key: this.$t('deviceType.NURSE_WATCH'), value: 7 },
         // { key: '护工腕表', value: 8 },
-        { key: '病人腕表', value: 9 },
-        { key: '手机App', value: 10 },
-        { key: '总线转换盒', value: 11 },
-        { key: '模拟分机', value: 12 },
-        { key: '模拟紧急按钮', value: 13 },
-        { key: '模拟门灯', value: 14 },
-        { key: '遥控器', value: 15 },
-        { key: '信标', value: 16 },
-        { key: '看板', value: 17 },
-        { key: '485转换盒', value: 20 },
-        { key: '紧急按钮', value: 21 },
-        { key: '485门口机', value: 22 },
-        { key: '红外报警器', value: 23 },
-        { key: '用水监控器', value: 24 },
-        { key: '家用燃起报警器', value: 25 },
-        { key: '家用烟雾报警器', value: 26 },
-        { key: '一键报警器', value: 27 },
-        { key: '门磁传感器', value: 30 }
+        { key: this.$t('deviceType.USER_WATCH'), value: 9 },
+        { key: this.$t('deviceType.CELL_PHONE'), value: 10 },
+        { key: this.$t('deviceType.TRANSFER_DEVICE'), value: 11 },
+        { key: this.$t('deviceType.SIMULATE_BED_DEVICE'), value: 12 },
+        { key: this.$t('deviceType.SIMULATE_EMERGENCY_BUTTON'), value: 13 },
+        { key: this.$t('deviceType.SIMULATE_DOOR_LIGHT'), value: 14 },
+        { key: this.$t('deviceType.REMOTE_CONTROL'), value: 15 },
+        { key: this.$t('deviceType.BEACON'), value: 16 },
+        { key: this.$t('deviceType.INFORMATION_BOARD'), value: 17 },
+        { key: this.$t('deviceType.ENTRANCE_GUARD'), value: 18 },
+        { key: this.$t('deviceType.VISITATION'), value: 19 },
+        { key: this.$t('deviceType.RS485_TRANSFER'), value: 20 },
+        { key: this.$t('deviceType.EMERGENCY_BUTTON'), value: 21 },
+        { key: this.$t('deviceType.RS485_DOOR'), value: 22 },
+        { key: this.$t('deviceType.ALARM_BODY_INDUCTIVE'), value: 23 },
+        { key: this.$t('deviceType.ALARM_WATER_OVERFLOW'), value: 24 },
+        { key: this.$t('deviceType.ALARM_HOUSEHOLD_GAS'), value: 25 },
+        { key: this.$t('deviceType.ALARM_HOUSEHOLD_SMOKE'), value: 26 },
+        { key: this.$t('deviceType.ALARM_BUTTON_SOS'), value: 27 },
+        { key: this.$t('deviceType.VITAL_SIGNS_DEVICE'), value: 28 },
+        { key: this.$t('deviceType.ALARM_RESTRAINT_BAND'), value: 29 },
+        { key: this.$t('deviceType.DOOR_LOCK'), value: 30 },
+        { key: this.$t('deviceType.EMERGENCY_GATEWAY'), value: 31 },
+        { key: this.$t('deviceType.ALARM_433BUTTON'), value: 32 }
       ],
       deviceStatusTransfer: [
-        { key: '启用', value: 1, color: 'green' },
-        { key: '未启用', value: 0, color: 'red' }
+        { key: this.$t('deviceManage.statusTure'), value: 1, color: 'green' },
+        { key: this.$t('deviceManage.statusFalse'), value: 0, color: 'red' }
       ],
       rolesOptions: [],
       hasRoleId: false,
@@ -459,7 +475,7 @@ export default {
         valueGetter: this.hashValueGetter
       },
       // { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 100 },
-      { headerName: '设备类型', field: 'device_type', sortable: true, filterFramework: 'ListFilter', width: 160,
+      { headerName: this.$t('deviceManage.deviceType'), field: 'device_type', sortable: true,
         filterParams: {
           listData: this.deviceTypeTransfer
         },
@@ -468,27 +484,28 @@ export default {
       // lockPosition 锁定位置,会在第一列
       // lockPinned = true 不能拖动然后固定
       // resizeable 单元个大小是否可以调整
-      { headerName: '设备别名', field: 'name', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '设备状态', field: 'status', sortable: true, filterFramework: 'RadioFilter',
+      { headerName: this.$t('deviceManage.deviceName'), field: 'name', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.status'), field: 'status', sortable: true,
+        filterFramework: 'RadioFilter',
         filterParams: {
           listData: this.deviceStatusTransfer
         },
         cellRenderer: this.deviceStatusFormatter
       },
 
-      { 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' },
-      { headerName: '设备型号', field: 'model', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '出厂编号', field: 'code', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '软件版本', field: 'soft_ver', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '硬件版本', field: 'hard_ver', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '无线MAC地址', field: 'wifi_mac', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '无线IP地址', field: 'wifi_ip', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: 'SIP账号', field: 'sip_id', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '更新时间', field: 'update_time', sortable: true, filter: 'agDateColumnFilter', valueFormatter: this.unixDateFormatter, filterParams: {
+      { headerName: this.$t('deviceManage.frameFullName'), field: 'full_name', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.phoneNumber'), field: 'phone_number', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.ethMac'), field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.ethIp'), field: 'eth_ip', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.ethIpPort'), field: 'eth_ip_port', sortable: true, filter: 'agNumberColumnFilter' },
+      { headerName: this.$t('deviceManage.model'), field: 'model', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.code'), field: 'code', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.softVer'), field: 'soft_ver', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.hardVer'), field: 'hard_ver', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.wifiMac'), field: 'wifi_mac', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.wifiIp'), field: 'wifi_ip', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.sipId'), field: 'sip_id', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('deviceManage.updateTime'), field: 'update_time', sortable: true, filter: 'agDateColumnFilter', valueFormatter: this.unixDateFormatter, filterParams: {
         comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
           const celldate = unixToDate(cellValue, 'yyyy-MM-dd 00:00:00')
           return (new Date(celldate).getTime() / 1000) - (filterLocalDateAtMidnight.getTime() / 1000)
@@ -636,7 +653,8 @@ export default {
     /** 获取设备类型文字显示,从deviceTypeTransfer 中找出value值对应的key显示出来 */
     deviceTypeGetter(params) {
       const gridVal = params.data.device_type
-      return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
+      // return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
+      return DEVICE_TYPE.getDescFromValue(gridVal)
     },
     /** 格式化时间函数 */
     unixDateFormatter(param) {
@@ -720,6 +738,7 @@ export default {
           val === DEVICE_TYPE.RS485_DOOR ||
           val === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON ||
           val === DEVICE_TYPE.SIMULATE_DOOR_LIGHT
+      this.isVitalSigns = val === DEVICE_TYPE.VITAL_SIGNS_DEVICE
       this.hasSosDeviceSettings = val === DEVICE_TYPE.ALARM_BODY_INDUCTIVE ||
           val === DEVICE_TYPE.DOOR_LOCK
       this.isLedDevice = val === DEVICE_TYPE.LED_SCREEN ||
@@ -749,7 +768,8 @@ export default {
       } else if (val === DEVICE_TYPE.DIGIT_BED_DEVICE ||
           val === DEVICE_TYPE.SIMULATE_BED_DEVICE ||
           val === DEVICE_TYPE.REMOTE_CONTROL ||
-          val === DEVICE_TYPE.CELL_PHONE
+          val === DEVICE_TYPE.CELL_PHONE ||
+          val === DEVICE_TYPE.ALARM_433BUTTON
       ) {
         this.getFramesByType(FRAME_TYPE.BED)
       } else {
@@ -781,10 +801,11 @@ export default {
       this.hasRoleId = false
       this.getRoles({ page_size: 200, page_no: 1, fixedCondition: ' shop_id = -1', sort: ' role_id', dir: 'desc' })
       this.hasAudioId = false
+      this.isVitalSigns = false
       this.hasSosDeviceSettings = false
       this.isLedDevice = false
       this.getDevices(this.$store.getters.partId)
-      this.deviceEditTitle = '添加设备'
+      this.deviceEditTitle = this.$t('deviceManage.deviceAdd')
       this.deviceDialogVisible = true
       this.deviceTypeDisabled = false // 新增设备可以选择设备类型
       this.deviceModel.full_name = this.frame.full_name
@@ -802,6 +823,7 @@ export default {
           params.device_type === DEVICE_TYPE.RS485_DOOR ||
           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 ||
           params.device_type === DEVICE_TYPE.DOOR_LOCK
       this.isLedDevice = params.device_type === DEVICE_TYPE.LED_SCREEN ||
@@ -812,7 +834,7 @@ export default {
       if (params.device_type === DEVICE_TYPE.NURSE_HOST && params.part_id == this.$store.getters.partId) {
         this.getGroupHost(params.id, params.part_id)
       }
-      this.deviceEditTitle = '修改设备'
+      this.deviceEditTitle = this.$t('deviceManage.deviceEdit')
       this.deviceDialogVisible = true
       this.deviceTypeDisabled = true // 修改设备时,不能改变设备类型
     },

+ 2 - 2
src/views/hospitalFrame/hospitalFrame.vue

@@ -237,7 +237,7 @@ export default {
       const params = { type: 4, name: this.frameName, part_id: this.$store.getters.partId, parent_id: parent_id }
       params.full_name = params.name + '房'
       HospitalFrame_API.addHospitalFrame(params).then(response => {
-        this.$message.success('添加成功!')
+        this.$message.success(this.$t('action.addSuccess2'))
         this.GET_All()
       })
     },
@@ -307,7 +307,7 @@ export default {
             }
             params.full_name = this.fullName + '房-' + params.name + '床'
             HospitalFrame_API.addHospitalFrame(params).then(response => {
-              this.$message.success('添加成功!')
+              this.$message.success(this.$t('action.addSuccess2'))
               this.handleFrameFinished()
             })
           }

+ 239 - 0
src/views/ncs-485/index.vue

@@ -0,0 +1,239 @@
+<template>
+  <div class="container">
+    <div style="margin: 10px">
+      <el-select v-model="shopId" @change="changeShop" filterable>
+        <el-option v-for="(item, index) in partList" :key="index" :label="item.shop_name" :value="item.shop_id" />
+      </el-select>
+    </div>
+    <el-tabs v-if="zhhList.length > 0" v-model="activeName" type="card" @tab-click="handleClick">
+      <el-tab-pane name="id-0" label="无转换盒"></el-tab-pane>
+      <el-tab-pane v-for="(item, index) in zhhList" :key="index" :name="item.eth_mac+ '-' + item.id" :label="item.name"></el-tab-pane>
+    </el-tabs>
+    <div class="table-wrapper" style="padding-bottom: 10px;padding-left: 10px">
+      <div v-if="tid !== '0'" style="padding: 5px;">
+        <el-button :disabled="multipleSelection.length === 0" type="success" @click="sendAll">
+          批量发送
+        </el-button>
+        <el-switch v-model="boolOpen" active-text="打印具体消息" inactive-text="不打印具体消息" style="margin-left: 10px"></el-switch>
+      </div>
+      <el-table :data="deviceList" stripe border style="width: 100%" @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" />
+        <el-table-column prop="sip_id" label="485地址" width="130" align="center" />
+<!--        <el-table-column prop="send_time" label="发送时间" min-width="130" align="center" />-->
+        <el-table-column prop="receive_time" label="流程耗时" width="130" align="center" />
+        <el-table-column prop="state" label="状态" width="140" align="center">
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.state === 0" type="warning" disable-transitions>等待发送</el-tag>
+            <el-tag v-if="scope.row.state === 1" type="primary" disable-transitions>发送成功等待返回</el-tag>
+            <el-tag v-if="scope.row.state === 2" type="success" disable-transitions>已返回完成流程</el-tag>
+            <el-tag v-if="scope.row.state === -1" type="danger" disable-transitions>发送失败</el-tag>
+            <el-tag v-if="scope.row.state === -2" type="danger" disable-transitions>返回超时</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column style="text-align: left;" label="操作" width="120" fixed="right">
+          <template slot-scope="scope">
+            <el-button v-if="tid !== '0'" type="success" size="mini" @click="handlerEdit(scope.$index, scope.row, 1)">
+              发送
+            </el-button>
+<!--            <el-button type="info" size="mini" @click="handlerEdit(scope.$index, scope.row, 2)">-->
+<!--              设置转换盒-->
+<!--            </el-button>-->
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div style="height: 500px;overflow:auto;margin: 10px;padding: 10px;" v-infinite-scroll>
+      <el-card class="box-card">
+        <div slot="header" class="clearfix">
+          <span>日志消息</span>
+          <el-button style="float: right; padding: 3px 0" type="text" @click="closeLog">清空日志</el-button>
+        </div>
+        <div>
+          <el-timeline :reverse="true">
+            <el-timeline-item
+                v-for="(activity, index) in activities"
+                :key="index"
+                :type="activity.type"
+                :icon="activity.icon"
+                :timestamp="unixDateFormatter(activity.timestamp)">
+              {{activity.content}}
+            </el-timeline-item>
+          </el-timeline>
+        </div>
+      </el-card>
+    </div>
+  </div>
+</template>
+
+<script>
+import { listByType } from '@/api/ncs_partInfo'
+import { get485DeviceAndFrame, getDeviceByType } from '@/api/ncs_device'
+import { unix2Date } from '@/utils/Foundation'
+const DeviceUrl = domain.DeviceUrl
+export default {
+  name: "index",
+  data() {
+    return {
+      partList: [],
+      zhhList: [],
+      shopId: null,
+      activeName: null,
+      deviceList: [],
+      tid: null,
+      activities: [],
+      multipleSelection: [],
+      boolOpen: false
+    }
+  },
+  mounted() {
+    this.initWebSocket()
+    this.API_getPartList()
+  },
+  methods: {
+    initWebSocket: function() {
+      let stockbase = DeviceUrl.replace('http', 'ws')
+      this.websock = new WebSocket(stockbase + '/device485/listening/485Id')
+      this.websock.onopen = this.websocketonopen
+      this.websock.onerror = this.websocketonerror
+      this.websock.onmessage = this.websocketonmessage
+      this.websock.onclose = this.websocketclose
+    },
+    websocketonopen: function() {
+      console.log(this.$t('deviceManage.webSocketSuccess'))
+    },
+    websocketonerror: function(e) {
+      console.log(this.$t('deviceManage.webSocketError'))
+    },
+    websocketonmessage: function(e) {
+      // console.log('收到消息:', e)
+      const data = JSON.parse(e.data)
+      const index = this.deviceList.findIndex(p => p.sip_id.toLowerCase() === data.rs485mac.toLowerCase())
+      if (index === -1) {
+        return
+      }
+      const time = (new Date()).valueOf()
+      const item = this.deviceList[index]
+      let active = {
+        content: '设备:' + data.rs485mac  + '----' + data.rs485msg,
+        timestamp: time,
+        // type: 'primary'
+      }
+      if (data.type === 1) { // 发送
+        // this.$set(this.deviceList[index], 'send_time', time)
+        item.send_time = time
+        active.icon = 'el-icon-more'
+        const strs = data.rs485msg.split(';')
+        if (!this.boolOpen) {
+          active.content = '设备:' + data.rs485mac  + '----' + strs[0]
+        }
+      } else if (data.type === 2) { // 有返回
+        item.receive_time = this.formateSeconds(item.send_time, time)
+        active.type = 'success'
+        active.icon = 'el-icon-check'
+      } else { // 发送失败
+        item.receive_time = this.formateSeconds(item.send_time, time)
+        active.type = 'danger'
+        active.icon = 'el-icon-close'
+      }
+
+      this.activities.push(active)
+      item.state = data.type
+      this.$set(this.deviceList, index, item)
+    },
+    websocketclose: function(e) {
+      console.log('connection closed (' + e.code + ')')
+      const _this = this
+      this.$alert('连接断开,是否重连', '提示', {
+        confirmButtonText: '确定',
+        callback: action => {
+          _this.initWebSocket()
+        }
+      })
+    },
+    API_getPartList() {
+      const _this = this
+      listByType(5).then(res => {
+        _this.partList = res
+        if (res.length > 0) {
+          _this.shopId = res[0].shop_id
+          _this.API_getZhhList()
+        }
+      })
+    },
+    API_getZhhList() {
+      const _this = this
+      this.deviceList = []
+      getDeviceByType(this.shopId, 20).then(res => {
+        _this.zhhList = res
+        if (res.length > 0) {
+          _this.activeName = 'id-0'
+          _this.tid =  '0'
+          _this.API_get485DeviceAndFrame()
+        }
+      })
+    },
+    API_get485DeviceAndFrame() {
+      const _this = this
+      get485DeviceAndFrame(this.shopId,  this.tid).then(res => {
+        _this.deviceList = res
+      })
+    },
+    changeShop() {
+      this.API_getZhhList()
+    },
+    handleClick() {
+      this.tid = this.activeName.split('-')[1]
+      this.API_get485DeviceAndFrame()
+    },
+    handlerEdit(index, row, type) {
+      if (type === 1) {
+        row.state = 0
+        row.send_time = row.receive_time = ''
+        this.$set(this.deviceList, index, row)
+        this.websock.send(row.sip_id + '-' + this.activeName.split('-')[0])
+      }
+    },
+    unixDateFormatter(value) {
+      return unix2Date(value)
+    },
+    closeLog() {
+      this.activities = []
+    },
+    selectFun(val) {
+      this.multipleSelection = val
+    },
+    sendAll() {
+      let list = []
+      this.multipleSelection.forEach(item => {
+        const index = this.deviceList.indexOf(item)
+        item.state = 0
+        item.send_time = item.receive_time = ''
+        this.$set(this.deviceList, index, item)
+        list.push(item.sip_id + '-' + this.activeName.split('-')[0])
+      })
+      this.multipleSelection = []
+      this.websock.send(list.join(','))
+    },
+    //将秒转化为时分秒
+    formateSeconds(startTime, endTime){
+      if (!startTime) {
+        return 0
+      }
+      let secondTime = endTime - startTime//将传入的秒的值转化为Number
+      let min = 0// 初始化分
+      if(secondTime>1000){//如果秒数大于60,将秒数转换成整数
+        min=parseInt(secondTime/1000)//获取秒,除以1000取整数,得到整数秒
+        return min + this.$t('action.second')
+      } else {
+        return secondTime + this.$t('action.millisecond')
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 10 - 10
src/views/ncs-auth/compontents/roleEdit.vue

@@ -1,20 +1,20 @@
 <template>
   <div class="permission-container">
     <el-form ref="permissionForm" :model="permissionForm" :rules="permissionRules" label-width="200px" class="demo-ruleForm">
-      <el-form-item label="角色名称" prop="role_name">
+      <el-form-item :label="this.$t('role.roleName')" prop="role_name">
         <el-input v-model="permissionForm.role_name" />
       </el-form-item>
-      <el-form-item label="角色描述" prop="role_describe">
-        <el-input v-model="permissionForm.role_describe" placeholder="最多200字" :maxlength="200" />
+      <el-form-item :label="this.$t('role.roleDescribe')" prop="role_describe">
+        <el-input v-model="permissionForm.role_describe" :placeholder="this.$t('role.roleDescribeMsg')" :maxlength="200" />
       </el-form-item>
-<!--      <el-form-item label="不用生成到科室" prop="role_describe">-->
+<!--      <el-form-item :label="不用生成到科室" prop="role_describe">-->
 <!--        <el-checkbox-->
 <!--          v-model="permissionForm.hidden_in_seller"-->
-<!--          label="是/否(勾选此项,该角色在创建科室时,不会在科室中创建此角色,不勾选则创建)。不同的科室对同一个角色可能分配不同的功能菜单,所以在创建科室时,将系统内的角色生成到科室上"-->
+<!--          :label="是/否(勾选此项,该角色在创建科室时,不会在科室中创建此角色,不勾选则创建)。不同的科室对同一个角色可能分配不同的功能菜单,所以在创建科室时,将系统内的角色生成到科室上"-->
 <!--        />-->
 <!--      </el-form-item>-->
-      <el-form-item label="角色权限" prop="permission">
-        <el-checkbox v-model="allCheck" :indeterminate="allIndeterminate" @change="handleCheckAll">全部选择</el-checkbox>
+      <el-form-item :label="this.$t('role.permission')" prop="permission">
+        <el-checkbox v-model="allCheck" :indeterminate="allIndeterminate" @change="handleCheckAll">{{ this.$t('action.choiceAll') }}</el-checkbox>
         <div v-for="(item, index) in permissions" :key="item.identifier" class="level_1">
           <el-row :gutter="20">
             <el-col :span="4">
@@ -52,7 +52,7 @@
         </div>
       </el-form-item>
       <el-form-item label="">
-        <el-button type="primary" size="small" style="margin-top: 15px" @click="saveRolePermission">保存设置</el-button>
+        <el-button type="primary" size="small" style="margin-top: 15px" @click="saveRolePermission">{{ this.$t('action.saveSettings') }}</el-button>
       </el-form-item>
     </el-form>
   </div>
@@ -82,8 +82,8 @@ export default {
       /** 权限 表单规则 */
       permissionRules: {
         role_name: [
-          this.MixinRequired('请输入角色名称!'),
-          { min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur' }
+          this.MixinRequired(this.$t('role.inputRoleName')),
+          { min: 1, max: 10, message: this.$t('role.roleNameMsg'), trigger: 'blur' }
         ]
       },
       permissions: [],

+ 10 - 10
src/views/ncs-auth/superadmin/defaultRoleManager.vue

@@ -13,29 +13,29 @@
         >
           <el-table-column
             prop="role_name"
-            label="角色名称"
+            :label="this.$t('role.roleName')"
           />
         </el-table>
       </el-aside>
       <el-main>
         <el-header style="text-align: right; font-size: 12px;height: 30px">
-          <el-button type="primary" size="mini" @click="createRole">新建角色</el-button>
-          <el-button :disabled="role_id === 0" type="success" size="mini" @click="roleEvent">角色事件</el-button>
-          <el-button :disabled="role_id === 0" type="danger" size="mini" @click="deleteRole">删除角色</el-button>
+          <el-button type="primary" size="mini" @click="createRole">{{ this.$t('role.roleAdd') }}</el-button>
+          <el-button :disabled="role_id === 0" type="success" size="mini" @click="roleEvent">{{ this.$t('role.roleEvent') }}</el-button>
+          <el-button :disabled="role_id === 0" type="danger" size="mini" @click="deleteRole">{{ this.$t('role.roleDelete') }}</el-button>
         </el-header>
         <role-edit :role_id="role_id" @aftersave="getRoleList" />
       </el-main>
     </el-container>
-    <el-dialog title="编辑角色事件" :visible.sync="formShow" width="50%">
+    <el-dialog :title="this.$t('role.roleEdit')" :visible.sync="formShow" width="50%">
       <el-form ref="editform" label-width="80px">
-        <el-checkbox v-model="allCheck" :indeterminate="indeterminate" @change="handleCheckAllChange">全选</el-checkbox>
+        <el-checkbox v-model="allCheck" :indeterminate="indeterminate" @change="handleCheckAllChange">{{ this.$t('action.choiceAll') }}</el-checkbox>
         <div style="margin: 15px 0;" />
         <el-checkbox-group v-model="newCheckList" @change="handleCheckedCitiesChange">
           <el-checkbox v-for="(item, index) in eventList" :key="index" :label="item.id" style="width: 200px;">{{ item.name }}</el-checkbox>
         </el-checkbox-group>
         <div align="center" class="margin-top-sm">
-          <el-button type="success" @click="onSubmit">保存设置</el-button>
-          <el-button @click="formShow = false">取消</el-button>
+          <el-button type="success" @click="onSubmit">{{ this.$t('action.saveSettings') }}</el-button>
+          <el-button @click="formShow = false">{{ this.$t('action.cancel') }}</el-button>
         </div>
       </el-form>
 
@@ -106,7 +106,7 @@ export default {
     },
     deleteRole() {
       if (this.role_id === 0) {
-        this.$message.error('没有选中任何角色!')
+        this.$message.error(this.$t('role.onChoiceRole'))
         return
       }
       this.$confirm(this.$t('action.sureDelete'), this.$t('action.waring'), {
@@ -181,7 +181,7 @@ export default {
       }
       API_event.updateRoleId(data).then(res => {
         this.formShow = false
-        this.$message.success('设置成功!')
+        this.$message.success(this.$t('action.settingsSuccess'))
       })
     }
   }

+ 2 - 2
src/views/ncs-broadcast/index.vue

@@ -693,10 +693,10 @@ export default {
       this.websock.onclose = this.websocketclose
     },
     websocketonopen: function() {
-      console.log(this.$t('action.webSocketSuccess'))
+      console.log(this.$t('deviceManage.webSocketSuccess'))
     },
     websocketonerror: function(e) {
-      console.log(this.$t('action.webSocketError'))
+      console.log(this.$t('deviceManage.webSocketError'))
     },
     websocketonmessage: function(e) {
       this.scheduledIds = JSON.parse(e.data)

+ 51 - 51
src/views/ncs-chars/index.vue

@@ -2,18 +2,18 @@
   <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-option :label="this.$t('interaction.all')" :value="0" />
+        <el-option :label="this.$t('interaction.customerAndClerk')" :value="1" />
+        <el-option :label="this.$t('interaction.clerkAndClerk')" :value="2" />
       </el-select>
       <span style="margin-left: 10px;">
-        <span>查询周期:</span>
+        <span>{{ this.$t('interaction.selectData') }}</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>
+        <span slot="label"><i class="el-icon-menu" /> {{ this.$t('interaction.all') }}</span>
         <div>
           <div style="margin: 10px">
             <el-row :gutter="30">
@@ -25,7 +25,7 @@
                   </div>
                   <div class="card-panel-description">
                     <div class="card-panel-text">
-                      交互类型
+                      {{ this.$t('interaction.actionType') }}
                     </div>
                     <count-to :start-val="0" :end-val="partTotal.lx" :duration="4600" class="card-panel-num" />
                   </div>
@@ -38,7 +38,7 @@
                   </div>
                   <div class="card-panel-description">
                     <div class="card-panel-text">
-                      交互次数
+                      {{ this.$t('interaction.actionTime') }}
                     </div>
                     <count-to :start-val="0" :end-val="partTotal.count" :duration="8600" class="card-panel-num" />
                   </div>
@@ -51,7 +51,7 @@
                   </div>
                   <div class="card-panel-description">
                     <div class="card-panel-text">
-                      未完成次数
+                      {{ this.$t('interaction.unSuccessTime') }}
                     </div>
                     <!--            <span>高温</span>-->
                     <count-to :start-val="0" :end-val="partTotal.noCount" :duration="3200" class="card-panel-num" />
@@ -64,10 +64,10 @@
           </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-column type="index" width="100" :label="this.$t('action.index')" align="center" />
+              <el-table-column prop="name" :label="this.$t('interaction.actionType')" min-width="130" align="center" />
+              <el-table-column prop="count" :label="this.$t('interaction.actionTime')" min-width="130" align="center" />
+              <el-table-column prop="noCount" :label="this.$t('interaction.unSuccessTime')" min-width="130" align="center" />
             </el-table>
           </div>
           <el-card shadow="always" style="margin-top: 15px;">
@@ -82,22 +82,22 @@
         </div>
       </el-tab-pane>
       <el-tab-pane name="VOICE">
-        <span slot="label"><i class="el-icon-phone-outline" /> 语音</span>
+        <span slot="label"><i class="el-icon-phone-outline" /> {{ this.$t('tcpType.VOICE') }}</span>
       </el-tab-pane>
       <el-tab-pane name="VIDEO">
-        <span slot="label"><i class="el-icon-video-camera" /> 视频</span>
+        <span slot="label"><i class="el-icon-video-camera" /> {{ this.$t('tcpType.VIDEO') }}</span>
       </el-tab-pane>
       <el-tab-pane name="IM">
-        <span slot="label"><i class="el-icon-microphone" /> 留言</span>
+        <span slot="label"><i class="el-icon-microphone" /> {{ this.$t('tcpType.IM') }}</span>
       </el-tab-pane>
       <el-tab-pane name="EVENT">
-        <span slot="label"><i class="el-icon-thumb" /> 事件</span>
+        <span slot="label"><i class="el-icon-thumb" /> {{ this.$t('tcpType.EVENT') }}</span>
       </el-tab-pane>
       <el-tab-pane name="ENTRACEGUARD">
-        <span slot="label"><i class="el-icon-wallet" /> 门禁</span>
+        <span slot="label"><i class="el-icon-wallet" /> {{ this.$t('tcpType.ENTRACEGUARD') }}</span>
       </el-tab-pane>
       <el-tab-pane name="SOS">
-        <span slot="label"><i class="el-icon-sunrise-1" /> 紧急按钮</span>
+        <span slot="label"><i class="el-icon-sunrise-1" /> {{ this.$t('tcpType.SOS') }}</span>
       </el-tab-pane>
     </el-tabs>
     <div v-if="sssparams.type">
@@ -106,30 +106,30 @@
       </el-card>
       <el-tabs v-model="activeName2" type="border-card" @tab-click="handleClick2">
         <el-tab-pane name="user">
-          <span slot="label"><i class="el-icon-s-custom" /> 用户交互统计</span>
+          <span slot="label"><i class="el-icon-s-custom" /> {{ this.$t('interaction.customerCensus') }}</span>
         </el-tab-pane>
         <el-tab-pane name="clerk">
-          <span slot="label"><i class="el-icon-user" /> 员工交互统计</span>
+          <span slot="label"><i class="el-icon-user" /> {{ this.$t('interaction.clerkCensus') }}</span>
         </el-tab-pane>
       </el-tabs>
       <div style="padding: 10px;margin: 10px;">
         <div class="table-wrapper">
           <el-table :data="userActionList" stripe border :default-sort = "{prop: 'num', order: 'descending'}" 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="num" label="交互次数" min-width="130" align="center" sortable />
-            <el-table-column prop="error_num" label="未完成次数" min-width="130" align="center" sortable />
-            <el-table-column prop="avg_num" label="平均响应时间" min-width="130" align="center" sortable >
+            <el-table-column type="index" width="100" :label="this.$t('action.index')" align="center" />
+            <el-table-column prop="name" :label="this.$t('member.name')" min-width="130" align="center" />
+            <el-table-column prop="num" :label="this.$t('interaction.actionTime')" min-width="130" align="center" sortable />
+            <el-table-column prop="error_num" :label="this.$t('interaction.unSuccessTime')" min-width="130" align="center" sortable />
+            <el-table-column prop="avg_num" :label="this.$t('interaction.avgResponseNum')" min-width="130" align="center" sortable >
               <template slot-scope="scope">
                 <span>{{ formateSeconds(scope.row.avg_num) }}</span>
               </template>
             </el-table-column>
-            <el-table-column prop="min_num" label="最小响应时间" min-width="130" align="center" sortable >
+            <el-table-column prop="min_num" :label="this.$t('interaction.MinNum')" min-width="130" align="center" sortable >
               <template slot-scope="scope">
                 <span>{{ formateSeconds(scope.row.min_num) }}</span>
               </template>
             </el-table-column>
-            <el-table-column prop="max_num" label="最大响应时间" min-width="130" align="center" sortable >
+            <el-table-column prop="max_num" :label="this.$t('interaction.MaxNum')" min-width="130" align="center" sortable >
               <template slot-scope="scope">
                 <span>{{ formateSeconds(scope.row.max_num) }}</span>
               </template>
@@ -171,7 +171,7 @@ export default {
         noCount: 0
       },
       tableData: [],
-      dataList: ['语音', '视频', '留言', '事件', '门禁', '紧急按钮'],
+      dataList: [this.$t('tcpType.VOICE'), this.$t('tcpType.VIDEO'), this.$t('tcpType.IM'), this.$t('tcpType.EVENT'), this.$t('tcpType.ENTRACEGUARD'), this.$t('tcpType.SOS')],
       activeName: 'ALL',
       userActionList: [],
       activeName2: 'user'
@@ -200,8 +200,8 @@ export default {
           _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', '未完成交互统计')
+          _this.buildChart(res.dataList, res.tilStr, res.xAxis, 'chart', this.$t('interaction.dataCensus'))
+          _this.buildChart(res.noDataList, res.noTilStr, res.xAxis, 'noChart', this.$t('interaction.unSuccessCensus'))
         }
       })
     },
@@ -234,7 +234,7 @@ export default {
           const d = {
             name: tilStr[index],
             type: 'line',
-            stack: '总量' + index,
+            stack: this.$t('interaction.total') + index,
             data: item,
             smooth: true,
             emphasis: {
@@ -293,8 +293,8 @@ export default {
       this.chart.clear()
       const options = {
         title: {
-          text: '交互记录统计',
-          subtext: '数量统计',
+          text: this.$t('interaction.interactionCensus'),
+          subtext: this.$t('interaction.quantityCensus'),
           left: 'center'
         },
         tooltip: {
@@ -316,7 +316,7 @@ export default {
         },
         series: [
           {
-            name: '交互记录',
+            name: this.$t('interaction.interactionRecord'),
             type: 'pie',
             radius: [20, 140],
             center: ['25%', '50%'],
@@ -332,7 +332,7 @@ export default {
             data: btList
           },
           {
-            name: '未完成交互',
+            name: this.$t('interaction.unSuccessInteraction'),
             type: 'pie',
             radius: [20, 140],
             center: ['75%', '50%'],
@@ -352,7 +352,7 @@ export default {
       this.chart.clear()
       const mySeries = [
         {
-          name: '交互记录',
+          name: this.$t('interaction.interactionRecord'),
           type: 'bar',
           emphasis: {
             focus: 'series'
@@ -360,7 +360,7 @@ export default {
           data: res.zztDate
         },
         {
-          name: '已响应交互',
+          name: this.$t('interaction.successInteraction'),
           type: 'bar',
           stack: 'Ad',
           barWidth: 5,
@@ -370,7 +370,7 @@ export default {
           data: res.hasZztDate
         },
         {
-          name: '未完成交互',
+          name: this.$t('interaction.unSuccessInteraction'),
           type: 'bar',
           stack: 'Ad',
           barWidth: 5,
@@ -382,7 +382,7 @@ export default {
       ]
       if (res.errorDate) {
         mySeries.push({
-          name: '未正常挂断交互',
+          name: this.$t('interaction.failedInteraction'),
           type: 'bar',
           stack: 'Ad',
           barWidth: 5,
@@ -452,19 +452,19 @@ export default {
     formatterType(param) {
       switch (param) {
         case 'VOICE':
-          return '语音'
+          return this.$t('tcpType.VOICE')
         case 'VIDEO':
-          return '视频'
+          return this.$t('tcpType.VIDEO')
         case 'IM':
-          return '留言'
+          return this.$t('tcpType.IM')
         case 'EVENT':
-          return '事件'
+          return this.$t('tcpType.EVENT')
         case 'ENTRACEGUARD':
-          return '门禁'
+          return this.$t('tcpType.ENTRACEGUARD')
         case 'SOS':
-          return '紧急按钮'
+          return this.$t('tcpType.SOS')
         default:
-          return '未知'
+          return this.$t('tcpType.UNKNOWN')
       }
     },
     handleClick(tab, event) {
@@ -496,9 +496,9 @@ export default {
     //将秒转化为时分秒
     formateSeconds(endTime){
       if (endTime === 0) {
-        return '1秒内'
+        return this.$t('action.oneSecond')
       } else if (endTime === -1) {
-        return '无'
+        return this.$t('action.null')
       }
       let secondTime = endTime//将传入的秒的值转化为Number
       let min = 0// 初始化分
@@ -509,12 +509,12 @@ export default {
         if(min>60){//如果分钟大于60,将分钟转换成小时
           h=parseInt(min/60)//获取小时,获取分钟除以60,得到整数小时
           min=parseInt(min%60) //获取小时后取佘的分,获取分钟除以60取佘的分
-          return h + '时' + min + '分' + secondTime + '秒'
+          return h + this.$t('action.time2') + min + this.$t('action.minute2') + secondTime + this.$t('action.second')
         } else {
-          return min +'分' + secondTime + '秒'
+          return min +this.$t('action.minute2') + secondTime + this.$t('action.second')
         }
       } else {
-        return secondTime + '秒'``
+        return secondTime + this.$t('action.second')
       }
     }
   }

+ 52 - 24
src/views/ncs-device/components/deviceManager.vue

@@ -182,6 +182,15 @@
             </el-form-item>
           </el-col>
         </el-row>
+        <el-row v-if="isVitalSigns">
+          <el-col :span="12">
+            <el-form-item :label="this.$t('deviceManage.signType')" prop="sign_type">
+              <el-select v-model="deviceModel.sign_type" :placeholder="this.$t('deviceManage.choiceSignType')" clearable>
+                <el-option v-for="(item, index) in Object.keys(vitalSignsDeviceEnum)" :key="index" :label="vitalSignsDeviceEnum[item]" :value="parseInt(item)" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
         <el-row v-if="hasSosDeviceSettings">
           <el-col :span="12">
             <el-form-item :label="this.$t('deviceManage.sosDeviceSettingType')" prop="type">
@@ -255,6 +264,7 @@ import * as clerk_API from '@/api/ncs_clerk'
 import { FRAME_TYPE } from '@/utils/enum/FrameTypeEnum'
 import { DEVICE_TYPE } from '@/utils/enum/DeviceTypeEnum'
 import {SOS_DEVICE_SETTING_TYPE} from "@/utils/enum/SosDeviceSettingTypeEnum";
+import {VITAL_SIGNS_DEVICE_TYPE} from "@/utils/enum/VitalSignsDeviceEnum";
 const DeviceUrl = domain.DeviceUrl
 export default {
   name: 'DeviceManager',
@@ -326,6 +336,9 @@ export default {
         trans_audio_id: [
           { required: true, message: this.$t('deviceManage.choiceTransAudio'), trigger: 'blur' }
         ],
+        sign_type: [
+          { required: true, message: this.$t('deviceManage.choiceSignType'), trigger: 'blur' }
+        ],
         // trans_rs485_id: [
         //   { required: true, message: '请选择485转换盒', trigger: 'blur' }
         // ],
@@ -363,26 +376,30 @@ export default {
         { key: this.$t('deviceType.LED_SCREEN'), value: 6 },
         { key: this.$t('deviceType.NURSE_WATCH'), value: 7 },
         // { key: '护工腕表', value: 8 },
-        { key: this.$t('deviceType.WORKER_WATCH'), value: 9 },
-        { key: this.$t('deviceType.USER_WATCH'), value: 10 },
-        { key: this.$t('deviceType.CELL_PHONE'), value: 11 },
-        { key: this.$t('deviceType.TRANSFER_DEVICE'), value: 12 },
-        { key: this.$t('deviceType.SIMULATE_BED_DEVICE'), value: 13 },
-        { key: this.$t('deviceType.SIMULATE_EMERGENCY_BUTTON'), value: 14 },
-        { key: this.$t('deviceType.SIMULATE_DOOR_LIGHT'), value: 15 },
-        { key: this.$t('deviceType.REMOTE_CONTROL'), value: 16 },
-        { key: this.$t('deviceType.BEACON'), value: 17 },
-        { key: this.$t('deviceType.INFORMATION_BOARD'), value: 18 },
-        { key: this.$t('deviceType.ENTRANCE_GUARD'), value: 19 },
-        { key: this.$t('deviceType.VISITATION'), value: 20 },
-        { key: this.$t('deviceType.RS485_TRANSFER'), value: 21 },
-        { key: this.$t('deviceType.EMERGENCY_BUTTON'), value: 22 },
-        { key: this.$t('deviceType.RS485_DOOR'), value: 23 },
-        { key: this.$t('deviceType.ALARM_BODY_INDUCTIVE'), value: 24 },
-        { key: this.$t('deviceType.ALARM_WATER_OVERFLOW'), value: 25 },
-        { key: this.$t('deviceType.ALARM_HOUSEHOLD_GAS'), value: 26 },
-        { key: this.$t('deviceType.ALARM_HOUSEHOLD_SMOKE'), value: 27 },
-        { key: this.$t('deviceType.DOOR_LOCK'), value: 30 }
+        { key: this.$t('deviceType.USER_WATCH'), value: 9 },
+        { key: this.$t('deviceType.CELL_PHONE'), value: 10 },
+        { key: this.$t('deviceType.TRANSFER_DEVICE'), value: 11 },
+        { key: this.$t('deviceType.SIMULATE_BED_DEVICE'), value: 12 },
+        { key: this.$t('deviceType.SIMULATE_EMERGENCY_BUTTON'), value: 13 },
+        { key: this.$t('deviceType.SIMULATE_DOOR_LIGHT'), value: 14 },
+        { key: this.$t('deviceType.REMOTE_CONTROL'), value: 15 },
+        { key: this.$t('deviceType.BEACON'), value: 16 },
+        { key: this.$t('deviceType.INFORMATION_BOARD'), value: 17 },
+        { key: this.$t('deviceType.ENTRANCE_GUARD'), value: 18 },
+        { key: this.$t('deviceType.VISITATION'), value: 19 },
+        { key: this.$t('deviceType.RS485_TRANSFER'), value: 20 },
+        { key: this.$t('deviceType.EMERGENCY_BUTTON'), value: 21 },
+        { key: this.$t('deviceType.RS485_DOOR'), value: 22 },
+        { key: this.$t('deviceType.ALARM_BODY_INDUCTIVE'), value: 23 },
+        { key: this.$t('deviceType.ALARM_WATER_OVERFLOW'), value: 24 },
+        { key: this.$t('deviceType.ALARM_HOUSEHOLD_GAS'), value: 25 },
+        { key: this.$t('deviceType.ALARM_HOUSEHOLD_SMOKE'), value: 26 },
+        { key: this.$t('deviceType.ALARM_BUTTON_SOS'), value: 27 },
+        { key: this.$t('deviceType.VITAL_SIGNS_DEVICE'), value: 28 },
+        { key: this.$t('deviceType.ALARM_RESTRAINT_BAND'), value: 29 },
+        { key: this.$t('deviceType.DOOR_LOCK'), value: 30 },
+        { key: this.$t('deviceType.EMERGENCY_GATEWAY'), value: 31 },
+        { key: this.$t('deviceType.ALARM_433BUTTON'), value: 32 },
       ],
       deviceTypeEnum: DEVICE_TYPE.getValueList(),
       deviceStatusTransfer: [
@@ -394,6 +411,7 @@ export default {
       audioOptions: [],
       rs485Options: [],
       hasAudioId: false,
+      isVitalSigns: false,
       hasSosDeviceSettings: false,
       sosDeviceSetting: {},
       sosDeviceSettingsTypeOptions: [
@@ -409,6 +427,7 @@ export default {
         }
       ],
       sosDeviceSettingEnum: SOS_DEVICE_SETTING_TYPE.getValueList(),
+      vitalSignsDeviceEnum: VITAL_SIGNS_DEVICE_TYPE.getValueList(),
       isLedDevice: false,
       websock: null,
       onlineDevice: []
@@ -423,7 +442,10 @@ export default {
   watch: {
     frame(val, oldvalue) {
       console.log('watch', val)
-      this.params.fixedCondition = Object.keys(this.frame).length === 0 ? 'part_id=' + this.$store.getters.partId : 'part_id=' + this.$store.getters.partId + ' and frame_id =' + this.frame.id
+      this.params.fixedCondition = Object.keys(this.frame).length === 0 ? 'part_id=' + this.$store.getters.partId :
+          (this.frame.part_id ?  'part_id=' + this.frame.part_id + ' and frame_id =' + this.frame.id :
+              'part_id=' + this.frame.hospital_id + ' and frame_id =' + this.frame.id)
+
       this.getList()
     }
   },
@@ -766,8 +788,10 @@ export default {
                         val === DEVICE_TYPE.RS485_DOOR ||
                         val === DEVICE_TYPE.SIMULATE_EMERGENCY_BUTTON ||
                         val === DEVICE_TYPE.SIMULATE_DOOR_LIGHT
+      this.isVitalSigns = val === DEVICE_TYPE.VITAL_SIGNS_DEVICE
       this.hasSosDeviceSettings = val === DEVICE_TYPE.ALARM_BODY_INDUCTIVE ||
-          val === DEVICE_TYPE.DOOR_LOCK
+          val === DEVICE_TYPE.DOOR_LOCK ||
+          val === DEVICE_TYPE.ALARM_RESTRAINT_BAND
       this.isLedDevice = val === DEVICE_TYPE.LED_SCREEN ||
           val === DEVICE_TYPE.LCD_SCREEN
     },
@@ -792,7 +816,8 @@ export default {
       } else if (val === DEVICE_TYPE.DIGIT_BED_DEVICE ||
           val === DEVICE_TYPE.SIMULATE_BED_DEVICE ||
           val === DEVICE_TYPE.REMOTE_CONTROL ||
-          val === DEVICE_TYPE.CELL_PHONE
+          val === DEVICE_TYPE.CELL_PHONE ||
+          val === DEVICE_TYPE.ALARM_433BUTTON
       ) {
         this.getFramesByType(FRAME_TYPE.BED)
       } else {
@@ -823,6 +848,7 @@ export default {
       this.hasRoleId = false
       this.getRoles({ page_size: 200, page_no: 1, fixedCondition: ' shop_id = -1', sort: ' role_id', dir: 'desc' })
       this.hasAudioId = false
+      this.isVitalSigns = false
       this.hasSosDeviceSettings = false
       this.isLedDevice = false
       this.getDevices(this.$store.getters.partId)
@@ -842,8 +868,10 @@ export default {
                         params.device_type === DEVICE_TYPE.RS485_DOOR ||
                         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 ||
-          params.device_type === DEVICE_TYPE.DOOR_LOCK
+          params.device_type === DEVICE_TYPE.DOOR_LOCK ||
+          params.device_type === DEVICE_TYPE.ALARM_RESTRAINT_BAND
       this.isLedDevice = params.device_type === DEVICE_TYPE.LED_SCREEN ||
           params.device_type === DEVICE_TYPE.LCD_SCREEN
       this.deviceModel = {

+ 20 - 20
src/views/ncs-device/nurse_watch.vue

@@ -223,25 +223,25 @@ export default {
         resizable: false,
         sortable: false
       }
-      // ,
-      // {
-      //   headerName: this.$t('watch.place'), field: 'shop_id',
-      //   cellRendererFramework: 'ButtonCellRender',
-      //   cellRendererParams: param => {
-      //     return {
-      //       onClick: this.getLocation,
-      //       label: this.$t('watch.place'),
-      //       buttonType: 'warning',
-      //       buttonSize: 'mini'
-      //     }
-      //   },
-      //   filter: false,
-      //   pinned: 'right',
-      //   lockPinned: true,
-      //   minWidth: 100,
-      //   resizable: false,
-      //   sortable: false
-      // }
+      ,
+      {
+        headerName: this.$t('watch.place'), field: 'shop_id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.getLocation,
+            label: this.$t('watch.place'),
+            buttonType: 'warning',
+            buttonSize: 'mini'
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        minWidth: 100,
+        resizable: false,
+        sortable: false
+      }
       // {
       //   headerName: '管理', field: 'shop_id',
       //   cellRendererFramework: 'ButtonCellRender',
@@ -451,7 +451,7 @@ export default {
       this.websock.send(JSON.stringify(sendData))
       const _this = this
       setTimeout(function() {
-        _this.$message.success(this.$t('action.handleSuccess'))
+        _this.$message.success(_this.$t('action.handleSuccess'))
         _this.getList()
       }, 1000)
     },

+ 518 - 0
src/views/ncs-device/user_watch.vue

@@ -0,0 +1,518 @@
+<template>
+  <div class="formwrap">
+    <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('watch.deviceKeywords')" @search="handlerSearch" />
+        </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 v-if="formshow" :title="this.$t('action.edit')+(member_id===null?'':'('+member_name+')')" :visible.sync="formshow" width="70%">
+      <el-form label-width="120px" ref="addMemberForm">
+        <el-form-item :label="this.$t('watch.ethMac')">
+          {{ deviceInfo.eth_mac }}
+        </el-form-item>
+        <el-form-item :label="this.$t('customerManage.named')">
+          <el-radio-group v-model="deviceInfo.member_id">
+            <el-radio v-for="(t, i) in users" :key="i" :label="t.member_id" :disabled="member_id === t.member_id && t.device_id !== null">
+              <i class="el-icon-user-solid" style="color: #b59abf;margin-top: 5px" />{{ t.named }}
+            </el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item style="margin-top:15px;">
+          <el-button type="success" @click="handlerFormSubmit('editform')">{{ this.$t('action.saveEdit') }}</el-button>
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+
+<!--    位置信息-->
+    <el-dialog :title="this.$t('watch.placeInfo')" :visible.sync="locationShow" width="70%">
+      <watch-location :device-id="deviceId" :is-show="locationShow"></watch-location>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import * as API_Device from '@/api/ncs_device'
+import { unixToDate } from '@/utils/Foundation'
+import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
+import ButtonCellRender from '@/components/AgGridCellRender/ButtonCellRender'
+import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
+import watchLocation from '@/views/ncs-device/watch_location'
+import { getListByPartId } from '@/api/ncs_customer'
+const DeviceUrl = domain.DeviceUrl
+export default {
+  name: 'Index',
+  components: { ButtonCellRender, RadioFilter, watchLocation },
+  data: function() {
+    return {
+      /** 表格数据 */
+      tableData: [],
+      /** 表单数据 */
+      formmodel: {},
+      formshow: false, // 编辑表单显示开关
+      /** 表单校验 */
+      rules: {
+        name: [
+          { required: true, message: this.$t('watch.inputName'), trigger: 'blur' }
+        ]
+      },
+      pageData: [],
+      loading: false,
+      multipleSelection: [],
+      /** 列表参数 */
+      params: {
+        page_size: 100,
+        page_no: 1,
+        fixedCondition: ' part_id=' + this.$store.getters.partId + ' and device_type = 9',
+        sort: 'id',
+        dir: 'desc'
+      },
+      editflag: 0,
+      deviceInfo: {},
+      users: [],
+      columnDefs: null, // 新表格
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      rowSelection: null,
+      showViewer: false,
+      deviceStatusTransfer: [
+        { key: this.$t('deviceManage.statusTure'), value: 1, color: 'green' },
+        { key: this.$t('deviceManage.statusFalse'), value: 0, color: 'red' }
+      ],
+      clerks: [],
+      role_id: null,
+      role_name: '',
+      member_id: null,
+      member_name:'',
+      onlineDevice: [],
+      locationShow: false,
+      deviceId: null
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 130
+    }
+  },
+  beforeMount() {
+    this.gridOptions = {
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false,
+        width: 80,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', minWidth: 100 },
+      { headerName: this.$t('deviceManage.deviceName'), field: 'name', sortable: true, filter: 'agTextColumnFilter', minWidth: 150 },
+      { headerName: this.$t('watch.deviceMember'), field: 'member_name', sortable: true, filter: 'agTextColumnFilter', minWidth: 220, valueFormatter: this.formatterName },
+      { headerName: this.$t('watch.ethMac'), field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter', minWidth: 150 },
+      { headerName: this.$t('deviceManage.connect'), field: 'online_state', sortable: false, filter: 'agTextColumnFilter', minWidth: 120,
+        filterParams: {
+          textCustomComparator: (filter, value, filterText) => {
+            const filterTextLowerCase = filterText.toLowerCase()
+            const valueLowerCase = value.toString().toLowerCase()
+            switch (filter) {
+              case 'contains':
+                return valueLowerCase.indexOf(filterTextLowerCase) >= 0
+              case 'notContains':
+                return valueLowerCase.indexOf(filterTextLowerCase) === -1
+              case 'equals':
+                return valueLowerCase === filterTextLowerCase
+              case 'notEqual':
+                return valueLowerCase !== filterTextLowerCase
+              case 'startsWith':
+                return valueLowerCase.indexOf(filterTextLowerCase) === 0
+              case 'endsWith':
+                var index = valueLowerCase.lastIndexOf(filterTextLowerCase)
+                return index >= 0 && index === (valueLowerCase.length - filterTextLowerCase.length)
+              default:
+                // should never happen
+                console.warn('invalid filter type ' + filter)
+                return false
+            }
+          }
+        },
+        cellRenderer: this.onlineStateFormatter
+      },
+      { headerName: this.$t('deviceManage.ethIp'), field: 'eth_ip', sortable: true, filter: 'agTextColumnFilter', minWidth: 150 },
+      { headerName: this.$t('deviceManage.model'), field: 'model', sortable: true, filter: 'agTextColumnFilter', minWidth: 150 },
+      { headerName: this.$t('deviceManage.code'), field: 'code', sortable: true, filter: 'agTextColumnFilter', minWidth: 150 },
+      { headerName: this.$t('deviceManage.sipId'), field: 'sip_id', sortable: true, filter: 'agTextColumnFilter', minWidth: 150 },
+      { headerName: this.$t('deviceManage.updateTime'), field: 'update_time', sortable: true, filter: 'agDateColumnFilter', minWidth: 170, valueFormatter: this.formatterDate,
+        filterParams: {
+          comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
+            const celldate = unixToDate(cellValue, 'yyyy-MM-dd 00:00:00')
+            return (new Date(celldate).getTime() / 1000) - (filterLocalDateAtMidnight.getTime() / 1000)
+          }
+        }
+      },
+      {
+        headerName: this.$t('watch.binding'), field: 'shop_id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.huanban,
+            label: this.$t('watch.binding'),
+            buttonType: param.data['member_id'] === null ? 'primary' : 'success',
+            buttonSize: 'mini'
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        minWidth: 100,
+        resizable: false,
+        sortable: false
+      }
+      ,
+      {
+        headerName: this.$t('watch.place'), field: 'shop_id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.getLocation,
+            label: this.$t('watch.place'),
+            buttonType: 'warning',
+            buttonSize: 'mini'
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        minWidth: 100,
+        resizable: false,
+        sortable: false
+      }
+    ]
+    this.defaultColDef = {
+      sortable: true,
+      resizable: true,
+      comparator: this.testComparator,
+      filterParams: {
+        debounceMs: 200,
+        newRowsAction: 'keep',
+        textCustomComparator: this.textCustomComparator,
+        comparator: this.testComparator
+      }
+    }
+    this.rowSelection = 'multiple'
+  },
+  mounted() {
+    window.onresize = this.windowResize()
+    this.gridApi = this.gridOptions.api
+    this.getList()
+    this.deviceOnlineWebSocket()
+  },
+  methods: {
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    deviceOnlineWebSocket: function() {
+      var stockbase = DeviceUrl.replace('http', 'ws')
+      this.websock1 = new WebSocket(stockbase + '/deviceonline/' + this.$store.getters.uuid)
+      this.websock1.onopen = this.deviceOnlineWebsocketonopen
+      this.websock1.onerror = this.deviceOnlineWebsocketonerror
+      this.websock1.onmessage = this.deviceOnlineWebsocketonmessage
+      this.websock1.onclose = this.deviceOnlineWebsocketclose
+    },
+    deviceOnlineWebsocketonopen: function() {
+      console.log(this.$t('deviceManage.webSocketSuccess'))
+    },
+    deviceOnlineWebsocketonerror: function(e) {
+      console.log(this.$t('deviceManage.webSocketError'))
+    },
+    deviceOnlineWebsocketonmessage: function(e) {
+      this.onlineDevice = JSON.parse(e.data)
+      if (this.tableData !== null) {
+        this.tableData.forEach(item => {
+          const mac = this.onlineDevice.filter(p => p.toLowerCase() === item.eth_mac.toLowerCase())[0]
+          item.online_state = (mac !== undefined && mac !== null) ? '在线' : '离线'
+        })
+        const tableData = [...this.tableData]
+        this.$set(this, 'tableData', tableData)
+      }
+    },
+    deviceOnlineWebsocketclose: function(e) {
+      console.log('connection closed (' + e.code + ')')
+    },
+    /** 选择行变化时,记录选中的行数据 */
+    selectFun(val) {
+      this.multipleSelection = val
+    },
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.getList()
+    },
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.getList()
+    },
+    /** 加载通知列表 */
+    getList() {
+      this.loading = true
+      this.gridApi.showLoadingOverlay()
+      this.gridApi.sizeColumnsToFit()
+      API_Device.getList(this.params).then(response => {
+        this.loading = false
+        response.data.forEach(item => {
+          if (this.onlineDevice.length > 0) {
+            const mac = this.onlineDevice.filter(p => p.toLowerCase() === item.eth_mac.toLowerCase())[0]
+            // console.log('在线设备1', mac)
+            if (mac !== undefined && mac !== null) {
+              item['online_state'] = this.$t('deviceManage.connectTrue')
+            } else {
+              item['online_state'] = this.$t('deviceManage.connectFalse')
+            }
+          } else {
+            item['online_state'] = this.$t('deviceManage.connectFalse')
+          }
+        })
+        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
+      })
+    },
+    /** 新增 提交表单 */
+    handlerFormSubmit(formName) {
+      if (this.deviceInfo.member_id === null || this.deviceInfo.member_id === '') {
+        this.$message.info(this.$t('watch.choiceUser'))
+        return
+      }
+      if (this.deviceInfo.member_id === this.member_id) {
+        this.$message.info(this.$t('watch.doNothing'))
+        return
+      }
+      const params = this.MixinClone(this.deviceInfo)
+      const sendData = {
+        member_id: params.member_id,
+        device_type: params.device_type,
+        status: 1
+      }
+      this.formshow = false
+      const _this = this
+      API_Device.update(params.id, sendData).then(res => {
+        _this.$message.success(_this.$t('action.editSuccess'))
+        _this.member_id = _this.deviceInfo.member_id
+        _this.getList()
+      })
+    },
+    /** 处理搜索 */
+    handlerSearch(keywords) {
+      this.params.query = 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()
+    },
+    formatterDate(params) {
+      return unixToDate(params.value)
+    },
+    formatterName(params) {
+      if (params.value && params.data.role_name) {
+        return params.value + ' ' + params.data.role_name
+      } else {
+        if (params.value) {
+          return params.value
+        } else if (params.data.role_name) {
+          return this.$t('watch.binding') + params.data.role_name
+        }
+      }
+    },
+    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()
+    },
+    formatterSatus(param) {
+      if (param.value === 1) {
+        return '<span style="color:green">' + this.$t('deviceManage.statusTure') + '</span>'
+      } else {
+        return '<span style="color:red">' + this.$t('deviceManage.statusFalse') + '</span>'
+      }
+    },
+    getEmployees() {
+      const _this = this
+      _this.users = []
+      getListByPartId(this.$store.getters.partId).then(res =>{
+        _this.users = res
+      })
+      // clerk_API.listByPartRoleId({ partId: this.$store.getters.partId }).then(res => {
+      //   _this.clerks = res
+      //   console.log('res',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) {
+      //     if (_this.deviceInfo.member_id) {
+      //       res.forEach(item=>{
+      //         if(item.member_id===_this.deviceInfo.member_id){
+      //           _this.member_name = item.clerk_name
+      //         }
+      //       })
+      //       Object.entries(groupData).forEach(item => {
+      //
+      //         if (item[0] === _this.role_name) {
+      //           _this.users.push(item)
+      //         }
+      //       })
+      //     } else {
+      //       _this.users = Object.entries(groupData)
+      //     }
+      //   }
+      // })
+    },
+    huanban(row) {
+      this.formshow = true
+      this.deviceInfo = Object.assign({}, row)
+      this.role_id = this.deviceInfo.role_id
+      this.member_id = this.deviceInfo.member_id
+      this.member_name = this.deviceInfo.member_name
+      this.role_name = this.deviceInfo.role_name
+      this.getEmployees()
+    },
+    fanhui() {
+      this.formshow = false
+    },
+    /** 设备连接状态格式化 **/
+    onlineStateFormatter(params) {
+      if (params.value === '在线') {
+        return '<span style="color:green;">' + this.$t('deviceManage.connectTrue') + '</span>'
+      } else {
+        return '<span style="color:gray;">' + this.$t('deviceManage.connectFalse') + '</span>'
+      }
+    },
+    getLocation(row) {
+      this.deviceId = row.id
+      this.locationShow = true
+    }
+  }
+}
+</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>

+ 3 - 3
src/views/ncs-device/watch_location.vue

@@ -30,9 +30,9 @@
     <div v-if="locationList.length > 0" style="margin-top: 20px;">
       <el-card>
         <div v-for="(item, index) in locationList" :key="index" class="text item">
-          <i class="el-icon-user-solid"></i> {{ this.$t('watch.you') }} <el-tag><i class="el-icon-time"></i>{{ formatterCreateTime(item.create_time )}}</el-tag> 在
+          <i class="el-icon-user-solid"></i> {{ $t('watch.you') }} <el-tag><i class="el-icon-time"></i>{{ formatterCreateTime(item.create_time )}}</el-tag> 在
           <el-tag type="success"><i class="el-icon-location-outline"></i>{{ item.full_name }}</el-tag>
-          {{ this.$t('watch.nearby') }}
+          {{ $t('watch.nearby') }}
         </div>
       </el-card>
     </div>
@@ -156,7 +156,7 @@ export default {
             document.getElementById('myIcon'+data.beacon_device_id).style.display='inline'
             _this.$notify({
               title: data.full_name,
-              message: unixToDate(data.create_time) + this.$t('watch.in') + data.full_name + this.$t('watch.nearby'),
+              message: unixToDate(data.create_time) + _this.$t('watch.in') + data.full_name + _this.$t('watch.nearby'),
               position: 'bottom-right',
               showClose: false,
               duration: 2500

+ 9 - 24
src/views/ncs-interaction/index.vue

@@ -64,6 +64,8 @@ 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";
 
 export default {
   name: 'Index',
@@ -306,28 +308,9 @@ export default {
       return named
     },
     formatterType(param) {
-      switch (param.value) {
-        case 'CALLBACK':
-          return this.$t('tcpType.CALLBACK')
-        case 'VOICE':
-          return this.$t('tcpType.VOICE')
-        case 'VIDEO':
-          return this.$t('tcpType.VIDEO')
-        case 'IM':
-          return this.$t('tcpType.IM')
-        case 'DEVICE':
-          return this.$t('tcpType.DEVICE')
-        case 'DATA':
-          return this.$t('tcpType.DATA')
-        case 'EVENT':
-          return this.$t('tcpType.EVENT')
-        case 'BROADCAST':
-          return this.$t('tcpType.BROADCAST')
-        case 'TIME':
-          return this.$t('tcpType.TIME')
-        default:
-          return this.$t('tcpType.UNKNOWN')
-      }
+      const gridVal = param.value
+      // return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
+      return TCP_TYPE.getDescFromValue(gridVal)
     },
     formatterResult(param) {
       if (param.value) {
@@ -338,10 +321,12 @@ export default {
     },
     formatterDeviceType(param) {
       if (param.data.outerior_action) {
-        return returnDeviceType(param.value)
+        // return returnDeviceType(param.value)
+        return DEVICE_TYPE.getDescFromValue(param.value)
       } else {
         if (param.value) {
-          return returnDeviceType(param.value)
+          // return returnDeviceType(param.value)
+          return DEVICE_TYPE.getDescFromValue(param.value)
         } else {
           return this.$t('interaction.notOperated')
         }

+ 23 - 19
src/views/ncs-menu/menuManager.vue

@@ -13,21 +13,21 @@
             size="mini"
             :disabled="node.level === 3"
             icon="el-icon-plus"
-            :title="node.level === 3 ? '菜单最多添加三级' : '增加'"
+            :title="node.level === 3 ? addMsg : add"
             @click.stop="handleAddMenu(data)"
           />
           <el-button
             type="text"
             size="mini"
             icon="el-icon-minus"
-            title="删除"
+            :title="deleteMenu"
             @click.stop="handleDeleteMenu(node, data)"
           />
           <el-button
             type="text"
             size="mini"
             icon="el-icon-edit"
-            title="编辑"
+            :title="editMenu"
             @click.stop="handleEditMenu(data)"
           />
         </span>
@@ -39,32 +39,32 @@
       size="mini"
       style="margin-top: 10px; margin-left: 20px"
       @click="handleAddMenu('')"
-    >添加顶级菜单</el-button>
+    >{{ this.$t('menu.addFirst') }}</el-button>
     <el-dialog
-      :title="menuForm.menu_name ? '编辑菜单' : '添加菜单'"
+      :title="menuForm.menu_name ? this.$t('menu.menuEdit') : this.$t('menu.menuAdd')"
       :visible.sync="dialogMenuVisible"
       width="500px"
       :close-on-click-modal="false"
       :close-on-press-escape="false"
     >
       <el-form ref="menuForm" :model="menuForm" :rules="menuRules" label-width="100px">
-        <el-form-item label="菜单标题" prop="title">
+        <el-form-item :label="this.$t('menu.title')" prop="title">
           <el-input v-model="menuForm.title" :maxlength="6" />
         </el-form-item>
-        <el-form-item label="菜单标识" prop="identifier">
+        <el-form-item :label="this.$t('menu.identifier')" prop="identifier">
           <el-input v-model="menuForm.identifier" :maxlength="50" />
         </el-form-item>
-        <el-form-item label="菜单权限" prop="auth_regular">
+        <el-form-item :label="this.$t('menu.authRegular')" prop="auth_regular">
           <el-input v-model="menuForm.auth_regular" :maxlength="50" />
         </el-form-item>
 
-<!--        <el-form-item label="默认给医生角色" prop="doctor_default">-->
+<!--        <el-form-item :label="默认给医生角色" prop="doctor_default">-->
 <!--          <el-checkbox v-model="menuForm.doctor_default" />-->
 <!--        </el-form-item>-->
       </el-form>
       <span slot="footer" class="dialog-footer">
-        <el-button @click="dialogMenuVisible = false">取 消</el-button>
-        <el-button type="primary" @click="submitMenuForm('menuForm')">确 定</el-button>
+        <el-button @click="dialogMenuVisible = false">{{ this.$t('action.cancel') }}</el-button>
+        <el-button type="primary" @click="submitMenuForm('menuForm')">{{ this.$t('action.yes') }}</el-button>
       </span>
     </el-dialog>
   </div>
@@ -82,22 +82,26 @@ export default {
       /** 添加、编辑菜单 表单规则 */
       menuRules: {
         title: [
-          this.MixinRequired('请输入菜单标题!'),
-          { min: 2, max: 6, message: '长度在 2 到 6 个字符', trigger: 'blur' }
+          this.MixinRequired(this.$t('menu.inputTitle')),
+          { min: 2, max: 6, message: this.$t('menu.titleMsg'), trigger: 'blur' }
         ],
         identifier: [
-          this.MixinRequired('请输入菜单标识!'),
-          { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' }
+          this.MixinRequired(this.$t('menu.inputIdentifier')),
+          { min: 1, max: 50, message: this.$t('menu.identifierMsg'), trigger: 'blur' }
         ],
         auth_regular: [
-          this.MixinRequired('请输入菜单权限!'),
-          { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' }
+          this.MixinRequired(this.$t('menu.inputAuthRegular')),
+          { min: 1, max: 50, message: this.$t('menu.authRegularMsg'), trigger: 'blur' }
         ]
       },
       /** 添加、编辑菜单 dialog */
       dialogMenuVisible: false,
       /** 当前操作的menu */
-      currentMenu: ''
+      currentMenu: '',
+      add: this.$t('menu.add'),
+      addMsg: this.$t('menu.addMsg'),
+      deleteMenu: this.$t('action.delete'),
+      editMenu: this.$t('menu.edit'),
     }
   },
   created() {
@@ -114,7 +118,7 @@ export default {
     },
     /** 删除菜单 */
     handleDeleteMenu(node, menu) {
-      this.$confirm('确定要删除这个菜单吗?如果有子菜单,子菜单也会被一并删除!', '提示', { type: 'warning' }).then(() => {
+      this.$confirm(this.$t('MenuDeleteMsg.edit'), this.$t('action.prompt'), { type: 'warning' }).then(() => {
         API_Menus.deleteMenu(menu.id).then(() => {
           const parent = node.parent
           const children = parent.data.children || parent.data

+ 15 - 15
src/views/ncs-orginazition/components/AppVersionManager.vue

@@ -4,7 +4,7 @@
 
       <el-row>
         <el-col :span="12">
-          <el-form-item label="APK文件上传">
+          <el-form-item :label="this.$t('action.uploadAPK')">
 
             <el-upload
               class="upload-demo"
@@ -15,24 +15,24 @@
               :before-upload="handleShopLogoBefore"
             >
               <i class="el-icon-upload" />
-              <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
-              <div slot="tip" class="el-upload__tip">只能上传APK文件</div>
+              <div class="el-upload__text">{{ this.$t('action.uploadFileMsg') }}<em>{{ this.$t('action.uploadFileMsg2') }}</em></div>
+              <div slot="tip" class="el-upload__tip">{{ this.$t('action.uploadFileMsg5') }}</div>
             </el-upload>
           </el-form-item>
-          <el-form-item label="版本数字" prop="version_no">
-            <el-input-number v-model="formmodel.version_no" :min="1" :max="1000" placeholder="请输入版本数字" />
-<!--            <el-input v-model="formmodel.version_no" type="number" clearable :maxlength="100" placeholder="请输入版本信息" />-->
+          <el-form-item :label="this.$t('action.uploadVersionNo')" prop="version_no">
+            <el-input-number v-model="formmodel.version_no" :min="1" :max="1000" :placeholderbel="this.$t('action.inputUploadVersionNo')" />
+<!--            <el-input v-model="formmodel.version_no" type="number" clearable :maxlength="100" :placeholderbel="请输入版本信息" />-->
           </el-form-item>
-          <el-form-item label="版本信息" prop="version_code">
-            <el-input v-model="formmodel.version_code" clearable :maxlength="100" placeholder="请输入版本信息" />
+          <el-form-item :label="this.$t('action.uploadVersionCode')" prop="version_code">
+            <el-input v-model="formmodel.version_code" clearable :maxlength="100" :placeholderbel="this.$t('action.inputUploadVersionCode')" />
           </el-form-item>
-          <el-form-item label="文件路径" prop="ver_filepath">
-            <el-input v-model="formmodel.app_path" clearable readonly placeholder="文件路径" />
+          <el-form-item :label="this.$t('action.uploadFileUrl')" prop="ver_filepath">
+            <el-input v-model="formmodel.app_path" clearable readonly :placeholderbel="this.$t('action.uploadFileUrl')" />
           </el-form-item>
         </el-col>
       </el-row>
       <el-form-item align="center" class="margin-top-sm">
-        <el-button type="success" @click="handlerFormSubmit">保存设置</el-button>
+        <el-button type="success" @click="handlerFormSubmit">{{ this.$t('action.saveSettings') }}</el-button>
       </el-form-item>
     </el-form>
   </el-card>
@@ -61,13 +61,13 @@ export default {
       },
       rules: {
         version_no: [
-          { required: true, message: '版本数字不能为空', trigger: 'blur' }
+          { required: true, message: this.$t('action.uploadVersionNoMsg'), trigger: 'blur' }
         ],
         version_code: [
-          { required: true, message: '版本信息不能为空', trigger: 'blur' }
+          { required: true, message: this.$t('action.uploadVersionCodeMsg'), trigger: 'blur' }
         ],
         app_path: [
-          { required: true, message: '请上传APK文件', trigger: 'blur' }
+          { required: true, message: this.$t('action.uploadFileUrlMsg2'), trigger: 'blur' }
         ]
       },
       uploadServer: serverUrl
@@ -88,7 +88,7 @@ export default {
       const ext = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase() === 'apk'
       const isapk = isImg || ext
       if (!isapk) {
-        this.$message.error('只能上传APK文件!')
+        this.$message.error(this.$t('action.uploadFileMsg5'))
       }
       return isapk
     },

+ 112 - 12
src/views/ncs-orginazition/components/partInfoEdit.vue

@@ -1,7 +1,7 @@
 <template>
   <div>
     <el-card style="margin: 15px">
-      <el-form ref="editform" :rules="rules" label-width="130px" :model="formmodel">
+      <el-form ref="editform" :rules="rules" label-width="140px" :model="formmodel">
         <fieldset>
           <legend>{{ this.$t('partInfo.baseInfo') }}</legend>
           <el-row>
@@ -37,10 +37,19 @@
                 <el-input v-model="formmodel.member_name"
                           clearable
                           :maxlength="100"
-                          readonly
+                          :readonly="noMember"
                           :placeholder="this.$t('partInfo.inputShopMemberName')" />
               </el-form-item>
             </el-col>
+            <el-col v-if="!noMember" :span="8">
+              <el-form-item :label="this.$t('partInfo.shopMemberPassword')" prop="member_password">
+                <el-input v-model="formmodel.member_password"
+                          type="password"
+                          clearable
+                          :maxlength="100"
+                          :placeholder="this.$t('partInfo.inputShopMemberPassword')" />
+              </el-form-item>
+            </el-col>
             <el-col :span="8">
               <el-form-item :label="this.$t('partInfo.shopParentId')" prop="parent_id">
                 <el-select v-model="formmodel.parent_id" :placeholder="this.$t('partInfo.choiceShopParentId')" clearable>
@@ -270,11 +279,31 @@
               </el-form-item>
             </el-col>
 
-            <el-form-item :label="this.$t('partInfo.autoAccept')" prop="auto_accept">
-              <el-checkbox v-model="formmodel.auto_accept" :true-label="1" :false-label="0">{{ this.$t('partInfo.openAutoAccept') }}</el-checkbox>
-            </el-form-item>
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.autoAccept')" prop="auto_accept">
+                <el-checkbox v-model="formmodel.auto_accept" :true-label="1" :false-label="0">{{ this.$t('partInfo.openAutoAccept') }}</el-checkbox>
+              </el-form-item>
+            </el-col>
+
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.eventForward')" prop="event_forward">
+                <el-checkbox v-model="formmodel.event_forward" :true-label="1" :false-label="0">{{ this.$t('partInfo.openEventForward') }}</el-checkbox>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+
+          <el-row>
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.nursingColorRgb')">
+<!--                <colorPicker v-model="formmodel.nursing_color_rgb" />-->
+                <el-input v-model="formmodel.nursing_color_rgb" />
+              </el-form-item>
+            </el-col>
           </el-row>
 
+
+
           <el-row>
             <el-col :span="8">
               <el-form-item :label="this.$t('partInfo.communicationModeBed')" prop="communication_mode_bed">
@@ -343,6 +372,26 @@
               </el-form-item>
             </el-col>
             <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.doorNurseTitle')">
+                <el-input v-model="formmodel.door_nurse_title" :label="this.$t('partInfo.doorNurseTitle')" :maxlength="15" >
+                  <el-select v-model="formmodel.door_nurse_valid" slot="prepend" :placeholder="this.$t('action.choice')">
+                    <el-option :label="this.$t('partInfo.display')" :value="1"></el-option>
+                    <el-option :label="this.$t('partInfo.onDisplay')" :value="0"></el-option>
+                  </el-select>
+                </el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.doorNursingTitle')">
+                <el-input v-model="formmodel.door_nursing_title" :label="this.$t('partInfo.doorNursingTitle')" :maxlength="15" >
+                  <el-select v-model="formmodel.door_nursing_valid" slot="prepend" :placeholder="this.$t('action.choice')">
+                    <el-option :label="this.$t('partInfo.display')" :value="1" />
+                    <el-option :label="this.$t('partInfo.onDisplay')" :value="0" />
+                  </el-select>
+                </el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
               <el-form-item :label="this.$t('partInfo.upSeconds')">
                 <el-input-number v-model="formmodel.up_seconds" :min="1" :max="300" :label="this.$t('partInfo.upSeconds')" />
               </el-form-item>
@@ -350,7 +399,7 @@
             </el-col>
             <el-col :span="8">
               <el-form-item  prop="board_show_empty_bed">
-                <el-checkbox v-model="formmodel.board_show_empty_bed">{{this.$t('partInfo.boardShowEmptyBed')}}</el-checkbox>
+                <el-checkbox v-model="formmodel.board_show_empty_bed">{{ this.$t('partInfo.boardShowEmptyBed') }}</el-checkbox>
               </el-form-item>
             </el-col>
           </el-row>
@@ -361,6 +410,7 @@
           <el-button type="success" @click="onSubmit">{{ this.$t('partInfo.saveSettings') }}</el-button>
           <el-button v-if="isShow" type="success" plain :disabled="isDisabled" @click="initialize485Device">{{ this.$t('partInfo.initialize485Device') }}</el-button>
           <el-button v-if="isShow" type="ss" @click="saveList">{{ this.$t('partInfo.addTestMemberList') }}</el-button>
+          <el-button v-if="isShow" type="ss" @click="devicesBind">{{ this.$t('partInfo.bindDevice') }}</el-button>
           <el-button v-if="isShow" type="ss" @click="devicesRef">{{ this.$t('partInfo.devicesRef') }}</el-button>
         </el-form-item>
       </el-form>
@@ -373,7 +423,7 @@
 import * as API_Part from '@/api/ncs_partInfo'
 import { saveListByCustomer } from '@/api/ncs_customer'
 import Storage from '@/utils/storage'
-import { init485Device, initData, initDeviceList } from '@/api/initialize'
+import {bindDeviceTransAudio, init485Device, initData, initDeviceList} from '@/api/initialize'
 import * as API_Clerk from '@/api/ncs_clerk'
 import * as API_SystemConfig from '@/api/ncs_systemconfig'
 export default {
@@ -386,8 +436,13 @@ export default {
   },
   data() {
     return {
-      formmodel: {},
-      rules: {},
+      formmodel: {
+      },
+      rules: {
+        // member_password: [
+        //   { required: true, message: this.$t('partInfo.inputShopMemberPassword'), trigger: 'blur' }
+        // ]
+      },
       dayStart: new Date(2020, 11, 11, 7, 0),
       nightStart: new Date(2020, 11, 11, 18, 0),
       nurseLevel0Config: [],
@@ -397,6 +452,7 @@ export default {
       partRoles: [],
       systemConfig: {},
       formmodelAdmin: {},
+      noMember: true
     }
   },
   async mounted() {
@@ -412,6 +468,11 @@ export default {
       if (this.partId) {
         API_Part.getPartSetting(this.partId).then(res => {
           this.formmodel = { ...res }
+          if (!this.formmodel.member_name || this.formmodel.member_name === '') {
+            this.noMember = false
+          } else {
+            this.noMember = true
+          }
           if (!this.formmodel.id) {
             this.formmodel = {
               ...this.formmodel, ...{
@@ -450,7 +511,13 @@ export default {
                 communication_mode_mobile: 1,
                 customize_role_call_first: 0,
                 customize_role_call_second: 0,
-                auto_accept: 0
+                auto_accept: 0,
+                door_nurse_title: '呼叫护士',
+                door_nurse_valid: 1,
+                door_nursing_title: '进入护理',
+                door_nursing_valid: 1,
+                event_forward: 0,
+                nursing_color_rgb: '#000000'
               }
             }
           } else {
@@ -465,6 +532,10 @@ export default {
           this.formmodel.doctor_valid = res.doctor_valid
           this.formmodel.nurse_title = res.nurse_title
           this.formmodel.nurse_valid = res.nurse_valid
+          // this.formmodel.door_nurse_title = res.door_nurse_title
+          // this.formmodel.door_nurse_valid = res.door_nurse_valid
+          // this.formmodel.door_nursing_title = res.door_nursing_title
+          // this.formmodel.door_nursing_valid = res.door_nursing_valid
           this.formmodel.up_seconds = res.up_seconds
           API_SystemConfig.getConfig('groupHostTransferSeconds').then(r => {
             this.systemConfig = r
@@ -497,17 +568,28 @@ export default {
     onSubmit() {
       this.$refs['editform'].validate((valid) => {
         if (valid) {
+          // this.formmodel.nursing_color_rgb = this.formmodel.nursing_color_rgb.replace('#', '')
           if (this.dayStart) {
             this.formmodel.day_start = this.dayStart.toLocaleTimeString('chinese', { hour12: false })
           }
           if (this.nightStart) {
             this.formmodel.night_start = this.nightStart.toLocaleTimeString('chinese', { hour12: false })
           }
+          if (this.formmodel.member_password) {
+            let params = {}
+            params.shop_id = this.partId
+            params.member_name = this.formmodel.member_name
+            params.member_password = this.formmodel.member_password
+            API_Part.editShopMember(params).then(res => {
+              this.$message.success(this.$t('action.saveSuccess'))
+              this.noMember = true
+            })
+          }
           API_Part.editPartSetting(this.formmodel, this.partId).then(res => {
-            this.$message.success(this.$t('action.saveSuccess') + '')
+            this.$message.success(this.$t('action.saveSuccess'))
             if (this.systemConfig.id != null) {
               API_SystemConfig.update(this.systemConfig.id, this.systemConfig).then(res => {
-                this.$message.success(this.$t('action.saveSuccess') + '')
+                this.$message.success(this.$t('action.saveSuccess'))
               })
             }
           })
@@ -568,6 +650,20 @@ export default {
         console.log(this.$t('action.cancel'))
       })
     },
+    devicesBind() {
+      const _this = this
+      this.$confirm(this.$t('partInfo.sureBindDevice') + '', this.$t('action.tips') + '', {
+        confirmButtonText: this.$t('action.yes'),
+        cancelButtonText: this.$t('action.cancel'),
+        type: 'warning'
+      }).then(() => {
+        bindDeviceTransAudio().then(res => {
+          _this.$message.info(res.message)
+        })
+      }).catch(() => {
+        console.log(this.$t('action.cancel'))
+      })
+    },
     createAdmin() {
       this.formshow = true
       this.formmodelAdmin = {
@@ -592,4 +688,8 @@ fieldset {
 .el-input .el-select {
   width: 100px;
 }
+
+/deep/ .m-colorPicker .box.open{
+  z-index: 1000 !important;
+}
 </style>

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

@@ -20,8 +20,8 @@
           <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
         </div>
         <div class="toolbar-btns">
-          <el-button type="primary" size="mini" @click="createOrginazition">新建组织</el-button>
-          <el-button type="s" size="mini" :disabled="isDisabled" @click="initializeSystem">初始化系统</el-button>
+          <el-button type="primary" size="mini" @click="createOrginazition">{{ this.$t('partInfo.organizationAdd') }}</el-button>
+          <el-button type="s" size="mini" :disabled="isDisabled" @click="initializeSystem">{{ this.$t('partInfo.initializeSystem') }}</el-button>
         </div>
       </div>
       <el-pagination
@@ -43,45 +43,45 @@
 
           <el-row>
             <el-col :span="8">
-              <el-form-item label="组织简称" prop="shop_name">
-                <el-input v-model="formmodel.shop_name" clearable :maxlength="100" placeholder="请输入组织简称" />
+              <el-form-item :label="this.$t('partInfo.shopName')" prop="shop_name">
+                <el-input v-model="formmodel.shop_name" clearable :maxlength="100" :placeholder="this.$t('partInfo.inputShopName')" />
               </el-form-item>
 
             </el-col>
             <el-col :span="16">
-              <el-form-item label="组织全称" prop="full_name">
-                <el-input v-model="formmodel.full_name" clearable :maxlength="100" placeholder="请输入组织全称" />
+              <el-form-item :label="this.$t('partInfo.shopFullName')" prop="full_name">
+                <el-input v-model="formmodel.full_name" clearable :maxlength="100" :placeholder="this.$t('partInfo.inputShopFullName')" />
               </el-form-item>
 
             </el-col>
           </el-row>
           <el-row>
             <el-col :span="8">
-              <el-form-item label="组织类型" prop="shop_type">
-                <el-select v-model="formmodel.shop_type" placeholder="请选择组织类型" clearable>
-                  <el-option label="医院" value="6" />
-                  <el-option label="科室" value="5" />
+              <el-form-item :label="this.$t('partInfo.shopType')" prop="shop_type">
+                <el-select v-model="formmodel.shop_type" :placeholder="this.$t('partInfo.choiceShopType')" clearable>
+                  <el-option :label="this.$t('partInfo.hospital')" value="6" />
+                  <el-option :label="this.$t('partInfo.part')" value="5" />
                 </el-select>
               </el-form-item>
             </el-col>
             <el-col :span="8">
 
-              <el-form-item label="管理员账号" prop="member_name">
-                <el-input v-model="formmodel.member_name" clearable :maxlength="100" placeholder="请输入管理员账号" />
+              <el-form-item :label="this.$t('partInfo.shopMemberName')" prop="member_name">
+                <el-input v-model="formmodel.member_name" clearable :maxlength="100" :placeholder="this.$t('partInfo.inputShopMemberName')" />
               </el-form-item>
             </el-col>
             <el-col :span="8">
 
-              <el-form-item label="管理员密码" prop="member_password">
-                <el-input v-model="formmodel.member_password" type="password" clearable :maxlength="100" placeholder="请输入管理员密码" />
+              <el-form-item :label="this.$t('partInfo.shopMemberPassword')" prop="member_password">
+                <el-input v-model="formmodel.member_password" type="password" clearable :maxlength="100" :placeholder="this.$t('partInfo.inputShopMemberPassword')" />
               </el-form-item>
             </el-col>
 
           </el-row>
           <el-row>
             <el-col :span="8">
-              <el-form-item label="所属组织" prop="parent_id">
-                <el-select v-model="formmodel.parent_id" placeholder="请选择上级组织" clearable>
+              <el-form-item :label="this.$t('partInfo.shopParentId')" prop="parent_id">
+                <el-select v-model="formmodel.parent_id" :placeholder="this.$t('partInfo.choiceShopParentId')" clearable>
                   <el-option v-for="(item,index) in parents" :key="index" :label="item.shop_name" :value="item.shop_id" />
                 </el-select>
               </el-form-item>
@@ -91,8 +91,8 @@
 
       </div>
       <div slot="footer" class="dialog-footer">
-        <el-button @click="formshow = false">取 消</el-button>
-        <el-button type="primary" @click="handlerFormSubmit('editform')">确 定</el-button>
+        <el-button @click="formshow = false">{{ this.$t('action.cancel') }}</el-button>
+        <el-button type="primary" @click="handlerFormSubmit('editform')">{{ this.$t('action.yes') }}</el-button>
       </div>
     </el-dialog>
     <!-- 新建组织弹窗结束 -->
@@ -117,24 +117,24 @@ export default {
         page_no: 1
       },
       /** 新建组织弹出参数 **/
-      formtitle: '新建组织',
+      formtitle: this.$t('partInfo.organizationAdd'),
       formshow: false,
       formmodel: {},
       rules: {
         shop_name: [
-          { required: true, message: '组织名称必须选择', trigger: 'blur' }
+          { required: true, message: this.$t('partInfo.shopNameMsg'), trigger: 'blur' }
         ],
         full_name: [
-          { required: true, message: '组织全称必须填写', trigger: 'blur' }
+          { required: true, message: this.$t('partInfo.shopFullNameMsg'), trigger: 'blur' }
         ],
         shop_type: [
-          { required: true, message: '组织类型必须选择', trigger: 'blur' }
+          { required: true, message: this.$t('partInfo.shopTypeMsg'), trigger: 'blur' }
         ],
         member_name: [
-          { required: true, message: '管理员账号必须填写', trigger: 'blur' }
+          { required: true, message: this.$t('partInfo.shopMemberNameMsg'), trigger: 'blur' }
         ],
         member_password: [
-          { required: true, message: '管理员密码必须填写', trigger: 'blur' }
+          { required: true, message: this.$t('partInfo.shopMemberPasswordMsg'), trigger: 'blur' }
         ]
       },
       /** 上级机构数组 **/
@@ -177,7 +177,7 @@ export default {
         valueGetter: this.hashValueGetter
       },
       { headerName: 'ID', field: 'shop_id', sortable: true, filter: 'agNumberColumnFilter', width: 100 },
-      { headerName: '组织简称', field: 'shop_name', sortable: true, filter: 'agTextColumnFilter', filterParams: {
+      { headerName: this.$t('partInfo.shopName'), field: 'shop_name', sortable: true, filter: 'agTextColumnFilter', filterParams: {
         debounceMs: 200,
         newRowsAction: 'keep'
       }
@@ -185,26 +185,26 @@ export default {
       // lockPosition 锁定位置,会在第一列
       // lockPinned = true 不能拖动然后固定
       // resizeable 单元个大小是否可以调整
-      { headerName: '组织全称', field: 'full_name', sortable: true, filter: 'agTextColumnFilter', filterParams: {
+      { headerName: this.$t('partInfo.shopFullName'), field: 'full_name', sortable: true, filter: 'agTextColumnFilter', filterParams: {
         debounceMs: 200,
         newRowsAction: 'keep'
       }},
-      { headerName: '组织类型', field: 'shop_type', sortable: true, filter: 'agTextColumnFilter', width: 110,
+      { headerName: this.$t('partInfo.shopType'), field: 'shop_type', sortable: true, filter: 'agTextColumnFilter', width: 110,
         // flex: 1,
         filterParams: {debounceMs: 200, newRowsAction: 'keep'},
         cellRenderer: this.shopTypeFormatter
       },
 
-      { headerName: '管理账号', field: 'member_name', sortable: true, filter: 'agTextColumnFilter', width: 130
+      { headerName: this.$t('partInfo.shopMemberName'), field: 'member_name', sortable: true, filter: 'agTextColumnFilter', width: 130
         // flex: 1
       },
-      { headerName: '上级组织简称', field: 'parent_name', sortable: true, filter: 'agTextColumnFilter', width: 200,
+      { headerName: this.$t('partInfo.shopParentName'), field: 'parent_name', sortable: true, filter: 'agTextColumnFilter', width: 200,
         filterParams: {
         debounceMs: 200,
         newRowsAction: 'keep'
       }
       },
-      { headerName: '上级组织全称', field: 'parent_full_name', sortable: true, filter: 'agTextColumnFilter', filterParams: {
+      { headerName: this.$t('partInfo.shopParentFullName'), field: 'parent_full_name', sortable: true, filter: 'agTextColumnFilter', filterParams: {
         debounceMs: 200,
         newRowsAction: 'keep',
         flex: 1
@@ -425,11 +425,11 @@ export default {
 
     shopTypeFormatter(param) {
       if (param.value === '0') {
-        return '<span style="color:green">机构</span>'
+        return '<span style="color:green">' + this.$t('partInfo.shop') + '</span>'
       } else if (param.value === '5') {
-        return '<span style="color:red">科室</span>'
+        return '<span style="color:red">' + this.$t('partInfo.part') + '</span>'
       } else if (param.value === '6') {
-        return '<span style="color:orange">医院</span>'
+        return '<span style="color:orange">' + this.$t('partInfo.hospital') + '</span>'
       }
     },
     handEdit(row) {
@@ -468,7 +468,7 @@ export default {
       setTimeout(() => {
         _this.isDisabled = false
       }, 60000)
-      _this.$message.info('正在初始化,请稍后...')
+      _this.$message.info(this.$t('action.initialing'))
       initData()
     }
   }

+ 18 - 13
src/views/ncs-orginazition/partInfoSetting.vue

@@ -1,70 +1,75 @@
 <template>
   <div>
     <el-tabs v-model="activeName" style="margin:15px;" type="border-card">
-      <el-tab-pane label="科室信息设置" name="partInfo">
+      <el-tab-pane :label="this.$t('partInfo.partInfoSetting')" name="partInfo">
         <keep-alive>
           <part-info-edit :part-id="part_id" />
         </keep-alive>
       </el-tab-pane>
-      <!--      <el-tab-pane label="科室管理账号" name="partInfoAccount">-->
+      <!--      <el-tab-pane :label="科室管理账号" name="partInfoAccount">-->
       <!--        <keep-alive>-->
       <!--          <part-user-manager :part-id="part_id" />-->
       <!--        </keep-alive>-->
       <!--      </el-tab-pane>-->
-      <el-tab-pane label="护士主机APP更新" name="nurse">
+      <el-tab-pane :label="this.$t('partInfo.nurse')" name="nurse">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="1" />
         </keep-alive>
       </el-tab-pane>
-      <el-tab-pane label="护士主机可视版" name="vnurse">
+      <el-tab-pane :label="this.$t('partInfo.vnurse')" name="vnurse">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="101" />
         </keep-alive>
       </el-tab-pane>
-      <el-tab-pane label="总控护士主机APP更新" name="znurse">
+      <el-tab-pane :label="this.$t('partInfo.znurse')" name="znurse">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="201" />
         </keep-alive>
       </el-tab-pane>
-      <el-tab-pane label="门口机APP更新" name="door">
+      <el-tab-pane :label="this.$t('partInfo.doctor')" name="doctor">
+        <keep-alive>
+          <app-version-manager :part-id="part_id" :device-type="2" />
+        </keep-alive>
+      </el-tab-pane>
+      <el-tab-pane :label="this.$t('partInfo.door')" name="door">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="3" />
         </keep-alive>
       </el-tab-pane>
 
-      <el-tab-pane label="门口机可视版" name="vdoor">
+      <el-tab-pane :label="this.$t('partInfo.vdoor')" name="vdoor">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="103" />
         </keep-alive>
       </el-tab-pane>
 
-      <el-tab-pane label="5寸床位分机APP" name="sickbed">
+      <el-tab-pane :label="this.$t('partInfo.sickbed')" name="sickbed">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="4" />
         </keep-alive>
       </el-tab-pane>
 
-      <el-tab-pane label="7寸床位分机APP" name="sevensickbed">
+      <el-tab-pane :label="this.$t('partInfo.sevensickbed')" name="sevensickbed">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="204" />
         </keep-alive>
       </el-tab-pane>
-      <el-tab-pane label="床位分机可视版" name="vsickbed">
+      <el-tab-pane :label="this.$t('partInfo.vsickbed')" name="vsickbed">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="104" />
         </keep-alive>
       </el-tab-pane>
-      <el-tab-pane label="移动设备" name="mobiledevice">
+      <el-tab-pane :label="this.$t('partInfo.mobiledevice')" name="mobiledevice">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="7" />
         </keep-alive>
       </el-tab-pane>
-      <el-tab-pane label="探视机" name="vistitation">
+      <el-tab-pane :label="this.$t('partInfo.vistitation')" name="vistitation">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="19" />
         </keep-alive>
       </el-tab-pane>
-      <el-tab-pane label="转换盒" name="transferDevice">
+      <el-tab-pane :label="this.$t('partInfo.transferDevice')" name="transferDevice">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="11" />
         </keep-alive>

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

@@ -240,7 +240,7 @@
                 }
                 let _this = this
                 API_Remark.save(data).then(res=> {
-                    _this.$message.success('添加成功!')
+                    _this.$message.success(this.$t('action.addSuccess2'))
                     _this.getList()
                     _this.quxiao()
                 })

+ 22 - 22
src/views/ncs-system-config/index.vue

@@ -21,7 +21,7 @@
           <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
         </div>
         <div class="toolbar-btns">
-          <el-button type="primary" size="mini" @click="createBroadcast">新增参数配置</el-button>
+          <el-button type="primary" size="mini" @click="createBroadcast">{{ this.$t('systemConfig.add') }}</el-button>
         </div>
       </div>
       <el-pagination
@@ -39,33 +39,33 @@
     <el-dialog :title.sync="formtitle" :visible.sync="formshow" width="50%">
       <div>
         <el-form ref="editform" :rules="rules" label-width="120px" :model="formmodel">
-          <el-form-item label="分组名称" prop="group_name">
-            <el-input v-model="formmodel.group_name" maxlength="20" placeholder="请输入分组名称" />
+          <el-form-item :label="this.$t('systemConfig.groupName')" prop="group_name">
+            <el-input v-model="formmodel.group_name" maxlength="20" :placeholder="this.$t('systemConfig.inputGroupName')" />
           </el-form-item>
-          <el-form-item label="引用代码" prop="key_code">
-            <el-input v-model="formmodel.key_code" maxlength="20" placeholder="请输入引用代码" />
+          <el-form-item :label="this.$t('systemConfig.keyCode')" prop="key_code">
+            <el-input v-model="formmodel.key_code" maxlength="20" :placeholder="this.$t('systemConfig.inputKeyCode')" />
           </el-form-item>
-          <el-form-item label="配置名称" prop="key_name">
-            <el-input v-model="formmodel.key_name" maxlength="50" placeholder="请输入配置名称" />
+          <el-form-item :label="this.$t('systemConfig.keyName')" prop="key_name">
+            <el-input v-model="formmodel.key_name" maxlength="50" :placeholder="this.$t('systemConfig.inputKeyName')" />
           </el-form-item>
-          <el-form-item label="配置值" prop="key_val">
-            <el-input v-model="formmodel.key_val" maxlength="50" placeholder="请输入配置值" />
+          <el-form-item :label="this.$t('systemConfig.keyVal')" prop="key_val">
+            <el-input v-model="formmodel.key_val" maxlength="50" :placeholder="this.$t('systemConfig.inputKeyVal')" />
           </el-form-item>
-          <el-form-item label="参数说明">
+          <el-form-item :label="this.$t('systemConfig.description')">
             <el-input
               v-model="formmodel.description"
               type="textarea"
               :rows="2"
               maxlength="200"
-              placeholder="请输入参数说明"
+              :placeholder="this.$t('systemConfig.inputDescription')"
             />
           </el-form-item>
 
         </el-form>
       </div>
       <div slot="footer" class="dialog-footer">
-        <el-button @click="formshow = false">取 消</el-button>
-        <el-button type="primary" @click="handlerFormSubmit('editform')">确 定</el-button>
+        <el-button @click="formshow = false">{{ this.$t('action.cancel') }}</el-button>
+        <el-button type="primary" @click="handlerFormSubmit('editform')">{{ this.$t('action.yes') }}</el-button>
       </div>
     </el-dialog>
   </div>
@@ -88,7 +88,7 @@ export default {
         page_no: 1
       },
       /** 新建组织弹出参数 **/
-      formtitle: '新增参数配置',
+      formtitle: this.$t('systemConfig.add'),
       formshow: false,
       formmodel: {
       },
@@ -109,10 +109,10 @@ export default {
       frameworkComponents: null,
       rules: {
         key_code: [
-          { required: true, message: '引用代码不能为空', trigger: 'blur' }
+          { required: true, message: this.$t('systemConfig.keyCodeMsg'), trigger: 'blur' }
         ],
         key_val: [
-          { required: true, message: '配置值不能为空', trigger: 'blur' }
+          { required: true, message: this.$t('systemConfig.keyValMsg'), trigger: 'blur' }
         ]
       }
     }
@@ -138,20 +138,20 @@ export default {
       },
       { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 130 },
       {
-        headerName: '分组名称', field: 'group_name', sortable: true, filter: 'agTextColumnFilter', width: 150
+        headerName: this.$t('systemConfig.groupName'), field: 'group_name', sortable: true, filter: 'agTextColumnFilter', width: 150
       },
       {
-        headerName: '引用代码', field: 'key_code', sortable: true, filter: 'agTextColumnFilter', width: 150
+        headerName: this.$t('systemConfig.keyCode'), field: 'key_code', sortable: true, filter: 'agTextColumnFilter', width: 150
       },
       {
-        headerName: '配置名称', field: 'key_name', sortable: true, filter: 'agTextColumnFilter', width: 150
+        headerName: this.$t('systemConfig.keyName'), field: 'key_name', sortable: true, filter: 'agTextColumnFilter', width: 150
       },
 
       {
-        headerName: '配置值', field: 'key_val', sortable: true, filter: 'agTextColumnFilter', width: 260
+        headerName: this.$t('systemConfig.keyVal'), field: 'key_val', sortable: true, filter: 'agTextColumnFilter', width: 260
       },
       {
-        headerName: '参数说明', field: 'description', sortable: true, filter: 'agTextColumnFilter', flex: 1
+        headerName: this.$t('systemConfig.description'), field: 'description', sortable: true, filter: 'agTextColumnFilter', flex: 1
       },
       {
         headerName: this.$t('action.edit'),
@@ -371,7 +371,7 @@ export default {
             })
           }
         } else {
-          this.$message.error('表单填写错误,请检查!')
+          this.$message.error(this.$t('action.fromError'))
         }
       })
     }

+ 7 - 7
src/views/vital-sign/log.vue

@@ -91,14 +91,14 @@
               :height="600">
         <!--表头-->
         <template slot="table-columns">
-          <el-table-column type="index" width="55" label="序号" />
-          <el-table-column prop="param_name" label="体征参数" min-width="160">
+          <el-table-column type="index" width="55" :label="this.$t('action.index')" />
+          <el-table-column prop="param_name" :label="this.$t('vital.paramName')" min-width="160">
             <template slot-scope="scope">
               <span>{{scope.row.group_name===scope.row.param_name?scope.row.param_name:scope.row.group_name+'-'+scope.row.param_name}}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="vs_value" label="体征值" min-width="120"/>
-          <el-table-column prop="log_time" label="测量时间" min-width="180">
+          <el-table-column prop="vs_value" :label="this.$t('vital.value')" min-width="120"/>
+          <el-table-column prop="log_time" :label="this.$t('vital.logTime')" min-width="180">
             <template slot-scope="scope">
               <i class="el-icon-time"></i>
               <span style="margin-left: 5px">{{ unixToDate(scope.row.log_time,'yyyy-MM-dd hh:mm:ss')}}</span>
@@ -279,14 +279,14 @@ export default {
             const legenddata = [] // 图例集合
             const zoom = this.MixinClone(zoomitem)
 
-            op.title.text = key.vital_signs_name + '体征参数'
+            op.title.text = key.vital_signs_name + this.$t('vital.paramName')
 
             key.paramlogs.forEach((elem, index) => {
               const xAxic = this.MixinClone(xAxi)
               const seriec = this.MixinClone(serie)
               legenddata.push(elem.param.param_name) // 加入图例
               op.yAxis.max = elem.param.max_limit_end + 5
-              op.yAxis[0].name = '单位:' + key.unit
+              op.yAxis[0].name = this.$t('vital.company') + key.unit
               zoom.xAxisIndex.push(index)
               xAxic.axisLine.lineStyle.color = this.colors[index] // 设置颜色
               xAxic.offset = 25 * index // 设置x轴偏移
@@ -393,7 +393,7 @@ export default {
           const param = { ...this.baseInfoForm.goods_params_list }
 
           API_Params.saveVitalSignsLog(this.baseInfoForm.goods_params_list, this.memberId).then((response) => {
-            this.$message.success('添加成功!')
+            this.$message.success(this.$t('action.addSuccess2'))
             this.formshow = false
             this.GET_VitalSingsGroupParamLogs()
           })