瀏覽代碼

解决es.js冲突

wuyunfeng 1 年之前
父節點
當前提交
4de5f20c0d

文件差異過大導致無法顯示
+ 1 - 1
dist/index.html


+ 41 - 2
languages/en.js

@@ -172,6 +172,7 @@ module.exports = {
     uploaderImg2: 'Upload avatar images can only be in JPG, PNG, GIF format!',
     uploaderSize: 'The upload attachment size cannot exceed 5MB!',
     uploaderSize2: 'The size of the uploaded avatar image cannot exceed 2MB!',
+    uploaderSize3: 'The size of the uploaded image cannot exceed 10MB!',
     uploaderImgMsg: 'The width of the image must be between 100 and 500, and the aspect ratio is 1:1! ',
     uploaderImgMsg2: 'Please upload an image with an aspect ratio of 1:1',
     uploaderImgMsg3: 'The height of the image must be between 100 and 500! ',
@@ -225,7 +226,10 @@ module.exports = {
     reboot: 'Reboot',
     count: 'Number of statistics',
     system: 'System',
-    simulateSend: 'Simulate Send'
+    simulateSend: 'Simulate Send',
+    justify: 'alignment',
+    indent: 'indentation',
+    image: 'picture'
   },
   member: {
     face: 'Avatar',
@@ -456,6 +460,29 @@ module.exports = {
     actIntent: 'Parameters of Activity',
     inputActIntent: 'Please enter the parameters for the activity'
   },
+  deviceMenuDetailManage: {
+    type: 'types of',
+    chooseType: 'Please select the type of introduction',
+    user: 'user',
+    chooseUser: 'Uncheck and display to all users by default',
+    title: 'title',
+    inputTitle: 'Please enter a title',
+    titleBg: 'Head background',
+    titleIcon: 'Titles Icon',
+    summary: 'brief introduction',
+    inputSummary: 'Please enter a brief introduction',
+    detail: 'content',
+    tags: 'label',
+    inputTags: 'Please enter a label',
+    hospitalAddr: 'Hospital address',
+    inputHospitalAddr: 'Please enter the hospital address',
+    hospitalTel: 'Hospital phone number',
+    inputHospitalTel: 'Please enter the hospital phone number',
+    hospital_web: 'Hospital website',
+    inputHospitalWeb: 'Please enter the hospital website',
+    partClerk: 'Related important members',
+    choosePartClerk: 'Please select relevant important members'
+  },
   clerkManage: {
     clerkEdit: 'Edit member information',
     choiceClerk: 'Please select an employee',
@@ -917,6 +944,10 @@ module.exports = {
     linuxBedGainSize: 'Digital extension volume gain',
     linuxDoorVolumeNative: 'Digital doorstep machine recording volume',
     linuxDoorGainSize: 'Digital doorstep machine volume gain',
+    androidBedVolumeNative: 'Android extension recording volume',
+    androidBedGainSize: 'Android extension volume gain',
+    androidDoorVolumeNative: 'Android doorstep machine recording volume',
+    androidDoorGainSize: 'Android doorstep machine volume gain',
     autoAccept: 'Extension automatic answering',
     openAutoAccept: 'Enable automatic answer',
     unmannedCall: 'Extension opens unmanned call',
@@ -996,7 +1027,8 @@ module.exports = {
     boolAllDoorStatus: 'Enable all doorstep call displays',
     boolDooLightAlwaysOn: 'Is the door light always on',
     convenientServiceEnabled: 'Convenient service',
-    ledServiceEnabled: 'Server control LED'
+    ledServiceEnabled: 'Server control LED',
+    autoPositionEnabled: 'Enable automatic positioning'
   },
   role: {
     roleName: 'Role name',
@@ -1088,6 +1120,7 @@ module.exports = {
     customBoardDesigner: 'Designer Board Screen',
     staffManageFrames: 'Staff Serve Structure',
     deviceMenuManager: 'Device Menu',
+    deviceMenuDetail: 'Device Menu Details',
     nbiotDeviceStatus: 'Faulty IoT equipment',
     offlineDevice: 'off-line equipment',
     lowBatteryDevice: 'Low battery devices',
@@ -1332,6 +1365,12 @@ module.exports = {
     FILE_UPLOAD_FAILED: 'No file storage directory configured!',
     FILE_FAILED: 'file error'
   },
+  deviceMenuDetailType: {
+    HOSPITAL: 'Hospital Introduction',
+    PART: 'Department Introduction',
+    IN_NOTICE: 'Admission Notice',
+    SATISFACTION: 'Satisfaction survey'
+  },
   entraceguardUser: {
     named: 'User Name',
     idNo: 'ID number',

文件差異過大導致無法顯示
+ 484 - 446
languages/es.js


+ 44 - 5
languages/ru-RU.js

@@ -170,8 +170,9 @@ module.exports = {
     uploaderDownload: 'Загрузить вложение',
     uploaderImg: 'Загружать вложения можно только в формате txt,doc,docx,xls,xlsx,jpg,png,jpeg!',
     uploaderImg2: 'Загружать изображения аватара можно только в формате JPG, PNG, GIF!',
-    uploaderSize: 'Размер загружаемого вложения не может превышать 5 МБ!',
-    uploaderSize2: 'Размер загружаемого аватара не может превышать 2 МБ!',
+    uploaderSize: 'Размер загружаемого вложения не может превышать 5МБ!',
+    uploaderSize2: 'Размер загружаемого аватара не может превышать 2МБ!',
+    uploaderSize3: 'Размер изображения не должен превышать 10 Мб!',
     uploaderImgMsg: 'Ширина изображения должна быть от 100 до 500, а соотношение сторон 1:1! ',
     uploaderImgMsg2: 'Пожалуйста, загрузите изображение с соотношением сторон 1:1',
     uploaderImgMsg3: 'Высота изображения должна быть между 100 и 500! ',
@@ -225,7 +226,10 @@ module.exports = {
     reboot: 'Перезагрузка',
     count: 'Статистика',
     system: 'Системы',
-    simulateSend: 'аналоговая передача'
+    simulateSend: 'аналоговая передача',
+    justify: 'Выровнять',
+    indent: 'Отступ',
+    image: 'Фотографии'
   },
   member: {
     face: 'Аватар',
@@ -456,6 +460,29 @@ module.exports = {
     actIntent: 'Параметры активности',
     inputActIntent: 'Введите параметры активности'
   },
+  deviceMenuDetailManage: {
+    type: 'Тип',
+    chooseType: 'Выберите тип профиля',
+    user: 'Пользователи',
+    chooseUser: 'Показывать не по умолчанию всем пользователям',
+    title: 'Заголовок',
+    inputTitle: 'Введите заголовок',
+    titleBg: 'Фон головы',
+    titleIcon: 'Значок заголовка',
+    summary: 'Введение',
+    inputSummary: 'Введите профиль',
+    detail: 'Содержание',
+    tags: 'Метки',
+    inputTags: 'Введите вкладку',
+    hospitalAddr: 'Адрес больницы',
+    inputHospitalAddr: 'Пожалуйста, введите адрес больницы.',
+    hospitalTel: 'Больничный телефон',
+    inputHospitalTel: 'Пожалуйста, введите телефон больницы.',
+    hospital_web: 'Сайт больницы',
+    inputHospitalWeb: 'Пожалуйста, введите сайт больницы.',
+    partClerk: 'Соответствующие важные члены',
+    choosePartClerk: 'Пожалуйста, выберите значимых членов.'
+  },
   clerkManage: {
     clerkEdit: 'Редактировать информацию об участнике',
     choiceClerk: 'Пожалуйста, выберите сотрудника',
@@ -917,6 +944,10 @@ module.exports = {
     linuxBedGainSize: 'Цифровое увеличение громкости',
     linuxDoorVolumeNative: 'Звуковая запись на цифровом клапане',
     linuxDoorGainSize: 'Коэффициент усиления громкости цифрового клапана',
+    androidBedVolumeNative: 'Звук на андроид',
+    androidBedGainSize: 'Коэффициент усиления громкости',
+    androidDoorVolumeNative: 'Звуковая запись на Android',
+    androidDoorGainSize: 'Коэффициент усиления громкости у ворот Android',
     autoAccept: 'Автоматический ответ на добавочный номер',
     openAutoAccept: 'Включить автоматический ответ',
     unmannedCall: 'Включите добавочный. Беспилотный звонок.',
@@ -980,7 +1011,7 @@ module.exports = {
     entraceguard_device: 'Вход',
     organizationAdd: 'Новая организация',
     boardShowEmptyBed: 'На доске показаны пустые кровати',
-    iotProductID:  'Идентификатор устройства NB',
+    iotProductID: 'Идентификатор устройства NB',
     iotProductKey: 'Ключ продукта устройства NB',
     nursingColorRgb: 'Светлый цвет двери медсестер',
     twoColorDoorLightValid: 'Поддерживается или нет двухцветная дверная подсветка',
@@ -996,7 +1027,8 @@ module.exports = {
     boolAllDoorStatus: 'Откройте все двери.',
     boolDooLightAlwaysOn: 'Светит ли дверь постоянно',
     convenientServiceEnabled: 'Удобное обслуживание',
-    ledServiceEnabled: 'Управление сервером LED'
+    ledServiceEnabled: 'Управление сервером LED',
+    autoPositionEnabled: 'Включить автоматическое позиционирование'
   },
   role: {
     roleName: 'Имя роли',
@@ -1088,6 +1120,7 @@ module.exports = {
     customBoardDesigner: 'Экран панели',
     staffManageFrames: 'Параметры управления пространством',
     deviceMenuManager: 'Меню Устройства',
+    deviceMenuDetail: 'Меню устройства Подробнее',
     nbiotDeviceStatus: 'неисправное оборудование МСУ',
     offlineDevice: 'Автономное оборудование',
     lowBatteryDevice: 'Низкоэлектрическое оборудование',
@@ -1332,6 +1365,12 @@ module.exports = {
     FILE_UPLOAD_FAILED: 'каталог без профиля!',
     FILE_FAILED: 'Ошибка файла'
   },
+  deviceMenuDetailType: {
+    HOSPITAL: 'Краткое описание больницы',
+    PART: 'Введение',
+    IN_NOTICE: 'Информация о госпитализации',
+    SATISFACTION: 'Обследование степени удовлетворенности'
+  },
   entraceguardUser: {
     named: 'Имя пользователя',
     idNo: 'Номер удостоверения личности',

+ 42 - 3
languages/zh-CN.js

@@ -171,7 +171,8 @@ module.exports = {
     uploaderImg: '上传附件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!',
     uploaderImg2: '上传头像图片只能是 JPG、PNG、GIF 格式!',
     uploaderSize: '上传附件大小不能超过 5MB!',
-    uploaderSize2: '上传头像图片大小不能超过 2MB!',
+    uploaderSize2: '上传图片大小不能超过 2MB!',
+    uploaderSize3: '上传图片大小不能超过 10MB!',
     uploaderImgMsg: '图片宽度必须在100~500之间,宽高比为1: 1!',
     uploaderImgMsg2: '请上传宽高比为1: 1的图片',
     uploaderImgMsg3: '图片高度必须在100~500之间!',
@@ -225,7 +226,10 @@ module.exports = {
     reboot: '重启',
     count: '统计次数',
     system: '系统',
-    simulateSend: '模拟发送'
+    simulateSend: '模拟发送',
+    justify: '对齐',
+    indent: '缩进',
+    image: '图片'
   },
   member: {
     face: '头像',
@@ -456,6 +460,29 @@ module.exports = {
     actIntent: 'Activity的参数',
     inputActIntent: '请输入Activity的参数'
   },
+  deviceMenuDetailManage: {
+    type: '类型',
+    chooseType: '请选择简介类型',
+    user: '用户',
+    chooseUser: '不选默认显示给所有用户',
+    title: '标题',
+    inputTitle: '请输入标题',
+    titleBg: '头部背景',
+    titleIcon: '标题图标',
+    summary: '简介',
+    inputSummary: '请输入简介',
+    detail: '内容',
+    tags: '标签',
+    inputTags: '请输入标签',
+    hospitalAddr: '医院地址',
+    inputHospitalAddr: '请输入医院地址',
+    hospitalTel: '医院电话',
+    inputHospitalTel: '请输入医院电话',
+    hospital_web: '医院网址',
+    inputHospitalWeb: '请输入医院网址',
+    partClerk: '相关重要成员',
+    choosePartClerk: '请选择相关重要成员'
+  },
   clerkManage: {
     clerkEdit: '编辑成员信息',
     choiceClerk: '请选择员工',
@@ -917,6 +944,10 @@ module.exports = {
     linuxBedGainSize: '数字分机音量增益',
     linuxDoorVolumeNative: '数字门口机录音音量',
     linuxDoorGainSize: '数字门口机音量增益',
+    androidBedVolumeNative: '安卓分机录音音量',
+    androidBedGainSize: '安卓分机音量增益',
+    androidDoorVolumeNative: '安卓门口机录音音量',
+    androidDoorGainSize: '安卓门口机音量增益',
     autoAccept: '分机开启自动接听',
     openAutoAccept: '开启自动接听',
     unmannedCall: '分机开启无人呼叫',
@@ -996,7 +1027,8 @@ module.exports = {
     boolAllDoorStatus: '开启所有门口机呼显示',
     boolDooLightAlwaysOn: '门灯是否常亮',
     convenientServiceEnabled: '便民服务',
-    ledServiceEnabled: '服务端控制点阵屏'
+    ledServiceEnabled: '服务端控制点阵屏',
+    autoPositionEnabled: '开启自动定位'
   },
   role: {
     roleName: '角色名称',
@@ -1088,6 +1120,7 @@ module.exports = {
     customBoardDesigner: '看板屏设计',
     staffManageFrames: '空间管理设置',
     deviceMenuManager: '设备菜单',
+    deviceMenuDetail: '设备菜单详情',
     nbiotDeviceStatus: '故障物联设备',
     offlineDevice: '离线设备',
     lowBatteryDevice: '低电量设备',
@@ -1332,6 +1365,12 @@ module.exports = {
     FILE_UPLOAD_FAILED: '未配置文件存放目录!',
     FILE_FAILED: '文件错误'
   },
+  deviceMenuDetailType: {
+    HOSPITAL: '医院简介',
+    PART: '科室简介',
+    IN_NOTICE: '入院须知',
+    SATISFACTION: '满意度调查'
+  },
   entraceguardUser: {
     named: '用户姓名',
     idNo: '身份证号',

+ 3 - 1
package.json

@@ -17,6 +17,8 @@
   "dependencies": {
     "@moefe/vue-aplayer": "^2.0.0-beta.5",
     "@toast-ui/editor": "^3.1.3",
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "^1.0.2",
     "ag-grid-community": "^25.0.0",
     "ag-grid-vue": "^25.0.0",
     "axios": "0.18.1",
@@ -58,6 +60,7 @@
     "vue-count-to": "^1.0.13",
     "vue-draggable-resizable": "^2.3.0",
     "vue-i18n": "^8.26.1",
+    "vue-json-viewer": "^2.2.22",
     "vue-lazyload": "^1.2.6",
     "vue-property-decorator": "^9.1.2",
     "vue-qr": "^3.2.4",
@@ -65,7 +68,6 @@
     "vue-seamless-scroll": "^1.1.23",
     "vue-splitpane": "1.0.4",
     "vuedraggable": "^2.20.0",
-    "vue-json-viewer": "^2.2.22",
     "vuex": "3.1.0",
     "xlsx": "0.14.1"
   },

+ 2 - 2
public/domain.js

@@ -11,7 +11,7 @@ const domain = {
   enableNBiot: false,  //NB设备
   enableCustomerDevice: false,  //用户设备
   enableSosDevice: false, //报警设备
-  enable485:false,
-  enableLinux:false
+  enable485: false,
+  enableLinux: false
 }
 

+ 7 - 0
src/api/ncs_clerk.js

@@ -125,3 +125,10 @@ export function getClerksByShopId(partId) {
     method: 'GET'
   })
 }
+
+export function getClerkVoByPartId(partId) {
+  return request({
+    url: `/ncs/clerk/get_clerk_by_part_id/${partId}`,
+    method: 'GET'
+  })
+}

+ 26 - 0
src/api/ncs_device_menu_detail.js

@@ -0,0 +1,26 @@
+import request from '@/utils/request'
+export function getModelByMenuId(menuId) {
+  return request({
+    url: `/ncs/device_menu_detail/get_model_by_menu_id/${menuId}`,
+    method: 'GET'
+  })
+}
+
+/** 修改 */
+export function update(id, params) {
+  return request({
+    url: `/ncs/device_menu_detail/${id}`,
+    method: 'put',
+    data: params
+  })
+}
+
+/** 新增 */
+export function add(params) {
+  return request({
+    url: '/ncs/device_menu_detail',
+    method: 'POST',
+    loading: true,
+    data: params
+  })
+}

+ 14 - 0
src/api/upload.js

@@ -0,0 +1,14 @@
+import request from '@/utils/request'
+export function upload(file) {
+  return request({
+    url: 'ncs/upload/uploadFile',
+    method: 'POST',
+    data: file,
+    headers: { 'Content-Type': 'multipart/form-data;' },
+    transformRequest: [
+      function() {
+        return file
+      }
+    ]
+  })
+}

+ 320 - 0
src/components/WangEdiitor/wangEditor.vue

@@ -0,0 +1,320 @@
+<template>
+  <div style="border: 1px solid #ccc;">
+    <Toolbar
+        style="border-bottom: 1px solid #ccc"
+        :editor="editor"
+        :mode="mode"
+        :default-config="toolbarConfig"
+    />
+    <Editor
+        style="height: 500px; overflow-y: hidden;"
+        v-model="content"
+        :mode="mode"
+        :default-config="editorConfig"
+        @onCreated="onCreated"
+        @onChange="onChange"
+        @onDestroyed="onDestroyed"
+        @onMaxLength="onMaxLength"
+        @onFocus="onFocus"
+        @onBlur="onBlur"
+        @customAlert="customAlert"
+        @customPaste="customPaste"
+    />
+  </div>
+</template>
+
+<script>
+import Vue from 'vue'
+import '@wangeditor/editor/dist/css/style.css'
+import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
+import { i18nChangeLanguage  } from '@wangeditor/editor'
+import * as API_Upload from "@/api/upload";
+import * as wangEditorConfig from "@/components/WangEdiitor/wangEditorConfig";
+
+
+const serverUrl = domain.serverUrl
+export default {
+  name: "wangEditor",
+  components: { Editor, Toolbar },
+  model: {
+    prop: 'value',
+    event: 'input'
+  },
+  props: {
+    value: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      editor: null,
+      mode: 'default', // 'simple' or 'default'
+      content: '',
+      toolbarConfig: wangEditorConfig.toolbarConfig,
+      // toolbarConfig: {},
+      editorConfig: {
+        placeholder: '请输入内容...',
+        withCredentials: true,
+        MENU_CONF: {
+          // 配置上传图片
+          uploadImage: {
+            // // 自定义上传图片的方法
+            customUpload: this.uploadImg,
+            // // 自定义插入图片的方法
+            customInsert: this.insertImg,
+            //server必须要配置正确
+            // server: serverUrl + '/ncs/upload/uploadFile',
+            // 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
+            fieldName: "file",
+            headers: {
+              // 'Content-Type': 'multipart/form-data;'
+            },
+
+            maxFileSize: 4 * 1024 * 1024, // 1M
+            // 最多可上传几个文件,默认为 100
+            maxNumberOfFiles: 100,
+            // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
+            allowedFileTypes: ['image/*'],
+            meta: {
+              //官网中把token放到了这里,但是请求的时候会看不到token
+            },
+            // 将 meta 拼接到 url 参数中,默认 false
+            metaWithUrl: false,
+            // 跨域是否传递 cookie ,默认为 false
+            withCredentials: false,
+            // 超时时间,默认为 10 秒
+            timeout: 5 * 1000, // 5 秒
+          },
+          // insertLink: {
+          //   checkLink: this.checkedLink,
+          // },
+          // editLink: {
+          //   checkLink: this.checkedLink,
+          // }
+
+        },
+      },
+    }
+  },
+  watch: {
+    value(val) {
+      if (this.$i18n.locale === 'zh') {
+        i18nChangeLanguage('zh-CN')
+      }
+      else {
+        i18nChangeLanguage('en')
+      }
+      this.content = val
+    },
+  },
+  beforeDestroy() {
+    const editor = this.editor
+    if (editor == null) return
+    editor.destroy() // 组件销毁时,及时销毁编辑器
+  },
+  methods: {
+    onCreated(editor) {
+      this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
+    },
+    onChange(editor) {
+      this.$emit('input', editor.getHtml())
+      this.content = editor.getHtml()
+      this.$emit('change', this.content)
+    },
+    onDestroyed(editor) {
+      // console.log("onDestroyed", editor);
+    },
+    onMaxLength(editor) {
+      // console.log("onMaxLength", editor);
+    },
+    onFocus(editor) {
+      // console.log("onFocus", editor);
+    },
+    onBlur(editor) {
+      // console.log("onBlur", editor);
+    },
+    customAlert(info, type) {
+      window.alert(`customAlert in Vue demo\n${type}:\n${info}`);
+    },
+
+    //重点来了: 自定义粘贴。可阻止编辑器的默认粘贴,实现自己的粘贴逻辑。(可以实现复制粘贴 word ,有图片)
+    customPaste(editor, event, callback) {
+      console.log("ClipboardEvent 粘贴事件对象", event);
+      let html = event.clipboardData.getData("text/html"); // 获取粘贴的 html
+      // let text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
+      let rtf = event.clipboardData.getData("text/rtf"); // 获取 rtf 数据(如从 word wsp 复制粘贴)
+      var that = this;
+      if (html && rtf) {
+
+        // 列表缩进会超出边框,直接过滤掉
+        html = html.replace(/text\-indent:\-(.*?)pt/gi, "");
+
+        // 从html内容中查找粘贴内容中是否有图片元素,并返回img标签的属性src值的集合
+        const imgSrcs = that.findAllImgSrcsFromHtml(html);
+
+        // 如果有
+        if (imgSrcs && Array.isArray(imgSrcs) && imgSrcs.length) {
+          // 从rtf内容中查找图片数据
+          const rtfImageData = that.extractImageDataFromRtf(rtf);
+
+          // 如果找到
+          if (rtfImageData.length) {
+            // TODO:此处可以将图片上传到自己的服务器上
+            this.uploadImg(rtfImageData, this.editor)
+
+            // 执行替换:将html内容中的img标签的src替换成ref中的图片数据,如果上面上传了则为图片路径
+            html = that.replaceImagesFileSourceWithInlineRepresentation(
+                html,
+                imgSrcs,
+                rtfImageData
+            );
+            editor.dangerouslyInsertHtml(html);
+          }
+        }
+
+        // 阻止默认的粘贴行为
+        event.preventDefault();
+        return false;
+      } else {
+        return true;
+      }
+    },
+
+    //自定义上传图片
+    uploadImg(file, insertFn) {
+      let imgData = new FormData();
+      imgData.append("file", file);
+      //调用上传图片接口,上传图片
+      API_Upload.upload(imgData).then((res) => {
+        // 插入后端返回的url
+        insertFn(serverUrl + '/' + res);
+        this.$message({
+          type: "success",
+          message: "上传成功",
+        });
+      }).catch((error) => {
+        this.$message("上传失败,请重新上传");
+      });
+    },
+
+    // 自定义插入图片
+    insertImg(file, insertFn) {
+      this.uploadImg(file, insertFn)
+    },
+    /**
+     * 从html代码中匹配返回图片标签img的属性src的值的集合
+     * @param htmlData
+     * @return Array
+     */
+    findAllImgSrcsFromHtml(htmlData) {
+      let imgReg = /<img.*?(?:>|\/>)/gi; //匹配图片中的img标签
+      let srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i; // 匹配图片中的src
+
+      let arr = htmlData.match(imgReg); //筛选出所有的img
+      if (!arr || (Array.isArray(arr) && !arr.length)) {
+        return false;
+      }
+
+      let srcArr = [];
+      for (let i = 0; i < arr.length; i++) {
+        let src = arr[i].match(srcReg);
+        // 获取图片地址
+        srcArr.push(src[1]);
+      }
+
+      return srcArr;
+    },
+    /**
+     * 从rtf内容中匹配返回图片数据的集合
+     * @param rtfData
+     * @return Array
+     */
+    extractImageDataFromRtf(rtfData) {
+      if (!rtfData) {
+        return [];
+      }
+
+      const regexPictureHeader =
+          /{\\pict[\s\S]+?({\\\*\\blipuid\s?[\da-fA-F]+)[\s}]*/;
+      const regexPicture = new RegExp(
+          "(?:(" + regexPictureHeader.source + "))([\\da-fA-F\\s]+)\\}",
+          "g"
+      );
+      const images = rtfData.match(regexPicture);
+      const result = [];
+
+      if (images) {
+        for (const image of images) {
+          let imageType = false;
+
+          if (image.includes("\\pngblip")) {
+            imageType = "image/png";
+          } else if (image.includes("\\jpegblip")) {
+            imageType = "image/jpeg";
+          }
+
+          if (imageType) {
+            result.push({
+              hex: image
+                  .replace(regexPictureHeader, "")
+                  .replace(/[^\da-fA-F]/g, ""),
+              type: imageType,
+            });
+          }
+        }
+      }
+
+      return result;
+    },
+    /**
+     * 将html内容中img标签的属性值替换
+     * @param htmlData html内容
+     * @param imageSrcs html中img的属性src的值的集合
+     * @param imagesHexSources rtf中图片数据的集合,与html内容中的img标签对应
+     * @param isBase64Data 是否是Base64的图片数据
+     * @return String
+     */
+    replaceImagesFileSourceWithInlineRepresentation(
+        htmlData,
+        imageSrcs,
+        imagesHexSources,
+        isBase64Data = true
+    ) {
+      if (imageSrcs.length === imagesHexSources.length) {
+        for (let i = 0; i < imageSrcs.length; i++) {
+          const newSrc = isBase64Data
+              ? `data:${
+                  imagesHexSources[i].type
+              };base64,${this._convertHexToBase64(imagesHexSources[i].hex)}`
+              : imagesHexSources[i];
+
+          htmlData = htmlData.replace(imageSrcs[i], newSrc);
+        }
+      }
+
+      return htmlData;
+    },
+    // 销毁富文本
+    beforeDestroy() {
+      const editor = this.editor;
+      if (editor == null) return;
+      editor.destroy(); // 组件销毁时,及时销毁编辑器
+    },
+    checkedLink(text, link) {
+      if (link !== "") {
+        var reg = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
+        if (!reg.test(link)) {
+          return '请输入正确的网址(例如 http://baidu.com)'
+        }else{
+          return true
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style src="@wangeditor/editor/dist/css/style.css">
+
+</style>

+ 83 - 0
src/components/WangEdiitor/wangEditorConfig.js

@@ -0,0 +1,83 @@
+import i18n from '@/utils/i18n'
+
+export const toolbarConfig = {
+  /* 工具栏配置 */
+  toolbarKeys: [
+    'headerSelect',
+    'blockquote',
+    '|',
+    'bold',
+    'underline',
+    'italic',
+    {
+      'key': 'group-more-style',
+      'title': i18n.t('action.more'),
+      'iconSvg': '<svg viewBox="0 0 1024 1024"><path d="M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path></svg>',
+      'menuKeys': [
+        'through',
+        'code',
+        'sup',
+        'sub',
+        'clearStyle'
+      ]
+    },
+    'color',
+    'bgColor',
+    '|',
+    'fontSize',
+    'fontFamily',
+    'lineHeight',
+    '|',
+    'bulletedList',
+    'numberedList',
+    'todo',
+    {
+      key: 'group-justify',
+      title: i18n.t('action.justify'),
+      iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>',
+      menuKeys: [
+        'justifyLeft',
+        'justifyRight',
+        'justifyCenter',
+        'justifyJustify'
+      ]
+    },
+    {
+      key: 'group-indent',
+      title: i18n.t('action.indent'),
+      iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z"></path></svg>',
+      menuKeys: [
+        'indent',
+        'delIndent'
+      ]
+    },
+    '|',
+    'emotion',
+    'insertLink',
+    // 菜单组,包含多个菜单
+    {
+      key: 'group-image', // 必填,要以 group 开头
+      title: i18n.t('action.image'), // 必填
+      iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z"></path></svg>',
+      menuKeys: ['uploadImage',
+        'insertImage']
+    },
+    // {
+    //   "key": "group-video",
+    //   "title": "视频",
+    //   "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M981.184 160.096C837.568 139.456 678.848 128 512 128S186.432 139.456 42.816 160.096C15.296 267.808 0 386.848 0 512s15.264 244.16 42.816 351.904C186.464 884.544 345.152 896 512 896s325.568-11.456 469.184-32.096C1008.704 756.192 1024 637.152 1024 512s-15.264-244.16-42.816-351.904zM384 704V320l320 192-320 192z\"></path></svg>",
+    //   "menuKeys": [
+    //     "insertVideo",
+    //     "uploadVideo"
+    //   ]
+    // },
+    'insertTable',
+    'codeBlock',
+    'divider',
+    '|',
+    'undo',
+    'redo',
+    '|',
+    'fullScreen'
+  ]
+}

+ 7 - 0
src/router/index.js

@@ -171,6 +171,13 @@ export const partRoutes = [
         name: 'device-menu',
         meta: { title: i18n.t('tab.deviceMenuManager'), icon: 'el-icon-menu', noCache: true }
       },
+      {
+        path: 'device_menu_detail/:id',
+        component: () => import('@/views/ncs-device-menu-detail/index'),
+        name: 'device-menu-detail',
+        meta: { title: i18n.t('tab.deviceMenuDetail'), icon: 'el-icon-tickets', noCache: true },
+        hidden: true
+      },
       // {
       //   path: 'led',
       //   component: () => import('@/views/ncs-led/ledDeviceManagement'),

文件差異過大導致無法顯示
+ 11 - 8
src/utils/domain.js


+ 11 - 0
src/utils/enum/DeviceMenuDetailTypeEnum.js

@@ -0,0 +1,11 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+
+export const DEVICE_MENU_DETAIL_TYPE = createEnum(
+  {
+    HOSPITAL: ['HOSPITAL', i18n.t('deviceMenuDetailType.HOSPITAL')],
+    PART: ['PART', i18n.t('deviceMenuDetailType.PART')],
+    IN_NOTICE: ['IN_NOTICE', i18n.t('deviceMenuDetailType.IN_NOTICE')],
+    SATISFACTION: ['SATISFACTION', i18n.t('deviceMenuDetailType.SATISFACTION')]
+  }
+)

+ 387 - 0
src/views/ncs-device-menu-detail/index.vue

@@ -0,0 +1,387 @@
+<template>
+  <div>
+    <el-card style="margin: 15px">
+      <div>
+        <el-form ref="editform" :rules="rules"  label-width="120px"  :model="formmodel" style="margin: 10px">
+          <el-row>
+            <el-form-item :label="this.$t('deviceMenuDetailManage.type')" prop="type">
+              <el-select v-model="formmodel.type"
+                         :placeholder="this.$t('deviceMenuDetailManage.chooseType')"
+                         filterable clearable>
+                <el-option v-for="(item,index) in deviceMenuDetailTypeTransfer" :key="index" :label="item.key" :value="item.value" />
+              </el-select>
+            </el-form-item>
+          </el-row>
+
+          <el-row>
+            <el-form-item :label="this.$t('deviceMenuDetailManage.user')" prop="customer_id">
+              <el-select v-model="formmodel.customer_id"
+                         :placeholder="this.$t('deviceMenuDetailManage.chooseUser')"
+                         filterable clearable>
+                <el-option v-for="(item,index) in users" :key="index" :label="item.named" :value="item.id" />
+              </el-select>
+            </el-form-item>
+          </el-row>
+
+          <el-row>
+            <el-col :span="10">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.hospitalAddr')" prop="hospital_addr" maxlength="50">
+                <el-input v-model="formmodel.hospital_addr" :placeholder="this.$t('deviceMenuDetailManage.inputHospitalAddr')" :maxlength="50" clearable/>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row>
+            <el-col :span="10">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.hospitalTel')" prop="hospital_tel" maxlength="50">
+                <el-input v-model="formmodel.hospital_tel" :placeholder="this.$t('deviceMenuDetailManage.inputHospitalTel')" :maxlength="50" clearable/>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row>
+            <el-col :span="10">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.hospital_web')" prop="hospital_web" maxlength="50">
+                <el-input v-model="formmodel.hospital_web" :placeholder="this.$t('deviceMenuDetailManage.inputHospitalWeb')" :maxlength="50" clearable/>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+
+          <el-row>
+            <el-form-item :label="partClerkStr"
+                          v-for="(item, index) in formmodelPartClerk" :key="'a' + index">
+              <el-col :span="4" style="margin: 0 10px 0 0">
+                <el-select v-model="item.clerk_id"
+                           :placeholder="choosePartClerkStr"
+                           filterable clearable>
+                  <el-option v-for="(_item,index) in clerks" :key="index" :label="_item.role_name + '-' + _item.clerk_name" :value="_item.clerk_id" />
+                </el-select>
+              </el-col>
+              <el-col :span="3" style="margin: auto">
+                <el-button v-if="index === 0" type="primary" @click="addInput(formmodelPartClerk)"> {{ addStr }} </el-button>
+                <el-button v-else type="danger" @click="delInput(formmodelPartClerk, index)"> {{ delStr }} </el-button>
+              </el-col>
+            </el-form-item>
+          </el-row>
+
+          <el-row>
+            <el-col :span="8">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.titleIcon')">
+                <el-upload
+                    class="avatar-uploader"
+                    :action="`${titleIconUploadUrl}?scene=avatar`"
+                    :show-file-list="false"
+                    :on-success="titleIconUploaded"
+                    :before-upload="handleTitleIconBefore"
+                    accept=".png,.jpeg,.jpg"
+                >
+                  <img v-if="titleIconUrl" :src="titleIconUrl" class="avatar">
+                  <i v-else class="el-icon-plus avatar-uploader-icon" />
+                </el-upload>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row>
+            <el-col :span="8">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.titleBg')">
+                <el-upload
+                    class="avatar-uploader"
+                    :action="`${titleBgUploadUrl}?scene=avatar`"
+                    :show-file-list="false"
+                    :on-success="titleBgUploaded"
+                    :before-upload="handleTitleBgBefore"
+                    accept=".png,.jpeg,.jpg"
+                >
+                  <img v-if="titleBgUrl" :src="titleBgUrl" class="rightullidiv">
+                  <i v-else class="el-icon-plus avatar-uploader-icon" />
+                </el-upload>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row>
+            <el-col :span="12">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.title')" prop="title" maxlength="50">
+                <el-input v-model="formmodel.title" :placeholder="this.$t('deviceMenuDetailManage.inputTitle')" :maxlength="50" clearable/>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row>
+            <el-col :span="24">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.summary')" prop="summary">
+                <el-input v-model="formmodel.summary" :placeholder="this.$t('deviceMenuDetailManage.inputSummary')" type="textarea" :maxlength="200" clearable/>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+
+          <el-row>
+            <el-col :span="24">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.detail')" prop="detail">
+                <wangEditor v-model="formmodel.detail" clearable/>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row>
+            <el-col :span="24">
+              <el-form-item :label="this.$t('deviceMenuDetailManage.tags')" prop="tags">
+                <el-input v-model="formmodel.tags" :placeholder="this.$t('deviceMenuDetailManage.inputTags')" :maxlength="50" clearable/>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+        </el-form>
+      </div>
+
+      <div align="center" class="margin-top-sm">
+        <el-button type="primary" @click="handlerFormSubmit('editform')">{{ this.$t('action.save') }}</el-button>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+import {DEVICE_MENU_DETAIL_TYPE} from "@/utils/enum/DeviceMenuDetailTypeEnum";
+import wangEditor from "@/components/WangEdiitor/wangEditor";
+import {getListByPartId} from "@/api/ncs_customer";
+import * as API_DeviceMenuDetail from '@/api/ncs_device_menu_detail'
+import * as API_Clerk from '@/api/ncs_clerk'
+
+const serverUrl = domain.serverUrl
+export default {
+  name: "index",
+  components: { wangEditor },
+  data() {
+    return {
+      rules: {
+        type: [
+          { required: true, message: this.$t('deviceMenuDetailManage.chooseType'), trigger: 'blur' }
+        ],
+        title: [
+          { required: true, message: this.$t('deviceMenuDetailManage.inputTitle'), trigger: 'blur' }
+        ],
+      },
+      formmodel: {
+        menu_id: this.$route.params.id,
+        part_id: this.$route.params.part_id
+      },
+      formmodelPartClerk: [{
+        clerk_id: '',
+      }],
+      loading: false,
+      users: [],
+      clerks: [],
+      titleIconUploadUrl: serverUrl + '/ncs/upload/uploadFile',
+      titleIconUrl: '',
+      titleBgUploadUrl: serverUrl + '/ncs/upload/uploadFile',
+      titleBgUrl: '',
+      deviceMenuDetailTypeTransfer: DEVICE_MENU_DETAIL_TYPE.getKeyValueList(),
+      partClerkStr: this.$t('deviceMenuDetailManage.partClerk'),
+      choosePartClerkStr: this.$t('deviceMenuDetailManage.choosePartClerk'),
+      actIntentStr: this.$t('deviceMenuManage.actIntent'),
+      addStr: this.$t('action.add'),
+      delStr: this.$t('action.delete')
+    }
+  },
+  mounted() {
+    this.getModel()
+    this.getEmployees()
+    this.getClerkList()
+  },
+  methods: {
+    getModel() {
+      this.loading = true
+      API_DeviceMenuDetail.getModelByMenuId(this.formmodel.menu_id).then(res => {
+        if (res) {
+          this.formmodel = res
+          this.titleIconUrl = res.title_icon
+          this.titleBgUrl = res.title_bg
+          this.formmodelPartClerk = this.strToId(this.formmodel.part_clerk)
+        }
+        else {
+          this.titleIconUrl = ''
+          this.titleBgUrl = ''
+        }
+        this.loading = false
+      })
+    },
+    getClerkList() {
+      const _this = this
+      API_Clerk.getClerkVoByPartId(this.formmodel.part_id).then(res => {
+        _this.clerks = res
+        this.clerks = _this.clerks.filter(item => item.role_id !== 0 && item.role_id !== 1)
+      })
+    },
+    /** 上传成功后的钩子 更换图片 置空存储数组*/
+    titleIconUploaded(res) {
+      this.titleIconUrl = serverUrl + '/' + res
+      this.formmodel.title_icon = this.titleIconUrl
+    },
+    titleBgUploaded(res) {
+      this.titleBgUrl = serverUrl + '/' + res
+      this.formmodel.title_bg = this.titleBgUrl
+    },
+    /** 图片上传之前的校验 */
+    handleTitleIconBefore(file) {
+      return new Promise((resolve, reject) => {
+        const isImg = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif'
+        const isLt2M = file.size / 1024 / 1024 < 2
+
+        if (!isImg) {
+          this.$message.error(this.$t('action.uploaderImg2'))
+          reject()
+        }
+        if (!isLt2M) {
+          this.$message.error(this.$t('action.uploaderSize2'))
+          reject()
+        }
+        const reader = new FileReader()
+        reader.onload = (event) => {
+          const image = new Image()
+          image.onload = () => {
+            const width = image.width
+            const height = image.height
+            if (width > 500 || width < 100) {
+              this.$message.error(this.$t('action.uploaderImgMsg'))
+              reject()
+            }
+            if (width !== height) {
+              this.$message.error(this.$t('action.uploaderImgMsg2'))
+              reject()
+            }
+            if (height > 500 || height < 100) {
+              this.$message.error(this.$t('action.uploaderImgMsg3'))
+              reject()
+            }
+            resolve()
+          }
+          image.src = event.target.result
+        }
+        reader.readAsDataURL(file)
+      })
+    },
+    /** 图片上传之前的校验 */
+    handleTitleBgBefore(file) {
+      return new Promise((resolve, reject) => {
+        const isImg = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif'
+        const isLt2M = file.size / 1024 / 1024 < 10
+
+        if (!isImg) {
+          this.$message.error(this.$t('action.uploaderImg2'))
+          reject()
+        }
+        if (!isLt2M) {
+          this.$message.error(this.$t('action.uploaderSize3'))
+          reject()
+        }
+        const reader = new FileReader()
+        reader.onload = (event) => {
+          const image = new Image()
+          image.onload = () => {
+            resolve()
+          }
+          image.src = event.target.result
+        }
+        reader.readAsDataURL(file)
+      })
+    },
+    handlerFormSubmit() {
+      console.log(this.formmodel)
+      this.formmodel.part_clerk = this.idToStr(this.formmodelPartClerk)
+      this.loading = true
+      if (this.formmodel.id) {
+        API_DeviceMenuDetail.update(this.formmodel.id, this.formmodel).then(res => {
+          this.loading = false
+          this.$message.success(this.$t('action.saveSuccess'))
+        })
+      }
+      else {
+        API_DeviceMenuDetail.add(this.formmodel).then(res => {
+          this.loading = false
+          this.$message.success(this.$t('action.saveSuccess'))
+          this.formmodel = res
+        })
+      }
+    },
+    getEmployees() {
+      const _this = this
+      _this.users = []
+      getListByPartId(this.$store.getters.partId).then(res => {
+        _this.users = res
+      })
+    },
+    addInput(paramsTemp){
+      paramsTemp.push({
+        clerk_id: '',
+      })
+    },
+    delInput(paramsTemp, index) {
+      paramsTemp.splice(index, 1)
+    },
+    idToStr(list) {
+      let partClerkStr = ''
+      let partClerk = []
+      let clerk = {}
+      if (list.length !== 0) {
+        console.log('list', list)
+        for (let i = 0; i < list.length; i++) {
+          console.log('list[i]', list[i])
+          if (list[i].clerk_id !== '') {
+            clerk = this.clerks.filter(item => item.clerk_id === list[i].clerk_id)[0]
+            partClerk.push({
+              clerk_id: clerk.clerk_id,
+              type: clerk.role_type,
+              name: clerk.role_name,
+              value: clerk.clerk_name
+            })
+          }
+        }
+        partClerkStr = JSON.stringify(partClerk)
+      }
+      else {
+        partClerkStr = ''
+      }
+      return partClerkStr
+    },
+    strToId(str) {
+      const partClerks = []
+      if (str !== null && str !== '') {
+        let partClerk = JSON.parse(str)
+        if (partClerk.length !== 0) {
+          for (let i = 0; i < partClerk.length; i++) {
+            partClerks.push({
+              clerk_id: partClerk[i].clerk_id
+            })
+          }
+        }
+      }
+      if (partClerks.length !== 0) {
+        return partClerks
+      } else {
+        return [{
+          clerk_id: ''
+        }]
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.rightullidiv {
+  width: 100%;
+  height: 200px;
+  background: #f2f2f2;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+    .rightulliimg {
+      max-width: 100%;
+      max-height: 200px;
+    }
+}
+</style>

+ 40 - 35
src/views/ncs-device-menu/index.vue

@@ -151,12 +151,13 @@ import {DEVICE_TYPE} from "@/utils/enum/DeviceTypeEnum";
 import {DEVICE_MENU_TYPE} from "@/utils/enum/DeviceMenuTypeEnum";
 import * as clerk_API from "@/api/ncs_clerk";
 import {ROLE_TYPE} from "@/utils/enum/RoleTypeEnum";
+import ButtonCellRenderList from "@/components/AgGridCellRender/ButtonCellRenderList";
 
 const serverUrl = domain.serverUrl
 
 export default {
   name: "index",
-  components: { ButtonCellRender, ImageViewer },
+  components: { ButtonCellRender, ImageViewer, ButtonCellRenderList },
   props: {
     part_view: { // 是否为科室视图
       type: Boolean,
@@ -272,40 +273,38 @@ export default {
       {
         headerName: this.$t('deviceMenuManage.actIntent'), field: 'act_intent', sortable: true, filter: 'agTextColumnFilter', flex: 1, valueFormatter: this.formatterUnEscape
       },
-      {
-        headerName: this.$t('action.edit'),
-        cellRendererFramework: 'ButtonCellRender',
-        cellRendererParams: {
-          onClick: this.handlerEdit,
-          label: this.$t('action.edit'),
-          buttonType: 'primary',
-          buttonSize: 'mini'
-        },
-        filter: false,
-        pinned: 'right',
-        lockPinned: true,
-        width: 100,
-        resizable: false,
-        sortable: false
-      },
-      {
-        headerName: this.$t('action.delete'),
-        cellRendererFramework: 'ButtonCellRender',
+      { headerName: this.$t('action.handle'), field: 'id',
+        cellRendererFramework: 'ButtonCellRenderList',
         cellRendererParams: param => {
           return {
-            onClick: this.deleteSingle,
-            label: this.$t('action.delete'),
-            buttonType: 'danger',
-            buttonSize: 'mini'
-          }
+            list: [
+              {
+                onClick: this.handlerEdit,
+                label: this.$t('action.edit'),
+                buttonType: 'primary',
+                buttonSize: 'mini'
+              },
+              {
+                onClick: this.handlerDetails,
+                label: this.$t('action.details'),
+                buttonType: 'success',
+                buttonSize: 'mini',
+                disabled: !this.isSys(param)
+              },
+              {
+                onClick: this.deleteSingle,
+                label: this.$t('action.delete'),
+                buttonType: 'danger',
+                buttonSize: 'mini',
+              }
+            ]}
         },
+        filter: false,
         pinned: 'right',
         lockPinned: true,
-        width: 100,
+        minWidth: this.$i18n.locale === 'zh' ? 210 : 330,
         resizable: false,
-        filter: false,
-        sortable: false
-      }
+        sortable: false },
     ]
     this.defaultColDef = {
       sortable: true,
@@ -351,12 +350,12 @@ export default {
           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)
-          }
-        })
+        // this.$nextTick(() => {
+        //   const node = this.gridApi.getDisplayedRowAtIndex(0)
+        //   if (node !== null && node !== undefined) {
+        //     node.setSelected(true)
+        //   }
+        // })
       }).catch(() => {
         this.loading = false
       })
@@ -653,6 +652,12 @@ export default {
         }]
       }
     },
+    handlerDetails(row) {
+      this.$router.push({ name: 'device-menu-detail', params: { id: row.id, part_id: row.part_id, callback: this.getList() }})
+    },
+    isSys(param) {
+      return param.data.type === DEVICE_MENU_TYPE.SYS
+    }
   }
 }
 </script>

+ 41 - 2
src/views/ncs-orginazition/components/partInfoEdit.vue

@@ -337,6 +337,36 @@
 
           <el-row>
             <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.androidBedVolumeNative')" prop="android_bed_volume_native">
+                <el-input-number v-model="formmodel.android_bed_volume_native" :min="1" :max="31" :label="this.$t('partInfo.androidBedVolumeNative')" />
+              </el-form-item>
+            </el-col>
+
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.androidBedGainSize')" prop="android_bed_gain_size">
+                <el-input-number v-model="formmodel.android_bed_gain_size" :min="1" :max="255" :label="this.$t('partInfo.androidBedGainSize')" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row>
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.androidDoorVolumeNative')" prop="android_door_volume_native">
+                <el-input-number v-model="formmodel.android_door_volume_native" :min="1" :max="31" :label="this.$t('partInfo.androidDoorVolumeNative')" />
+              </el-form-item>
+            </el-col>
+
+
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.androidDoorGainSize')" prop="android_door_gain_size">
+                <el-input-number v-model="formmodel.android_door_gain_size" :min="1" :max="255" :label="this.$t('partInfo.androidDoorGainSize')" />
+              </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" />
@@ -416,12 +446,19 @@
 
             <el-col :span="8">
               <el-form-item :label="this.$t('partInfo.convenientServiceEnabled')">
-                <el-checkbox v-model="formmodel.convenient_service_enabled" :true-label="true" :false-label="false">{{ this.$t('action.enabled') }}</el-checkbox>
+                <el-checkbox v-model="formmodel.convenient_service_enabled" :true-label="1" :false-label="0">{{ this.$t('action.enabled') }}</el-checkbox>
               </el-form-item>
             </el-col>
+
             <el-col :span="8">
               <el-form-item :label="this.$t('partInfo.ledServiceEnabled')">
-                <el-checkbox v-model="formmodel.bool_led_service" :true-label="true" :false-label="false">{{ this.$t('action.enabled') }}</el-checkbox>
+                <el-checkbox v-model="formmodel.bool_led_service" :true-label="1" :false-label="0">{{ this.$t('action.enabled') }}</el-checkbox>
+              </el-form-item>
+            </el-col>
+
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.autoPositionEnabled')" prop="auto_position">
+                <el-checkbox v-model="formmodel.auto_position" :true-label="1" :false-label="0">{{ this.$t('action.enabled') }}</el-checkbox>
               </el-form-item>
             </el-col>
           </el-row>
@@ -732,6 +769,7 @@ export default {
       if (this.partId) {
         API_Part.getPartSetting(this.partId).then(res => {
           this.formmodel = { ...res }
+          console.log(this.formmodel)
           if (!this.formmodel.member_name || this.formmodel.member_name === '') {
             this.noMember = false
           } else {
@@ -872,6 +910,7 @@ export default {
           if (this.formmodel.qr_url) {
             this.imageUrl = this.formmodel.qr_url
           }
+          console.log(this.formmodel)
           API_Part.editPartSetting(this.formmodel, this.partId).then(res => {
             this.$message.success(this.$t('action.saveSuccess'))
             if (this.systemConfig.id != null) {