Преглед изворни кода

Merge branch 'develop'

# Conflicts:
#	languages/en.js
#	languages/zh-CN.js
#	src/views/ncs-device/components/deviceManager.vue
wuyunfeng пре 2 година
родитељ
комит
f5a88375eb
100 измењених фајлова са 14196 додато и 3537 уклоњено
  1. 0 0
      .env
  2. 0 6
      .idea/jsLinters/eslint.xml
  3. 262 15
      languages/en.js
  4. 1212 0
      languages/es.js
  5. 1143 0
      languages/ru-RU.js
  6. 282 33
      languages/zh-CN.js
  7. 29 14
      package-lock.json
  8. 4 2
      package.json
  9. 46 0
      src/api/ncs_advice.js
  10. 69 0
      src/api/ncs_board_item.js
  11. 83 0
      src/api/ncs_board_title.js
  12. 26 1
      src/api/ncs_clerk.js
  13. 19 0
      src/api/ncs_customer_fee_config.js
  14. 9 0
      src/api/ncs_customer_mapping.js
  15. 28 0
      src/api/ncs_entrace_guard_user.js
  16. 11 0
      src/api/ncs_excel.js
  17. 33 0
      src/api/ncs_frameGroup.js
  18. 7 0
      src/api/ncs_functions.js
  19. 41 0
      src/api/ncs_functions_role_mapping.js
  20. 91 0
      src/api/ncs_his.js
  21. 35 0
      src/api/ncs_interaction-chain.js
  22. 20 0
      src/api/ncs_relative.js
  23. 16 0
      src/api/ncs_sleep_data.js
  24. 15 0
      src/api/role.js
  25. BIN
      src/assets/avatar.png
  26. 1 0
      src/icons/svg/delete.svg
  27. 1 0
      src/icons/svg/designer.svg
  28. 1 0
      src/icons/svg/frame_manage.svg
  29. 1 0
      src/icons/svg/list-move.svg
  30. 1 0
      src/icons/svg/pass_through.svg
  31. 1 0
      src/icons/svg/pen-leather.svg
  32. 1 0
      src/icons/svg/role.svg
  33. 1 0
      src/icons/svg/setting.svg
  34. 1 0
      src/icons/svg/squence.svg
  35. 17 4
      src/layout/components/Navbar.vue
  36. 132 5
      src/router/index.js
  37. 15 1
      src/settings.js
  38. 102 0
      src/styles/element-ui.scss
  39. 244 242
      src/utils/AgGridVueLocaleCn.js
  40. 9 0
      src/utils/enum/AdviceStatusTypeEnum.js
  41. 9 0
      src/utils/enum/AdviceTypeEnym.js
  42. 6 1
      src/utils/enum/DeviceTypeEnum.js
  43. 47 0
      src/utils/enum/ErrorEnum.js
  44. 2 0
      src/utils/enum/RelativeNameTypeEnum
  45. 5 1
      src/utils/i18n.js
  46. 5 2
      src/utils/mixin.js
  47. 12 3
      src/utils/request.js
  48. 426 0
      src/views/custom-infoboard/board-title.vue
  49. 69 0
      src/views/custom-infoboard/mixin.js
  50. 459 0
      src/views/custom-infoboard/screen-designer.vue
  51. 183 0
      src/views/custom-infoboard/templates/board-item-setting.vue
  52. 166 0
      src/views/custom-infoboard/templates/board-module-setting.vue
  53. 9 0
      src/views/custom-infoboard/templates/common/index.js
  54. 438 0
      src/views/custom-infoboard/templates/common/tpl-one-cloum.vue
  55. 466 0
      src/views/custom-infoboard/templates/common/tpl-three-colum.vue
  56. 451 0
      src/views/custom-infoboard/templates/common/tpl-two-cloum.vue
  57. 14 0
      src/views/custom-infoboard/templates/index.js
  58. 304 0
      src/views/custom-infoboard/templates/layout-item.vue
  59. 73 32
      src/views/customer/components/customerManager.vue
  60. 126 47
      src/views/customer/components/elderlyCareManager.vue
  61. 206 90
      src/views/customer/components/patientManager.vue
  62. 0 612
      src/views/customer/customerEdit.vue
  63. 1 0
      src/views/customer/customerManagement.vue
  64. 0 284
      src/views/customer/customer_relative.vue
  65. 1 0
      src/views/customer/elderlyCareManagement.vue
  66. 0 474
      src/views/customer/list.vue
  67. 1 0
      src/views/customer/patientManagement.vue
  68. 421 0
      src/views/customer/sleep-detect-data.vue
  69. 407 0
      src/views/entrace-guard/users.vue
  70. 143 0
      src/views/function-mapping/components/RoleForFunction.vue
  71. 43 0
      src/views/function-mapping/index.vue
  72. 0 460
      src/views/hospitalFrame/hospitalFrame.vue
  73. 14 12
      src/views/hospitalFrame/nurse_watch_frame.vue
  74. 552 0
      src/views/interaction-chain/index.vue
  75. 14 14
      src/views/login/index.vue
  76. 588 0
      src/views/ncs-advice/index.vue
  77. 31 2
      src/views/ncs-auth/compontents/roleEdit.vue
  78. 2 1
      src/views/ncs-auth/superadmin/defaultRoleManager.vue
  79. 4 3
      src/views/ncs-channel/index.vue
  80. 9 4
      src/views/ncs-chars/index.vue
  81. 3 3
      src/views/ncs-chars/info.vue
  82. 480 0
      src/views/ncs-clerk-frame-manage/components/employeeView.vue
  83. 500 0
      src/views/ncs-clerk-frame-manage/components/frameView.vue
  84. 500 0
      src/views/ncs-clerk-frame-manage/components/multiClerkManageFrame.vue
  85. 49 0
      src/views/ncs-clerk-frame-manage/index.vue
  86. 139 50
      src/views/ncs-clerk/components/clerkList.vue
  87. 1224 1076
      src/views/ncs-device/components/deviceManager.vue
  88. 0 1
      src/views/ncs-device/deviceInfo.vue
  89. 283 0
      src/views/ncs-his/his-clerk/hisClerkManager.vue
  90. 306 0
      src/views/ncs-his/his-nurse-config/hisNurseConfigManager.vue
  91. 272 0
      src/views/ncs-his/his-part/hisPartManager.vue
  92. 495 0
      src/views/ncs-his/his-patient/hisPatientManage.vue
  93. 48 0
      src/views/ncs-his/hisManagement.vue
  94. 71 8
      src/views/ncs-interaction/index.vue
  95. 13 5
      src/views/ncs-orginazition/components/AppVersionManager.vue
  96. 77 24
      src/views/ncs-orginazition/components/partInfoEdit.vue
  97. 1 1
      src/views/ncs-orginazition/index.vue
  98. 15 0
      src/views/ncs-orginazition/partInfoSetting.vue
  99. 4 4
      src/views/ncs-remark/index.vue
  100. 0 0
      src/views/ncs_fee/index.vue

+ 0 - 6
.idea/jsLinters/eslint.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="EslintConfiguration">
-    <custom-configuration-file used="true" path="$PROJECT_DIR$/.eslintrc.js" />
-  </component>
-</project>

+ 262 - 15
languages/en.js

@@ -1,12 +1,14 @@
 module.exports = {
   action: {
-    wdklCallingSystem: 'Wreadycare Calling System',
+    wdklCallingSystem: 'System Configuration',
     home: 'Home',
     add: 'Add',
     edit: 'Edit',
     more: 'More',
     delete: 'Delete',
     login: 'Login',
+    usernameMsg: 'Username',
+    passwordMsg: 'Password',
     loginError: 'Your login status has expired, please login again!',
     permissionError: 'Permission Error',
     logout: 'Log out',
@@ -55,7 +57,9 @@ module.exports = {
     notDevelopedYet: 'Not yet developed',
     search: 'Enter search',
     keywords: 'Please enter a search keyword',
+    FontSize: 'Font size',
     chooseLang: 'Choose language',
+    SynchronizeHISInformation: 'Synchronize HIS information',
     perpetualLicence: 'Perpetual License',
     licenseValidity: 'The license is valid until: ',
     licenseRemainsValid: 'The remaining validity period of the license:',
@@ -83,9 +87,57 @@ module.exports = {
     times: 'Times',
     choice: 'Please choose',
     choiceAll: 'Select all',
+    choiceAllSearchResults: '(choose all search results)',
+    searchOoo: 'Search...',
+    blanks: '(space)',
+    noMatches: 'No matching results',
+    filterOoo: 'Filter value...',
+    equals: 'equal to',
+    notEqual: 'not equal to',
+    empty: 'Please select a record',
+    lessThan: 'less than',
+    greaterThan: 'greater than',
+    lessThanOrEqual: 'less than or equal to',
+    greaterThanOrEqual: 'greater than or equal to',
+    inRange: 'Range',
+    inRangeStart: 'to',
+    inRangeEnd: 'from',
+    contains: 'contains',
+    notContains: 'does not contain',
+    startsWith: 'starts with',
+    endsWith: 'ends with',
+    andCondition: 'and',
+    orCondition: 'or',
+    applyFilter: 'Apply',
+    resetFilter: 'reset',
+    clearFilter: 'Clear',
+    cancelFilter: 'Cancel',
+    textFilter: 'text filter',
+    numberFilter: 'number filter',
+    dateFilter: 'date filter',
+    setFilter: 'list filter',
+    columns: 'columns',
+    filters: 'filter',
+    loadingOoo: 'Loading...',
+    noRowsToShow: 'No data to show',
+    enabled: 'open',
+    pinColumn: 'fixed column',
+    pinLeft: 'Fixed to the left',
+    pinRight: 'Fixed to the right',
+    noPin: 'not fixed',
+    autosizeThiscolumn: 'Automatically scale this column',
+    autosizeAllColumns: 'Automatically scale all columns',
+    groupBy: 'group',
+    resetColumns: 'Reset column settings',
+    expandAll: 'Expand all',
+    collapseAll: 'Collapse all',
+    copy: 'Copy',
+    copyWithHeaders: 'Copy with headers',
+    paste: 'paste',
     colour: 'Colour',
     searchDateRange: 'Search time period',
-    to: 'to',
+    to: ' to ',
+    of: ' of ',
     index: 'Serial number',
     null: 'None',
     all: 'All',
@@ -117,17 +169,17 @@ module.exports = {
     uploaderImgMsg2: 'Please upload an image with an aspect ratio of 1:1',
     uploaderImgMsg3: 'The height of the image must be between 100 and 500! ',
     uploadFile: 'Upload file',
-    uploadAPK: 'APK file upload',
+    uploadAPK: 'APK/IMG file upload',
     uploadFileMsg: 'Drag file here, or',
     uploadFileMsg2: 'Click to upload',
     uploadFileMsg3: 'Only mp3 or flac files can be uploaded',
     uploadFileMsg4: 'The upload attachment size cannot exceed 50MB!',
-    uploadFileMsg5: 'Only upload APK files',
+    uploadFileMsg5: 'Only upload APK/IMG files',
     uploadFileName: 'File name',
     uploadFileNameMsg: 'The file name cannot be empty',
     uploadFileUrl: 'File path',
     uploadFileUrlMsg: 'The file path cannot be empty, please upload the file',
-    uploadFileUrlMsg2: 'Please upload the APK file',
+    uploadFileUrlMsg2: 'Please upload the APK/IMG file',
     uploadFileAuthor: 'Uploaded by',
     uploadFileDate: 'Upload Date',
     uploadVersionNo: 'Version number',
@@ -145,9 +197,19 @@ module.exports = {
     byEvent: 'By Event',
     export: 'Export',
     icon: 'Icon',
+    excelUpload: 'Upload an excel sheet',
     play: 'Play',
     pause: 'Pause',
-    noFile: 'File does not exist, cannot be played'
+    noFile: 'File does not exist, cannot be played',
+    inputMsg: 'Please enter the content!',
+    year: 'year',
+    month: 'month',
+    day: 'day',
+    timeMsg: 'Please select a time range!',
+    param: 'Parameter',
+    inputParamName: 'Please enter the parameter name',
+    inputParamValue: 'Please enter the parameter value',
+    addParam: 'New parameter'
   },
   member: {
     face: 'Avatar',
@@ -188,7 +250,8 @@ module.exports = {
     disabled: 'Disabled!',
     disableCancel: 'Disabled',
     deleteMember: 'Are you sure you want to delete this user information?',
-    cannotDeleteAdmin: 'Cannot delete the person in charge of the organization'
+    cannotDeleteAdmin: 'Cannot delete the person in charge of the organization',
+    leaderName:'Leader Name'
   },
   home: {
     todayTask: "Today's task",
@@ -423,6 +486,16 @@ module.exports = {
     remarkTime: 'Time:',
     remarkName: 'Remark person:',
     addRemark: 'Add remark',
+    fee: 'Expense',
+    feeName: 'Expense name',
+    feeValue: 'Specific expenses',
+    feeNumber: 'Expense batch',
+    feeTime: 'Time of expense',
+    feeGroupName: 'Group Name',
+    feeKeyCode: 'Code',
+    feeUnit: 'Unit',
+    feeDescription: 'Describe',
+    feeKeyType: 'Parameter Type',
     outBed: 'Log out of bed',
     outBed2: 'Unregister',
     outBed3: 'Unregister',
@@ -440,7 +513,10 @@ module.exports = {
     customerStatus: 'Current status',
     customerStatusTrue: 'Checking in',
     customerStatusFalse: 'Left',
-    footprint: 'Footprint'
+    footprint: 'Footprint',
+    babyName: 'Child name',
+    babySex: 'Child gender',
+    babyBirthday: 'Child\'s birthday'
   },
   vital: {
     customerVital: 'User Log',
@@ -449,6 +525,16 @@ module.exports = {
     logTime: 'Measurement time',
     company: 'Unit'
   },
+  adviceManage: {
+    adviceAdd: 'Adding an order',
+    adviceEdit: 'Order Editing',
+    adviceType: 'Order Type',
+    adviceStatus: 'Status',
+    loseEfficacy: 'invalid',
+    takeEffect: 'take effect',
+    longTerm: 'long-term',
+    temp: 'temporary'
+  },
   watch: {
     deviceKeywords: 'Please enter the device alias or device identification code',
     dateKeywords: 'Select a date to search',
@@ -459,6 +545,7 @@ module.exports = {
     initializeDevice: 'Initialize the device',
     watchFrame: 'Manage space',
     watchDeviceFrame: 'Manage space for mobile device',
+    allFrame: 'All rooms',
     place: 'Location',
     placeInfo: 'Location information',
     getNewPlace: 'Get the latest location',
@@ -519,6 +606,7 @@ module.exports = {
     actionTime: 'Number of interactions',
     actionTime2: 'Number of calls',
     success: 'Success',
+    excelFileMsg: 'Excel file will be exported. Continue?',
     successInteraction: 'Response to interaction',
     successInteraction2: 'The call has been connected',
     unSuccessInteraction: 'Unfinished interaction',
@@ -530,6 +618,7 @@ module.exports = {
     notOperated: 'Not responding',
     data: 'Interaction data',
     createDate: 'Interaction time',
+    responseTime: 'Response time',
     fromDevice: 'Initiating device',
     toDevice: 'Receive device',
     interactionRecord: 'Interaction record',
@@ -552,7 +641,9 @@ module.exports = {
     MaxNum2: 'Maximum on time',
     SumNum: 'Total call time',
     total: 'Total',
-    recordPlay: 'Play the audio recording'
+    recordPlay: 'Play the audio recording',
+    eventStatistics: 'Event Statistics',
+    statisticalTable: 'Statistical table'
   },
   frameGroup: {
     frameGroupAdd: 'New area',
@@ -813,17 +904,20 @@ module.exports = {
     sickbed: '5-inch bed extension APP',
     sevensickbed: '7 inch bed extension APP',
     vsickbed: ' Visual version of Bed extension',
+    linuxsickbed: 'Linux bed extension IMG',
     mobiledevice: 'Mobile device',
     visitation: 'Visitor',
     transferDevice: 'Transfer box',
     lcdDevice: 'LCD corridor screen',
+    entraceguard_device: 'Access control APP',
     organizationAdd: 'New Organization',
     boardShowEmptyBed: 'The board shows empty beds',
     nursingColorRgb: 'Nursing door light color',
     twoColorDoorLightValid: 'Two-color door lights are supported',
     support: 'Support two-color door lights',
-    customerNameHidden: 'Turn on user name hide',
-    hidden: 'Turn on user name hide',
+    customerNameHidden: 'Activar ocultar nombre de usuario',
+    clerkNameHidden: 'Enable employee name hiding',
+    hidden: 'Turn on hide',
     channelImHistoryStoreDays: 'The number of days that channel messages are retained',
     recordEnabled: 'Turn on the audio and video recording function',
     recordAble: 'Turn on the audio and video recording function'
@@ -839,7 +933,29 @@ module.exports = {
     roleEvent: 'Role event',
     roleDelete: 'Delete role',
     roleEdit: 'Edit role event',
-    onChoiceRole: 'No role has been selected!'
+    onChoiceRole: 'No role has been selected!',
+    leaderRole:'Superior role',
+    leaderRolePlaceholder:'Choose the superior role',
+    roleEnum:'Type of the role',
+    roleEnumPlaceholder:'Choose the Type'
+  },
+  his: {
+    hisPart: 'Department Query',
+    hisPartKeyval: 'Department His PK',
+    hisPartName: 'Department name',
+    summary: 'Department Profile',
+    tel: 'Department telephone',
+    hisError: 'His error',
+    hisPatient: 'Patient',
+    hisPatientKeyval: 'Patient His primary key',
+    hisPatientInfo: 'Query information',
+    hisClerk: 'Working personnel',
+    hisClerkKeyval: 'Staff his PK',
+    hisDockerKeyval: 'Responsible doctor his PK',
+    hisNurseKeyval: 'Responsible nurse his PK',
+    passNo: 'Entrance guard card',
+    hisNurseConfig: 'Nursing items',
+    hisNurseOptionsKeyval: 'Nursing item classification his PK'
   },
   tab: {
     home: 'Home',
@@ -865,8 +981,11 @@ module.exports = {
     nurseConfig: 'Nursing parameters',
     boardManage: 'Information board settings',
     eventManage: 'Button event management',
+    hisManage: 'His query',
     interactionChars: 'Interaction statistics',
     partSetting: 'Organization settings',
+    functionRoleMapping:'Function Role Setting',
+    interactionChain:'Interaction Accept Order',
     allClerk: 'All employees',
     allCustomer: 'All users',
     allDevice: 'All devices',
@@ -878,7 +997,11 @@ module.exports = {
     roleManage: 'Role management',
     debugging485: '485 debugging',
     deviceFrame: 'Device space',
-    ledDevice: 'LED devices'
+    ledDevice: 'LED devices',
+    entraceguardUser:'Passage setting',
+    customBoardManage: 'Custom Board Screen',
+    customBoardDesigner:'Designer Board Screen',
+    staffManageFrames:'Staff Serve Structure'
   },
   deviceType: {
     NURSE_HOST: 'Nurse Host',
@@ -916,7 +1039,8 @@ module.exports = {
     OTHER_HOST: 'Other Host',
     BREASTPLATE: 'Breast Plate',
     OWON_X5_GATEWAY: 'X5 Gateway',
-    FALL_DETECTION_RADAR: 'Fall Detection Radar'
+    FALL_DETECTION_RADAR: 'Fall Detection Radar',
+    HUMAN_DETECTION_RADAR: 'Sleep Detection Radar'
   },
   vitalSignsDeviceType: {
     BLOOD_SUGAR: 'Blood Pressure Meter',
@@ -940,7 +1064,7 @@ module.exports = {
     DEVICE: 'Device',
     DATA: 'Data',
     EVENT: 'Event',
-    SIDE: 'Outside Information',
+    SIDE: 'nursing',
     BROADCAST: 'Broadcast',
     TIME: 'Time',
     ENTRACEGUARD: 'Access Control',
@@ -951,6 +1075,8 @@ module.exports = {
   },
   relativeNameType: {
     CHILDREN: 'Child',
+    BOY: 'Boy',
+    GIRL: 'Girl',
     HUSBAND: 'Husband',
     WIFE: 'Wife',
     FATHER: 'Father',
@@ -961,5 +1087,126 @@ module.exports = {
   childbirthType: {
     SPONTANEOUS_LABOR: 'Natrual Birth',
     CAESAREAN_BIRTH: 'Caesarean Birth'
+  },
+  sleepData: {
+    Awake: 'Awake',
+    DeepSleep: 'Deep Sleep',
+    LightSleep: 'Light Sleep',
+    Hour: 'h',
+    Minute: 'm',
+    Quality: 'Quality',
+    InBed: 'In Bed',
+    Asleep: 'Asleep',
+    AvarageBreath: 'Avarage Breath',
+    AvarageHeartBeat: 'Avarage Heart Beat',
+    LeaveBedTimes: 'Leave Bed Times',
+    TurnOverTimes: 'Turnover Times',
+    BreathPauseTimes: 'Breath Pause Times',
+    GetInBedTime: 'Get In Bed Time',
+    AwakeTime: 'Awake Time',
+    NoData: 'Empty',
+    Times: 'Times',
+    ChooseDate: 'Choose Date',
+    SleepData: 'Sleep Data'
+  },
+
+  interactionChain:{
+    ActionType:'Interaction Type',
+    FirstRole:'The First Acceptor',
+    SpreadRoleNamePath:'Acception Role Sequence',
+    AddInteractionSpreadPath:'Create a new recorder',
+    AllRoles:'All Roles',
+    AcceptRoles:'Acception',
+    NoticeSequence:'Notice Sequence',
+    SearchPlaceHolder:'Enter a role name',
+    Customer:'Customer',
+    NURSE_HOST: 'Nurse Host',
+    AcceptSequence:'Accept Sequence',
+    chooseActionTypeTip:'Choose the type of interaction pls',
+    chooseRoleSquence:'Choose the role to accept pls',
+    sketchMap:'The Sketch Map Of Acception'
+  },
+  functionRoleMapping:{
+    configurateLeft:'configurate the roles own[',
+    configurateRight:']'
+  },
+  functions:{
+    MANAGE_BED:'Manage Bed'
+  },
+  clerkFrameManage: {
+    employeeView: 'Staff View',
+    frameView: 'Structure View',
+    multiClerkView: 'Structure With Multiple Staff',
+    managedFrames: 'Served Structures',
+    notManagedFrames: 'Unserved Structures',
+    settableEmployee: 'Settable Staff',
+    settedEmployee: 'Setted Staff',
+    allEmployee: 'All Staff',
+    phoneAcceptorLabel: 'The Phone Call Acceptor',
+    phoneAcceptorTipsLeft: 'If Other Employee Of Same Role With ',
+    phoneAcceptorTipsMid: ' Manage Space Frame Overlaping',
+    phoneAcceptorTipsRight: ' Charge The Phone Call'
+  },
+  errorType: {
+    REFRESH_TOKEN_FAILED: 'The current refresh token has expired',
+    TOKEN_FAILED: 'The current token has expired',
+    USER_NULL: 'The account does not exist!',
+    USER_DISABLE: 'The current account has been disabled. Please contact the administrator',
+    PASSWORD_ERROR: 'Account password error!',
+    LOGIN_FAILED: 'Your current identity is not allowed to log in to the system!',
+    LOGOUT: 'El usuario ha dejado de iniciar sesión',
+    MEMBER_NULL: 'The current user does not exist!',
+    MEMBER_ADD_FAILED: 'Failed to add member, non-existent user ID',
+    MEMBER_FAILED: 'User ID error, non-existent user',
+    MOBILE_OCCUPY: 'This mobile number has been occupied',
+    MEMBER_NAME_OCCUPY: 'The current user has already registered',
+    CHANNEL_FAILED: 'Channel Id error, non-existent channel',
+    CHANNEL_SUBSCRIBE_MEMBER_NULL: 'Cannot subscribe to non-existent users',
+    CHANNEL_MEMBER_FAILED: 'Users that do not exist cannot subscribe. Users do not belong to any organization and cannot subscribe',
+    CHANNEL_NULL: 'Cannot subscribe to non-existent channel',
+    FRAME_HOSPITAL_NULL: 'The hospital structure does not exist',
+    FRAME_PART_NULL: 'The department level node does not exist, and the parameter is invalid!',
+    FRAME_ADD_FAILED: 'The department level node does not exist, and the parameter is invalid! The ending room number is less than the starting room number, and the parameter is invalid!',
+    CUSTOMER_INFO_NULL: 'Patient information does not exist',
+    CLOUD_ADDRESS_NULL: 'Cloud path is not set',
+    CLOUD_SAVE_FAILED: 'Failed to save cloud',
+    SHOP_NULL: 'Organization does not exist!',
+    SHOP_DAYTIME_ERROR: 'The format of daytime start time is incorrect, please select again!',
+    SHOP_NIGHTTIME_ERROR: 'The format of night start time is incorrect, please select again!',
+    ADMIN_PASSWORD_ERROR: 'The administrator account has been saved, but the password does not match! Please use another account or enter the correct password.',
+    DEVICE_MAC_REPEAT: 'Duplicate device MAC address',
+    DEVICE_ADD_FAILED: 'There are already emergency buttons in the current space, unable to register multiple emergency buttons',
+    DEVICE_FRAME_FAILED: 'Equipment type and space structure type do not match!',
+    DATA_NULL: 'No data found',
+    PARAM_ERROR: 'Parameter error!',
+    PRIMARY_KEY_NULL: 'Parameter error, department PK value is null!',
+    ROLE_NULL: 'This role does not exist',
+    ROLE_NAME_OCCUPY: 'Duplicate role name',
+    ROLE_DELETE_FAILED: 'This role is in use and cannot be deleted!',
+    LICENSE_ERROR: 'The authorization serial number is wrong, please contact after-sales service',
+    LICENSE_EXPIRE: 'The authorization expires, please contact after-sales service',
+    LICENSE_FAILED: 'Invalid authorization, please contact after-sales service',
+    FILE_UPLOAD_FAILED: 'No file storage directory configured!'
+  },
+  entraceguardUser:{
+    named: 'User Name',
+    idNo:'ID number',
+    ic:'IC Card No',
+    phone:'cell-phone number',
+    password:'Access code',
+    forbidden:'No Entry',
+    refreshUser:'Refresh Users',
+    yes:'YES',
+    nop:'NO'
+  },
+  boardTitle:{
+    add:'Add information board screen',
+    screenTitle:'Screen Title',
+    showIndex:'Display order',
+    partId:'Department ID',
+    design:'Design content',
+    titleRequire:'Screen title cannot be empty',
+    createTitle:'New information board custom screen',
+    editTitle:'Edit information board custom screen'
   }
 }

Разлика између датотеке није приказан због своје велике величине
+ 1212 - 0
languages/es.js


Разлика између датотеке није приказан због своје велике величине
+ 1143 - 0
languages/ru-RU.js


+ 282 - 33
languages/zh-CN.js

@@ -1,13 +1,14 @@
-const i18n = require('@/utils/i18n')
 module.exports = {
   action: {
-    wdklCallingSystem: '维鼎康联呼叫系统配置中心',
+    wdklCallingSystem: '呼叫系统配置中心',
     home: '首页',
     add: '新增',
     edit: '编辑',
     more: '更多',
     delete: '删除',
     login: '登录',
+    usernameMsg: 'Username',
+    passwordMsg: 'Password',
     loginError: '您的登录状态已失效,请重新登录!',
     permissionError: '权限错误',
     logout: '退出登录',
@@ -56,10 +57,12 @@ module.exports = {
     notDevelopedYet: '暂未开发',
     search: '输入搜索',
     keywords: '请输入搜索关键字',
+    FontSize: '字体大小',
     chooseLang: '选择语言',
+    SynchronizeHISInformation: '同步HIS信息',
     perpetualLicence: '永久授权',
     licenseValidity: '授权有效期至: ',
-    licenseRemainsValid: '授权剩余有效期',
+    licenseRemainsValid: '授权剩余有效期: ',
     getLicense: '天,请联系售后获得授权',
     name: '名称',
     fullName: '全称',
@@ -84,9 +87,57 @@ module.exports = {
     times: '次',
     choice: '请选择',
     choiceAll: '全选',
+    choiceAllSearchResults: ':  选择所有搜索结果',
+    searchOoo: '搜索...',
+    blanks: ':  空格',
+    noMatches: '无匹配结果',
+    filterOoo: '筛选值...',
+    equals: '等于',
+    notEqual: '不等于',
+    empty: '请选择一条记录',
+    lessThan: '小于',
+    greaterThan: '大于',
+    lessThanOrEqual: '小于等于',
+    greaterThanOrEqual: '大于等于',
+    inRange: '范围',
+    inRangeStart: '至',
+    inRangeEnd: '从',
+    contains: '包含',
+    notContains: '不包含',
+    startsWith: '开始于',
+    endsWith: '结束于',
+    andCondition: '且',
+    orCondition: '或',
+    applyFilter: '应用',
+    resetFilter: '重置',
+    clearFilter: '清除',
+    cancelFilter: '取消',
+    textFilter: '文本筛选',
+    numberFilter: '数字筛选',
+    dateFilter: '日期筛选',
+    setFilter: '列表筛选',
+    columns: '列',
+    filters: '筛选器',
+    loadingOoo: '加载中...',
+    noRowsToShow: '无数据显示',
+    enabled: '开启',
+    pinColumn: '固定列',
+    pinLeft: '固定到左边',
+    pinRight: '固定到右边',
+    noPin: '不固定',
+    autosizeThiscolumn: '自动缩放此列',
+    autosizeAllColumns: '自动缩放所有列',
+    groupBy: '分组',
+    resetColumns: '重置列设置',
+    expandAll: '展开所有',
+    collapseAll: '收缩所有',
+    copy: '复制',
+    copyWithHeaders: '连同表头复制',
+    paste: '粘贴',
     colour: '颜色',
     searchDateRange: '搜索时间段',
     to: '至',
+    of: '的',
     index: '序号',
     null: '无',
     all: '全部',
@@ -103,7 +154,7 @@ module.exports = {
     lastWeek: '最近一周',
     lastMonth: '最近一个月',
     lastThreeMonths: '最近三个月',
-    getMsg: '收到消息',
+    getMsg: '收到消息: ',
     sureInitialize: '您确定要初始化吗?',
     dateNull: '暂无数据',
     content: '内容',
@@ -114,21 +165,21 @@ module.exports = {
     uploaderImg2: '上传头像图片只能是 JPG、PNG、GIF 格式!',
     uploaderSize: '上传附件大小不能超过 5MB!',
     uploaderSize2: '上传头像图片大小不能超过 2MB!',
-    uploaderImgMsg: '图片宽度必须在100~500之间,宽高比为11!',
-    uploaderImgMsg2: '请上传宽高比为11的图片',
+    uploaderImgMsg: '图片宽度必须在100~500之间,宽高比为1: 1!',
+    uploaderImgMsg2: '请上传宽高比为1: 1的图片',
     uploaderImgMsg3: '图片高度必须在100~500之间!',
     uploadFile: '上传文件',
-    uploadAPK: 'APK文件上传',
+    uploadAPK: 'APK/IMG文件上传',
     uploadFileMsg: '将文件拖到此处,或',
     uploadFileMsg2: '点击上传',
     uploadFileMsg3: '只能上传mp3或flac文件',
     uploadFileMsg4: '上传附件大小不能超过 50MB!',
-    uploadFileMsg5: '只能上传APK文件',
+    uploadFileMsg5: '只能上传APK/IMG文件',
     uploadFileName: '文件名称',
     uploadFileNameMsg: '文件名称不能为空',
     uploadFileUrl: '文件路径',
     uploadFileUrlMsg: '文件路径不能为空,请上传文件',
-    uploadFileUrlMsg2: '请上传APK文件',
+    uploadFileUrlMsg2: '请上传APK/IMG文件',
     uploadFileAuthor: '上传者',
     uploadFileDate: '上传日期',
     uploadVersionNo: '版本数字',
@@ -146,16 +197,26 @@ module.exports = {
     byEvent: '按事件',
     export: '导出',
     icon: '图标',
+    excelUpload: '上传excel表',
     play: '播放',
     pause: '暂停',
-    noFile: '文件不存在,无法播放'
+    noFile: '文件不存在,无法播放',
+    inputMsg: '请输入内容!',
+    year: '年',
+    month: '月',
+    day: '日',
+    timeMsg: '请选择时间范围!',
+    param: '参数',
+    inputParamName: '请输入参数名',
+    inputParamValue: '请输入参数值',
+    addParam: '新增参数'
   },
   member: {
     face: '头像',
     faceImg: '上传头像图片只能是 JPG、PNG、GIF 格式!',
     faceSize: '上传头像图片大小不能超过 2MB!',
-    faceError1: '图片宽度必须在100~500之间,宽高比为1:1!',
-    faceError2: '请上传宽高比为1:1的图片',
+    faceError1: '图片宽度必须在100~500之间,宽高比为1: 1!',
+    faceError2: '请上传宽高比为1: 1的图片',
     faceError3: '图片高度必须在100~500之间!',
     uname: '登录名',
     inputUname: '请输入用户名',
@@ -189,7 +250,8 @@ module.exports = {
     disabled: '已禁用!',
     disableCancel: '已取消禁用',
     deleteMember: '你确定要删除此用户信息?',
-    cannotDeleteAdmin: '不能删除机构负责人'
+    cannotDeleteAdmin: '不能删除机构负责人',
+    leaderName:'上级职员'
   },
   home: {
     todayTask: '今日任务',
@@ -415,15 +477,25 @@ module.exports = {
     customerRelativeTrueName: '亲属姓名',
     inputCustomerRelativeTrueName: '请输入亲属姓名',
     relativeName: '关系',
-    inputRelativeName: '请输入亲属关系 如朋友',
+    inputRelativeName: '请输入亲属关系 如: 朋友',
     choiceRelativeName: '请选择亲属关系',
     vital: '体征',
     remark: '备注',
-    remarks: '备注内容',
+    remarks: '备注内容: ',
     inputRemarks: '请输入备注内容',
-    remarkTime: '时间',
-    remarkName: '备注人',
+    remarkTime: '时间: ',
+    remarkName: '备注人: ',
     addRemark: '添加备注',
+    fee: '费用',
+    feeName: '费用名称',
+    feeValue: '具体费用',
+    feeNumber: '费用批次',
+    feeTime: '费用产生的时间',
+    feeGroupName: '费用项组名',
+    feeKeyCode: '费用编码',
+    feeUnit: '单位',
+    feeDescription: '描述',
+    feeKeyType: '参数类型',
     outBed: '退床',
     outBed2: '注销登记',
     outBed3: '注销',
@@ -436,12 +508,15 @@ module.exports = {
     oldBed: '当前床位',
     newBed: '换到床位',
     choiceNewBed: '请选择床位',
-    getEmptyBed: '获取空床位',
+    getEmptyBed: '获取空床位: ',
     message: '的信息',
     customerStatus: '当前状态',
     customerStatusTrue: '入住中',
     customerStatusFalse: '已离开',
-    footprint: '足迹'
+    footprint: '足迹',
+    babyName: '孩子姓名',
+    babySex: '孩子性别',
+    babyBirthday: '孩子生日'
   },
   vital: {
     customerVital: '用户体征日志',
@@ -450,6 +525,16 @@ module.exports = {
     logTime: '测量时间',
     company: '单位'
   },
+  adviceManage: {
+    adviceAdd: '新增医嘱',
+    adviceEdit: '医嘱编辑',
+    adviceType: '医嘱类型',
+    adviceStatus: '状态',
+    loseEfficacy: '失效',
+    takeEffect: '生效',
+    longTerm: '长期',
+    temp: '临时'
+  },
   watch: {
     deviceKeywords: '请输入设备别名或设备标识码',
     dateKeywords: '选择日期进行搜索',
@@ -460,6 +545,7 @@ module.exports = {
     initializeDevice: '初始化设备',
     watchFrame: '管理空间',
     watchDeviceFrame: '移动设备管辖空间',
+    allFrame: '所有房间',
     place: '位置',
     placeInfo: '位置信息',
     getNewPlace: '获取最新位置',
@@ -487,9 +573,9 @@ module.exports = {
   },
   remark: {
     remarkAdd: '新建便签',
-    remarkContent: '便签内容',
-    remarkCreateTime: '创建时间',
-    remarkCreateName: '创建人'
+    remarkContent: '便签内容: ',
+    remarkCreateTime: '创建时间: ',
+    remarkCreateName: '创建人: '
   },
   task: {
     all: '全部',
@@ -502,7 +588,7 @@ module.exports = {
     failed: '失败',
     noticeAndTask: '通知/任务',
     taskPlanTime: '计划任务执行时间',
-    taskPlanTime2: '计划执行时间',
+    taskPlanTime2: '计划执行时间: ',
     taskToTime: '实际任务执行时间',
     taskToName: '任务操作人',
     doTask: '操作任务',
@@ -520,6 +606,7 @@ module.exports = {
     actionTime: '交互次数',
     actionTime2: '通话次数',
     success: '成功',
+    excelFileMsg: '将导出Excel文件,是否继续?',
     successInteraction: '已响应交互',
     successInteraction2: '已接通通话',
     unSuccessInteraction: '未完成交互',
@@ -531,6 +618,7 @@ module.exports = {
     notOperated: '未响应',
     data: '交互数据',
     createDate: '交互时间',
+    responseTime: '响应时间',
     fromDevice: '发起设备',
     toDevice: '接收设备',
     interactionRecord: '交互记录',
@@ -538,7 +626,7 @@ module.exports = {
     all: '全部',
     customerAndClerk: '客户与员工',
     clerkAndClerk: '同事与同事',
-    selectData: '查询周期',
+    selectData: '查询周期: ',
     customerCensus: '用户交互统计',
     clerkCensus: '员工交互统计',
     dataCensus: '时间段交互统计',
@@ -553,7 +641,9 @@ module.exports = {
     MaxNum2: '最大接通时间',
     SumNum: '总通话时间',
     total: '总量',
-    recordPlay: '播放录音录像'
+    recordPlay: '播放录音录像',
+    eventStatistics: '事件统计表',
+    statisticalTable: '统计表'
   },
   frameGroup: {
     frameGroupAdd: '新建区域',
@@ -602,7 +692,7 @@ module.exports = {
     broadcastInfo: '广播信息',
     broadcastFile: '广播文件',
     broadcastLoadFailed: '加载广播插件失败',
-    broadPlugInError: '广播插件错误'
+    broadPlugInError: '广播插件错误: '
   },
   event: {
     eventEdit: '编辑按钮事件',
@@ -813,18 +903,21 @@ module.exports = {
     vdoor: '门口机可视版',
     sickbed: '5寸床位分机APP',
     sevensickbed: '7寸床位分机APP',
+    linuxsickbed: 'Linux床位分机IMG',
     vsickbed: '床位分机可视版',
     mobiledevice: '移动设备',
     vistitation: '探视机',
     transferDevice: '转换盒',
     lcdDevice: 'LCD走廊屏',
+    entraceguard_device: '门禁设备APP',
     organizationAdd: '新建组织',
     boardShowEmptyBed: '看板显示空床',
     nursingColorRgb: '护理门灯颜色',
     twoColorDoorLightValid: '支持双色门灯',
     support: '支持双色门灯',
-    customerNameHidden: '开启用户名隐藏',
-    hidden: '开启用户名隐藏',
+    customerNameHidden: '开启用户姓名隐藏',
+    clerkNameHidden: '开启员工姓名隐藏',
+    hidden: '开启隐藏',
     channelImHistoryStoreDays: '频道留言保留天数',
     recordEnabled: '开启录音录像功能',
     recordAble: '开启录音录像功能'
@@ -840,7 +933,29 @@ module.exports = {
     roleEvent: '角色事件',
     roleDelete: '删除角色',
     roleEdit: '编辑角色事件',
-    onChoiceRole: '没有选中任何角色!'
+    onChoiceRole: '没有选中任何角色!',
+    leaderRole:'上级角色',
+    leaderRolePlaceholder:'请选择上级角色',
+    roleEnum:'角色类型',
+    roleEnumPlaceholder:'请选择角色类型'
+  },
+  his: {
+    hisPart: '科室查询',
+    hisPartKeyval: '科室his主键',
+    hisPartName: '科室名称',
+    summary: '科室简介',
+    tel: '科室电话',
+    hisError: 'his错误',
+    hisPatient: '入住人',
+    hisPatientKeyval: '入住人his主键',
+    hisPatientInfo: '查询信息',
+    hisClerk: '工作人员',
+    hisClerkKeyval: '工作人员his主键',
+    hisDockerKeyval: '责任医生his主键',
+    hisNurseKeyval: '责任护士his主键',
+    passNo: '门禁卡',
+    hisNurseConfig: '护理项',
+    hisNurseOptionsKeyval: '护理项分类his主键'
   },
   tab: {
     home: '首页',
@@ -850,6 +965,7 @@ module.exports = {
     patientManage: '入住人员管理',
     customerManage: '用户管理',
     customerQrCode: '用户二维码',
+    customerAdvice: '医嘱',
     mobileDeviceManage: '移动设备',
     userLocationManage: '用户位置',
     sosDeviceSettingManage: '报警设备',
@@ -866,8 +982,11 @@ module.exports = {
     nurseConfig: '护理参数',
     boardManage: '看板设置',
     eventManage: '按钮事件管理',
+    hisManage: 'his查询',
     interactionChars: '交互统计',
     partSetting: '机构设置',
+    functionRoleMapping:'功能角色设置',
+    interactionChain:'交互接收顺序',
     allClerk: '所有员工',
     allCustomer: '所有用户',
     allDevice: '所有设备',
@@ -879,7 +998,11 @@ module.exports = {
     roleManage: '角色管理',
     debugging485: '485调试',
     deviceFrame: '设备空间',
-    ledDevice: 'LED点阵屏'
+    ledDevice: 'LED点阵屏',
+    entraceguardUser:'用户通行设置',
+    customBoardManage: '自定义信息看板屏',
+    customBoardDesigner:'看板屏设计',
+    staffManageFrames:'空间管理设置'
   },
   deviceType: {
     NURSE_HOST: '护士主机',
@@ -916,8 +1039,11 @@ module.exports = {
     ALARM_433BUTTON: '433报警器',
     OTHER_HOST: '其他主机',
     BREASTPLATE: '胸牌',
-    OWON_X5_GATEWAY: 'X5网关',
-    FALL_DETECTION_RADAR: '防跌倒雷达'
+    OWON_X5_GATEWAY: 'OWONX5网关',
+    FALL_DETECTION_RADAR: '防跌倒雷达',
+    HUMAN_DETECTION_RADAR: '睡眠监测雷达',
+    ALARM_INFUSION: '输液报警器'
+
   },
   vitalSignsDeviceType: {
     BLOOD_SUGAR: '血糖仪',
@@ -941,7 +1067,7 @@ module.exports = {
     DEVICE: '设备',
     DATA: '数据',
     EVENT: '事件',
-    SIDE: '边外信息',
+    SIDE: '护理',
     BROADCAST: '广播',
     TIME: '时间',
     ENTRACEGUARD: '门禁',
@@ -952,6 +1078,8 @@ module.exports = {
   },
   relativeNameType: {
     CHILDREN: '孩子',
+    BOY: '男孩',
+    GIRL: '女孩',
     HUSBAND: '丈夫',
     WIFE: '妻子',
     FATHER: '父亲',
@@ -962,5 +1090,126 @@ module.exports = {
   childbirthType: {
     SPONTANEOUS_LABOR: '顺产',
     CAESAREAN_BIRTH: '剖腹产'
+  },
+  sleepData: {
+    Awake: '醒着',
+    DeepSleep: '深睡',
+    LightSleep: '浅睡',
+    Hour: '时',
+    Minute: '分',
+    Quality: '睡眠质量',
+    InBed: '在床上',
+    Asleep: '睡眠',
+    AvarageBreath: '平均呼吸',
+    AvarageHeartBeat: '平均心跳',
+    LeaveBedTimes: '离床次数',
+    TurnOverTimes: '翻身次数',
+    BreathPauseTimes: '呼吸暂停次数',
+    GetInBedTime: '上床时间',
+    AwakeTime: '醒来时间',
+    NoData: '没有数据',
+    Times: '次',
+    ChooseDate: '日期',
+    SleepData: '睡眠数据'
+  },
+
+  interactionChain:{
+    ActionType:'交互类型',
+    FirstRole:'最先接收角色',
+    SpreadRoleNamePath:'交互接收角色顺序',
+    AddInteractionSpreadPath:'新增交互接收顺序',
+    AllRoles:'所有角色',
+    AcceptRoles:'接收角色',
+    NoticeSequence:'注意顺序',
+    SearchPlaceHolder:'请输入角色名称',
+    Customer:'客户',
+    NURSE_HOST: '护士主机',
+    AcceptSequence:'接收顺序',
+    chooseActionTypeTip:'请选择交互类型',
+    chooseRoleSquence:'请选择接收角色的顺序',
+    sketchMap:'交互接收流程示意图'
+  },
+  functionRoleMapping:{
+    configurateLeft:'配置拥有[',
+    configurateRight:']功能的角色'
+  },
+  functions:{
+    MANAGE_BED:'管理床位'
+  },
+  clerkFrameManage:{
+    employeeView:'职员视图',
+    frameView:'空间视图',
+    multiClerkView:'多人共管空间',
+    managedFrames:'已管理空间',
+    notManagedFrames:'未管理空间',
+    settableEmployee:'可设置职员',
+    settedEmployee:'已设置职员',
+    allEmployee:'所有职员',
+    phoneAcceptorLabel:'普通电话接收人',
+    phoneAcceptorTipsLeft:'如有其他同角色职员与',
+    phoneAcceptorTipsMid:'管理空间重叠',
+    phoneAcceptorTipsRight:'负责处理普通电话呼叫'
+},
+  errorType: {
+    REFRESH_TOKEN_FAILED: '当前刷新Token已经失效',
+    TOKEN_FAILED: '当前token已经失效',
+    USER_NULL: '账号不存在!',
+    USER_DISABLE: '当前账号已经禁用,请联系管理员',
+    PASSWORD_ERROR: '账号密码错误!',
+    LOGIN_FAILED: '您的当前身份不允许登陆系统!',
+    LOGOUT: '用户已经退出登陆',
+    MEMBER_NULL: '当前用户不存在!',
+    MEMBER_ADD_FAILED: '添加成员失败,不存在的用户ID',
+    MEMBER_FAILED: '用户id错误,不存在的用户D',
+    MOBILE_OCCUPY: '该手机号已经被占用',
+    MEMBER_NAME_OCCUPY: '当前用户已经注册',
+    CHANNEL_FAILED: '频道Id错误,不存在的频道',
+    CHANNEL_SUBSCRIBE_MEMBER_NULL: '不存在的用户,无法订阅',
+    CHANNEL_MEMBER_FAILED: '用户不属于任何机构,不能订阅',
+    CHANNEL_NULL: '不存在的频道,不能订阅',
+    FRAME_HOSPITAL_NULL: '医院结构不存在',
+    FRAME_PART_NULL: '科室级节点不存在,参数无效!',
+    FRAME_ADD_FAILED: '结束房号小于起始房号,参数无效!',
+    CUSTOMER_INFO_NULL: '病人信息不存在',
+    CLOUD_ADDRESS_NULL: '未设置云路径',
+    CLOUD_SAVE_FAILED: '保存云失败',
+    SHOP_NULL: '不存在的组织!',
+    SHOP_DAYTIME_ERROR: '白天开始时间格式不正确,请重新选择!',
+    SHOP_NIGHTTIME_ERROR: '夜晚开始时间格式不正确,请重新选择!',
+    ADMIN_PASSWORD_ERROR: '管理员账号已经存,但是密码不匹配!请使用其他账号,或者输入正确密码。',
+    DEVICE_MAC_REPEAT: '设备MAC地址重复',
+    DEVICE_ADD_FAILED: '当前空间已经存在紧急按钮,无法注册多个紧急按钮',
+    DEVICE_FRAME_FAILED: '设备类型和空间结构类型不匹配!',
+    DATA_NULL: '没有找到数据',
+    PARAM_ERROR: '参数错误!',
+    PRIMARY_KEY_NULL: '参数错误,科室主键值为空!',
+    ROLE_NULL: '此角色不存在',
+    ROLE_NAME_OCCUPY: '角色名称重复',
+    ROLE_DELETE_FAILED: '此角色正在使用中,不能删除!',
+    LICENSE_ERROR: '授权序列号错误,请联系售后',
+    LICENSE_EXPIRE: '授权到期,请联系售后',
+    LICENSE_FAILED: '无效授权,请联系售后',
+    FILE_UPLOAD_FAILED: '未配置文件存放目录!'
+  },
+  entraceguardUser:{
+    named: '用户姓名',
+    idNo:'身份证号',
+    ic:'IC卡号',
+    phone:'手机号',
+    password:'通行密码',
+    forbidden:'禁止通行',
+    refreshUser:'刷新可用用户',
+    yes:'是',
+    nop:'否'
+  },
+  boardTitle:{
+    add:'添加看板屏幕',
+    screenTitle:'屏幕标题',
+    showIndex:'显示顺序',
+    partId:'科室ID',
+    design:'设计内容',
+    titleRequire:'屏幕标题不能为空',
+    createTitle:'新增看板自定义屏',
+    editTitle:'编辑自定义看板屏'
   }
 }

+ 29 - 14
package-lock.json

@@ -7254,8 +7254,8 @@
       "dev": true
     },
     "eve": {
-      "version": "git://github.com/adobe-webplatform/eve.git#eef80ed8d188423c2272746fb8ae5cc8dad84cb1",
-      "from": "git://github.com/adobe-webplatform/eve.git#eef80ed"
+      "version": "git+ssh://git@github.com/adobe-webplatform/eve.git#eef80ed8d188423c2272746fb8ae5cc8dad84cb1",
+      "from": "eve@git://github.com/adobe-webplatform/eve.git#eef80ed"
     },
     "event-pubsub": {
       "version": "4.3.0",
@@ -8174,7 +8174,8 @@
         "ansi-regex": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "optional": true
         },
         "is-fullwidth-code-point": {
           "version": "1.0.0",
@@ -8200,6 +8201,7 @@
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
           "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -9834,8 +9836,8 @@
       }
     },
     "janus-gateway": {
-      "version": "git+https://github.com/meetecho/janus-gateway.git#d884b2a9d978e18514bf2fbaddc19cc3e1cc03a9",
-      "from": "git+https://github.com/meetecho/janus-gateway.git",
+      "version": "git+ssh://git@github.com/meetecho/janus-gateway.git#d884b2a9d978e18514bf2fbaddc19cc3e1cc03a9",
+      "from": "janus-gateway@https://github.com/meetecho/janus-gateway.git",
       "requires": {
         "webrtc-adapter": "8.1.1"
       }
@@ -11852,6 +11854,11 @@
         "commander": "*"
       }
     },
+    "moment": {
+      "version": "2.29.4",
+      "resolved": "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz",
+      "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
+    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -12495,7 +12502,8 @@
     "npm-normalize-package-bin": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
-      "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
+      "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
+      "optional": true
     },
     "npm-packlist": {
       "version": "1.4.8",
@@ -13255,7 +13263,8 @@
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
       "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
-      "dev": true
+      "dev": true,
+      "optional": true
     },
     "pify": {
       "version": "4.0.1",
@@ -14392,10 +14401,10 @@
       "dev": true
     },
     "raphael": {
-      "version": "git+https://github.com/nhn/raphael.git#78a6ed3ec269f33b6457b0ec66f8c3d1f2ed70e0",
-      "from": "git+https://github.com/nhn/raphael.git#2.2.0-c",
+      "version": "git+ssh://git@github.com/nhn/raphael.git#78a6ed3ec269f33b6457b0ec66f8c3d1f2ed70e0",
+      "from": "raphael@git+https://github.com/nhn/raphael.git#2.2.0-c",
       "requires": {
-        "eve": "git://github.com/adobe-webplatform/eve.git#eef80ed8d188423c2272746fb8ae5cc8dad84cb1"
+        "eve": "eve@git://github.com/adobe-webplatform/eve.git#eef80ed"
       }
     },
     "raw-body": {
@@ -15903,8 +15912,8 @@
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
     },
     "squire-rte": {
-      "version": "github:sohee-lee7/Squire#b1e0e1031fa18912d233c204cbe7c7fae4a42621",
-      "from": "github:sohee-lee7/Squire#b1e0e1031fa18912d233c204cbe7c7fae4a42621"
+      "version": "git+ssh://git@github.com/sohee-lee7/Squire.git#b1e0e1031fa18912d233c204cbe7c7fae4a42621",
+      "from": "squire-rte@github:sohee-lee7/Squire#b1e0e1031fa18912d233c204cbe7c7fae4a42621"
     },
     "ssf": {
       "version": "0.10.3",
@@ -16637,6 +16646,7 @@
           "version": "2.9.0",
           "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
           "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -17015,7 +17025,7 @@
       "integrity": "sha512-DUJIutBG/tOdvJnGCo1PcBhFyGBWsY8VIMdXe3WRtGXynMwOcC5cojYpULf3qFJ4Jj1Riv3/kbF6Ygmi+BpjCw==",
       "requires": {
         "core-js": "^3.6.4",
-        "raphael": "git+https://github.com/nhn/raphael.git#78a6ed3ec269f33b6457b0ec66f8c3d1f2ed70e0",
+        "raphael": "raphael@git+https://github.com/nhn/raphael.git#2.2.0-c",
         "tui-code-snippet": "^2.3.1"
       },
       "dependencies": {
@@ -17060,7 +17070,7 @@
         "markdown-it": "^8.4.0",
         "plantuml-encoder": "^1.2.5",
         "resize-observer-polyfill": "^1.5.0",
-        "squire-rte": "github:sohee-lee7/Squire#b1e0e1031fa18912d233c204cbe7c7fae4a42621",
+        "squire-rte": "squire-rte@github:sohee-lee7/Squire#b1e0e1031fa18912d233c204cbe7c7fae4a42621",
         "to-mark": "^1.1.4",
         "tui-chart": "^3.0.1",
         "tui-code-snippet": "^1.5.0",
@@ -17632,6 +17642,11 @@
         "vue-template-es2015-compiler": "^1.6.0"
       }
     },
+    "vue-lazyload": {
+      "version": "1.3.4",
+      "resolved": "https://registry.npmmirror.com/vue-lazyload/-/vue-lazyload-1.3.4.tgz",
+      "integrity": "sha512-K0frbPQJuvFHVpdl/ov5CqCR/CHWeLGs8E8V1d/09DIETqBjeGhC1fLMmwUy3Go2Yd/VX610AZ7Mdn4B54592Q=="
+    },
     "vue-loader": {
       "version": "15.9.5",
       "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.5.tgz",

+ 4 - 2
package.json

@@ -29,12 +29,14 @@
     "eslint-plugin-html": "^6.2.0",
     "file-saver": "2.0.1",
     "fuse.js": "3.4.4",
+    "janus-gateway": "https://github.com/meetecho/janus-gateway.git",
     "jquery": "^3.6.0",
     "js-cookie": "2.2.0",
     "js-md5": "^0.7.3",
     "jsonlint": "1.6.3",
     "jszip": "3.2.1",
     "jwt-decode": "^3.1.2",
+    "moment": "^2.29.4",
     "normalize.css": "7.0.0",
     "nprogress": "0.2.0",
     "particles.js": "2.0.0",
@@ -57,9 +59,9 @@
     "vue-seamless-scroll": "^1.1.23",
     "vue-splitpane": "1.0.4",
     "vuedraggable": "^2.20.0",
+    "vue-lazyload": "^1.2.6",
     "vuex": "3.1.0",
-    "xlsx": "0.14.1",
-    "janus-gateway": "https://github.com/meetecho/janus-gateway.git"
+    "xlsx": "0.14.1"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "4.4.4",

+ 46 - 0
src/api/ncs_advice.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+/**
+ * 医嘱相关接口
+ * @param params
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function getList(params) {
+  return request({
+    url: '/ncs/advice/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+/** 新增医嘱 */
+export function add(params) {
+  return request({
+    url: '/ncs/advice',
+    method: 'POST',
+    loading: true,
+    data: params
+  })
+}
+
+/** 删除医嘱 */
+export function remove(params) {
+  const ids = params.toString()
+  return request({
+    url: `/ncs/advice/${ids}`,
+    method: 'DELETE',
+    loading: true,
+    data: params
+  })
+}
+
+/** 更新医嘱 */
+export function update(id, params) {
+  return request({
+    url: `/ncs/advice/${id}`,
+    method: 'put',
+    data: params
+  })
+}

+ 69 - 0
src/api/ncs_board_item.js

@@ -0,0 +1,69 @@
+import request from '@/utils/request'
+
+/**
+ * 自定义看板项相关接口
+ * @param params
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function getList(params) {
+    return request({
+        url: '/ncs/boarditem/page',
+        method: 'POST',
+        loading: true,
+        data: params,
+        headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+    })
+}
+
+/** 新增自定义看板项 */
+export function add(params) {
+    return request({
+        url: '/ncs/boarditem',
+        method: 'POST',
+        loading: true,
+        data: params
+    })
+}
+
+/** 删除自定义看板项 */
+export function remove(params) {
+    const ids = params.toString()
+    return request({
+        url: `/ncs/boarditem/${ids}`,
+        method: 'DELETE',
+        loading: true,
+        data: params
+    })
+}
+
+/** 更新自定义看板项 */
+export function update(id, params) {
+    return request({
+        url: `/ncs/boarditem/${id}`,
+        method: 'put',
+        data: params
+    })
+}
+
+/** 查询自定义看板项 */
+export function get(id, params) {
+    return request({
+        url: `/ncs/boarditem/${id}`,
+        method: 'get',
+        loading: false,
+        params
+    })
+}
+
+
+/** 获取某科室下的所有看板项 */
+export function getPartList(part_id) {
+    return request({
+        url: `/ncs/boarditem/partboarditem/${part_id}`,
+        method: 'get',
+        loading: false
+    })
+}
+
+
+

+ 83 - 0
src/api/ncs_board_title.js

@@ -0,0 +1,83 @@
+import request from '@/utils/request'
+
+/**
+ * 自定义看板屏幕相关接口
+ * @param params
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function getList(params) {
+    return request({
+        url: '/ncs/boardtitle/page',
+        method: 'POST',
+        loading: true,
+        data: params,
+        headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+    })
+}
+
+/** 新增自定义看板屏幕 */
+export function add(params) {
+    return request({
+        url: '/ncs/boardtitle',
+        method: 'POST',
+        loading: true,
+        data: params
+    })
+}
+
+/** 删除自定义看板屏幕 */
+export function remove(params) {
+    const ids = params.toString()
+    return request({
+        url: `/ncs/boardtitle/${ids}`,
+        method: 'DELETE',
+        loading: true,
+        data: params
+    })
+}
+
+/** 更新自定义看板屏幕 */
+export function update(id, params) {
+    return request({
+        url: `/ncs/boardtitle/${id}`,
+        method: 'put',
+        data: params
+    })
+}
+
+/** 查询自定义看板屏幕 */
+export function get(id, params) {
+    return request({
+        url: `/ncs/boardtitle/${id}`,
+        method: 'get',
+        loading: false,
+        params
+    })
+}
+
+/**
+ * 获取频道的订阅者列表 返回List<ClerkDO> 或null
+ * @param id 频道Id
+ * @returns {AxiosPromise | * | Promise | Promise<unknown>}
+ */
+export function getChannelSubscribers(id) {
+    return request({
+        url: `/channelsubscribe/subscribers/${id}`,
+        method: 'get',
+        loading: false
+    })
+}
+
+/**
+ * 批量设置频道订阅者
+ * @param params {channel_id:12,member_ids:[]}
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function setChannelSubscribers(params) {
+    return request({
+        url: `/channelsubscribe/subscribers`,
+        method: 'post',
+        loading: false,
+        data: params
+    })
+}

+ 26 - 1
src/api/ncs_clerk.js

@@ -54,7 +54,8 @@ export function update(id, params) {
   return request({
     url: `/ncs/clerk/${id}`,
     method: 'put',
-    data: params
+    data: params,
+    headers: { 'Content-Type': 'application/json' }
   })
 }
 export function getRoles(params) {
@@ -85,3 +86,27 @@ export function updateParentById(params) {
     data: params
   })
 }
+export function getRoleGroupClerk(partId) {
+  return request({
+    url: `/ncs/clerk/getrolegroupclerk/${partId}`,
+    method: 'GET'
+  })
+}
+
+export function getClerkManageFrame(clerkId,frameRootType) {
+  return request({
+    url: `/ncs/clerk/getclerkmanageframe/${clerkId}/${frameRootType}`,
+    method: 'GET'
+  })
+}
+
+
+export function saveClerkManageFrame(params) {
+  return request({
+    url: '/ncs/clerk/saveclerkmanageframe',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/json' }
+  })
+}

+ 19 - 0
src/api/ncs_customer_fee_config.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+export function getCustomerFeeConfig(customerId) {
+  return request({
+    url: `/ncs/customer_fee_config/getCustomerFeeConfig/${customerId}`,
+    method: 'GET'
+  })
+}
+
+export function getCustomerFeeConfigPage(params) {
+  return request({
+    url: '/ncs/customer_fee_config/get_customer_fee_config_page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+

+ 9 - 0
src/api/ncs_customer_mapping.js

@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+export function deleteByCustomerAndNurseConfigId(customer, ids) {
+  return request({
+    url: `/ncs/customer_mapping/${customer}/${ids}`,
+    method: 'DELETE',
+    loading: true
+  })
+}

+ 28 - 0
src/api/ncs_entrace_guard_user.js

@@ -0,0 +1,28 @@
+import request from '@/utils/request'
+export function getList(params) {
+    return request({
+        url: '/ncs/entrace_guard_user/page',
+        method: 'POST',
+        loading: true,
+        data: params,
+        headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+    })
+}
+
+/** 更新用户设置 */
+export function update(id, params) {
+    return request({
+        url: `/ncs/entrace_guard_user/${id}`,
+        method: 'put',
+        loading: false,
+        data: params
+    })
+}
+
+/** 更新用户记录 */
+export function refreshUser(part_id) {
+    return request({
+        url: `/ncs/entrace_guard_user/refresh/${part_id}`,
+        method: 'post'
+    })
+}

+ 11 - 0
src/api/ncs_excel.js

@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+/** 插入表格数据 **/
+export function getExcelFile(params) {
+  return request({
+    url: '/ncs/excel/excel_file',
+    method: 'post',
+    loading: false,
+    data: params
+  })
+}

+ 33 - 0
src/api/ncs_frameGroup.js

@@ -81,3 +81,36 @@ export function getAllFrameTreeByType(frame_type) {
   })
 }
 
+
+/** 查询空间结构的管理人员信息 */
+export function getFrameManagedClerk(frameId) {
+  return request({
+    url: `/ncs/frame/getframemanagedclerk/${frameId}`,
+    method: 'get',
+    loading: false
+  })
+}
+
+
+/** 保存空间结构的管理人员信息 */
+export function saveFrameManagedClerk(params) {
+  return request({
+    url: `/ncs/frame/saveframemanagedclerk`,
+    method: 'POST',
+    loading: true,
+    headers: { 'Content-Type': 'application/json' },
+    data:params
+  })
+}
+
+/** 查询某科室下多人共管的房间结构 */
+export function getframemultimanagedstruct(part_id, frame_type) {
+  return request({
+    url: `/ncs/frame/getframemultimanagedstruct/${part_id}/${frame_type}`,
+    method: 'get',
+    loading: false
+  })
+}
+
+
+

+ 7 - 0
src/api/ncs_functions.js

@@ -0,0 +1,7 @@
+import request from '@/utils/request'
+export function getAll() {
+    return request({
+        url: '/ncs/functions/getall',
+        method: 'get'
+    })
+}

+ 41 - 0
src/api/ncs_functions_role_mapping.js

@@ -0,0 +1,41 @@
+import request from '@/utils/request'
+export function getList(params) {
+    return request({
+        url: '/ncs/functionrolemapping/page',
+        method: 'POST',
+        data: params,
+        headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+    })
+}
+export function getFunctionsRoleMappingByCodeAndPartId(function_code,part_id) {
+    return request({
+        url: `/ncs/functionrolemapping/${function_code}/${part_id}`,
+        method: 'GET'
+    })
+}
+export function remove(id) {
+    return request({
+        url: `/ncs/functionrolemapping/${id}`,
+        method: 'DELETE',
+        loading: true
+    })
+}
+/** 修改 */
+export function update(id, params) {
+    return request({
+        url: `/ncs/functionrolemapping/${id}`,
+        method: 'put',
+        data: params,
+        headers: { 'Content-Type': 'application/json' }
+    })
+}
+/** 新增 */
+export function add(params) {
+    return request({
+        url: '/ncs/functionrolemapping',
+        method: 'POST',
+        loading: true,
+        data: params,
+        headers: { 'Content-Type': 'application/json' }
+    })
+}

+ 91 - 0
src/api/ncs_his.js

@@ -0,0 +1,91 @@
+import request from '@/utils/request'
+const serverUrl = domain.serverUrl
+const url = serverUrl.substring(0, serverUrl.length - 4) + '8009'
+
+// 查询科室列表
+export function getList(params) {
+  return request({
+    url: url + '/hisquery/depart/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+// 根据主键查询科室
+export function getPartByKeyval(keyval) {
+  return request({
+    url: url + `/hisquery/depart/${keyval}`,
+    method: 'GET',
+    loading: false
+  })
+}
+
+// 查询用户列表
+export function getPatientList(params) {
+  return request({
+    url: url + '/hisquery/patient/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+// 查询工作人员列表
+export function getClerkList(params) {
+  return request({
+    url: url + '/hisquery/employee/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+// 根据主键查询工作人员
+export function getClerkByKeyval(keyval) {
+  return request({
+    url: url + `/hisquery/employee/${keyval}`,
+    method: 'GET',
+    loading: false
+  })
+}
+
+// 查询工作人员列表
+export function getNurseConfigList(params) {
+  return request({
+    url: url + '/hisquery/nursecategory/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+// 查询工作人员列表
+export function getNurseOptionsList(params) {
+  return request({
+    url: url + '/hisquery/nurseoptions/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+export function getNurseOptionsByPartKeyval(part_keyval) {
+  return request({
+    url: url + `/hisquery/nurse_options_list/${part_keyval}`,
+    method: 'get'
+  })
+}
+
+export function getPatientNurseMappingByPatientKeyval(patient_keyval) {
+  return request({
+    url: url + `/hisquery/patient_nurse_mapping_list/${patient_keyval}`,
+    method: 'get'
+  })
+}
+

+ 35 - 0
src/api/ncs_interaction-chain.js

@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+export function getList(params) {
+    return request({
+        url: '/ncs/spreadchain/page',
+        method: 'POST',
+        data: params,
+        headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+    })
+}
+
+export function remove(id) {
+    return request({
+        url: `/ncs/spreadchain/${id}`,
+        method: 'DELETE',
+        loading: true
+    })
+}
+/** 修改 */
+export function update(id, params) {
+    return request({
+        url: `/ncs/spreadchain/${id}`,
+        method: 'put',
+        data: params
+    })
+}
+/** 新增 */
+export function add(params) {
+    return request({
+        url: '/ncs/spreadchain',
+        method: 'POST',
+        loading: true,
+        data: params,
+        headers: { 'Content-Type': 'application/json' }
+    })
+}

+ 20 - 0
src/api/ncs_relative.js

@@ -0,0 +1,20 @@
+import request from '@/utils/request'
+
+export function getRelativeList(data) {
+    return request({
+        url: '/ncs/relative/page',
+        method: 'POST',
+        params: data,
+        loading: false
+    })
+}
+
+export function removeRelative(params) {
+    const ids = params.toString()
+    return request({
+        url: `/ncs/relative/${ids}`,
+        method: 'DELETE',
+        loading: false,
+        data: params
+    })
+}

+ 16 - 0
src/api/ncs_sleep_data.js

@@ -0,0 +1,16 @@
+import request from '@/utils/request'
+
+export function getSleepData(member_id,dateStr) {
+    return request({
+        url: `/ncs/sleepdata/${member_id}/${dateStr}`,
+        method: 'GET'
+    })
+}
+
+export function getJsonData(url) {
+
+    return request({
+        url: url,
+        method: 'GET'
+    })
+}

+ 15 - 0
src/api/role.js

@@ -60,3 +60,18 @@ export function editRole(id, params) {
     data: params
   })
 }
+
+/**
+ * 获取代码中角色枚举类型
+ * @param id
+ */
+export function getRoleEnums() {
+  return request({
+    url: `/mgr/role/rolenums`,
+    method: 'get'
+  })
+}
+
+
+
+

BIN
src/assets/avatar.png


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/delete.svg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/designer.svg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/frame_manage.svg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/list-move.svg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/pass_through.svg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/pen-leather.svg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/role.svg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/setting.svg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/icons/svg/squence.svg


+ 17 - 4
src/layout/components/Navbar.vue

@@ -13,7 +13,7 @@
 
         <screenfull id="screenfull" class="right-menu-item hover-effect" />
 
-        <el-tooltip content="字体大小" effect="dark" placement="bottom">
+        <el-tooltip :content="this.$t('action.FontSize')" effect="dark" placement="bottom">
           <size-select id="size-select" class="right-menu-item hover-effect" />
         </el-tooltip>
 
@@ -50,7 +50,7 @@
             </el-dropdown>
           </el-dropdown-item>
           <el-dropdown-item divided @click.native="syncHis">
-            <span style="display:block;">同步HIS信息</span>
+            <span style="display:block;">{{ this.$t("action.SynchronizeHISInformation") }}</span>
           </el-dropdown-item>
           <el-dropdown-item divided @click.native="logout">
             <span style="display:block;">{{ this.$t("action.logout") }}</span>
@@ -69,7 +69,7 @@ import ErrorLog from '@/components/ErrorLog'
 import Screenfull from '@/components/Screenfull'
 import SizeSelect from '@/components/SizeSelect'
 import Search from '@/components/HeaderSearch'
-import avator from '@/assets/avatar.jpeg'
+import avator from '@/assets/avatar.png'
 import * as API_Part from '@/api/calling-part'
 import Storage from '@/utils/storage'
 export default {
@@ -94,6 +94,14 @@ export default {
         {
           value: 'zh',
           label: '中文简体'
+        },
+        {
+          value: 'es',
+          label: 'Español'
+        },
+        {
+          value: 'ru',
+          label: 'Русский'
         }
       ]
 
@@ -135,7 +143,7 @@ export default {
       API_Part.syncHis().then(res => {
         this.$message({
           type: 'success',
-          message: '开启HIS信息同步!'
+          message: this.$t("action.SynchronizeHISInformation")
         })
       })
     },
@@ -149,8 +157,13 @@ export default {
     switchLanguage(value) {
       if (value === 'zh') {
         this.$i18n.locale = 'zh'
+
       } else if (value === 'en') {
         this.$i18n.locale = 'en'
+      } else if (value === 'es') {
+        this.$i18n.locale = 'es'
+      } else if (value === 'ru') {
+        this.$i18n.locale = 'ru'
       }
       // 在选择了显示的语言后,将配置保存到缓存里
       Storage.setItem('DefaultLanguage', value)

+ 132 - 5
src/router/index.js

@@ -146,6 +146,34 @@ export const partRoutes = [
       }
     ]
   },
+  {
+    path: '/entrace-guard',
+    component: Layout,
+    redirect: '/entrace-guard/users',
+    children: [
+      {
+        path: 'users',
+        component: () => import('@/views/entrace-guard/users'),
+        name: 'users',
+        meta: {title: i18n.t('tab.entraceguardUser'), icon: 'pass_through', noCache: true}
+      }]
+
+  },
+  {
+    path: '/ncs-clerk-frame-manage',
+    component: Layout,
+    redirect: '/ncs-clerk-frame-manage/index',
+    children: [
+      {
+        path: 'clerkList',
+        component: () => import('@/views/ncs-clerk-frame-manage/index'),
+        name: 'clerkList',
+        meta: {title: i18n.t('tab.staffManageFrames'), icon: 'frame_manage', noCache: true}
+
+      }
+    ]
+  },
+
   // {
   //   path: '/customer',
   //   component: Layout,
@@ -176,6 +204,13 @@ export const partRoutes = [
         name: 'allMap',
         meta: { title: '用户分布', icon: 'area', noCache: true },
         hidden: true
+      },
+      {
+        path: '/advice/:id?',
+        component: () => import('@/views/ncs-advice/index'),
+        name: 'advice',
+        meta: { title: i18n.t('tab.customerAdvice'), icon: 'area', noCache: true },
+        hidden: true
       }
     ]
   },
@@ -224,8 +259,7 @@ export const partRoutes = [
         name: 'user_watch',
         meta: { title: i18n.t('tab.userLocationManage'), icon: 'el-icon-watch', noCache: true }
       }
-    ],
-    hidden: uiVersion === 1
+    ]
   },
   {
     path: '/ncs-sos-device',
@@ -258,8 +292,7 @@ export const partRoutes = [
         meta: { title: i18n.t('tab.channelImHistory'), icon: 'area', noCache: true },
         hidden: true
       }
-    ],
-    hidden: uiVersion !== 2
+    ]
   },
   {
     path: '/remark',
@@ -300,6 +333,7 @@ export const partRoutes = [
       }
     ]
   },
+
   // {
   //   path: '/calling-message',
   //   component: Layout,
@@ -313,6 +347,7 @@ export const partRoutes = [
   //     }
   //   ]
   // },
+
   {
     path: '',
     component: Layout,
@@ -375,7 +410,8 @@ export const partRoutes = [
       }
     ],
     hidden: uiVersion !== 1
-  }, {
+  },
+  {
     path: '/calling-board',
     component: Layout,
     redirect: '/calling-board/index',
@@ -389,6 +425,37 @@ export const partRoutes = [
     ],
     hidden: uiVersion === 2
   },
+
+  {
+    path: '/board-title',
+    component: Layout,
+    redirect: '/custom-infoboard/board-title',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/custom-infoboard/board-title'),
+        name: 'BoardTitle',
+        meta: { title: i18n.t('tab.customBoardManage'), icon: 'designer', noCache: true }
+      }
+    ],
+    hidden: uiVersion === 2
+  },
+  {
+    path: '/calling-board-designer',
+    component: Layout,
+    redirect: '/custom-infoboard/screen-designer',
+    children: [
+      {
+        path: 'index/:id?',
+        component: () => import('@/views/custom-infoboard/screen-designer'),
+        name: 'BoardDesigner',
+        meta: { title: i18n.t('tab.customBoardDesigner'), icon: 'el-icon-data-board', noCache: true }
+      }
+    ],
+    hidden: true
+  },
+
+
   {
     path: '/ncs-event',
     component: Layout,
@@ -430,6 +497,32 @@ export const partRoutes = [
     ]
   },
   {
+    path: '/function-mapping',
+    component: Layout,
+    redirect: '/function-mapping/index',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/function-mapping/index'),
+        name: 'functionMapping',
+        meta: { title: i18n.t('tab.functionRoleMapping'), icon: 'function', noCache: true }
+      }
+    ]
+  },
+  {
+    path: '/interaction-chain',
+    component: Layout,
+    redirect: '/interaction-chain/index',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/interaction-chain/index'),
+        name: 'interactionChain',
+        meta: { title: i18n.t('tab.interactionChain'), icon: 'squence', noCache: true }
+      }
+    ]
+  },
+  {
     path: '/calling-setting',
     component: Layout,
     redirect: '/calling-setting/index',
@@ -600,6 +693,40 @@ export const adminRoutes = [
     ]
   },
   {
+    path: '/admin/ncs-his',
+    component: Layout,
+    redirect: '/ncs-his/hisManager',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/ncs-his/hisManagement'),
+        name: 'hisManagement',
+        meta: { title: i18n.t('tab.hisManage'), icon: 'el-icon-search', noCache: true }
+      },
+      {
+        path: 'patientManage/:keyval?',
+        component: () => import('@/views/ncs-his/his-patient/hisPatientManage'),
+        name: 'hisPatientManage',
+        meta: { title: i18n.t('his.hisPatient'), icon: 'el-icon-search', noCache: true },
+        hidden: true
+      },
+      {
+        path: 'clerkManage/:keyval?',
+        component: () => import('@/views/ncs-his/his-clerk/hisClerkManager'),
+        name: 'hisClerkManage',
+        meta: { title: i18n.t('his.hisClerk'), icon: 'el-icon-search', noCache: true },
+        hidden: true
+      },
+      {
+        path: 'nurseConfigManage/:keyval?',
+        component: () => import('@/views/ncs-his/his-nurse-config/hisNurseConfigManager'),
+        name: 'hisNurseConfigManage',
+        meta: { title: i18n.t('his.hisNurseConfig'), icon: 'el-icon-search', noCache: true },
+        hidden: true
+      }
+    ]
+  },
+  {
     path: '/calling-ncError',
     component: Layout,
     redirect: '/calling-ncError/index',

+ 15 - 1
src/settings.js

@@ -1,5 +1,19 @@
+const Cookies = require('js-cookie')
+
+function getTitle() {
+  let lang = Cookies.get('DefaultLanguage')
+
+  if (lang === 'zh') {
+    return '呼叫系统配置中心'
+  } else if (lang === 'en') {
+    return 'System Configuration'
+  } else {
+    return 'Configuración del sistema'
+  }
+}
+
 module.exports = {
-  title: '维鼎康联呼叫中心',
+  title: getTitle(),
 
   /**
    * @type {boolean} true | false

+ 102 - 0
src/styles/element-ui.scss

@@ -82,3 +82,105 @@
 .el-range-separator {
   box-sizing: content-box;
 }
+
+/*  -- flex弹性布局 -- */
+
+.flex {
+  display: flex;
+}
+
+.basis-xs {
+  flex-basis: 20%;
+}
+
+.basis-sm {
+  flex-basis: 40%;
+}
+
+.basis-df {
+  flex-basis: 50%;
+}
+
+.basis-lg {
+  flex-basis: 60%;
+}
+
+.basis-xl {
+  flex-basis: 80%;
+}
+
+.flex-sub {
+  flex: 1;
+}
+
+.flex-twice {
+  flex: 2;
+}
+
+.flex-treble {
+  flex: 3;
+}
+
+.flex-direction {
+  flex-direction: column;
+}
+
+.flex-wrap {
+  flex-wrap: wrap;
+}
+
+.align-start {
+  align-items: flex-start;
+}
+
+.align-end {
+  align-items: flex-end;
+}
+
+.align-center {
+  align-items: center;
+}
+
+.align-stretch {
+  align-items: stretch;
+}
+
+.self-start {
+  align-self: flex-start;
+}
+
+.self-center {
+  align-self: flex-center;
+}
+
+.self-end {
+  align-self: flex-end;
+}
+
+.self-stretch {
+  align-self: stretch;
+}
+
+.align-stretch {
+  align-items: stretch;
+}
+
+.justify-start {
+  justify-content: flex-start;
+}
+
+.justify-end {
+  justify-content: flex-end;
+}
+
+.justify-center {
+  justify-content: center;
+}
+
+.justify-between {
+  justify-content: space-between;
+}
+
+.justify-around {
+  justify-content: space-around;
+}

+ 244 - 242
src/utils/AgGridVueLocaleCn.js

@@ -1,267 +1,269 @@
+import i18n from '@/utils/i18n'
+
 export const AG_GRID_LOCALE_CN = {
-    // Set Filter
-    selectAll: '(全选)',
-    selectAllSearchResults: '(选择所有搜索结果)',
-    searchOoo: '搜索...',
-    blanks: '(空格)',
-    noMatches: '无匹配结果',
+  // Set Filter
+  selectAll: i18n.t('action.choiceAll'),
+  selectAllSearchResults: i18n.t('action.choiceAllSearchResults'),
+  searchOoo: i18n.t('action.searchOoo'),
+  blanks: i18n.t('action.blanks'),
+  noMatches: i18n.t('action.noMatches'),
 
-    // Number Filter & Text Filter
-    filterOoo: '筛选值...',
-    equals: '等于',
-    notEqual: '不等于',
-    empty: '请选择一条记录',
+  // Number Filter & Text Filter
+  filterOoo: i18n.t('action.filterOoo'),
+  equals: i18n.t('action.equals'),
+  notEqual: i18n.t('action.notEqual'),
+  empty: i18n.t('action.empty'),
 
-    // Number Filter
-    lessThan: '小于',
-    greaterThan: '大于',
-    lessThanOrEqual: '小于等于',
-    greaterThanOrEqual: '大于等于',
-    inRange: '范围',
-    inRangeStart: '至',
-    inRangeEnd: '从',
+  // Number Filter
+  lessThan: i18n.t('action.lessThan'),
+  greaterThan: i18n.t('action.greaterThan'),
+  lessThanOrEqual: i18n.t('action.lessThanOrEqual'),
+  greaterThanOrEqual: i18n.t('action.greaterThanOrEqual'),
+  inRange: i18n.t('action.inRange'),
+  inRangeStart: i18n.t('action.inRangeStart'),
+  inRangeEnd: i18n.t('action.inRangeEnd'),
 
-    // Text Filter
-    contains: '包含',
-    notContains: '不包含',
-    startsWith: '开始于',
-    endsWith: '结束于',
+  // Text Filter
+  contains: i18n.t('action.contains'),
+  notContains: i18n.t('action.notContains'),
+  startsWith: i18n.t('action.startsWith'),
+  endsWith: i18n.t('action.endsWith'),
 
-    // Date Filter
-    dateFormatOoo: 'yyyy-mm-dd',
+  // Date Filter
+  dateFormatOoo: 'yyyy-mm-dd',
 
-    // Filter Conditions
-    andCondition: '且',
-    orCondition: '或',
+  // Filter Conditions
+  andCondition: i18n.t('action.andCondition'),
+  orCondition: i18n.t('action.orCondition'),
 
-    // Filter Buttons
-    applyFilter: '应用',
-    resetFilter: '重置',
-    clearFilter: '清除',
-    cancelFilter: '取消',
+  // Filter Buttons
+  applyFilter: i18n.t('action.applyFilter'),
+  resetFilter: i18n.t('action.resetFilter'),
+  clearFilter: i18n.t('action.clearFilter'),
+  cancelFilter: i18n.t('action.cancelFilter'),
 
-    // Filter Titles
-    textFilter: '文本筛选',
-    numberFilter: '数字筛选',
-    dateFilter: '日期筛选',
-    setFilter: '列表筛选',
+  // Filter Titles
+  textFilter: i18n.t('action.textFilter'),
+  numberFilter: i18n.t('action.numberFilter'),
+  dateFilter: i18n.t('action.dateFilter'),
+  setFilter: i18n.t('action.setFilter'),
 
-    // Side Bar
-    columns: '列',
-    filters: '筛选器',
+  // Side Bar
+  columns: i18n.t('action.columns'),
+  filters: i18n.t('action.filters'),
 
-    // columns tool panel
-    pivotMode: 'Pivot Mode',
-    groups: 'Row Groups',
-    rowGroupColumnsEmptyMessage: 'Drag here to set row groups',
-    values: 'Values',
-    valueColumnsEmptyMessage: 'Drag here to aggregate',
-    pivots: 'Column Labels',
-    pivotColumnsEmptyMessage: 'Drag here to set column labels',
+  // columns tool panel
+  pivotMode: 'Pivot Mode',
+  groups: 'Row Groups',
+  rowGroupColumnsEmptyMessage: 'Drag here to set row groups',
+  values: 'Values',
+  valueColumnsEmptyMessage: 'Drag here to aggregate',
+  pivots: 'Column Labels',
+  pivotColumnsEmptyMessage: 'Drag here to set column labels',
 
-    // Header of the Default Group Column
-    group: 'Group',
+  // Header of the Default Group Column
+  group: 'Group',
 
-    // Other
-    loadingOoo: '加载中...',
-    noRowsToShow: '无数据显示',
-    enabled: '开启',
+  // Other
+  loadingOoo: i18n.t('action.loadingOoo'),
+  noRowsToShow: i18n.t('action.noRowsToShow'),
+  enabled: i18n.t('action.enabled'),
 
-    // Menu
-    pinColumn: '固定列',
-    pinLeft: '固定到左边',
-    pinRight: '固定到右边',
-    noPin: '不固定',
-    valueAggregation: 'Value Aggregation',
-    autosizeThiscolumn: '自动缩放此列',
-    autosizeAllColumns: '自动缩放所有列',
-    groupBy: '分组',
-    ungroupBy: 'Un-Group by',
-    resetColumns: '重置列设置',
-    expandAll: '展开所有',
-    collapseAll: '收缩所有',
-    copy: '复制',
-    ctrlC: 'Ctrl+C',
-    copyWithHeaders: '连同表头复制',
-    paste: '粘贴',
-    ctrlV: 'Ctrl+V',
-    export: '导出',
-    csvExport: 'CSV Export',
-    excelExport: 'Excel Export (.xlsx)',
-    excelXmlExport: 'Excel Export (.xml)',
+  // Menu
+  pinColumn: i18n.t('action.pinColumn'),
+  pinLeft: i18n.t('action.pinLeft'),
+  pinRight: i18n.t('action.pinRight'),
+  noPin: i18n.t('action.noPin'),
+  valueAggregation: 'Value Aggregation',
+  autosizeThiscolumn: i18n.t('action.autosizeThiscolumn'),
+  autosizeAllColumns: i18n.t('action.autosizeAllColumns'),
+  groupBy: i18n.t('action.groupBy'),
+  ungroupBy: 'Un-Group by',
+  resetColumns: i18n.t('action.resetColumns'),
+  expandAll: i18n.t('action.expandAll'),
+  collapseAll: i18n.t('action.collapseAll'),
+  copy: i18n.t('action.copy'),
+  ctrlC: 'Ctrl+C',
+  copyWithHeaders: i18n.t('action.copyWithHeaders'),
+  paste: i18n.t('action.paste'),
+  ctrlV: 'Ctrl+V',
+  export: i18n.t('action.export'),
+  csvExport: 'CSV Export',
+  excelExport: 'Excel Export (.xlsx)',
+  excelXmlExport: 'Excel Export (.xml)',
 
-    // Enterprise Menu Aggregation and Status Bar
-    sum: 'Sum',
-    min: 'Min',
-    max: 'Max',
-    none: 'None',
-    count: 'Count',
-    avg: 'Average',
-    filteredRows: 'Filtered',
-    selectedRows: 'Selected',
-    totalRows: 'Total Rows',
-    totalAndFilteredRows: 'Rows',
-    more: 'More',
-    to: 'to',
-    of: 'of',
-    page: 'Page',
-    nextPage: 'Next Page',
-    lastPage: 'Last Page',
-    firstPage: 'First Page',
-    previousPage: 'Previous Page',
+  // Enterprise Menu Aggregation and Status Bar
+  sum: 'Sum',
+  min: 'Min',
+  max: 'Max',
+  none: 'None',
+  count: 'Count',
+  avg: 'Average',
+  filteredRows: 'Filtered',
+  selectedRows: 'Selected',
+  totalRows: 'Total Rows',
+  totalAndFilteredRows: 'Rows',
+  more: 'More',
+  to: 'to',
+  of: 'of',
+  page: 'Page',
+  nextPage: 'Next Page',
+  lastPage: 'Last Page',
+  firstPage: 'First Page',
+  previousPage: 'Previous Page',
 
-    // Enterprise Menu (Charts)
-    pivotChartAndPivotMode: 'Pivot Chart & Pivot Mode',
-    pivotChart: 'Pivot Chart',
-    chartRange: 'Chart Range',
+  // Enterprise Menu (Charts)
+  pivotChartAndPivotMode: 'Pivot Chart & Pivot Mode',
+  pivotChart: 'Pivot Chart',
+  chartRange: 'Chart Range',
 
-    columnChart: 'Column',
-    groupedColumn: 'Grouped',
-    stackedColumn: 'Stacked',
-    normalizedColumn: '100% Stacked',
+  columnChart: 'Column',
+  groupedColumn: 'Grouped',
+  stackedColumn: 'Stacked',
+  normalizedColumn: '100% Stacked',
 
-    barChart: 'Bar',
-    groupedBar: 'Grouped',
-    stackedBar: 'Stacked',
-    normalizedBar: '100% Stacked',
+  barChart: 'Bar',
+  groupedBar: 'Grouped',
+  stackedBar: 'Stacked',
+  normalizedBar: '100% Stacked',
 
-    pieChart: 'Pie',
-    pie: 'Pie',
-    doughnut: 'Doughnut',
+  pieChart: 'Pie',
+  pie: 'Pie',
+  doughnut: 'Doughnut',
 
-    line: 'Line',
+  line: 'Line',
 
-    xyChart: 'X Y (Scatter)',
-    scatter: 'Scatter',
-    bubble: 'Bubble',
+  xyChart: 'X Y (Scatter)',
+  scatter: 'Scatter',
+  bubble: 'Bubble',
 
-    areaChart: 'Area',
-    area: 'Area',
-    stackedArea: 'Stacked',
-    normalizedArea: '100% Stacked',
+  areaChart: 'Area',
+  area: 'Area',
+  stackedArea: 'Stacked',
+  normalizedArea: '100% Stacked',
 
-    histogramChart: 'Histogram',
+  histogramChart: 'Histogram',
 
-    // Charts
-    pivotChartTitle: 'Pivot Chart',
-    rangeChartTitle: 'Range Chart',
-    settings: 'Settings',
-    data: 'Data',
-    format: 'Format',
-    categories: 'Categories',
-    defaultCategory: '(None)',
-    series: 'Series',
-    xyValues: 'X Y Values',
-    paired: 'Paired Mode',
-    axis: 'Axis',
-    navigator: 'Navigator',
-    color: 'Color',
-    thickness: 'Thickness',
-    xType: 'X Type',
-    automatic: 'Automatic',
-    category: 'Category',
-    number: 'Number',
-    time: 'Time',
-    xRotation: 'X Rotation',
-    yRotation: 'Y Rotation',
-    ticks: 'Ticks',
-    width: 'Width',
-    height: 'Height',
-    length: 'Length',
-    padding: 'Padding',
-    spacing: 'Spacing',
-    chart: 'Chart',
-    title: 'Title',
-    titlePlaceholder: 'Chart title - double click to edit',
-    background: 'Background',
-    font: 'Font',
-    top: 'Top',
-    right: 'Right',
-    bottom: 'Bottom',
-    left: 'Left',
-    labels: 'Labels',
-    size: 'Size',
-    minSize: 'Minimum Size',
-    maxSize: 'Maximum Size',
-    legend: 'Legend',
-    position: 'Position',
-    markerSize: 'Marker Size',
-    markerStroke: 'Marker Stroke',
-    markerPadding: 'Marker Padding',
-    itemSpacing: 'Item Spacing',
-    itemPaddingX: 'Item Padding X',
-    itemPaddingY: 'Item Padding Y',
-    layoutHorizontalSpacing: 'Horizontal Spacing',
-    layoutVerticalSpacing: 'Vertical Spacing',
-    strokeWidth: 'Stroke Width',
-    offset: 'Offset',
-    offsets: 'Offsets',
-    tooltips: 'Tooltips',
-    callout: 'Callout',
-    markers: 'Markers',
-    shadow: 'Shadow',
-    blur: 'Blur',
-    xOffset: 'X Offset',
-    yOffset: 'Y Offset',
-    lineWidth: 'Line Width',
-    normal: 'Normal',
-    bold: 'Bold',
-    italic: 'Italic',
-    boldItalic: 'Bold Italic',
-    predefined: 'Predefined',
-    fillOpacity: 'Fill Opacity',
-    strokeOpacity: 'Line Opacity',
-    histogramBinCount: 'Bin count',
-    columnGroup: 'Column',
-    barGroup: 'Bar',
-    pieGroup: 'Pie',
-    lineGroup: 'Line',
-    scatterGroup: 'X Y (Scatter)',
-    areaGroup: 'Area',
-    histogramGroup: 'Histogram',
-    groupedColumnTooltip: 'Grouped',
-    stackedColumnTooltip: 'Stacked',
-    normalizedColumnTooltip: '100% Stacked',
-    groupedBarTooltip: 'Grouped',
-    stackedBarTooltip: 'Stacked',
-    normalizedBarTooltip: '100% Stacked',
-    pieTooltip: 'Pie',
-    doughnutTooltip: 'Doughnut',
-    lineTooltip: 'Line',
-    groupedAreaTooltip: 'Area',
-    stackedAreaTooltip: 'Stacked',
-    normalizedAreaTooltip: '100% Stacked',
-    scatterTooltip: 'Scatter',
-    bubbleTooltip: 'Bubble',
-    histogramTooltip: 'Histogram',
-    noDataToChart: 'No data available to be charted.',
-    pivotChartRequiresPivotMode: 'Pivot Chart requires Pivot Mode enabled.',
-    chartSettingsToolbarTooltip: 'Menu',
-    chartLinkToolbarTooltip: 'Linked to Grid',
-    chartUnlinkToolbarTooltip: 'Unlinked from Grid',
-    chartDownloadToolbarTooltip: 'Download Chart',
+  // Charts
+  pivotChartTitle: 'Pivot Chart',
+  rangeChartTitle: 'Range Chart',
+  settings: 'Settings',
+  data: 'Data',
+  format: 'Format',
+  categories: 'Categories',
+  defaultCategory: '(None)',
+  series: 'Series',
+  xyValues: 'X Y Values',
+  paired: 'Paired Mode',
+  axis: 'Axis',
+  navigator: 'Navigator',
+  color: 'Color',
+  thickness: 'Thickness',
+  xType: 'X Type',
+  automatic: 'Automatic',
+  category: 'Category',
+  number: 'Number',
+  time: 'Time',
+  xRotation: 'X Rotation',
+  yRotation: 'Y Rotation',
+  ticks: 'Ticks',
+  width: 'Width',
+  height: 'Height',
+  length: 'Length',
+  padding: 'Padding',
+  spacing: 'Spacing',
+  chart: 'Chart',
+  title: 'Title',
+  titlePlaceholder: 'Chart title - double click to edit',
+  background: 'Background',
+  font: 'Font',
+  top: 'Top',
+  right: 'Right',
+  bottom: 'Bottom',
+  left: 'Left',
+  labels: 'Labels',
+  size: 'Size',
+  minSize: 'Minimum Size',
+  maxSize: 'Maximum Size',
+  legend: 'Legend',
+  position: 'Position',
+  markerSize: 'Marker Size',
+  markerStroke: 'Marker Stroke',
+  markerPadding: 'Marker Padding',
+  itemSpacing: 'Item Spacing',
+  itemPaddingX: 'Item Padding X',
+  itemPaddingY: 'Item Padding Y',
+  layoutHorizontalSpacing: 'Horizontal Spacing',
+  layoutVerticalSpacing: 'Vertical Spacing',
+  strokeWidth: 'Stroke Width',
+  offset: 'Offset',
+  offsets: 'Offsets',
+  tooltips: 'Tooltips',
+  callout: 'Callout',
+  markers: 'Markers',
+  shadow: 'Shadow',
+  blur: 'Blur',
+  xOffset: 'X Offset',
+  yOffset: 'Y Offset',
+  lineWidth: 'Line Width',
+  normal: 'Normal',
+  bold: 'Bold',
+  italic: 'Italic',
+  boldItalic: 'Bold Italic',
+  predefined: 'Predefined',
+  fillOpacity: 'Fill Opacity',
+  strokeOpacity: 'Line Opacity',
+  histogramBinCount: 'Bin count',
+  columnGroup: 'Column',
+  barGroup: 'Bar',
+  pieGroup: 'Pie',
+  lineGroup: 'Line',
+  scatterGroup: 'X Y (Scatter)',
+  areaGroup: 'Area',
+  histogramGroup: 'Histogram',
+  groupedColumnTooltip: 'Grouped',
+  stackedColumnTooltip: 'Stacked',
+  normalizedColumnTooltip: '100% Stacked',
+  groupedBarTooltip: 'Grouped',
+  stackedBarTooltip: 'Stacked',
+  normalizedBarTooltip: '100% Stacked',
+  pieTooltip: 'Pie',
+  doughnutTooltip: 'Doughnut',
+  lineTooltip: 'Line',
+  groupedAreaTooltip: 'Area',
+  stackedAreaTooltip: 'Stacked',
+  normalizedAreaTooltip: '100% Stacked',
+  scatterTooltip: 'Scatter',
+  bubbleTooltip: 'Bubble',
+  histogramTooltip: 'Histogram',
+  noDataToChart: 'No data available to be charted.',
+  pivotChartRequiresPivotMode: 'Pivot Chart requires Pivot Mode enabled.',
+  chartSettingsToolbarTooltip: 'Menu',
+  chartLinkToolbarTooltip: 'Linked to Grid',
+  chartUnlinkToolbarTooltip: 'Unlinked from Grid',
+  chartDownloadToolbarTooltip: 'Download Chart',
 
-    // ARIA
-    ariaHidden: 'hidden',
-    ariaVisible: 'visible',
-    ariaChecked: 'checked',
-    ariaUnchecked: 'unchecked',
-    ariaIndeterminate:'indeterminate',
-    ariaColumnSelectAll: 'Toggle Select All Columns',
-    ariaInputEditor: 'Input Editor',
-    ariaDateFilterInput: 'Date Filter Input',
-    ariaFilterInput: 'Filter Input',
-    ariaFilterColumnsInput: 'Filter Columns Input',
-    ariaFilterValue: 'Filter Value',
-    ariaFilterFromValue: 'Filter from value',
-    ariaFilterToValue: 'Filter to value',
-    ariaFilteringOperator: 'Filtering Operator',
-    ariaColumnToggleVisibility: 'column toggle visibility',
-    ariaColumnGroupToggleVisibility: 'column group toggle visibility',
-    ariaRowSelect: 'Press SPACE to select this row',
-    ariaRowDeselect: 'Press SPACE to deselect this row',
-    ariaRowToggleSelection: 'Press Space to toggle row selection',
-    ariaRowSelectAll: 'Press Space to toggle all rows selection',
-    ariaSearch: 'Search',
-    ariaSearchFilterValues: 'Search filter values'
+  // ARIA
+  ariaHidden: 'hidden',
+  ariaVisible: 'visible',
+  ariaChecked: 'checked',
+  ariaUnchecked: 'unchecked',
+  ariaIndeterminate: 'indeterminate',
+  ariaColumnSelectAll: 'Toggle Select All Columns',
+  ariaInputEditor: 'Input Editor',
+  ariaDateFilterInput: 'Date Filter Input',
+  ariaFilterInput: 'Filter Input',
+  ariaFilterColumnsInput: 'Filter Columns Input',
+  ariaFilterValue: 'Filter Value',
+  ariaFilterFromValue: 'Filter from value',
+  ariaFilterToValue: 'Filter to value',
+  ariaFilteringOperator: 'Filtering Operator',
+  ariaColumnToggleVisibility: 'column toggle visibility',
+  ariaColumnGroupToggleVisibility: 'column group toggle visibility',
+  ariaRowSelect: 'Press SPACE to select this row',
+  ariaRowDeselect: 'Press SPACE to deselect this row',
+  ariaRowToggleSelection: 'Press Space to toggle row selection',
+  ariaRowSelectAll: 'Press Space to toggle all rows selection',
+  ariaSearch: 'Search',
+  ariaSearchFilterValues: 'Search filter values'
 }

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

@@ -0,0 +1,9 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+
+export const ADVICE_STATUS_TYPE = createEnum(
+  {
+    LOSE_EFFICACY: [0, i18n.t('adviceManage.loseEfficacy')],
+    TAKE_EFFECT: [1, i18n.t('adviceManage.takeEffect')]
+  }
+)

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

@@ -0,0 +1,9 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+
+export const ADVICE_TYPE = createEnum(
+  {
+    LONG_TERM: ['LONG_TERM', i18n.t('adviceManage.longTerm')],
+    TEMP: ['TEMP', i18n.t('adviceManage.temp')]
+  }
+)

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

@@ -35,6 +35,11 @@ export const DEVICE_TYPE = createEnum(
     DOOR_LOCK: [30, i18n.t('deviceType.DOOR_LOCK')],
     EMERGENCY_GATEWAY: [31, i18n.t('deviceType.EMERGENCY_GATEWAY')],
     ALARM_433BUTTON: [32, i18n.t('deviceType.ALARM_433BUTTON')],
-    OTHER_HOST: [33, i18n.t('deviceType.OTHER_HOST')]
+    OTHER_HOST: [33, i18n.t('deviceType.OTHER_HOST')],
+    BREASTPLATE: [34, i18n.t('deviceType.BREASTPLATE')],
+    OWON_X5_GATEWAY: [35, i18n.t('deviceType.OWON_X5_GATEWAY')],
+    FALL_DETECTION_RADAR: [36, i18n.t('deviceType.FALL_DETECTION_RADAR')],
+    HUMAN_DETECTION_RADAR: [37, i18n.t('deviceType.HUMAN_DETECTION_RADAR')],
+    ALARM_INFUSION: [38, i18n.t('deviceType.ALARM_INFUSION')]
   }
 )

+ 47 - 0
src/utils/enum/ErrorEnum.js

@@ -0,0 +1,47 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+
+export const ERROR_TYPE = createEnum(
+  {
+    TOKEN_FAILED: [8, i18n.t('errorType.TOKEN_FAILED')],
+    USER_NULL: [9, i18n.t('errorType.USER_NULL')],
+    USER_DISABLE: [10, i18n.t('errorType.USER_DISABLE')],
+    PASSWORD_ERROR: [11, i18n.t('errorType.PASSWORD_ERROR')],
+    LOGIN_FAILED: [12, i18n.t('errorType.LOGIN_FAILED')],
+    LOGOUT: [13, i18n.t('errorType.LOGOUT')],
+    MEMBER_NULL: [14, i18n.t('errorType.MEMBER_NULL')],
+    MEMBER_ADD_FAILED: [15, i18n.t('errorType.MEMBER_ADD_FAILED')],
+    MEMBER_FAILED: [16, i18n.t('errorType.MEMBER_FAILED')],
+    MOBILE_OCCUPY: [17, i18n.t('errorType.MOBILE_OCCUPY')],
+    MEMBER_NAME_OCCUPY: [18, i18n.t('errorType.MEMBER_NAME_OCCUPY')],
+    CHANNEL_FAILED: [19, i18n.t('errorType.CHANNEL_FAILED')],
+    CHANNEL_SUBSCRIBE_MEMBER_NULL: [20, i18n.t('errorType.CHANNEL_SUBSCRIBE_MEMBER_NULL')],
+    CHANNEL_MEMBER_FAILED: [21, i18n.t('errorType.CHANNEL_MEMBER_FAILED')],
+    CHANNEL_NULL: [22, i18n.t('errorType.CHANNEL_NULL')],
+    FRAME_HOSPITAL_NULL: [23, i18n.t('errorType.FRAME_HOSPITAL_NULL')],
+    FRAME_PART_NULL: [24, i18n.t('errorType.FRAME_PART_NULL')],
+    FRAME_ADD_FAILED: [25, i18n.t('errorType.FRAME_ADD_FAILED')],
+    CUSTOMER_INFO_NULL: [28, i18n.t('errorType.CUSTOMER_INFO_NULL')],
+    CLOUD_ADDRESS_NULL: [29, i18n.t('errorType.CLOUD_ADDRESS_NULL')],
+    CLOUD_SAVE_FAILED: [30, i18n.t('errorType.CLOUD_SAVE_FAILED')],
+    SHOP_NULL: [31, i18n.t('errorType.SHOP_NULL')],
+    SHOP_DAYTIME_ERROR: [32, i18n.t('errorType.SHOP_DAYTIME_ERROR')],
+    SHOP_NIGHTTIME_ERROR: [33, i18n.t('errorType.SHOP_NIGHTTIME_ERROR')],
+    ADMIN_PASSWORD_ERROR: [34, i18n.t('errorType.ADMIN_PASSWORD_ERROR')],
+    DEVICE_MAC_REPEAT: [35, i18n.t('errorType.DEVICE_MAC_REPEAT')],
+    DEVICE_ADD_FAILED: [36, i18n.t('errorType.DEVICE_ADD_FAILED')],
+    DEVICE_FRAME_FAILED: [37, i18n.t('errorType.DEVICE_FRAME_FAILED')],
+    DATA_NULL: [38, i18n.t('errorType.DATA_NULL')],
+    PARAM_ERROR: [39, i18n.t('errorType.PARAM_ERROR')],
+    PRIMARY_KEY_NULL: [40, i18n.t('errorType.PRIMARY_KEY_NULL')],
+    ROLE_NULL: [41, i18n.t('errorType.ROLE_NULL')],
+    ROLE_NAME_OCCUPY: [42, i18n.t('errorType.ROLE_NAME_OCCUPY')],
+    ROLE_DELETE_FAILED: [43, i18n.t('errorType.ROLE_DELETE_FAILED')],
+    LICENSE_ERROR: [44, i18n.t('errorType.LICENSE_ERROR')],
+    LICENSE_EXPIRE: [45, i18n.t('errorType.LICENSE_EXPIRE')],
+    LICENSE_FAILED: [46, i18n.t('errorType.LICENSE_FAILED')],
+    FILE_UPLOAD_FAILED: [47, i18n.t('errorType.FILE_UPLOAD_FAILED')],
+    FILE_FAILED: [48, i18n.t('errorType.FILE_FAILED')]
+  }
+)
+

+ 2 - 0
src/utils/enum/RelativeNameTypeEnum

@@ -4,6 +4,8 @@ import i18n from '@/utils/i18n'
 export const RELATIVE_NAME_TYPE = createEnum(
     {
         CHILDREN: [ '孩子', i18n.t('relativeNameType.CHILDREN') ],
+        BOY: [ '男孩', i18n.t('relativeNameType.BOY') ],
+        GIRL: [ '女孩', i18n.t('relativeNameType.GIRL') ],
         HUSBAND: [ '丈夫', i18n.t('relativeNameType.HUSBAND') ],
         WIFE: [ '妻子', i18n.t('relativeNameType.WIFE') ],
         FATHER: [ '父亲', i18n.t('relativeNameType.FATHER') ],

+ 5 - 1
src/utils/i18n.js

@@ -1,6 +1,8 @@
 import Vue from 'vue'
 import enLang from 'element-ui/lib/locale/lang/en'// 如果使用中文语言包请默认支持,无需额外引入,请删除该依赖
+import esLang from 'element-ui/lib/locale/lang/es'
 import zhLang from 'element-ui/lib/locale/lang/zh-CN'
+import ruLang from 'element-ui/lib/locale/lang/ru-RU'
 import VueI18n from 'vue-i18n'
 import locale from 'element-ui/lib/locale'
 import Storage from '@/utils/storage'
@@ -13,7 +15,9 @@ const i18n = new VueI18n({
   // 添加多语言(每一个语言标示对应一个语言文件)
   messages: {
     'zh': Object.assign(require('../../languages/zh-CN'), zhLang),
-    'en': Object.assign(require('../../languages/en'), enLang)
+    'en': Object.assign(require('../../languages/en'), enLang),
+    'es': Object.assign(require('../../languages/es'), esLang),
+    'ru': Object.assign(require('../../languages/ru-RU'), ruLang)
   }
 })
 locale.i18n((key, value) => i18n.t(key, value))

+ 5 - 2
src/utils/mixin.js

@@ -35,9 +35,10 @@ export default {
           picker.$emit('pick', [start, end])
         }
       }],
-      mainAreaHeight: Number(document.documentElement.clientHeight) - 84
+      mainAreaHeight:Number(document.documentElement.clientHeight) - 84
     }
   },
+
   computed: {
     /**
      * 缓存页面数组
@@ -46,6 +47,7 @@ export default {
     cachedViews() {
       return this.$store.state.tagsView.cachedViews
     },
+
     /**
      * 返回默认时间 + 5分钟
      * 用于日期时间选择器的默认时间
@@ -64,8 +66,9 @@ export default {
     }
   },
   methods: {
-    /** 返回克隆后的对象 */
 
+
+    /** 返回克隆后的对象 */
     MixinClone(obj) {
       return JSON.parse(JSON.stringify(obj))
     },

+ 12 - 3
src/utils/request.js

@@ -8,6 +8,7 @@ import Storage from '@/utils/storage'
 import * as Foundation from '@/utils/Foundation'
 import md5 from 'js-md5'
 import checkToken from '@/utils/checkToken'
+import { ERROR_TYPE } from '@/utils/enum/ErrorEnum'
 const qs = require('qs')
 // create an axios instance
 const serverUrl = domain.serverUrl
@@ -15,13 +16,13 @@ const apiMode = domain.apiMode
 const service = axios.create({
   baseURL: serverUrl, // url = base url + request url
   // withCredentials: true, // send cookies when cross-domain requests
-  timeout: 5000, // request timeout
+  timeout: 30000, // request timeout
   paramsSerializer: params => qs.stringify(params, { arryFormat: 'repeat' })
 })
 
 export const mediaRequest = axios.create({
   baseURL: domain.mediaUrl,
-  timeout: 5000,
+  timeout: 30000,
   headers: {
     'Content-Type': 'application/json;charset=UTF-8'
   },
@@ -147,7 +148,7 @@ service.interceptors.response.use(
     }
 
     Message({
-      message: error_data.message,
+      message: getErrorMgs(error_data.message),
       type: 'error',
       duration: 5 * 1000
     })
@@ -155,6 +156,14 @@ service.interceptors.response.use(
   }
 )
 
+function getErrorMgs(msg) {
+  if (ERROR_TYPE.getDesc(msg) !== undefined) {
+    return ERROR_TYPE.getDesc(msg)
+  } else {
+    return msg
+  }
+}
+
 /**
  * 关闭全局加载
  * 延迟200毫秒关闭,以免晃眼睛

+ 426 - 0
src/views/custom-infoboard/board-title.vue

@@ -0,0 +1,426 @@
+<template>
+    <div>
+        <ag-grid-layout
+                toolbar
+                :table-height="tableHeight"
+                theme="ag-theme-alpine"
+                :column-defs="columnDefs"
+                :row-data="rowData"
+                :locale-text="localeText"
+                :grid-options="gridOptions"
+                :default-col-def="defaultColDef"
+                :animate-rows="true"
+                :row-selection="rowSelection"
+                :enable-cell-change-flash="true"
+                @filterChanged="filterModifed"
+                @sortChanged="gridSortChange"
+        >
+            <!--        @rowDoubleClicked="getList"-->
+            <div slot="toolbar" class="inner-toolbar">
+                <div class="toolbar-search">
+                    <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
+                </div>
+                <div class="toolbar-btns">
+                    <el-button type="primary" size="mini" @click="createChannel">{{ this.$t('boardTitle.add') }}</el-button>
+                </div>
+            </div>
+            <el-pagination
+                    v-if="pageData"
+                    slot="pagination"
+                    :current-page="pageData.page_no"
+                    :page-sizes="[10, 20, 50, 100]"
+                    :page-size="pageData.page_size"
+                    layout="total, sizes, prev, pager, next, jumper"
+                    :total="pageData.data_total"
+                    @size-change="handlePageSizeChange"
+                    @current-change="handlePageCurrentChange"
+            />
+        </ag-grid-layout>
+        <el-dialog :title.sync="formtitle" :visible.sync="formshow" width="35%">
+            <div>
+                <el-form ref="editform" :rules="rules" label-width="120px" :model="formmodel">
+
+                    <el-row>
+                        <el-col :span="24">
+                            <el-form-item :label="this.$t('boardTitle.screenTitle')" prop="board_title">
+                                <el-input
+                                        v-model="formmodel.board_title"
+                                        clearable
+                                        :maxlength="100"
+                                        :placeholder="this.$t('boardTitle.screenTitle')"
+                                />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="12">
+                            <el-form-item :label="this.$t('boardTitle.showIndex')" prop="board_index">
+                                <el-input-number v-model="formmodel.board_index" :min="3" :max="100" :label="this.$t('boardTitle.showIndex')" />
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                </el-form>
+
+            </div>
+            <div slot="footer" class="dialog-footer">
+                <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>
+
+</template>
+
+<script>
+    import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
+    import ButtonCellRender from '../../components/AgGridCellRender/ButtonCellRender'
+    import * as API_BoardTitle from '@/api/ncs_board_title'
+    import { unix2Date } from '@/utils/Foundation'
+    import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
+    import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
+    import ButtonCellRenderList from "@/components/AgGridCellRender/ButtonCellRenderList";
+
+    export default {
+        name: "board-title",
+        components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter },
+        data() {
+            return {
+                tableData: [],
+                /** 列表参数 */
+                params: {
+                    page_size: 20,
+                    page_no: 1,
+                    fixedCondition: ' part_id = ' + this.$store.getters.partId
+                },
+                /** 新建组织弹出参数 **/
+                formtitle: this.$t('boardTitle.createTitle'),
+                formshow: false,
+                /** 频道订阅设置 */
+                formSubscribe: false,
+                formmodel: {},
+                frameGroups: [],
+                rules: {
+                    board_title: [
+                        { required: true, message: this.$t('boardTitle.titleRequire'), trigger: 'blur' }
+                    ]
+                },
+                /** ag-grid参数 **/
+                pageData: [],
+                loading: false,
+                errorId: null,
+                shopVisible: false,
+                columnDefs: null,
+                rowData: null,
+                defaultColDef: null,
+                gridOptions: null,
+                gridApi: null,
+                columnApi: null,
+                localeText: AG_GRID_LOCALE_CN,
+                filterState: null,
+                rowSelection: null,
+                frameworkComponents: null,
+                /** 频道订阅者情况数组 */
+                channelSubscribers: [],
+                subscribeTitle: '',
+                choiceAll: this.$t('action.choiceAll')
+            }
+        },
+        computed: {
+            tableHeight() {
+                return this.mainAreaHeight - 130
+            }
+
+        },
+        beforeMount() {
+            this.gridOptions = {}
+            this.columnDefs = [
+                {
+                    headerName: '#',
+                    headerCheckboxSelection: true,
+                    headerCheckboxSelectionFilteredOnly: true,
+                    checkboxSelection: true,
+                    sortable: false, filter: false,
+                    width: 100,
+                    resizable: false,
+                    valueGetter: this.hashValueGetter
+                },
+                { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 130 },
+                {
+                    headerName: this.$t('boardTitle.screenTitle'), field: 'board_title', sortable: true, filter: 'agTextColumnFilter', flex: 1
+                },
+                {
+                    headerName: this.$t('boardTitle.showIndex'), field: 'board_index', sortable: true, filter: 'agNumberColumnFilter', flex: 1
+                },
+                {
+                    headerName: this.$t('boardTitle.partId'), field: 'part_id', sortable: true, filter: 'agNumberColumnFilter', flex: 1
+                },
+
+                // lockPosition 锁定位置,会在第一列
+                // lockPinned = true 不能拖动然后固定
+                // resizeable 单元个大小是否可以调整
+                { headerName: this.$t('action.handle'), field: 'id',
+                    cellRendererFramework: 'ButtonCellRenderList',
+                    cellRendererParams: param => {
+                        return {
+                            list: [
+                                {
+                                    onClick: this.handEdit,
+                                    label: this.$t('action.edit'),
+                                    buttonType: 'primary',
+                                    buttonSize: 'mini'
+                                },
+                                {
+                                    onClick: this.deleteSingle,
+                                    label: this.$t('action.delete'),
+                                    buttonType: 'danger',
+                                    buttonSize: 'mini',
+                                },
+                                {
+                                    onClick: this.toDesigner,
+                                    label: this.$t('boardTitle.design'),
+                                    buttonType: 'warning',
+                                    buttonSize: 'mini',
+                                }
+
+                            ]}
+                    },
+                    filter: false,
+                    pinned: 'right',
+                    lockPinned: true,
+                    minWidth: this.$i18n.locale === 'zh' ? 310 : 350,
+                    resizable: false,
+                    sortable: false
+                }
+
+            ]
+            this.defaultColDef = {
+                sortable: true,
+                resizable: true,
+                comparator: this.dateCustomComparator,
+                filterParams: {
+                    debounceMs: 200,
+                    newRowsAction: 'keep',
+                    textCustomComparator: this.textCustomComparator,
+                    comparator: this.dateCustomComparator
+                }
+            }
+            this.rowSelection = 'multiple'
+        },
+        mounted() {
+            window.onresize = this.windowResize
+            this.gridApi = this.gridOptions.api
+            this.gridColumnApi = this.gridOptions.columnApi
+            // 设置默认排序字段,应用列状态之后会触发 gridSortChange 函数,会调用getlist,后面不需要再调用this.getlist
+            this.gridColumnApi.applyColumnState({
+                state: [
+                    {
+                        colId: 'id',
+                        sort: 'asc'
+                    }
+                ]
+            })
+
+        },
+        methods: {
+            windowResize() {
+                this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+            },
+            handlerDelete(ids) {
+                this.$confirm(this.$t('action.sureDelete'), this.$t('action.waring'), {
+                    confirmButtonText: this.$t('action.yes'),
+                    cancelButtonText: this.$t('action.cancel'),
+                    type: 'warning'
+                }).then(() => {
+                    API_BoardTitle.remove(ids).then(
+                        response => {
+                            this.getList()
+                            this.$message({
+                                type: 'success',
+                                message: this.$t('action.deleted')
+                            })
+                        }
+                    ).catch(response => {
+                        this.$message({
+                            type: 'info',
+                            message: response.message
+                        })
+                    })
+                }).catch(() => {
+                    this.$message({
+                        type: 'info',
+                        message: this.$t('action.cancelDelete')
+                    })
+                })
+            },
+            deleteSingle(row) {
+                this.handlerDelete(row.id)
+            },
+
+            /**
+             * 创建频道
+             */
+            createChannel() {
+                this.formshow = true
+                this.formmodel = {
+                    channel_name: '',
+                    part_id: this.$store.getters.partId
+                }
+            },
+            /** 分页大小发生改变 */
+            handlePageSizeChange(size) {
+                this.params.page_size = size
+                this.getList()
+            },
+
+            /** 分页页数发生改变 */
+            handlePageCurrentChange(page) {
+                this.params.page_no = page
+                this.getList()
+            },
+            /** 加载列表数据 */
+            getList() {
+                this.loading = true
+                const param = this.MixinClone(this.params)
+                this.gridApi.showLoadingOverlay()
+                API_BoardTitle.getList(param).then(response => {
+                    this.loading = false
+                    // this.tableData = [...response.data]
+                    this.pageData = {
+                        page_no: response.page_no,
+                        page_size: response.page_size,
+                        data_total: response.data_total
+                    }
+                    this.$nextTick(() => {
+                        const node = this.gridApi.getDisplayedRowAtIndex(0)
+                        if (node !== null && node !== undefined) {
+                            node.setSelected(true)
+                        }
+                    })
+                    this.rowData = [...response.data]
+                    this.refreshPlayStatus()
+                }).catch(() => {
+                    this.loading = false
+                })
+            },
+            /** 处理搜索 */
+            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()
+            },
+            /**
+             * 格式化unix时间戳
+             **/
+            unixDateFormatter(param) {
+                if (!param.value) return ''
+                return unix2Date(param.value * 1000)
+            },
+
+            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()
+            },
+
+            filterModifed(param) { // todo 通过转换后的数值过滤,需要转回原始数值
+                var model = param.api.getFilterModel()
+                this.params.filter = JSON.stringify(model)
+                this.getList()
+            },
+
+            handEdit(row) {
+                this.formtitle=this.$t('boardTitle.editTitle')
+                this.formmodel = {
+                    ...row
+                }
+                this.formshow = true
+            },
+            /**
+             * 提交新增表单
+             * @param formname
+             */
+            handlerFormSubmit(formName) {
+                this.$refs[formName].validate((valid) => {
+                    if (valid) {
+                        if (!this.formmodel.id) {
+                            /** 新增 */
+                            this.formmodel.part_id = this.$store.getters.partId
+
+                            API_BoardTitle.add(this.formmodel).then(() => {
+                                this.formshow = false
+                                this.$message.success(this.$t('action.addSuccess'))
+                                this.getList()
+                            })
+                        } else {
+                            API_BoardTitle.update(this.formmodel.id, this.formmodel).then(() => {
+                                this.formshow = false
+                                this.$message.success(this.$t('action.editSuccess'))
+                                this.getList()
+                            })
+                        }
+                    } else {
+                        this.$message.error(this.$t('action.fromError'))
+                    }
+                })
+            },
+
+            handlerSubscribeSubmit() {
+                let subscribeIds = []
+                this.channelSubscribers.forEach(item => {
+                    subscribeIds = [...item.clerks.filter(p => p.checked).map(p => p.member_id), ...subscribeIds]
+                })
+                API_BoardTitle.setChannelSubscribers({ channel_id: this.formmodel.id, member_ids: subscribeIds.length === 0 ? null : [...subscribeIds] }).then(() => {
+                    this.formSubscribe = false
+                    this.$message.success(this.$t('action.editSuccess'))
+                })
+            },
+
+            toDesigner(row) {
+                this.$router.push({ name: 'BoardDesigner', params: { id:row.id }})
+            }
+
+
+        }
+    }
+
+</script>
+
+<style scoped>
+
+</style>

+ 69 - 0
src/views/custom-infoboard/mixin.js

@@ -0,0 +1,69 @@
+import layoutItem from './templates/layout-item'
+export default {
+    props: {
+        /** 数据 */
+        data: {
+            type: Object,
+            default: () => ({})
+        },
+        /** 是否为编辑模式 */
+        isEdit: {
+            type: Boolean,
+            default: false
+        }
+    },
+    components: {
+        layoutItem
+    },
+    methods: {
+        /** 获取颜色相关信息 */
+        colors(columnIndex = 0) {
+            const _colors = this.data.columnList[columnIndex].titleColors
+            return {
+                title: `background-color: ${_colors[0]}; background-image: linear-gradient(90deg, ${_colors.join(',')});`,
+                color: (colorIndex = 0) => `color: ${_colors[colorIndex]}`
+            }
+        },
+        /** 获取区块链接 */
+        blockHref(block) {
+            const { opt_type, opt_value } = block.block_opt
+            switch (opt_type) {
+                // 链接地址
+                case 'URL': return opt_value
+                // 商品
+                case 'GOODS': return `/goods/${opt_value}`
+                // 关键字
+                case 'KEYWORD': return `/goods?keyword=${encodeURIComponent(opt_value)}`
+                // 店铺
+                case 'SHOP': return `/shop/${opt_value}`
+                // 分类
+                case 'CATEGORY': return `/goods?category=${opt_value}`
+                default: return '/'
+            }
+        },
+        /** 构建空的block */
+        emptyBlock(num = 3, type) {
+            return [...new Array(num)].map(() => ({
+                block_type: type,
+                block_value: '',
+                block_opt: {
+                    opt_type: 'NONE',
+                    opt_value: ''
+                }
+            }))
+        },
+        /** 编辑区块 */
+        handleEditBlock(columnIndex, blockIndex) {
+            console.log(JSON.stringify(this.data))
+            this.$emit('edit-block', JSON.parse(JSON.stringify(this.data)), columnIndex, blockIndex)
+        },
+        /** 编辑标题 */
+        handleEditTitle(columnIndex) {
+            this.$emit('edit-title', JSON.parse(JSON.stringify(this.data)), columnIndex)
+        },
+        /** 编辑标签 */
+        handleEditTags(columnIndex) {
+            this.$emit('edit-tags', JSON.parse(JSON.stringify(this.data)), columnIndex)
+        }
+    }
+}

+ 459 - 0
src/views/custom-infoboard/screen-designer.vue

@@ -0,0 +1,459 @@
+<template>
+    <div class="container">
+        <el-header class="bg-blue" style="width: 1210px;margin:0 auto;">
+            <!--        <el-image :src="logo" style="width: 50px; height: 50px" fit="fill" />-->
+            <el-row>
+                <el-col :span="8">
+                    <div class="title text-shadow text-white text-left " style="font-size: 26px;overflow: hidden;text-overflow: ellipsis;width: 100%;height:60px;">{{ partInfo.full_name }} {{ partInfo.part_name }}</div>
+                </el-col>
+                <el-col :span="8">
+                    <div class="content_title" data-aos="zoom-in-up">{{ titleData.board_title }}</div>
+                </el-col>
+                <el-col :span="8" >
+                    <div class="time text-right" style="font-size: 26px">{{ currentTime }}</div>
+                </el-col>
+            </el-row>
+        </el-header>
+        <div class="floor-container" :style="{height:floorContainerHeight+'px' }">
+
+            <div class="tpl-box" :style="tplBoxStyle">
+                <draggable v-model="templateArray" :options="tplOptions" class="tpl-list">
+                    <div v-for="item in templateArray" :class="'item-' + item.tpl_id" class="tpl-item">
+                        <el-row>
+                            <el-col :span="24/item.tpl_id" v-for="size in item.tpl_id" :key="size" class="grid-content" :class="'bg-purple-'+size"></el-col>
+                        </el-row>
+                        <span class="text-tpl">{{ templates[item.tpl_id].title }}</span>
+                    </div>
+                </draggable>
+                <el-button type="primary" @click="handleSaveFloor" class="save-btn">保存发布</el-button>
+                <div class="tpl-btns">
+                    <div class="btn-item" @click="tplBoxShow = !tplBoxShow">
+                        <i v-if="tplBoxShow" class="el-icon-d-arrow-left"></i>
+                        <i v-else class="el-icon-d-arrow-right"></i>
+                    </div>
+                    <div style="border-top: 1px dashed #ccc;margin: 2px 0"></div>
+                    <el-tooltip class="item" effect="dark" content="快捷保存" placement="right">
+                        <div class="btn-item" @click="handleSaveFloor">
+                            <i class="el-icon-upload"></i>
+                        </div>
+                    </el-tooltip>
+                </div>
+            </div>
+
+            <div class="draggable-box floor">
+                <div class="floor-body">
+                    <draggable v-model="floorList" :options="floorOptions" class="floor-list">
+                        <div v-for="(item, index) in floorList" :class="'item-' + item.tpl_id" class="floor-item">
+                            <component
+                                    :is="templates[item.tpl_id]"
+                                    :data="JSON.parse(JSON.stringify(item))"
+                                    is-edit
+                                    @edit-block="(...props) => {  handleEditBlock(index, ...props) }"
+                                    @edit-title="(...props) => { handleEditTitle(index, ...props) }"
+                                    @edit-tags="(...props) => { handleEditTags(index, ...props) }"
+                            ></component>
+                            <div class="panel-handle">
+                                <span class="icon-handle handle-move"><svg-icon icon-class="drag"/></span>
+                                <span class="icon-handle handle-setting" @click="() => { handleModule(index, JSON.parse(JSON.stringify(item))) }"><svg-icon icon-class="setting"/></span>
+                                <span class="icon-handle handle-delete" @click="floorList.splice(index, 1)"><svg-icon icon-class="delete"/></span>
+                            </div>
+                        </div>
+                    </draggable>
+                </div>
+
+            </div>
+
+        </div>
+
+        <board-item-setting
+        :default-data="boardItemConfig"
+        :show="settingShow"
+        :board-items="boardItems"
+        @close="settingShow=false"
+        @confirm="handleBoardItemSet"
+        ></board-item-setting>
+
+        <board-module-setting
+                :default-data="boardModuleConfig"
+                :show="moduleSettingShow"
+                @close="moduleSettingShow=false"
+                @confirm="handleBoardModuleSet"
+        >
+
+        </board-module-setting>
+    </div>
+</template>
+
+<script>
+    import Vue from 'vue'
+    import draggable from 'vuedraggable'
+    import templates, { templateArray } from './templates'
+    import VueLazyload from 'vue-lazyload'
+    import BoardItemSetting from "./templates/board-item-setting";
+    import BoardModuleSetting from "./templates/board-module-setting";
+    import * as API_BoardTitle from '@/api/ncs_board_title'
+    import * as API_BoardItem from '@/api/ncs_board_item'
+    Vue.use(VueLazyload)
+    import moment from 'moment'
+    require('moment/locale/zh-cn')
+    export default {
+        name: "screen-designer",
+        components: {BoardModuleSetting, BoardItemSetting, draggable },
+        data(){
+            return{
+                currentTime: '',
+                templates,
+                templateArray,
+                boardItemConfig:{},
+                boardModuleConfig:{},
+                settingShow:false,
+                moduleSettingShow:false,
+                //看板标题
+                titleData:{},
+                //标题id
+                titleId:this.$route.params.id,
+                /** 模板列表 */
+                tplList: [],
+                /** 模板配置 */
+                tplOptions: {
+                    group: { name: 'tplGroup', pull: 'clone', put: false },
+                    sort: false
+                },
+                tplBoxShow:true,
+                /** 楼层列表 */
+                floorList: [],
+                /** 楼层配置 */
+                floorOptions: {
+                    animation: 150,
+                    group: { name: 'tplGroup', put: true },
+                    sort: true,
+                    handle: '.handle-move'
+                },
+                boardItems:[{
+                    area_content: "2,5,7",
+                    area_content_style: "color:green;",
+                    area_label: "今日出院",
+                    area_label_style: "color:red;",
+                    area_size: 1,
+                    his_board_title_keyval: "1",
+                    his_keyval: "1",
+                    his_part_keyval: "1"
+                }]
+
+            }
+        },
+        computed: {
+            // 楼层模板盒子样式
+            tplBoxStyle() {
+                const { sidebar } = this.$store.getters
+                let left = (sidebar.opened ? 210 : 60)
+                left = this.tplBoxShow ? left : left - 300
+                return {
+                    left: left + 'px'
+                }
+            },
+            floorContainerHeight() {
+                return  this.mainAreaHeight-60
+            },
+            partInfo() {
+                return this.$store.getters.organization
+            }
+        },
+        beforeRouteUpdate(to, from, next) {
+            this.titleId = to.params.id
+            next()
+        },
+        activated() {
+            this.titleId = this.$route.params.id
+        },
+       async mounted(){
+           this.boardItems = await API_BoardItem.getPartList(this.$store.getters.partId)
+            moment.locale()
+            this.currentTime = moment().format('YYYY-MM-DD HH:mm:ss dddd')
+            this.getBoardTitle()
+
+        },
+        methods:{
+            /** 保存发布 */
+            handleSaveFloor() {
+                this.titleData.content_config= JSON.stringify(this.floorList)
+                API_BoardTitle.update(this.titleData.id, this.titleData).then(() => this.$message.success('保存发布成功!'))
+            },
+
+            handleBoardItemSet(settingData){
+              console.log(settingData)
+                const { index, target, columnIndex } = this.editOptions
+                const blockData = {...settingData}
+                target.columnList[columnIndex]=blockData
+                this.$set(this.floorList, index, target)
+            },
+            handleBoardModuleSet(settingData){
+                const { index, blockdata } = this.editOptions
+                const moduleSetting = {...settingData}
+                blockdata.moduleStyle=moduleSetting
+                this.$set(this.floorList, index, blockdata)
+            },
+
+            /** 编辑楼层区块 */
+            handleEditBlock(index, target, columnIndex) {
+
+                const blockData = target.columnList[columnIndex]
+
+                this.settingShow=true
+                this.boardItemConfig = {...blockData}
+                // const block = target.columnList[columnIndex].blockList[blockIndex]
+                // const type = block.block_type
+                 this.editOptions = { index, target, columnIndex }
+                // const blockData = JSON.parse(JSON.stringify(block))
+                // if (type === 'IMAGE') {
+                //     this.defaultImageData = blockData.block_value ? [{
+                //         url: blockData.block_value,
+                //         opt: blockData.block_opt
+                //     }] : null
+                //     this.dialogImageShow = true
+                // } else if (type === 'GOODS') {
+                //     // 填充默认数据
+                //     // this.defaultGoodsData = blockData.block_value ? [blockData.block_value.goods_id] : []
+                //     // this.dialogGoodsShow = true
+                // } else if (type === 'BRAND') {
+                //     console.log('品牌模块')
+                // }
+            },
+
+            handleModule(index,blockdata){
+               this.boardModuleConfig = {...blockdata.moduleStyle}
+                this.editOptions = { index, blockdata }
+                this.moduleSettingShow=true
+              console.log(index,blockdata)
+            },
+
+            /** 编辑楼层标题 */
+            handleEditTitle(index, target, columnIndex) {
+                this.editOptions = { index, target, columnIndex }
+                const column = target.columnList[columnIndex]
+                const columnData = JSON.parse(JSON.stringify(column))
+                this.defaultTitleData = {
+                    text: column.title,
+                    start_color: column.titleColors[0],
+                    end_color: column.titleColors[1]
+                }
+                this.dialogTitleShow = true
+            },
+            /** 编辑楼层标签 */
+            handleEditTags(index, target, columnIndex) {
+                this.editOptions = { index, target, columnIndex }
+                const column = target.columnList[columnIndex]
+                const columnData = JSON.parse(JSON.stringify(column))
+                this.defaultTagsData = columnData.tagList
+                this.dialogTagsShow = true
+            },
+            getBoardTitle(){
+                API_BoardTitle.get(this.titleId,{}).then(
+                    res=>{
+                        console.log('res',res)
+                     this.titleData={...res}
+                     if(res.content_config!==null&&res.content_config!==''){
+                         this.floorList=JSON.parse(res.content_config)
+                         this.floorList.forEach(item=>{
+                             item.columnList.forEach(col=>{
+                                 if(col.boardItemHisKeyVal!==''){
+                                     console.log('col', this.boardItems)
+                                     const boardItem = this.boardItems.filter(p=>p.his_keyval===col.boardItemHisKeyVal)[0]
+                                     console.log('boardItem',boardItem)
+                                     if(boardItem!==null&&boardItem!==undefined){
+                                         col.content=boardItem.area_content
+                                         col.label=boardItem.area_label
+                                     }
+                                 }
+                             })
+                         })
+                     }else{
+                         this.floorList=[]
+                     }
+                    }
+                ).catch(error=>{
+                  this.$message.error(error.message)
+                })
+            }
+
+        }
+    }
+</script>
+
+<style scoped type="text/scss">
+    .container {
+        min-width: 1366px;
+    }
+    .floor-container {
+        display: flex;
+        justify-content: space-around;
+        background-color: #E5E7EA;
+        padding: 10px;
+    }
+    .draggable-box {
+        position: relative;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-direction: column;
+        width: 80%;
+
+    }
+    .draggable-box .floor {
+        width: 1210px + 50px;
+        flex-shrink: 0;
+        align-items: center;
+    }
+    .tpl-list {
+        display: flex;
+        flex-wrap: wrap;
+        overflow: hidden;
+        width: 100%;
+        background-color: #fff;
+    }
+    .tpl-item {
+        display: flex;
+        width: 100%;
+        flex-direction: column;
+        justify-content: center;
+        box-sizing: border-box;
+        border-bottom: 2px solid #D9E0E7;
+        margin-bottom: 10px;
+        /*&.item-1 .img-tpl {*/
+        /*    background: url("../../../assets/pc-tpl-01.png") no-repeat;*/
+        /*    background-size: 100%;*/
+        /*}*/
+        /*&.item-2 .img-tpl {*/
+        /*    background: url("../../../assets/pc-tpl-02.png") no-repeat;*/
+        /*    background-size: 100%;*/
+        /*}*/
+        /*&.item-3 .img-tpl {*/
+        /*    background: url("../../../assets/pc-tpl-03.png") no-repeat;*/
+        /*    background-size: 100%;*/
+        /*}*/
+        /*&.item-4 .img-tpl {*/
+        /*    background: url("../../../assets/pc-tpl-04.png") no-repeat;*/
+        /*    background-size: 100%;*/
+        /*}*/
+    }
+    .img-tpl {
+        width: 100%;
+        min-height: 150px;
+    }
+    .text-tpl {
+        text-align: center;
+        margin: 5px 0;
+        color: #ACB0B9;
+        font-size: 12px;
+    }
+    .floor-body {
+        display: flex;
+        justify-content: center;
+        width: 100%;
+        height: 100%;
+        overflow-y: scroll;
+    }
+    .floor-list {
+        background-color: #E5E7EA;
+        min-width: 75%;
+        min-height: 500px;
+    }
+    .floor-item {
+        position: relative;
+        box-sizing: border-box;
+
+    }
+
+
+    .floor-item .panel-handle {
+        display: none;
+        position: absolute;
+        top: 0;
+        right: -25px;
+
+    }
+    .floor-item .panel-handle .icon-handle {
+        display: block;
+        cursor: pointer;
+        text-align: center;
+    }
+    .floor-item .panel-handle .svg-icon {
+        width: 25px;
+        height: 25px;
+        background-color: #fff;
+    }
+    .floor-item:hover .panel-handle{
+        display: block;
+    }
+    .floor-item:first-child .floor-layout {
+        margin-top: 0;
+    }
+    .tpl-box {
+        position: fixed;
+        top: 20%;
+        left: 180px;
+        z-index: 99;
+        width: 300px;
+        margin-top: (-500px - 32px + 84px) / 2;
+        border-top: 10px solid #fff;
+        box-shadow: 4px 5px 20px 0 rgba(0,0,0,.6);
+        transition: all ease .3s;
+    }
+
+    .tpl-box .tpl-list {
+        height: 300px;
+        overflow-y: scroll;
+    }
+    .tpl-box .save-btn {
+        width: 100%;
+    }
+    .tpl-box .tpl-btns {
+        position: absolute;
+        top: 50%;
+        right: -25px;
+        margin-top: -35px;
+        width: 25px;
+        height: 70px;
+        background-color: #fff;
+        text-align: center;
+        padding: 5px 0;
+
+    }
+
+    .tpl-box .tpl-btns .btn-item {
+        cursor: pointer;
+        padding: 5px 0;
+
+    }
+    .tpl-box .tpl-btns .btn-item + .btn-item {
+        margin-top: 8px;
+    }
+    .tpl-box .tpl-btns .btn-item:hover {
+        background-color: #46A0FC;
+        color: #fff
+    }
+    .bg-blue {
+        background-color: #0081ff;
+        color: #ffffff;
+    }
+    /deep/ .el-header{
+        line-height: 60px;
+    }
+    .content_title{font-size: 26px}
+    .grid-content {
+        border-radius: 4px;
+        min-height: 36px;
+    }
+    .el-col {
+        border-radius: 4px;
+    }
+    .bg-purple-1 {
+        background: #99a9bf;
+    }
+    .bg-purple-2 {
+        background: #d3dce6;
+    }
+    .bg-purple-3 {
+        background: #e5e9f2;
+    }
+</style>

+ 183 - 0
src/views/custom-infoboard/templates/board-item-setting.vue

@@ -0,0 +1,183 @@
+<template>
+    <el-dialog
+            :visible.sync="dialogVisible"
+            :close-on-click-modal="false"
+            :close-on-press-escape="false"
+            append-to-body
+            width="805px">
+        <div slot="title" class="image-picker-title">设置看板项</div>
+        <div class="image-picker-body">
+            <el-form :model="formmodel" label-width="100px">
+                <el-row :gutter="20">
+                    <el-col :span="12">
+                        <el-form-item label="标题文字颜色">
+                            <el-input placeholder="标题文字颜色" v-model="formmodel.labelColor">
+                                <el-color-picker slot="append" v-model="formmodel.labelColor" size="mini"></el-color-picker>
+                            </el-input>
+
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="标题背景颜色">
+                            <el-input placeholder="标题背景颜色" v-model="formmodel.labelBgColor">
+                                <el-color-picker slot="append" v-model="formmodel.labelBgColor" size="mini"></el-color-picker>
+                            </el-input>
+
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="内容文字颜色">
+                            <el-input placeholder="内容文字颜色" v-model="formmodel.contentColor">
+                                <el-color-picker slot="append" v-model="formmodel.contentColor" size="mini"></el-color-picker>
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+
+                            <el-form-item label="内容背景颜色">
+                                <el-input placeholder="内容背景颜色" v-model="formmodel.contentBgColor">
+                                    <el-color-picker slot="append" v-model="formmodel.contentBgColor" size="mini"></el-color-picker>
+                                </el-input>
+                            </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+
+                        <el-form-item label="标题区域宽度">
+                            <el-input placeholder="标题区域宽度" v-model="formmodel.labelWidth" type="number">
+                                <template slot="append">px</template>
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+
+                        <el-form-item label="标题文字大小">
+                            <el-input placeholder="标题文字大小" v-model="formmodel.labelTextSize" type="number">
+                                <template slot="append">px</template>
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+
+                    <el-col :span="12">
+                        <el-form-item label="内容文字大小">
+                            <el-input placeholder="内容文字大小" v-model="formmodel.contentTextSize" type="number">
+                                <template slot="append" class="padding-content">px</template>
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+               <el-col :span="24">
+                   <el-form-item label="显示看板项" prop="boardItemHisKeyVal">
+                       <el-select v-model="formmodel.boardItemHisKeyVal"
+                                  placeholder="请选择要显示的看板项"
+                                  @change="boardItemChange"
+                                  clearable
+                                  >
+                           <el-option v-for="(item, index) in boardItems" :key="index"
+                                      :label="item.area_label" :value="item.his_keyval"/>
+                       </el-select>
+                   </el-form-item>
+               </el-col>
+                </el-row>
+            </el-form>
+        </div>
+        <div slot="footer" class="image-picker-footer">
+            <span>
+        <el-button @click="dialogVisible = false">取 消</el-button>
+      <el-button type="primary" @click="handleConfirm">确 定</el-button>
+      </span>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+    export default {
+        name: "board-item-setting",
+        props: {
+            /** 显示dialog */
+            show: {
+                type: Boolean,
+                default: false
+            },
+            /** 默认数据 */
+            defaultData: {
+                type: Object,
+                default: () => {
+                }
+            },
+            boardItems:{
+                type:Array,
+                default:()=>([])
+            }
+        },
+        data() {
+            return {
+                dialogVisible: this.show,
+                color:'#ffffff',
+                formmodel:{...this.defaultData},
+                predefineColors: [
+                    '#ff4500',
+                    '#ff8c00',
+                    '#ffd700',
+                    '#90ee90',
+                    '#00ced1',
+                    '#1e90ff',
+                    '#c71585',
+                    'rgba(255, 69, 0, 0.68)',
+                    'rgb(255, 120, 0)',
+                    'hsv(51, 100, 98)',
+                    'hsva(120, 40, 94, 0.5)',
+                    'hsl(181, 100%, 37%)',
+                    'hsla(209, 100%, 56%, 0.73)',
+                    '#c7158577'
+                ]
+            }
+        },
+        methods: {
+            handleConfirm() {
+                this.$emit('confirm', this.formmodel)
+                this.$emit('close')
+            },
+            boardItemChange(val){
+                console.log('selectchagne',val)
+                if(val!==''){
+                    const selected = this.boardItems.filter(p=>p.his_keyval===val)[0]
+                    this.formmodel.label = selected.area_label
+                    this.formmodel.content=selected.area_content
+                }else{
+                    this.formmodel.label = '标题'
+                    this.formmodel.content='内容'
+                }
+            }
+        },
+        watch: {
+            show(newVal) {
+                console.log('show', newVal)
+                this.dialogVisible = newVal
+            },
+            dialogVisible(newVal) {
+                newVal === false && this.$emit('close')
+            },
+            defaultData(newVal) {
+                console.log('newVal',newVal)
+              this.formmodel={...newVal}
+            }
+        }
+    }
+</script>
+
+<style scoped type="text/scss" >
+    /deep/ .el-input-group__append {
+        padding: 0 10px;
+    .el-color-picker {
+        display: table-cell;
+        padding: 0;
+        border: none;
+    }
+    .el-color-picker__trigger {
+        display: inline-table;
+    }
+    }
+    .color-preview {
+        width: 100%;
+        height: 32px;
+    }
+</style>

+ 166 - 0
src/views/custom-infoboard/templates/board-module-setting.vue

@@ -0,0 +1,166 @@
+<template>
+    <el-dialog
+            :visible.sync="dialogVisible"
+            :close-on-click-modal="false"
+            :close-on-press-escape="false"
+            append-to-body
+            width="805px">
+        <div slot="title" class="image-picker-title">模块设置</div>
+        <div class="image-picker-body">
+            <el-form :model="formmodel" label-width="100px">
+                <el-row :gutter="20">
+                    <el-col :span="12">
+                        <el-form-item label="上边框">
+                            <el-switch
+                                    v-model="formmodel.borderTopShow"
+                                    active-color="#13ce66"
+                                    >
+                            </el-switch>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="右边框">
+                            <el-switch
+                                    v-model="formmodel.borderRightShow"
+                                    active-color="#13ce66"
+                                    >
+                            </el-switch>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="下边框">
+                            <el-switch
+                                    v-model="formmodel.borderBottomShow"
+                                    active-color="#13ce66"
+                                    >
+                            </el-switch>
+                        </el-form-item>
+                    </el-col>
+
+                    <el-col :span="12">
+                        <el-form-item label="左边框">
+                            <el-switch
+                                    v-model="formmodel.borderLeftShow"
+                                    active-color="#13ce66"
+                                    >
+                            </el-switch>
+                        </el-form-item>
+                    </el-col>
+
+                    <el-col :span="12">
+                        <el-form-item label="边框颜色">
+                            <el-input placeholder="分割线颜色" v-model="formmodel.borderColor">
+                                <el-color-picker slot="append" v-model="formmodel.borderColor" size="mini"></el-color-picker>
+                            </el-input>
+
+                        </el-form-item>
+                    </el-col>
+
+                    <el-col :span="12">
+                        <el-form-item label="边框大小">
+                            <el-input placeholder="边框大小" v-model="formmodel.borderWidth" type="number">
+                                <template slot="append">px</template>
+                            </el-input>
+
+                        </el-form-item>
+                    </el-col>
+
+                    <el-col :span="12">
+                        <el-form-item label="模块高度">
+                            <el-input placeholder="模块高度" v-model="formmodel.blockHeight" type="number">
+                                <template slot="append">px</template>
+                            </el-input>
+
+                        </el-form-item>
+                    </el-col>
+
+                </el-row>
+            </el-form>
+        </div>
+        <div slot="footer" class="image-picker-footer">
+            <span>
+        <el-button @click="dialogVisible = false">取 消</el-button>
+      <el-button type="primary" @click="handleConfirm">确 定</el-button>
+      </span>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+    export default {
+        name: "board-module-setting",
+        props: {
+            /** 显示dialog */
+            show: {
+                type: Boolean,
+                default: false
+            },
+            /** 默认数据 */
+            defaultData: {
+                type: Object,
+                default: () => {
+                }
+            }
+        },
+        data() {
+            return {
+                dialogVisible: this.show,
+                color:'#ffffff',
+                formmodel:{...this.defaultData},
+                predefineColors: [
+                    '#ff4500',
+                    '#ff8c00',
+                    '#ffd700',
+                    '#90ee90',
+                    '#00ced1',
+                    '#1e90ff',
+                    '#c71585',
+                    'rgba(255, 69, 0, 0.68)',
+                    'rgb(255, 120, 0)',
+                    'hsv(51, 100, 98)',
+                    'hsva(120, 40, 94, 0.5)',
+                    'hsl(181, 100%, 37%)',
+                    'hsla(209, 100%, 56%, 0.73)',
+                    '#c7158577'
+                ]
+            }
+        },
+        methods: {
+            handleConfirm() {
+                this.$emit('confirm', this.formmodel)
+                this.$emit('close')
+            }
+        },
+        watch: {
+            show(newVal) {
+                console.log('show', newVal)
+                this.dialogVisible = newVal
+            },
+            dialogVisible(newVal) {
+                newVal === false && this.$emit('close')
+            },
+            defaultData(newVal) {
+                console.log('hl',newVal)
+                this.formmodel={...newVal}
+            }
+        }
+    }
+</script>
+
+<style scoped type="text/scss" >
+    /deep/ .el-input-group__append {
+        padding: 0 10px;
+        .el-color-picker {
+            display: table-cell;
+            padding: 0;
+            border: none;
+        }
+        .el-color-picker__trigger {
+            display: inline-table;
+        }
+    }
+    .color-preview {
+        width: 100%;
+        height: 32px;
+    }
+</style>

+ 9 - 0
src/views/custom-infoboard/templates/common/index.js

@@ -0,0 +1,9 @@
+import tpl_one_cloum from './tpl-one-cloum'
+import tpl_two_cloum from './tpl-two-cloum'
+import tpl_three_cloum from './tpl-three-colum'
+
+export default {
+    1: tpl_one_cloum,
+    2: tpl_two_cloum,
+    3: tpl_three_cloum
+}

Разлика између датотеке није приказан због своје велике величине
+ 438 - 0
src/views/custom-infoboard/templates/common/tpl-one-cloum.vue


Разлика између датотеке није приказан због своје велике величине
+ 466 - 0
src/views/custom-infoboard/templates/common/tpl-three-colum.vue


Разлика између датотеке није приказан због своје велике величине
+ 451 - 0
src/views/custom-infoboard/templates/common/tpl-two-cloum.vue


+ 14 - 0
src/views/custom-infoboard/templates/index.js

@@ -0,0 +1,14 @@
+import common from './common'
+
+const templates = {
+    ...common
+}
+
+const templateArray = []
+Object.keys(common).forEach(key => {
+    if (common[key].dataTpl) templateArray.push(common[key].dataTpl)
+})
+
+
+export { templateArray }
+export default templates

Разлика између датотеке није приказан због своје велике величине
+ 304 - 0
src/views/custom-infoboard/templates/layout-item.vue


+ 73 - 32
src/views/customer/components/customerManager.vue

@@ -260,16 +260,16 @@
                 style="width: 100%"
             >
               <el-table-column
-                  prop="true_name"
+                  prop="named"
                   :label="this.$t('customerManage.customerRelativeTrueName')"
                   width="180"
               />
-              <el-table-column
-                  prop="sex"
-                  :label="this.$t('member.sex')"
-                  width="180"
-                  :formatter="formatterSex"
-              />
+<!--              <el-table-column-->
+<!--                  prop="sex"-->
+<!--                  :label="this.$t('member.sex')"-->
+<!--                  width="180"-->
+<!--                  :formatter="formatterSex"-->
+<!--              />-->
               <el-table-column
                   prop="relative_name"
                   :label="this.$t('customerManage.relativeName')"
@@ -285,7 +285,7 @@
                   width="100"
               >
                 <template slot-scope="scope">
-                  <el-button type="danger" size="mini" @click="handlerDeleteRelative(scope.row.member_id)">{{ deleted }}</el-button>
+                  <el-button type="danger" size="mini" @click="handlerDeleteRelative(scope.row.id)">{{ deleted }}</el-button>
                 </template>
               </el-table-column>
             </el-table>
@@ -308,13 +308,13 @@
                 </el-col>
               </el-row>
               <el-row>
-                <el-col :span="12">
-                  <el-form-item :label="this.$t('member.sex')" class="form-item-sex">
-                    <el-radio v-model="relativeFormModel.sex" :label="0">{{ this.$t('member.woman') }}</el-radio>
-                    <el-radio v-model="relativeFormModel.sex" :label="1">{{ this.$t('member.man') }}</el-radio>
-                    <!--                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>-->
-                  </el-form-item>
-                </el-col>
+<!--                <el-col :span="12">-->
+<!--                  <el-form-item :label="this.$t('member.sex')" class="form-item-sex">-->
+<!--                    <el-radio v-model="relativeFormModel.sex" :label="0">{{ this.$t('member.woman') }}</el-radio>-->
+<!--                    <el-radio v-model="relativeFormModel.sex" :label="1">{{ this.$t('member.man') }}</el-radio>-->
+<!--                    &lt;!&ndash;                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>&ndash;&gt;-->
+<!--                  </el-form-item>-->
+<!--                </el-col>-->
                 <el-col :span="12">
                   <el-form-item :label="this.$t('member.mobile')" prop="mobile">
                     <el-input v-model="relativeFormModel.mobile" clearable :placeholder="this.$t('member.inputMobile')" :maxlength="20" />
@@ -412,6 +412,10 @@
         <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-tab-pane v-if="formmodel.id" :label="this.$t('customerManage.fee')" name="customer-fee-sign">
+          <customer-fee :customer-id="formmodel.id" :active-name="'fee_signs1'"/>
+        </el-tab-pane>
       </el-tabs>
     </el-dialog>
     <!-- 用户信息 -->
@@ -543,6 +547,7 @@ import * as API_Remark from '@/api/ncs_remark'
 import * as API_User from '@/api/user'
 import { FRAME_TYPE } from '@/utils/enum/FrameTypeEnum'
 import vitalSignLog from '@/views/vital-sign/log'
+import CustomerFee from '@/views/ncs_fee/index'
 import vueQr from 'vue-qr'
 import * as API_SystemConfig from '@/api/ncs_systemconfig'
 import {RELATIVE_NAME_TYPE} from "@/utils/enum/RelativeNameTypeEnum";
@@ -550,10 +555,11 @@ import {CHILDBIRTH_TYPE} from "@/utils/enum/ChildbirthTypeEnum";
 import * as shop_API from "@/api/ncs_shop";
 import {getDevicesByUuid} from "@/api/initialize"
 import myMapHtml from '@/views/customer/myMapHtml'
+import {getRelativeList, removeRelative} from "@/api/ncs_relative";
 const serverUrl = domain.serverUrl
 export default {
   name: 'CustomerManager',
-  components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr, myMapHtml },
+  components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr, myMapHtml, CustomerFee },
   filters: {
     unixDateFilter(val) {
       return unixToDate(val)
@@ -798,17 +804,22 @@ export default {
         cellRenderer: this.sexRenderer },
       { headerName: this.$t('customerManage.age'), field: 'age', sortable: true, filter: 'agNumberColumnFilter', width: 130, valueFormatter: this.sexFormatter
       },
-      // { headerName: '生日', field: 'birthday', sortable: true, filter: 'agDateColumnFilter', width: 130, valueFormatter: this.unixDateFormatter2, 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: '入住编号', field: 'card_no', sortable: true, filter: 'agTextColumnFilter' },
-      // { headerName: '身份证件类型', field: 'id_type', sortable: true, filter: 'agTextColumnFilter' },
-      // { headerName: '证件', field: 'id_no', sortable: true, filter: 'agNumberColumnFilter', valueFormatter: this.idNoFormatter },
+      { headerName: this.$t('member.birthday'), field: 'birthday', sortable: true, filter: 'agDateColumnFilter', width: 130, valueFormatter: this.unixDateFormatter2, 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('customerManage.cardNo'), field: 'card_no', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('customerManage.idType'),
+        field: 'id_type',
+        sortable: true,
+        filter: 'agTextColumnFilter',
+        valueFormatter: this.idCardFormatter
+      },
+      { headerName: this.$t('customerManage.idNo'), field: 'id_no', sortable: true, filter: 'agNumberColumnFilter', valueFormatter: this.idNoFormatter },
       { headerName: this.$t('member.mobile'), field: 'mobile', sortable: true, filter: 'agTextColumnFilter' },
-      // { headerName: '家庭住址', field: 'address', sortable: true, filter: 'agTextColumnFilter', width: 260 },
+      { headerName: this.$t('member.homeAddress'), field: 'address', sortable: true, filter: 'agTextColumnFilter', width: 260 },
 
       { headerName: this.$t('customerManage.inDate'), field: 'in_date', sortable: true, filter: 'agDateColumnFilter', valueFormatter: this.formatterDate, filterParams: {
         comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
@@ -1092,6 +1103,20 @@ export default {
     sexFormatter(param) {
       return param.value + param.data.age_unit
     },
+    /**
+     * 身份证转换
+     */
+    idCardFormatter(param) {
+      if (param.value === '身份证') {
+        return this.$t('customerManage.idCard');
+      } else if (param.value === '护照') {
+        return this.$t('customerManage.passport');
+      } else if (param.value === '军人证') {
+        return this.$t('customerManage.servicemanCard');
+      } else {
+        return this.$t('customerManage.null');
+      }
+    },
     idNoFormatter(param) {
       if (param.value) {
         return param.data.id_type + ':' +  param.value
@@ -1117,7 +1142,6 @@ export default {
     },
     /** 生日选择变化,修改年龄字段 */
     birthdayChange(val) {
-      console.log(val)
       const ageObj = this.getAge(val)
       console.log('ageobj', ageObj)
       this.$set(this.formmodel, 'age_unit', ageObj.ageunit)
@@ -1431,8 +1455,8 @@ export default {
     },
     /** 拉取亲属列表 **/
     getRelatives() {
-      this.relativeParams.fixedCondition = ' relative_id=' + this.formmodel.member_id
-      API_User.getList(this.relativeParams).then(res => {
+      this.relativeParams.fixedCondition = ' member_id=' + this.formmodel.member_id
+      getRelativeList(this.relativeParams).then(res => {
         this.relativeData = res.data
       }).catch(() => {
 
@@ -1446,7 +1470,7 @@ export default {
         cancelButtonText: this.$t('action.cancel'),
         type: 'warning'
       }).then(() => {
-        API_User.remove(ids).then(
+        removeRelative(ids).then(
           response => {
             this.getRelatives()
           }
@@ -1471,11 +1495,28 @@ export default {
       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) {
+
+      if (val === RELATIVE_NAME_TYPE.CHILDREN || val === RELATIVE_NAME_TYPE.BOY || val === RELATIVE_NAME_TYPE.GIRL) {
         this.relativeRules.mobile[0].required = false
         this.relativeRules.mobile[0].validator = (rule, value, callback) => { callback() }
         this.isChild = true
-      } else {
+        if (val === RELATIVE_NAME_TYPE.BOY) {
+          this.relativeFormModel.sex = 1
+        } else if (val === RELATIVE_NAME_TYPE.GIRL) {
+          this.relativeFormModel.sex = 0
+        }
+      }
+      else if (val === RELATIVE_NAME_TYPE.HUSBAND || val === RELATIVE_NAME_TYPE.FATHER) {
+        this.relativeRules.mobile[0].required = true
+        this.isChild = false
+        this.relativeFormModel.sex = 1
+      }
+      else if (val === RELATIVE_NAME_TYPE.WIFE || val === RELATIVE_NAME_TYPE.MOTHER) {
+        this.relativeRules.mobile[0].required = true
+        this.isChild = false
+        this.relativeFormModel.sex = 0
+      }
+      else {
         this.relativeRules.mobile[0].required = true
         this.isChild = false
       }

+ 126 - 47
src/views/customer/components/elderlyCareManager.vue

@@ -132,7 +132,9 @@
                                 <el-col :span="12">
                                     <el-form-item :label="this.$t('customerManage.idNo')">
                                         <el-input v-model="formmodel.id_no" clearable :placeholder="this.$t('customerManage.inputIdNo')"
-                                                  :maxlength="20"/>
+                                                  :maxlength="20"
+                                                  @blur="onBlurCard"
+                                        />
                                     </el-form-item>
                                 </el-col>
                             </el-row>
@@ -251,20 +253,21 @@
                                 style="width: 100%"
                         >
                             <el-table-column
-                                    prop="true_name"
+                                    prop="named"
                                     :label="this.$t('customerManage.customerRelativeTrueName')"
                                     width="180"
                             />
-                            <el-table-column
-                                    prop="sex"
-                                    :label="this.$t('member.sex')"
-                                    width="180"
-                                    :formatter="formatterSex"
-                            />
+<!--                            <el-table-column-->
+<!--                                    prop="sex"-->
+<!--                                    :label="this.$t('member.sex')"-->
+<!--                                    width="180"-->
+<!--                                    :formatter="formatterSex"-->
+<!--                            />-->
                             <el-table-column
                                     prop="relative_name"
                                     :label="this.$t('customerManage.relativeName')"
                                     width="180"
+                                    :formatter="formatterRelativeName"
                             />
                             <el-table-column
                                     prop="mobile"
@@ -276,7 +279,7 @@
                             >
                                 <template slot-scope="scope">
                                     <el-button type="danger" size="mini"
-                                               @click="handlerDeleteRelative(scope.row.member_id)">{{ deleted }}
+                                               @click="handlerDeleteRelative(scope.row.id)">{{ deleted }}
                                     </el-button>
                                 </template>
                             </el-table-column>
@@ -293,25 +296,41 @@
                                 </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>
                             <el-row>
-                                <el-col :span="12">
-                                    <el-form-item :label="this.$t('member.sex')" class="form-item-sex">
-                                        <el-radio v-model="relativeFormModel.sex" :label="0">{{ this.$t('member.woman') }}</el-radio>
-                                        <el-radio v-model="relativeFormModel.sex" :label="1">{{ this.$t('member.man') }}</el-radio>
-                                        <!--                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>-->
-                                    </el-form-item>
-                                </el-col>
+<!--                                <el-col :span="12">-->
+<!--                                    <el-form-item :label="this.$t('member.sex')" class="form-item-sex">-->
+<!--                                        <el-radio v-model="relativeFormModel.sex" :label="0">{{ this.$t('member.woman') }}</el-radio>-->
+<!--                                        <el-radio v-model="relativeFormModel.sex" :label="1">{{ this.$t('member.man') }}</el-radio>-->
+<!--                                        &lt;!&ndash;                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>&ndash;&gt;-->
+<!--                                    </el-form-item>-->
+<!--                                </el-col>-->
                                 <el-col :span="12">
                                     <el-form-item :label="this.$t('member.mobile')" prop="mobile">
                                         <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>
@@ -398,6 +417,9 @@
               <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-tab-pane  :label="this.$t('sleepData.SleepData')" name="sleepData">
+                    <sleep-detect-data :member-id="formmodel.member_id"></sleep-detect-data>
+                </el-tab-pane>
 
             </el-tabs>
         </el-dialog>
@@ -498,10 +520,13 @@
     import myMap from '@/views/customer/myMap'
     import * as API_SystemConfig from '@/api/ncs_systemconfig'
     import { getDevicesByUuid } from '@/api/initialize'
+    import {RELATIVE_NAME_TYPE} from "@/utils/enum/RelativeNameTypeEnum";
+    import SleepDetectData from "../sleep-detect-data";
+    import {getRelativeList, removeRelative} from "@/api/ncs_relative";
     const serverUrl = domain.serverUrl
     export default {
         name: 'ElderlyCareManager',
-        components: {ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, myMap, myMapHtml},
+        components: {SleepDetectData,ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, myMap, myMapHtml},
         filters: {
             unixDateFilter(val) {
                 return unixToDate(val)
@@ -577,7 +602,6 @@
                     page_no: 1,
                     sort: 'create_time',
                     dir: 'desc',
-                    fixedCondition: Object.keys(this.frame).length === 0 ? 'part_id=' + this.$store.getters.partId : 'part_id=' + this.$store.getters.partId + ' and relative_id =' + this.formmodel.member_id
                 },
                 relativeRules: {
                     true_name: [{required: true, message: this.$t('customerManage.inputRemarks'), trigger: 'blur'}],
@@ -653,7 +677,9 @@
               locationShow: false,
               isCloud: false,
               boolDevice: false,
-              mapUrl: null
+              mapUrl: null,
+              relativeNameTypeEnum: RELATIVE_NAME_TYPE.getValueList(),
+              isChild: false,
             }
         },
         computed: {
@@ -1387,8 +1413,8 @@
             },
             /** 拉取亲属列表 **/
             getRelatives() {
-                this.relativeParams.fixedCondition = ' relative_id=' + this.formmodel.member_id
-                API_User.getList(this.relativeParams).then(res => {
+                this.relativeParams.fixedCondition = ' member_id=' + this.formmodel.member_id
+              getRelativeList(this.relativeParams).then(res => {
                     this.relativeData = res.data
                 }).catch(() => {
 
@@ -1402,7 +1428,7 @@
                     cancelButtonText: this.$t('action.cancel'),
                     type: 'warning'
                 }).then(() => {
-                    API_User.remove(ids).then(
+                  removeRelative(ids).then(
                         response => {
                             this.getRelatives()
                         }
@@ -1423,6 +1449,35 @@
                     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 || val === RELATIVE_NAME_TYPE.BOY || val === RELATIVE_NAME_TYPE.GIRL) {
+              this.relativeRules.mobile[0].required = false
+              this.relativeRules.mobile[0].validator = (rule, value, callback) => { callback() }
+              this.isChild = true
+              if (val === RELATIVE_NAME_TYPE.BOY) {
+                this.relativeFormModel.sex = 1
+              } else if (val === RELATIVE_NAME_TYPE.GIRL) {
+                this.relativeFormModel.sex = 0
+              }
+            }
+            else if (val === RELATIVE_NAME_TYPE.HUSBAND || val === RELATIVE_NAME_TYPE.FATHER) {
+              this.relativeRules.mobile[0].required = true
+              this.isChild = false
+              this.relativeFormModel.sex = 1
+            }
+            else if (val === RELATIVE_NAME_TYPE.WIFE || val === RELATIVE_NAME_TYPE.MOTHER) {
+              this.relativeRules.mobile[0].required = true
+              this.isChild = false
+              this.relativeFormModel.sex = 0
+            }
+            else {
+              this.relativeRules.mobile[0].required = true
+              this.isChild = false
+            }
+          },
             /** 信息变化后操作,如床位状态改变,传入的空间结构变化了 **/
             infoChanged() {
                 this.getEmptyBeds().then(() => {
@@ -1469,29 +1524,29 @@
              * 医护人员选择变化
              * @param type
              */
-            doctorChange(type) {
-                if (this.customerId !== 0) {
-                    if (type === 1) {
-                        if (this.doctor_mapping_id === null) {
-                            this.formmodel.doctor_mapping_id = 0 // 为0则新增,// 其他值为修改
-                        } else {
-                            this.formmodel.doctor_mapping_id = this.doctor_mapping_id
-                        }
-                    } else if (type === 2) {
-                        if (this.nurse_Mapping_id === null) {
-                            this.formmodel.nurse_Mapping_id = 0 // 为0则新增,// 其他值为修改
-                        } else {
-                            this.formmodel.nurse_Mapping_id = this.nurse_Mapping_id
-                        }
-                    } else if (type === 3) {
-                        if (this.worker_mapping_id === null) {
-                            this.formmodel.worker_mapping_id = 0 // 为0则新增,// 其他值为修改
-                        } else {
-                            this.formmodel.worker_mapping_id = this.worker_mapping_id
-                        }
-                    }
-                }
-            },
+            // doctorChange(type) {
+            //     if (this.customerId !== 0) {
+            //         if (type === 1) {
+            //             if (this.doctor_mapping_id === null) {
+            //                 this.formmodel.doctor_mapping_id = 0 // 为0则新增,// 其他值为修改
+            //             } else {
+            //                 this.formmodel.doctor_mapping_id = this.doctor_mapping_id
+            //             }
+            //         } else if (type === 2) {
+            //             if (this.nurse_Mapping_id === null) {
+            //                 this.formmodel.nurse_Mapping_id = 0 // 为0则新增,// 其他值为修改
+            //             } else {
+            //                 this.formmodel.nurse_Mapping_id = this.nurse_Mapping_id
+            //             }
+            //         } else if (type === 3) {
+            //             if (this.worker_mapping_id === null) {
+            //                 this.formmodel.worker_mapping_id = 0 // 为0则新增,// 其他值为修改
+            //             } else {
+            //                 this.formmodel.worker_mapping_id = this.worker_mapping_id
+            //             }
+            //         }
+            //     }
+            // },
             // 护理项选择 设置选中项的颜色
             changeNurseData(val, configid, index) {
                 const currentCfg = this.nurseconfigSelection.find(p => p.config.id === configid).options.find(p => p.id === val)
@@ -1551,6 +1606,30 @@
             API_SystemConfig.cloud().then(r => {
               this.isCloud = r
             })
+          },
+          onBlurCard() {
+            if (this.formmodel.id_type === "身份证") {
+              const val = this.formmodel.id_no.length
+              const idNo = this.formmodel.id_no
+              let sex = null
+
+              if (val === 18) {
+                this.formmodel.birthday = new Date(idNo.substring(6, 10) + '-' + idNo.substring(10, 12) + '-' + idNo.substring(12, 14)).getTime()
+                this.birthdayChange(this.formmodel.birthday)
+                sex = idNo.substring(16, 17)
+              }
+              if (val === 15) {
+                this.formmodel.birthday = new Date( '19' + idNo.substring(6, 8) + '-' + idNo.substring(8, 10) + '-' + idNo.substring(10, 12)).getTime()
+                this.birthdayChange(this.formmodel.birthday)
+                sex = idNo.substring(13, 14)
+              }
+
+              if (sex % 2 === 0) {
+                this.formmodel.sex = 0
+              } else {
+                this.formmodel.sex = 1
+              }
+            }
           }
         }
     }

+ 206 - 90
src/views/customer/components/patientManager.vue

@@ -131,7 +131,9 @@
                                 <el-col :span="12">
                                     <el-form-item :label="this.$t('customerManage.idNo')">
                                         <el-input v-model="formmodel.id_no" clearable :placeholder="this.$t('customerManage.inputIdNo')"
-                                                  :maxlength="20"/>
+                                                  :maxlength="20"
+                                                  @blur="onBlurCard"
+                                        />
                                     </el-form-item>
                                 </el-col>
                             </el-row>
@@ -198,8 +200,8 @@
                             <el-row>
                                 <el-col :span="8">
                                     <el-form-item :label="this.$t('customerManage.doctor')">
-                                        <el-select v-model="formmodel.doctor_id" :placeholder="this.$t('customerManage.choiceDoctor')" clearable
-                                                   @change="doctorChange(1)">
+                                        <el-select v-model="formmodel.doctor_id" :placeholder="this.$t('customerManage.choiceDoctor')" clearable>
+<!--                                                   @change="doctorChange(1)">-->
                                             <el-option v-for="(item,index) in doctors" :key="index"
                                                        :label="item.clerk_name" :value="item.clerk_id"/>
                                         </el-select>
@@ -207,8 +209,8 @@
                                 </el-col>
                                 <el-col :span="8">
                                     <el-form-item :label="this.$t('customerManage.nurse')">
-                                        <el-select v-model="formmodel.nurse_id" :placeholder="this.$t('customerManage.choiceNurse')" clearable
-                                                   @change="doctorChange(2)">
+                                        <el-select v-model="formmodel.nurse_id" :placeholder="this.$t('customerManage.choiceNurse')" clearable>
+<!--                                                   @change="doctorChange(2)">-->
                                             <el-option v-for="(item,index) in nurses" :key="index"
                                                        :label="item.clerk_name" :value="item.clerk_id"/>
                                         </el-select>
@@ -216,8 +218,8 @@
                                 </el-col>
                                 <el-col :span="8">
                                     <el-form-item :label="this.$t('customerManage.worker')">
-                                        <el-select v-model="formmodel.worker_id" :placeholder="this.$t('customerManage.choiceWorker')" clearable
-                                                   @change="doctorChange(3)">
+                                        <el-select v-model="formmodel.worker_id" :placeholder="this.$t('customerManage.choiceWorker')" clearable>
+<!--                                                   @change="doctorChange(3)">-->
                                             <el-option v-for="(item,index) in workers" :key="index"
                                                        :label="item.clerk_name" :value="item.clerk_id"/>
                                         </el-select>
@@ -271,20 +273,21 @@
                                 style="width: 100%"
                         >
                             <el-table-column
-                                    prop="true_name"
+                                    prop="named"
                                     :label="this.$t('customerManage.customerRelativeTrueName')"
                                     width="180"
                             />
-                            <el-table-column
-                                    prop="sex"
-                                    :label="this.$t('member.sex')"
-                                    width="180"
-                                    :formatter="formatterSex"
-                            />
+<!--                            <el-table-column-->
+<!--                                    prop="sex"-->
+<!--                                    :label="this.$t('member.sex')"-->
+<!--                                    width="180"-->
+<!--                                    :formatter="formatterSex"-->
+<!--                            />-->
                             <el-table-column
                                     prop="relative_name"
                                     :label="this.$t('customerManage.relativeName')"
                                     width="180"
+                                    :formatter="formatterRelativeName"
                             />
                             <el-table-column
                                     prop="mobile"
@@ -296,7 +299,7 @@
                             >
                                 <template slot-scope="scope">
                                     <el-button type="danger" size="mini"
-                                               @click="handlerDeleteRelative(scope.row.member_id)">{{ deleted }}
+                                               @click="handlerDeleteRelative(scope.row.id)">{{ deleted }}
                                     </el-button>
                                 </template>
                             </el-table-column>
@@ -313,25 +316,39 @@
                                 </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-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>
                             <el-row>
-                                <el-col :span="12">
-                                    <el-form-item :label="this.$t('member.sex')" class="form-item-sex">
-                                        <el-radio v-model="relativeFormModel.sex" :label="0">{{ this.$t('member.woman') }}</el-radio>
-                                        <el-radio v-model="relativeFormModel.sex" :label="1">{{ this.$t('member.man') }}</el-radio>
-                                        <!--                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>-->
-                                    </el-form-item>
-                                </el-col>
+<!--                                <el-col :span="12">-->
+<!--                                    <el-form-item :label="this.$t('member.sex')" class="form-item-sex">-->
+<!--                                        <el-radio v-model="relativeFormModel.sex" :label="0">{{ this.$t('member.woman') }}</el-radio>-->
+<!--                                        <el-radio v-model="relativeFormModel.sex" :label="1">{{ this.$t('member.man') }}</el-radio>-->
+<!--                                        &lt;!&ndash;                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>&ndash;&gt;-->
+<!--                                    </el-form-item>-->
+<!--                                </el-col>-->
                                 <el-col :span="12">
                                     <el-form-item :label="this.$t('member.mobile')" prop="mobile">
                                         <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>
@@ -350,26 +367,26 @@
                     <div style="height: 450px;display: flex;flex-direction: column;">
                         <div style="height: 350px;overflow-y: auto;box-sizing:border-box;box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);margin:5px -10px">
                             <el-card v-for="(item, index) in remarks" :key="index" style="margin-bottom: 10px">
-                                <div>
-                                    <span style="margin-left: 20px;font-weight:bold">{{ customerRemarks }}</span><span
-                                        style="line-height:1.5">{{ item.content }}</span>
-                                </div>
-                                <div style="margin: 10px">
-                                    <div style="float: left">
-                    <span v-if="item.file_name">
-                      <el-link :href="item.file_path" icon="el-icon-folder" type="success" target="_blank"
-                               :download="item.file_name">{{ item.file_name }}</el-link>
-                    </span>
-                                    </div>
-                                    <div style="float: right">
-                                        <p>
-                                            <span style="font-weight:bold">{{ customerRemarkTime }}</span>{{ item.create_time |
-                                            unixDateFilter }}
-                                            <span style="font-weight:bold;margin-left: 10px;">{{ customerRemarkName }}</span>{{
-                                            item.create_name }}
-                                        </p>
-                                    </div>
+                              <div>
+                                  <span style="margin-left: 20px;font-weight:bold">{{ customerRemarks }}</span><span
+                                      style="line-height:1.5">{{ item.content }}</span>
+                              </div>
+                              <div style="margin: 10px">
+                                <div style="float: left">
+                                  <span v-if="item.file_name">
+                                    <el-link :href="item.file_path" icon="el-icon-folder" type="success" target="_blank"
+                                             :download="item.file_name">{{ item.file_name }}</el-link>
+                                  </span>
                                 </div>
+                                  <div style="float: right">
+                                    <p>
+                                      <span style="font-weight:bold">{{ customerRemarkTime }}</span>{{ item.create_time |
+                                      unixDateFilter }}
+                                      <span style="font-weight:bold;margin-left: 10px;">{{ customerRemarkName }}</span>{{
+                                      item.create_name }}
+                                    </p>
+                                  </div>
+                              </div>
                             </el-card>
 
                         </div>
@@ -419,6 +436,18 @@
                 <my-map-html :map-url="mapUrl" style="width: 100%; height: 670px;"></my-map-html>
               </el-tab-pane>
 
+              <el-tab-pane v-if="formmodel.id" :label="this.$t('customerManage.fee')" name="customer-fee">
+                <customer-fee :customer-id="formmodel.id" :active-name="'customer_fee'"/>
+              </el-tab-pane>
+
+              <el-tab-pane v-if="formmodel.id" :label="this.$t('customerManage.advice')" name="customer-advice">
+                <advice :customer-id="formmodel.id" :part-id="formmodel.part_id" :active-name="'customer_advice'"/>
+              </el-tab-pane>
+
+<!--                <el-tab-pane  :label="this.$t('sleepData.SleepData')" name="sleepData">-->
+<!--                  <sleep-detect-data :member-id="formmodel.member_id"></sleep-detect-data>-->
+<!--                </el-tab-pane>-->
+
             </el-tabs>
         </el-dialog>
         <!-- 用户信息 -->
@@ -508,18 +537,24 @@
     import * as API_User from '@/api/user'
     import * as API_Clerk from '@/api/ncs_clerk'
     import * as API_NurseConfig from '@/api/ncs_nurse_config'
+    import * as API_CustomerMapping from "@/api/ncs_customer_mapping";
     import vitalSignLog from '@/views/vital-sign/log'
+    import customerFee from '@/views/ncs_fee/index'
+    import advice from '@/views/ncs-advice/index'
     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";
     import * as shop_API from "@/api/ncs_shop";
     import myMapHtml from '@/views/customer/myMapHtml'
     import {getDevicesByUuid} from "@/api/initialize";
+    import {RELATIVE_NAME_TYPE} from "@/utils/enum/RelativeNameTypeEnum";
+    import {CHILDBIRTH_TYPE} from "@/utils/enum/ChildbirthTypeEnum";
+    import SleepDetectData from "../sleep-detect-data";
+    import {getRelativeList, removeRelative} from "@/api/ncs_relative";
     const serverUrl = domain.serverUrl
     export default {
         name: 'PatientManager',
-        components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr, myMapHtml },
+        components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter, vitalSignLog, vueQr, myMapHtml, customerFee, advice },
         filters: {
             unixDateFilter(val) {
                 return unixToDate(val)
@@ -599,7 +634,6 @@
                     page_no: 1,
                     sort: 'create_time',
                     dir: 'desc',
-                    fixedCondition: Object.keys(this.frame).length === 0 ? 'part_id=' + this.$store.getters.partId : 'part_id=' + this.$store.getters.partId + ' and relative_id =' + this.formmodel.member_id
                 },
                 relativeRules: {
                     true_name: [{required: true, message: this.$t('customerManage.inputRemarks'), trigger: 'blur'}],
@@ -663,6 +697,7 @@
                 workers: [],
                 nurseData: [],
                 nurseconfigSelection: [],
+              deleteNurseConfig: [],
                 sexTransfer: [
                     {key: this.$t('member.man'), value: 1, color: 'green'},
                     {key: this.$t('member.woman'), value: 0, color: 'red'}
@@ -676,7 +711,9 @@
                 deleted: this.$t('action.delete'),
                 qrCode: null,
                 boolDevice: false,
-                mapUrl: null
+                mapUrl: null,
+              relativeNameTypeEnum: RELATIVE_NAME_TYPE.getValueList(),
+              isChild: false,
             }
         },
         computed: {
@@ -898,13 +935,20 @@
                         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'
-                      }
+                      },
+                      // {
+                      //   onClick: this.advice,
+                      //   label: this.$t('customerManage.advice'),
+                      //   buttonType: 'primary',
+                      //   buttonSize: 'mini',
+                      // },
                     ]}
                 },
                 filter: false,
@@ -1121,7 +1165,6 @@
             },
             /** 生日选择变化,修改年龄字段 */
             birthdayChange(val) {
-                console.log(val)
                 const ageObj = this.getAge(val)
                 console.log('ageobj', ageObj)
                 this.$set(this.formmodel, 'age_unit', ageObj.ageunit)
@@ -1236,12 +1279,19 @@
                                 this.$message.success(this.$t('action.editSuccess'))
                                 this.customerFormVisible = false
                                 this.getList()
-                                this.isDisabled = false
-                                this.$emit('saved')
+                              this.isDisabled = false
+                              this.$emit('saved')
                             }).catch(err => {
                                 this.$message.error(err.message)
                                 this.isDisabled = false
                             })
+                          if (this.deleteNurseConfig.length > 0) {
+                            console.log("this.deleteNurseConfig = " + this.deleteNurseConfig)
+                            API_CustomerMapping.deleteByCustomerAndNurseConfigId(this.formmodel.id, this.deleteNurseConfig).then(res => {
+                              this.isDisabled = false
+                            })
+                          }
+
                         }
                     } else {
                         this.$message.error(this.$t('action.fromError'))
@@ -1429,11 +1479,7 @@
             },
             /** 添加亲属 */
             addRelative() {
-              console.log('8888888888888888888888888888')
-              console.log(this.$refs['relativeForm'])
                 this.$refs['relativeForm'].validate(valid => {
-                  console.log('222222222222222')
-                  console.log(valid)
                     if (valid) {
                         this.relativeFormModel.relative_id = this.formmodel.member_id
                         API_User.addRelative(this.relativeFormModel).then(res => {
@@ -1450,12 +1496,12 @@
             },
             /** 拉取亲属列表 **/
             getRelatives() {
-                this.relativeParams.fixedCondition = ' relative_id=' + this.formmodel.member_id
-                API_User.getList(this.relativeParams).then(res => {
-                    this.relativeData = res.data
-                }).catch(() => {
+              this.relativeParams.fixedCondition = ' member_id=' + this.formmodel.member_id
+              getRelativeList(this.relativeParams).then(res => {
+                this.relativeData = res.data
+              }).catch(() => {
 
-                })
+              })
             },
             /** 单条数据删除处理 */
             handlerDeleteRelative(ids) {
@@ -1465,7 +1511,7 @@
                     cancelButtonText: this.$t('action.cancel'),
                     type: 'warning'
                 }).then(() => {
-                    API_User.remove(ids).then(
+                  removeRelative(ids).then(
                         response => {
                             this.getRelatives()
                         }
@@ -1486,6 +1532,35 @@
                     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 || val === RELATIVE_NAME_TYPE.BOY || val === RELATIVE_NAME_TYPE.GIRL) {
+              this.relativeRules.mobile[0].required = false
+              this.relativeRules.mobile[0].validator = (rule, value, callback) => { callback() }
+              this.isChild = true
+              if (val === RELATIVE_NAME_TYPE.BOY) {
+                this.relativeFormModel.sex = 1
+              } else if (val === RELATIVE_NAME_TYPE.GIRL) {
+                this.relativeFormModel.sex = 0
+              }
+            }
+            else if (val === RELATIVE_NAME_TYPE.HUSBAND || val === RELATIVE_NAME_TYPE.FATHER) {
+              this.relativeRules.mobile[0].required = true
+              this.isChild = false
+              this.relativeFormModel.sex = 1
+            }
+            else if (val === RELATIVE_NAME_TYPE.WIFE || val === RELATIVE_NAME_TYPE.MOTHER) {
+              this.relativeRules.mobile[0].required = true
+              this.isChild = false
+              this.relativeFormModel.sex = 0
+            }
+            else {
+              this.relativeRules.mobile[0].required = true
+              this.isChild = false
+            }
+          },
             /** 信息变化后操作,如床位状态改变,传入的空间结构变化了 **/
             infoChanged() {
                 this.getEmptyBeds().then(() => {
@@ -1505,14 +1580,14 @@
                             acc[val] = (acc[val] || []).concat(arr[i])
                             return acc
                         }, {})
-                    const groupData = groupBy(res, item => item.role_name)
+                    const groupData = groupBy(res, item => item.role_id)
                     if (Object.entries(groupData).length > 0) {
                         Object.entries(groupData).forEach(item => {
-                            if (item[0] === '医生') {
+                            if (item[0] === '2') {
                                 _this.doctors = item[1]
-                            } else if (item[0] === '护士') {
+                            } else if (item[0] === '3') {
                                 _this.nurses = item[1]
-                            } else if (item[0] === '护工') {
+                            } else if (item[0] === '4') {
                                 _this.workers = item[1]
                             }
                         })
@@ -1532,31 +1607,36 @@
              * 医护人员选择变化
              * @param type
              */
-            doctorChange(type) {
-                if (this.customerId !== 0) {
-                    if (type === 1) {
-                        if (this.doctor_mapping_id === null) {
-                            this.formmodel.doctor_mapping_id = 0 // 为0则新增,// 其他值为修改
-                        } else {
-                            this.formmodel.doctor_mapping_id = this.doctor_mapping_id
-                        }
-                    } else if (type === 2) {
-                        if (this.nurse_Mapping_id === null) {
-                            this.formmodel.nurse_Mapping_id = 0 // 为0则新增,// 其他值为修改
-                        } else {
-                            this.formmodel.nurse_Mapping_id = this.nurse_Mapping_id
-                        }
-                    } else if (type === 3) {
-                        if (this.worker_mapping_id === null) {
-                            this.formmodel.worker_mapping_id = 0 // 为0则新增,// 其他值为修改
-                        } else {
-                            this.formmodel.worker_mapping_id = this.worker_mapping_id
-                        }
-                    }
-                }
-            },
+            // doctorChange(type) {
+            //     if (this.customerId !== 0) {
+            //         if (type === 1) {
+            //             if (this.doctor_mapping_id === null) {
+            //                 this.formmodel.doctor_mapping_id = 0 // 为0则新增,// 其他值为修改
+            //             } else {
+            //                 this.formmodel.doctor_mapping_id = this.doctor_mapping_id
+            //             }
+            //         } else if (type === 2) {
+            //             if (this.nurse_mapping_id === null) {
+            //                 this.formmodel.nurse_mapping_id = 0 // 为0则新增,// 其他值为修改
+            //             } else {
+            //                 this.formmodel.nurse_mapping_id = this.nurse_mapping_id
+            //             }
+            //         } else if (type === 3) {
+            //             if (this.worker_mapping_id === null) {
+            //                 this.formmodel.worker_mapping_id = 0 // 为0则新增,// 其他值为修改
+            //             } else {
+            //                 this.formmodel.worker_mapping_id = this.worker_mapping_id
+            //             }
+            //         }
+            //     }
+            // },
             // 护理项选择 设置选中项的颜色
             changeNurseData(val, configid, index) {
+              if (val === null || val === '') {
+                this.setDeleteNurseConfig(configid);
+              } else {
+                this.removeDeleteNurseConfig(configid)
+              }
                 const currentCfg = this.nurseconfigSelection.find(p => p.config.id === configid).options.find(p => p.id === val)
                 if (currentCfg) {
                     this.$refs['patient_nurse_' + configid][0].$el.getElementsByClassName('el-input__inner')[0].style = 'color:#' + currentCfg.color_rgb + ' !important'
@@ -1630,7 +1710,43 @@
                 this.partFrames = [...res]
               })
             }
-          }
+          },
+          onBlurCard() {
+            if (this.formmodel.id_type === "身份证") {
+              const val = this.formmodel.id_no.length
+              const idNo = this.formmodel.id_no
+              let sex = null
+
+              if (val === 18) {
+                this.formmodel.birthday = new Date(idNo.substring(6, 10) + '-' + idNo.substring(10, 12) + '-' + idNo.substring(12, 14)).getTime()
+                this.birthdayChange(this.formmodel.birthday)
+                sex = idNo.substring(16, 17)
+              }
+              if (val === 15) {
+                this.formmodel.birthday = new Date( '19' + idNo.substring(6, 8) + '-' + idNo.substring(8, 10) + '-' + idNo.substring(10, 12)).getTime()
+                this.birthdayChange(this.formmodel.birthday)
+                sex = idNo.substring(13, 14)
+              }
+
+              if (sex % 2 === 0) {
+                this.formmodel.sex = 0
+              } else {
+                this.formmodel.sex = 1
+              }
+            }
+          },
+          setDeleteNurseConfig(config) {
+            this.deleteNurseConfig.push(config)
+          },
+          removeDeleteNurseConfig(config) {
+            var index = this.deleteNurseConfig.map(item => item).indexOf(config)
+            if (index != null) {
+              this.deleteNurseConfig.splice(index, index + 1)
+            }
+          },
+          advice(row) {
+            this.$router.push({ name: 'advice', params: { id: row.id, callback: this.getList() }})
+          },
         }
     }
 </script>

+ 0 - 612
src/views/customer/customerEdit.vue

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

+ 1 - 0
src/views/customer/customerManagement.vue

@@ -5,6 +5,7 @@
 </template>
 
 <script>
+// 月子中心版
 import CustomerManager from './components/customerManager'
 export default {
   name: 'CustomerManagement',

+ 0 - 284
src/views/customer/customer_relative.vue

@@ -1,284 +0,0 @@
-<template>
-  <div>
-    <en-table-layout
-      toolbar
-      @selection-change="selectFun"
-      pagination
-      :tableData="tableData"
-      :height="600"
-      :loading="loading"
-      :default-sort="{prop: 'id', order: 'ascending'}"
-    >
-      <!--工具栏-->
-      <div slot="toolbar" class="inner-toolbar">
-        <div class="toolbar-search">
-          <en-table-search @search="handlerSearch" :placeholder="this.$t('action.keywords')"/>
-        </div>
-        <div class="toolbar-btns">
-          <el-button type="primary" @click="handleAdd">添加亲属</el-button>
-           <el-button type="danger" :disabled="multipleSelection.length === 0" @click="batchDelete">批量删除</el-button>
-        </div>
-      </div>
-      <!--表头-->
-      <template slot="table-columns">
-        <el-table-column type="selection" width="55" align="center"></el-table-column>
-        <el-table-column prop="nickname" label="姓名" align="center"></el-table-column>
-        <el-table-column prop="relative_name" label="亲属称呼" align="center"></el-table-column>
-        <el-table-column prop="sex" label="性别" align="center" :formatter="formatterSex"></el-table-column>
-        <el-table-column prop="mobile" label="手机" align="center"></el-table-column>
-        <el-table-column label="操作" width="120">
-          <template slot-scope="scope">
-            <el-button type="danger" size="mini" @click="handlerDelete(scope.row.member_id)">
-              删除
-            </el-button>
-          </template>
-        </el-table-column>
-      </template>
-
-      <!--翻页-->
-      <el-pagination
-        slot="pagination"
-        v-if="pageData"
-        :current-page="pageData.page_no"
-        :page-sizes="[20, 30, 50, 100]"
-        :page-size="pageData.page_size"
-        @size-change="handlePageSizeChange"
-        @current-change="handlePageCurrentChange"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="pageData.data_total">
-      </el-pagination>
-    </en-table-layout>
-
-    <el-dialog title="添加用户亲属" :visible.sync="dialogAddVisible" :append-to-body="true" width="80%">
-      <el-form :model="formmodel" :rules="rules" ref="editForm" label-width="140px">
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="姓名" prop="nickname">
-              <el-input v-model="formmodel.nickname" clearable placeholder="请输入姓名" :maxlength="20"></el-input>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="亲属称呼" prop="relative_name">
-              <el-input v-model="formmodel.relative_name" clearable placeholder="请输入亲属称呼" :maxlength="20"></el-input>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="性别" class="form-item-sex">
-              <el-radio v-model="formmodel.sex" :label="1">男</el-radio>
-              <el-radio v-model="formmodel.sex" :label="0">女</el-radio>
-              <el-radio v-model="formmodel.sex" :label="3">未知</el-radio>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="手机号码">
-              <el-input v-model="formmodel.mobile" clearable placeholder="请输入手机号码" :maxlength="20"></el-input>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-form-item>
-          <el-button type="primary" @click="addMember">立即添加</el-button>
-          <el-button @click="quxiao">取消</el-button>
-        </el-form-item>
-      </el-form>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-  import * as API_user from '@/api/user'
-  import * as RegExp from "@/utils/RegExp";
-
-  export default {
-    name: 'customer_relative',
-    props: {
-      memberId: {
-        type: Number,
-        default: 0
-      }
-    },
-    data: function() {
-      return {
-        /** 列表loading状态 */
-        loading: false,
-        /** 列表参数 */
-        params: {
-          page_size: 10,
-          page_no: 1,
-          sort: 'create_time',
-          dir: 'desc',
-          fixedCondition: ''
-        },
-        currentRow: {},
-        /** 列表数据 */
-        tableData: [],
-        pageData: [],
-        dialogAddVisible: false,
-        /** 选中行数据 */
-        multipleSelection: [],
-        lookForm: {},
-        formshow: false,
-        formmodel: {
-          sex: 1
-        },
-        rules: {
-          nickname: [
-            this.MixinRequired('请输入亲属姓名!'),
-            { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
-            {
-              validator: (rule, value, callback) => {
-                if (!RegExp.userName.test(value)) {
-                  callback(new Error('只支持汉字、字母、数字、“-”、“_”的组合!'))
-                } else {
-                  callback()
-                }
-              }
-            }
-          ],
-          relative_name: [
-            this.MixinRequired('请输入亲属称呼!'),
-            { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
-            {
-              validator: (rule, value, callback) => {
-                if (!RegExp.userName.test(value)) {
-                  callback(new Error('只支持汉字、字母、数字、“-”、“_”的组合!'))
-                } else {
-                  callback()
-                }
-              }
-            }
-          ],
-        },
-      }
-    },
-    mounted() {
-      // if (this.memberId) {
-      //   this.GET_List()
-      // }
-    },
-    watch: {
-      memberId: function() {
-        if (this.memberId) {
-          this.GET_List()
-        }
-      }
-    },
-    methods: {
-      /** 选择行变化时,记录选中的行数据 */
-      selectFun(val) {
-        this.multipleSelection = val
-      },
-      /** 加载设备信息列表 */
-      GET_List() {
-        this.loading = true
-        this.params.fixedCondition = ' relative_id=' + this.memberId
-        API_user.getList(this.params).then(res => {
-          this.loading = false
-          this.tableData = res.data
-          this.pageData = {
-            page_no: res.page_no,
-            page_size: res.page_size,
-            data_total: res.data_total
-          }
-        }).catch(() => {
-          this.loading = false
-        })
-      },
-      /** 处理搜索 **/
-      handlerSearch(keywords) {
-        this.params.query = keywords
-        this.GET_List()
-      },
-      /** 单条数据删除处理 */
-      handlerDelete(ids) {
-        let test = '你确定要删除此用户亲属信息?'
-        let _this = this
-        this.$confirm(test, this.$t('action.waring'), {
-          confirmButtonText: this.$t('action.yes'),
-          cancelButtonText: this.$t('action.cancel'),
-          type: 'warning'
-        }).then(() => {
-          API_user.remove(ids).then(
-            response => {
-              _this.GET_List()
-            }
-          ).catch(response => {
-            _this.$message({
-              type: 'info',
-              message: response.message
-            })
-          })
-        })
-      },
-      /** 批量数据删除处理(删除选中的行) */
-      batchDelete: function() {
-        const ids = []
-        this.multipleSelection.forEach(function(item) {
-          ids.push(item.member_id)
-        })
-        this.handlerDelete(ids.join(','), 'del')
-      },
-      /** 添加设备信息 */
-      handleAdd() {
-        this.dialogAddVisible = true
-      },
-      /** 编辑设备信息 */
-      handlerEdit(index, row) {
-        this.lookForm = Object.assign({}, row);
-        this.formshow = true
-      },
-      /** 分页大小发生改变 */
-      handlePageSizeChange(size) {
-        this.params.page_size = size
-        this.GET_List()
-      },
-      /** 分页页数发生改变 */
-      handlePageCurrentChange(page) {
-        this.params.page_no = page
-        this.GET_List()
-      },
-      addMember() {
-        this.formmodel.relative_id = this.memberId
-        let _this = this
-        API_user.add(this.formmodel).then(res=> {
-          _this.GET_List()
-          _this.quxiao()
-        })
-      },
-      quxiao() {
-        this.dialogAddVisible = false
-        this.formmodel = {
-          sex: 1
-        }
-      },
-      formatterSex(row, column, cellValue) {
-        if (row.sex === 1) {
-          return '男'
-        } else if (row.sex === 0) {
-          return '女'
-        } else {
-          return '未知'
-        }
-      }
-    }
-  }
-</script>
-
-<style type="text/scss" scoped>
-
-  /deep/ div.toolbar {
-    height: 70px;
-    padding: 20px 0;
-  }
-
-  /deep/ .el-table {
-    width: 100%;
-    overflow-x: scroll;
-
-    & td:not(.is-left) {
-      text-align: center;
-    }
-  }
-
-</style>

+ 1 - 0
src/views/customer/elderlyCareManagement.vue

@@ -5,6 +5,7 @@
 </template>
 
 <script>
+// 养老院版
     import elderlyCareManager from "./components/elderlyCareManager"
     export default {
         name: "ElderlyCareManagement",

+ 0 - 474
src/views/customer/list.vue

@@ -1,474 +0,0 @@
-<template>
-  <div>
-    <!--工具栏-->
-    <div class="toolbar" style="padding-left: 20px">
-      <el-form :inline="true" label-width="120px">
-        <el-form-item>
-          <el-input v-model="searchStr" placeholder="请输入用户姓名、编号、床位" clearable @clear="clickSearch" @keyup.native.enter="clickSearch">
-            <el-button slot="append" icon="el-icon-search" @click="clickSearch"></el-button>
-          </el-input>
-        </el-form-item>
-        <el-form-item label="用户状态">
-          <el-select v-model="callingType" placeholder="请选择用户状态" clearable @change="changeStatus">
-            <el-option label="在院" :value="0" />
-            <el-option label="已出院" :value="1" />
-          </el-select>
-        </el-form-item>
-        <el-form-item>
-          <el-button type="danger" @click="batchDelete">批量删除</el-button>
-        </el-form-item>
-      </el-form>
-    </div>
-    <ag-grid-layout
-            :toolbar="false"
-            :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"
-            @filterChanged="filterModifed"
-            @sortChanged="gridSortChange"
-    >
-      <el-pagination
-              v-if="pageData"
-              slot="pagination"
-              :current-page="pageData.page_no"
-              :page-sizes="[10, 20, 50, 100]"
-              :page-size="pageData.page_size"
-              layout="total, sizes, prev, pager, next, jumper"
-              :total="pageData.data_total"
-              @size-change="handlePageSizeChange"
-              @current-change="handlePageCurrentChange"
-      />
-    </ag-grid-layout>
-    <el-dialog title="编辑用户信息" :visible.sync="dialogAddVisible" :append-to-body="true" width="85%">
-      <customer-edit :customer-id="customerId" :frame-id="frameId" @saved="handlePatientFinished"></customer-edit>
-    </el-dialog>
-
-    <el-dialog title="换床" :visible.sync="formshow" :append-to-body="true" width="80%">
-      <el-form ref="editForm" label-width="140px">
-        <el-form-item label="当前床位:"><svg-icon icon-class="bed" style="color: #9aaabf;margin-top: 5px" />{{ full_name }}</el-form-item>
-        <el-form-item label="可换床位:">
-          <el-radio-group v-model="changeFrameId">
-            <el-radio v-for="(item, index) in frameList" :label="item.id" :key="index">
-              <svg-icon icon-class="bed" style="color: #9aaabf;margin-top: 5px" />{{ item.full_name }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-
-        <el-form-item>
-          <el-button type="primary" @click="updateFrameId">确定换床</el-button>
-        </el-form-item>
-      </el-form>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-  import * as API_customer from '@/api/ncs_customer'
-  import { unixToDate } from "@/utils/Foundation"
-  import customerEdit from '@/views/customer/customerEdit'
-  import * as RegExp from "@/utils/RegExp"
-  import * as API_hospitalFrame from "@/api/ncs_hospitalFrame"
-  import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
-  import {param} from "@/utils"
-  import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
-  import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter";
-
-  export default {
-    name: 'customer_list',
-    components: { customerEdit, ButtonCellRender, RadioFilter },
-    data: function() {
-      return {
-        /** 列表loading状态 */
-        loading: false,
-        /** 列表参数 */
-        params: {
-          page_size: 10,
-          page_no: 1,
-          sort: 'status,create_time',
-          dir: 'desc',
-          fixedCondition: ' part_id = ' + this.$store.getters.partId,
-          alias: 'nc'
-        },
-        currentRow: {},
-        /** 列表数据 */
-        tableData: [],
-        pageData: [],
-        dialogAddVisible: false,
-        /** 选中行数据 */
-        multipleSelection: [],
-        lookForm: {},
-        formshow: false,
-        changeFrameId: null,
-        customerId: null,
-        frameId: null,
-        callingType: null,
-        frameList: [],
-        searchStr: null,
-        full_name: '',
-        columnDefs: null,
-        defaultColDef: null,
-        gridOptions: null,
-        gridApi: null,
-        columnApi: null,
-        localeText: AG_GRID_LOCALE_CN,
-        rowSelection: null,
-        sexTransfer: [
-          { key: '男', value: 1, color: 'green' },
-          { key: '女', value: 0, color: 'red' }
-        ],
-        statusTransfer: [
-        { key: '已出院', value: 1,  color: 'orange' },
-          { key: '在院', value: 0,  color: 'green' }
-        ]
-      }
-    },
-    computed: {
-      tableHeight() {
-        return this.mainAreaHeight - 130
-      }
-    },
-    beforeMount() {
-      this.gridOptions = {
-      }
-      this.columnDefs = [
-        {
-          headerName: '#',
-          headerCheckboxSelection: true,
-          headerCheckboxSelectionFilteredOnly: true,
-          checkboxSelection: true,
-          sortable: false, filter: false,
-          width: 50,
-          resizable: false,
-          valueGetter: this.hashValueGetter
-        },
-        { headerName: '姓名', field: 'named', sortable: true, filter: 'agTextColumnFilter', minWidth: 160 },
-        { headerName: '用户编号', field: 'card_no', sortable: true, filter: true, minWidth: 170 },
-        { headerName: '年龄', field: 'age', sortable: true, filter: 'agNumberColumnFilter', valueFormatter: this.formatterAge, minWidth: 100 },
-        { headerName: '性别', field: 'sex', sortable: true, filter: true, cellRenderer: this.formatterSex, minWidth: 100, filterFramework: 'RadioFilter',
-          filterParams: {
-            listData: this.sexTransfer
-          }
-        },
-        { headerName: '住院时间', field: 'in_date', valueFormatter: this.formatterDate, sortable: true, minWidth: 220, filter: 'agDateColumnFilter',
-          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: '状态', field: 'status', sortable: true, filter: false, cellRenderer: this.formatterStatus, minWidth: 100, filterFramework: 'RadioFilter',
-          filterParams: {
-            listData: this.statusTransfer
-          }
-        },
-        { headerName: '床位', field: 'full_name', sortable: true, filter: true, minWidth: 120 },
-        { headerName: '操作任务', field: 'id',
-          cellRendererFramework: 'ButtonCellRender',
-          cellRendererParams: param => {
-            return {
-              onClick: this.handleAdd,
-              label: this.$t('action.edit'),
-              buttonType: 'primary',
-              buttonSize: 'mini'
-            }
-          },
-          filter: false,
-          pinned: 'right',
-          lockPinned: true,
-          width: 100,
-          resizable: false,
-          sortable: false },
-        { headerName: '换床', field: 'id',
-          cellRendererFramework: 'ButtonCellRender',
-          cellRendererParams: param => {
-            return {
-              onClick: this.handlerEdit,
-              label: '换床',
-              buttonType: 'success',
-              buttonSize: 'mini',
-              show: !param.data['status']
-            }
-          },
-          filter: false,
-          pinned: 'right',
-          lockPinned: true,
-          width: 100,
-          resizable: false,
-          sortable: false },
-        { headerName: '出院', field: 'id',
-          cellRendererFramework: 'ButtonCellRender',
-          cellRendererParams: param => {
-            return {
-              onClick: this.cy,
-              label: '出院',
-              buttonType: 'danger',
-              buttonSize: 'mini',
-              show: !param.data['status']
-            }
-          },
-          pinned: 'right',
-          lockPinned: true,
-          width: 100,
-          resizable: false,
-          filter: false,
-          sortable: false }
-      ]
-      this.defaultColDef = {
-        filter: 'agTextColumnFilter',
-        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.GET_List()
-    },
-    methods: {
-      windowResize() {
-        this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
-      },
-      /** 选择行变化时,记录选中的行数据 */
-      selectFun(val) {
-        this.multipleSelection = val
-      },
-      /** 加载设备信息列表 */
-      GET_List() {
-        this.loading = true
-        this.gridApi.showLoadingOverlay()
-        this.gridApi.sizeColumnsToFit()
-        API_customer.getList(this.params).then(res => {
-          this.loading = false
-          this.tableData = res.data
-          this.pageData = {
-            page_no: res.page_no,
-            page_size: res.page_size,
-            data_total: res.data_total
-          }
-        }).catch(() => {
-          this.loading = false
-        })
-      },
-      /** 处理搜索 **/
-      handlerSearch(keywords) {
-        this.params.query = keywords
-        this.GET_List()
-      },
-      changeStatus(value) {
-        delete this.params.fixedCondition
-        if (value) {
-          this.params.fixedCondition = ' part_id =' + this.$store.getters.partId + ' and status=' + value
-        } else {
-          this.params.fixedCondition = ' 1 = 1'
-        }
-        this.GET_List()
-      },
-      /** 单条数据删除处理 */
-      handlerDelete(ids) {
-        let test = '你确定要删除此用户信息?'
-        let _this = this
-        this.$confirm(test, this.$t('action.waring'), {
-          confirmButtonText: this.$t('action.yes'),
-          cancelButtonText: this.$t('action.cancel'),
-          type: 'warning'
-        }).then(() => {
-          API_customer.remove(ids).then(
-            response => {
-              _this.GET_List()
-            }
-          ).catch(response => {
-            _this.$message({
-              type: 'info',
-              message: response.message
-            })
-          })
-        })
-      },
-      /** 批量数据删除处理(删除选中的行) */
-      batchDelete: function() {
-        let rows = this.gridApi.getSelectedRows()
-        if (rows.length === 0) {
-          this.$message({ type: 'info', message: '请先勾选需要删除的数据' })
-          return
-        }
-        const ids = []
-        rows.forEach(function (item) {
-          ids.push(item.id)
-        })
-        this.handlerDelete(ids.join(','), 'del')
-      },
-      /** 添加设备信息 */
-      handleAdd(row) {
-        this.dialogAddVisible = true
-        this.customerId = row.id
-        this.frameId = row.frame_id
-      },
-      handlerEdit(row) {
-        this.customerId = row.id
-        this.full_name = row.full_name
-        API_hospitalFrame.getSickbedByPartId(this.$store.getters.partId).then(res=> {
-          this.frameList = res
-        })
-        this.formshow = true
-      },
-      cy(row) {
-        this.customerId = row.id
-        let _this = this
-        this.$confirm('你确定要进行出院操作吗', this.$t('action.waring'), {
-          confirmButtonText: this.$t('action.yes'),
-          cancelButtonText: this.$t('action.cancel'),
-          type: 'warning'
-        }).then(() => {
-          const data = {
-            out_date: new Date(new Date().toLocaleDateString()).getTime(),
-            status: 1
-          }
-          _this.updateSave(data)
-        })
-      },
-      /** 分页大小发生改变 */
-      handlePageSizeChange(size) {
-        this.params.page_size = size
-        this.GET_List()
-      },
-      /** 分页页数发生改变 */
-      handlePageCurrentChange(page) {
-        this.params.page_no = page
-        this.GET_List()
-      },
-      formatterAge(param) {
-        return param.data.age + param.data.age_unit
-      },
-      formatterStatus(params) {
-        if (params.value === null || params.value === undefined) return ''
-        const item = this.statusTransfer.filter(p => p.value === params.value)[0]
-        if (item) {
-          return '<span style="color:' + item.color + ';">' + item.key + '</span>'
-        } else {
-          return '未知'
-        }
-      },
-      formatterDate(param) {
-        let date = unixToDate(param.data.in_date, 'yyyy-MM-dd')
-        if (param.data.out_date) {
-          date += '至' + unixToDate(param.data.out_date, 'yyyy-MM-dd')
-        } else {
-          if (param.data.in_date) {
-            date += '至今'
-          }
-        }
-        return date
-      },
-      handlePatientFinished() {
-        this.dialogAddVisible = false
-        this.GET_List()
-      },
-      updateFrameId() {
-        if (!this.changeFrameId) {
-          this.$message({
-            type: 'info',
-            message: '请选择床位'
-          })
-          return
-        }
-        const data = {
-          frame_id: this.changeFrameId
-        }
-        this.updateSave(data)
-      },
-      updateSave(data) {
-        API_customer.update(this.customerId, data).then(res=> {
-          this.$message({
-            type: 'success',
-            message: '修改成功'
-          })
-          this.formshow = false
-          this.GET_List()
-        })
-      },
-      clickSearch(value) {
-        this.params.query = this.searchStr
-        this.GET_List()
-      },
-      /** 性别格式化 */
-      formatterSex(params) {
-        if (params.value === null || params.value === undefined) return ''
-        const item = this.sexTransfer.filter(p => p.value === params.value)[0]
-        if (item) {
-          return '<span style="color:' + item.color + ';">' + item.key + '</span>'
-        } else {
-          return '未知'
-        }
-      },
-      filterModifed(param) {
-        let model = param.api.getFilterModel()
-        this.params.filter = JSON.stringify(model)
-        this.GET_List()
-      },
-      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.GET_List()
-      },
-    }
-  }
-</script>
-
-<style type="text/scss" scoped>
-
-  /deep/ div.toolbar {
-    height: 70px;
-    padding: 20px 0;
-  }
-
-  /deep/ .el-table {
-    width: 100%;
-    overflow-x: scroll;
-
-    & td:not(.is-left) {
-      text-align: center;
-    }
-  }
-</style>

+ 1 - 0
src/views/customer/patientManagement.vue

@@ -5,6 +5,7 @@
 </template>
 
 <script>
+// 医院版
 import PatientManager from './components/patientManager'
 export default {
   name: 'PatientManagement',

+ 421 - 0
src/views/customer/sleep-detect-data.vue

@@ -0,0 +1,421 @@
+<template>
+    <div style="width: 100%" id="charsPanel" >
+        <el-header>
+        <el-row>
+            <el-form>
+            <el-col :span="12">
+                <el-form-item :label="this.$t('sleepData.ChooseDate')" >
+                    <el-date-picker
+                            type="date"
+                            :editable="false"
+                            value-format="yyyy-MM-dd"
+                            v-model="chooseDate"
+                            :picker-options="{ disabledDate(time) { return time.getTime() > Date.now() }}"
+                            @change="chooseDateChange"
+                    />
+                </el-form-item>
+            </el-col>
+            </el-form>
+
+        </el-row>
+        </el-header>
+        <el-row>
+            <el-col :offset="2" :span="2">
+             <h2>{{chooseDate| WeekFilter}}</h2>
+                <h4>{{chooseDate | DayFilter}}</h4>
+            </el-col>
+            <el-col :span="5" v-show="sleepDataJson!==null">
+                <div class="" id="gaugeChart"  :style="{height:'200px', width:dialogWidth/4+'px'}"> </div>
+
+             </el-col>
+            <el-col :span="5" v-if="sleepDataJson!==null">
+                <div class="sleep_datashow_item" style="margin-top:30px">
+                    <h2>{{Math.floor(sleepDataJson.inBedDuration/60)+this.$t('sleepData.Hour')+Math.floor(sleepDataJson.inBedDuration%60)+this.$t('sleepData.Minute') }}</h2>
+                    <p>{{this.$t('sleepData.InBed')}}</p>
+                </div>
+                <div class="sleep_datashow_item">
+                <h2>{{Math.floor(sleepDataJson.sleepDuration/60)+this.$t('sleepData.Hour')+Math.floor(sleepDataJson.sleepDuration%60)+this.$t('sleepData.Minute') }}</h2>
+                <p>{{this.$t('sleepData.Asleep')}}</p>
+                </div>
+            </el-col>
+            <el-col :span="8" v-show="sleepDataJson!==null">
+                <div id="pieChart" :style="{height:'200px', width:dialogWidth/3+'px'}"></div>
+
+            </el-col>
+        </el-row>
+
+        <div v-show="sleepDataJson!==null"
+                id="chartSleep"
+                :style="{height:'200px', width:dialogWidth+'px'}"
+        />
+        <el-row v-if="sleepDataJson!==null">
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{sleepDataJson.getInBedTime | HmFilter}}</h2>
+                    <p>{{this.$t('sleepData.GetInBedTime')}}</p>
+                </div>
+            </el-col>
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{sleepDataJson.awakeTime | HmFilter}}</h2>
+                    <p>{{this.$t('sleepData.AwakeTime')}}</p>
+                </div>
+            </el-col>
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{sleepDataJson.avarageBreath}}<span>{{this.$t('sleepData.Times')}}/{{this.$t('sleepData.Minute')}}</span></h2>
+                    <p>{{this.$t('sleepData.AvarageBreath')}}</p>
+                </div>
+            </el-col>
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{sleepDataJson.avarageHeartRate}}<span>{{this.$t('sleepData.Times')}}/{{this.$t('sleepData.Minute')}}</span></h2>
+                    <p>{{this.$t('sleepData.AvarageHeartBeat')}}</p>
+                </div>
+            </el-col>
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{sleepDataJson.leaveBedTimes}}<span>{{this.$t('sleepData.Times')}}</span></h2>
+                    <p>{{this.$t('sleepData.LeaveBedTimes')}}</p>
+                </div>
+            </el-col>
+
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{sleepDataJson.sleepScore}}</h2>
+                    <p>{{this.$t('sleepData.Quality')}}</p>
+                </div>
+            </el-col>
+
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{Math.floor(sleepDataJson.sleepDuration/60)+this.$t('sleepData.Hour')+Math.floor(sleepDataJson.sleepDuration%60)+this.$t('sleepData.Minute') }}</h2>
+                    <p>{{this.$t('sleepData.Asleep')}}</p>
+                </div>
+            </el-col>
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{sleepDataJson.turnOverTimes}}<span>{{this.$t('sleepData.Times')}}</span></h2>
+                    <p>{{this.$t('sleepData.TurnOverTimes')}}</p>
+                </div>
+            </el-col>
+            <el-col :span="6" :offset="2">
+                <div class="sleep_datashow_item">
+                    <h2>{{sleepDataJson.breathStopTimes}}<span>{{this.$t('sleepData.Times')}}</span></h2>
+                    <p>{{this.$t('sleepData.BreathPauseTimes')}}</p>
+                </div>
+            </el-col>
+
+
+        </el-row>
+        <el-empty :description="this.$t('sleepData.NoData')" v-if="sleepDataJson===null"></el-empty>
+
+    </div>
+</template>
+
+ <script>
+     import * as API_SleepData from "@/api/ncs_sleep_data";
+     import moment from 'moment'
+
+
+    export default {
+        name: "sleep-detect-data",
+        props: {
+            memberId: {
+                type: Number,
+                default: 0
+            }
+        },
+        filters:{
+            HmFilter(value){
+                if(value===null){
+                    return ''
+                }
+               return  moment(value).format('HH:mm')
+            },
+            DayFilter(value){
+                if(value===null){
+                    return ''
+                }
+                return moment(value).format('YYYY-MM-DD')
+            },
+            WeekFilter(value){
+                if(value===null){
+                    return ''
+                }
+                return moment(value).format('dddd')
+            }
+        },
+        watch: {
+            memberId: function() {
+                if (this.memberId) {
+                    let dateStr = moment(this.chooseDate).format('YYYY-MM-DD')
+                    this.getSleepData(this.memberId,dateStr)
+                }
+            }
+        },
+        data(){
+            const _this=this
+            return{
+                sleepChart:null,
+                pieChart:null,
+                gaugeChart:null,
+                weekDay:'',
+                chooseDate:new Date(),
+                sleepDataJson:{},
+              option:{
+                    grid:{
+                      right:100,
+                      top:20,
+                        left:100,
+                        bottom:30
+                    },
+                  xAxis: {
+                      type: 'category',
+                      boundaryGap: false,
+                      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+                      axisLabel:{
+
+                          interval:6,
+                          rotate:45,
+                          formatter:function (value, index) {
+                              return moment(value).format('HH') + _this.$t('sleepData.Hour');
+                          }
+                          }
+                  },
+                  yAxis: {
+                      type: 'value',
+                      splitLine:false,
+                      axisLabel:{
+                          formatter:function(value,index){
+                              if(value==1){
+                                  return _this.$t('sleepData.DeepSleep')
+                              }
+                              if(value==2){
+                                  return _this.$t('sleepData.LightSleep')
+                              }
+                              if(value==3){
+                                  return _this.$t('sleepData.Awake')
+                              }
+                          }
+                      }
+                  },
+                  series: [
+                      {
+                          data: [3, 2, 2, 3, 1, 1, 3],
+                          type: 'line',
+                          areaStyle: {},
+                          smooth:true,
+                          lineStyle:{
+                              width:4
+                          },
+                          symbol:false
+                      }
+                  ]
+              },
+                gaugeOption:
+            {
+                series: [
+                    {
+                        type: 'gauge',
+                        startAngle: 90,
+                        endAngle: -270,
+                        pointer: {
+                            show: false
+                        },
+                        progress: {
+                            show: true,
+                            overlap: false,
+                            roundCap: true,
+                            clip: false,
+                            itemStyle: {
+                                borderWidth: 2,
+                                borderColor: '#fac858'
+                            }
+                        },
+                        axisLine: {
+                            lineStyle: {
+                                width: 10
+                            }
+                        },
+                        splitLine: {
+                            show: false,
+                            distance: 0,
+                            length: 10
+                        },
+                        axisTick: {
+                            show: false
+                        },
+                        axisLabel: {
+                            show: false,
+                            distance: 50
+                        },
+                        data: [
+                            {
+                                value: 87,
+                                name: this.$t('sleepData.Quality'),
+                                title: {
+                                    offsetCenter: ['0%', '30%']
+                                },
+                                detail: {
+                                    valueAnimation: true,
+                                    offsetCenter: ['0%', '-10%']
+                                }
+                            }
+                        ],
+                        title: {
+                            fontSize: 15
+                        },
+                        detail: {
+                            width: 50,
+                            height: 20,
+                            fontSize: 20,
+                            color: '#f00',
+                            borderColor: 'auto',
+                            borderRadius: 0,
+                            borderWidth: 0,
+                            formatter: '{value}%'
+                        }
+                    }
+                ]
+            }
+                ,
+                pieOption:{
+                    tooltip: {
+                        trigger: 'item',
+                        formatter: function(params){
+                            return params.name+' '+Math.floor(params.value/60)+_this.$t('sleepData.Hour')+Math.floor(params.value%60)+_this.$t('sleepData.Minute')
+                        }
+                    },
+                    legend: {
+                        orient:'vertical',
+                        right: '10%',
+                        top:'center'
+                    },
+                    series: [
+                        {
+                            name: '睡眠时长分布',
+                            type: 'pie',
+                            radius: ['40%', '70%'],
+                            avoidLabelOverlap: true,
+                            itemStyle: {
+                                borderRadius: 10,
+                                borderColor: '#fff',
+                                borderWidth: 2
+                            },
+                            label: {
+                                show: true,
+                                position: 'left',
+
+                                    formatter: function(params){
+                                        return params.name+' '+Math.floor(params.value/60)+_this.$t('sleepData.Hour')+Math.floor(params.value%60)+_this.$t('sleepData.Minute')+'('+params.percent+'%)'
+                                    }
+
+                            },
+                            emphasis: {
+                                label: {
+                                    show: true,
+                                    fontSize: '14',
+                                    fontWeight: 'bold'
+                                }
+                            },
+                            labelLine: {
+                                show: true
+                            },
+                            data: [
+                                { value: 20, name: _this.$t('sleepData.Awake') },
+                                { value: 70, name: _this.$t('sleepData.LightSleep') },
+                                { value: 10, name: _this.$t('sleepData.DeepSleep') }
+                            ]
+                        }
+                    ]
+                },
+                dialogWidth: 0
+            }
+        },
+
+        mounted(){
+            if(this.$i18n.locale==='zh'){
+                require('moment/locale/zh-cn')
+            }else if(this.$i18n.locale==='en'){
+                require('moment/locale/en-in')
+            }
+         this.dialogWidth =this.$parent.$parent.$el.clientWidth-30
+             moment.locale()
+
+console.log(this.dialogWidth)
+            this.$nextTick(function () {
+                // this.dialogWidth=this.$parent.$refs.changeBedForm.clientWidth
+                 console.log()
+                this.sleepChart= this.$echarts.init(document.getElementById('chartSleep'))
+                this.pieChart= this.$echarts.init(document.getElementById('pieChart'))
+                this.gaugeChart= this.$echarts.init(document.getElementById('gaugeChart'))
+                this.sleepChart.clear()
+                this.sleepChart.setOption(this.option)
+                this.gaugeChart.setOption(this.gaugeOption)
+                this.pieChart.setOption(this.pieOption)
+
+
+            })
+          this.getSleepData(this.memberId,moment().format('YYYY-MM-DD'))
+            // console.log(document.getElementById("charsPanel").clientWidth)
+        },
+        methods:{
+            chooseDateChange(val){
+                if(val!==null){
+                   let dateStr = moment(val).format('YYYY-MM-DD')
+                    this.getSleepData(this.memberId,dateStr)
+                }
+
+            },
+            getSleepData(memberId,datastr){
+                API_SleepData.getSleepData(memberId,datastr).then(res=>{
+                    console.log('res',res)
+                    if(res!==''){
+                   API_SleepData.getJsonData(res.json_data_url).then(rs=>{
+
+                       this.sleepDataJson=rs
+                       this.gaugeOption.series[0].data[0].value=rs.sleepScore
+                       this.gaugeChart.setOption(this.gaugeOption)
+                       this.pieOption.series[0].data[0].value=rs.sleepPieSeries[0]
+                       this.pieOption.series[0].data[1].value=rs.sleepPieSeries[1]
+                       this.pieOption.series[0].data[2].value=rs.sleepPieSeries[2]
+                       this.pieChart.setOption(this.pieOption)
+                       this.option.xAxis.data=[...rs.sleepStatusXaxis]
+                       this.option.series[0].data=[...rs.sleepStatusYaxis]
+                       this.sleepChart.setOption(this.option)
+                       console.log('json',rs)
+                   }).catch(er=>{
+                       this.sleepDataJson=null
+                   })
+                    }else{
+                        this.sleepDataJson=null
+                    }
+                }).catch(err=>{
+                    this.sleepDataJson=null
+                    console.log('err',err)
+                })
+            }
+        }
+    }
+ </script>
+
+<style type="text/scss" lang="scss" scoped>
+.sleep_datashow_item {
+    h2{
+        margin: 0;
+        margin-top: 0px;
+        span{
+            margin-left: 10px;
+            font-size: 14px;
+            font-weight: normal;
+        }
+    }
+ p{
+     margin-top: 5px;
+     color: #888;
+ }
+
+
+}
+</style>

+ 407 - 0
src/views/entrace-guard/users.vue

@@ -0,0 +1,407 @@
+<template>
+    <div>
+
+        <ag-grid-layout
+                toolbar
+                :table-height="tableHeight"
+                theme="ag-theme-alpine"
+                :column-defs="columnDefs"
+                :row-data="rowData"
+                :locale-text="localeText"
+                :grid-options="gridOptions"
+                :default-col-def="defaultColDef"
+                :animate-rows="true"
+                :row-selection="rowSelection"
+                :framework-components="frameworkComponents"
+                @filterChanged="filterModifed"
+                @sortChanged="gridSortChange"
+        >
+
+            <div slot="toolbar" class="inner-toolbar">
+                <div class="toolbar-search">
+                    <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch"/>
+                </div>
+                <div class="toolbar-btns">
+                    <el-button type="primary" size="mini" @click="refreshUser">{{ this.$t('entraceguardUser.refreshUser') }}
+                    </el-button>
+                </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 :visible.sync="customerFormVisible" :title="this.$t('customerManage.customerInfo')"
+                   class="customer-dialog" width="50%">
+
+            <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="145px">
+                <el-row>
+                    <el-col :span="12">
+                        <el-form-item :label="this.$t('entraceguardUser.named')" prop="name">
+                            <el-input v-model="formmodel.name" clearable
+                                      :placeholder="this.$t('entraceguardUser.named')" :maxlength="20"/>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item :label="this.$t('entraceguardUser.idNo')">
+                            <el-input v-model="formmodel.id_card" clearable
+                                      :placeholder="this.$t('entraceguardUser.idNo')" :maxlength="20"/>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+                <el-row>
+                    <el-col :span="12">
+                        <el-form-item :label="this.$t('entraceguardUser.ic')" prop="name">
+                            <el-input v-model="formmodel.ic" clearable
+                                      :placeholder="this.$t('entraceguardUser.ic')" :maxlength="20"/>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item :label="this.$t('entraceguardUser.phone')">
+                            <el-input v-model="formmodel.phone" clearable
+                                      :placeholder="this.$t('entraceguardUser.phone')" :maxlength="13"/>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+
+                <el-row>
+                    <el-col :span="12">
+                        <el-form-item :label="this.$t('entraceguardUser.password')" prop="name">
+                            <el-input v-model="formmodel.password" clearable
+                                      :placeholder="this.$t('entraceguardUser.password')" :maxlength="20"/>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item :label="this.$t('entraceguardUser.forbidden')">
+                            <el-switch
+                                    v-model="formmodel.forbidden"
+                                    >
+                            </el-switch>
+
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+
+                <el-form-item>
+                    <el-button type="primary" class="save" @click="handlerSubmit('editForm')">{{ this.$t('action.save')
+                        }}
+                    </el-button>
+                </el-form-item>
+            </el-form>
+
+        </el-dialog>
+        <!-- 用户信息 -->
+
+    </div>
+</template>
+
+<script>
+    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_entrace_guard_user'
+    import {unix2Date, unixToDate} from '@/utils/Foundation'
+
+    export default {
+        name: "users",
+        components: {ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter},
+        data() {
+            return {
+                /** ag-grid参数 **/
+                pageData: {}, // 翻页数据
+                columnDefs: null,
+                rowData: null,
+                defaultColDef: null,
+                gridOptions: null,
+                gridApi: null,
+                columnApi: null,
+                localeText: AG_GRID_LOCALE_CN,
+                filterState: null,
+                rowSelection: null,
+                frameworkComponents: null,
+                formmodel: {},
+                customerFormVisible: false,
+                /** 列表参数 */
+                params: {
+                    page_size: 20,
+                    page_no: 1,
+                    fixedCondition: 'partment_id=' + this.$store.getters.partId
+                },
+                booleanRender: [
+                    {key: this.$t('entraceguardUser.yes'), value: true, color: 'green'},
+                    {key: this.$t('entraceguardUser.nop'), value: false, color: 'red'}
+                ],
+                rules: {}
+            }
+        },
+        computed: {
+            tableHeight() {
+                return this.mainAreaHeight - 130
+            }
+        },
+        beforeMount() {
+            const _this = this
+            this.gridOptions = {
+                onCellDoubleClicked: function (row) {
+                    _this.formmodel = {
+                        ...row.data
+                    }
+                    _this.detailsVisible = true
+                }
+            }
+            this.columnDefs = [
+                {
+                    headerName: '#',
+                    headerCheckboxSelection: true,
+                    headerCheckboxSelectionFilteredOnly: true,
+                    checkboxSelection: true,
+                    sortable: false, filter: false,
+                    width: 50,
+                    resizable: false,
+                    valueGetter: this.hashValueGetter
+                },
+                {headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 100},
+                {
+                    headerName: this.$t('entraceguardUser.named'),
+                    field: 'name',
+                    sortable: true,
+                    filter: 'agTextColumnFilter',
+                    width: 160
+                },
+                {
+                    headerName: this.$t('entraceguardUser.idNo'),
+                    field: 'id_card',
+                    sortable: true,
+                    filter: 'agNumberColumnFilter',
+                    flex: 1
+                },
+
+                {
+                    headerName: this.$t('entraceguardUser.ic'),
+                    field: 'ic',
+                    sortable: true,
+                    filter: 'agTextColumnFilter',
+                    width: 160
+                },
+                {
+                    headerName: this.$t('entraceguardUser.phone'),
+                    field: 'phone',
+                    sortable: true,
+                    filter: 'agTextColumnFilter'
+                },
+                {
+                    headerName: this.$t('entraceguardUser.password'),
+                    field: 'password',
+                    sortable: true,
+                    filter: 'agTextColumnFilter',
+                    width: 160
+                },
+                // lockPosition 锁定位置,会在第一列
+                // lockPinned = true 不能拖动然后固定
+                // resizeable 单元个大小是否可以调整
+                {
+                    headerName: this.$t('entraceguardUser.forbidden'),
+                    field: 'forbidden',
+                    sortable: true,
+                    filterFramework: 'RadioFilter',
+                    filterParams: {
+                        listData: this.booleanRender
+                    },
+                    width: 150,
+                    cellRenderer: (para) => {
+                        return this.radioFilterFormatter(para, this.booleanRender)
+                    }
+                },
+
+
+                {
+                    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,
+                    minWidth: this.$i18n.locale === 'zh' ? 260 : 380,
+                    resizable: false,
+                    sortable: false
+                },
+            ]
+            this.defaultColDef = {
+                // filter: 'agTextColumnFilter',
+                sortable: true,
+                resizable: true,
+                // comparator: this.dateCustomComparator,
+                filterParams: {
+                    debounceMs: 500,
+                    newRowsAction: 'keep',
+                    textCustomComparator: this.textCustomComparator
+                }
+            }
+            this.rowSelection = 'multiple'
+        },
+        mounted() {
+            window.onresize = this.windowResize()
+            this.gridApi = this.gridOptions.api
+            this.gridColumnApi = this.gridOptions.columnApi
+            this.gridColumnApi.applyColumnState({
+                state: [
+                    {
+                        colId: 'id',
+                        sort: 'asc'
+                    }
+                ]
+            })
+        },
+
+        methods: {
+            windowResize() {
+                this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+            },
+            /** 分页大小发生改变 */
+            handlePageSizeChange(size) {
+                this.params.page_size = size
+                this.getList()
+            },
+
+            /** 分页页数发生改变 */
+            handlePageCurrentChange(page) {
+                this.params.page_no = page
+                this.getList()
+            },
+            /** 加载列表数据 */
+            getList() {
+                const param = this.MixinClone(this.params)
+                this.gridApi.showLoadingOverlay()
+                API_Customer.getList(param).then(response => {
+                    this.rowData = [...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)
+                        }
+                    })
+                })
+            },
+            /**
+             * 过滤状态发生变化,发送到服务器检索数据
+             */
+            filterModifed(param) {
+                var model = param.api.getFilterModel()
+                this.params.filter = JSON.stringify(model)
+                this.getList()
+            },
+            gridSortChange(param) {
+                console.log('sortparam', 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()
+            },
+            /** 处理搜索 */
+            handlerSearch(keywords) {
+                this.params.query = keywords
+                this.getList()
+            },
+
+            handleEdit(row) {
+                this.formmodel = {
+                    ...row
+                }
+                this.customerFormVisible = true
+            },
+            refreshUser() {
+                API_Customer.refreshUser(this.$store.getters.partId).then(res => {
+                    this.getList()
+                }).catch(err => {
+                    this.$message.error(err.message)
+                })
+            },
+            radioFilterFormatter(params, array) {
+                const item = array.filter(p => p.value === params.value)[0]
+                if (item) {
+                    if (item.color) {
+                        return '<span style="color:' + item.color + '">' + item.key + '</span>'
+                    } else {
+                        return item.key
+                    }
+                } else {
+                    return ''
+                }
+            },
+            handlerSubmit(formName){
+                this.$refs[formName].validate(valid => {
+                    if (valid) {
+
+                            API_Customer.update(this.formmodel.id,this.formmodel).then(res => {
+                                this.getList()
+                                this.$message.success(this.$t('action.editSuccess'))
+                                this.customerFormVisible = false
+                            })
+
+                    } else {
+                        this.$message.error(this.$t('action.fromError'))
+                        return false
+                    }
+                })
+            }
+        }
+    }
+</script>
+
+<style scoped>
+
+</style>

+ 143 - 0
src/views/function-mapping/components/RoleForFunction.vue

@@ -0,0 +1,143 @@
+<template>
+    <div>
+        <el-card>
+
+            <fieldset style="margin-top: 10px">
+                <legend><span
+                        style="margin-right: 10px">{{this.$t('functionRoleMapping.configurateLeft')+this.$t(functions.language_dependence_code)+this.$t('functionRoleMapping.configurateRight')}}</span>
+                    <el-checkbox v-model="allCkeck" style="float: right;" :indeterminate="indeterminate"
+                                 @change="(checked)=>{handleCheckAll(checked)}">{{ this.$t('action.choiceAll') }}
+                    </el-checkbox>
+                </legend>
+                <el-row :gutter="20" type="flex" style="padding: 10px">
+                    <el-col :span="24">
+                        <el-checkbox v-for="(role,_index) in roles" :key="_index" v-model="role.checked"
+                                     @change="handleCheckboxChanged(role)">{{ role.role_name }}
+                        </el-checkbox>
+                    </el-col>
+                </el-row>
+            </fieldset>
+
+
+            <div align="center" class="margin-top-sm">
+                <el-button type="success" @click="handlerSubscribeSubmit">{{ this.$t('action.saveSettings') }}
+                </el-button>
+
+            </div>
+
+
+        </el-card>
+
+    </div>
+</template>
+
+<script>
+    import * as API_Role from '@/api/role'
+    import * as API_FunctionRoleMapping from '@/api/ncs_functions_role_mapping'
+
+    export default {
+        name: "RoleForFunction",
+        props: {
+            functions: {
+                type: Object,
+                default: () => {
+                }
+            }
+        },
+        data() {
+            return {
+                allCkeck: false,
+                roles: [],
+                indeterminate: false,
+                functionRoleMapping: {}
+            }
+        },
+       async mounted() {
+            this.roles = await API_Role.getRoleList(-1)
+            this.getFunctionsRoleMappingByCodeAndPartId()
+        },
+        methods: {
+            handleCheckboxChanged(role) {
+
+                this.caculateCheckAllState()
+            },
+            handleCheckAll(checked) {
+                this.roles.forEach(item => {
+                    this.$set(item, 'checked', checked)
+                })
+                this.caculateCheckAllState()
+            },
+
+            caculateCheckAllState(){
+                const checkedLength = this.roles.filter(p => p.checked).length
+                this.allCkeck = checkedLength === this.roles.length
+                this.indeterminate = checkedLength !== 0 && checkedLength !== this.roles.length
+            },
+
+            // getRoleList() { // roleEdit 保存成功时回调会传入当前role实体,新增时需要根据当前role选择新添加的角色
+            //     API_Role.getRoleList(-1).then(res => {
+            //         this.roles = [...res]
+            //     }).catch(err => {
+            //         this.$error(err.message)
+            //     })
+            // },
+            getFunctionsRoleMappingByCodeAndPartId() {
+                API_FunctionRoleMapping.getFunctionsRoleMappingByCodeAndPartId(this.functions.function_code, this.$store.getters.partId).then(res => {
+                    if (res !== null && res !== '') {
+                        this.functionRoleMapping = {...res}
+                        const roleids = res.role_ids.split(',').map(p=>Number(p))
+                        this.roles.forEach(item => {
+                            this.$set(item, 'checked', roleids.includes(item.role_id))
+                        })
+
+                        this.caculateCheckAllState()
+                    }
+                }).catch(err => {
+                    this.$message.error(err.message)
+                })
+            },
+            handlerSubscribeSubmit() {
+
+                const checkedRoleId = this.roles.filter(p => p.checked).map(p => p.role_id).join(',')
+                if(Object.keys(this.functionRoleMapping).length>0){
+                    this.functionRoleMapping.role_ids =checkedRoleId
+                }
+                else{
+                    this.functionRoleMapping={
+                        function_code:this.functions.function_code,
+                        part_id:this.$store.getters.partId,
+                        function_id:this.functions.id,
+                        role_ids:checkedRoleId
+                    }
+                }
+                if(this.functionRoleMapping.id!==null&&this.functionRoleMapping.id!==undefined){
+                    API_FunctionRoleMapping.update(this.functionRoleMapping.id,this.functionRoleMapping).then(res=>{
+                     this.functionRoleMapping={...res}
+                        this.$message.success(this.$t('action.settingsSuccess'))
+                    }).catch(err=>{
+                        this.$message.error(err.message)
+                    })
+                }else{
+                    API_FunctionRoleMapping.add(this.functionRoleMapping).then(res=>{
+                        this.functionRoleMapping={...res}
+                        this.$message.success(this.$t('action.settingsSuccess'))
+                    }).catch(err=>{
+                        this.$message.error(err.message)
+                    })
+                }
+
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    fieldset {
+        border: 1px solid #DCDFE6;
+        border-radius: 5px;
+    }
+
+    .margin-top-sm {
+        margin-top: 20px;
+    }
+</style>

+ 43 - 0
src/views/function-mapping/index.vue

@@ -0,0 +1,43 @@
+<template>
+    <div class="app-container">
+        <el-tabs tab-position="left" :style="{height: (mainAreaHeight-40)+'px'}">
+            <el-tab-pane :label="$t(item.language_dependence_code)" v-for="(item,index) in functions" :key="index">
+                <role-for-function :functions="item"></role-for-function>
+            </el-tab-pane>
+
+
+        </el-tabs>
+    </div>
+</template>
+
+<script>
+    import * as API_Function from '@/api/ncs_functions'
+    import RoleForFunction from "./components/RoleForFunction";
+    export default {
+        name: "index",
+        components: {RoleForFunction},
+        data(){
+            return{
+                functions:[]
+            }
+        },
+        mounted(){
+            this.getAllFunctions()
+        },
+        methods:{
+            getAllFunctions(){
+                API_Function.getAll().then(
+                    res=>{
+                        this.functions=[...res]
+                    }
+                ).catch(err=>{
+                    this.$error(err.message)
+                })
+            }
+        }
+    }
+</script>
+
+<style scoped>
+
+</style>

+ 0 - 460
src/views/hospitalFrame/hospitalFrame.vue

@@ -1,460 +0,0 @@
-<template>
-  <div>
-    <div id="add-new-group">
-      <i class="add-btn" @click="frameAddVisible = true">+</i>
-      <div v-show="frameAddVisible" class="add-div">
-        <span class="add-div-title">房间</span>
-        <input v-model="frameName">
-        <el-button type="text" size="mini" @click="handleAddRoom">保存</el-button>
-        <el-button type="text" size="mini" @click="frameAddVisible = false">取消</el-button>
-      </div>
-    </div>
-    <div v-if="hospital_frame" id="params-container">
-      <el-card>
-        <div slot="header" class="clearfix">
-          <span><i class="el-icon-school" />科室</span>
-        </div>
-        <div>
-          <el-button type="text" class="add-params-btn" @click="handlePartDevice"><i class="el-icon-cpu" /> 查看设备 [{{ hospital_frame.device_count }}]</el-button>
-        </div>
-      </el-card>
-      <el-card v-for="(item,index) in hospital_frame.frame_room_vos" v-if="hospital_frame.frame_room_vos" :key="index">
-        <div v-if="item.frame_room!=null" slot="header" class="clearfix">
-          <span><i class="el-icon-house" /> {{ item.frame_room.name }} 房</span>
-          <el-dropdown trigger="click" style="float: right" @command="handleGroupCommand">
-            <span class="el-dropdown-link">操作<i class="el-icon-arrow-down el-icon--right" /></span>
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item :command="{type: 'edit', frame: item.frame_room}">编辑</el-dropdown-item>
-              <el-dropdown-item :command="{type: 'delete', frame: item.frame_room}">删除</el-dropdown-item>
-              <el-dropdown-item :command="{type: 'device', frame: item.frame_room}" divided><i class="el-icon-cpu" /> 设备 {{ item.device_count }}</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
-        </div>
-        <template v-if="item.frame_bed_vos && item.frame_bed_vos.length > 0">
-          <div v-for="(subItem, i) in item.frame_bed_vos" :key="i" class="param-item">
-            <span><i class="el-icon-s-flag" /> {{ subItem.frame_bed.name }} 床</span>
-            <span v-if="subItem.customer_id">
-              <el-button style="width: 150px;" size="mini" plain round @click="handleEditPatient(subItem.customer_id,subItem.frame_bed.id)">
-                <i class="el-icon-user" /> {{ subItem.customer_name+ ' '+ subItem.customer_age+subItem.customer_age_unit }}
-                <span v-if="subItem.customer_sex === 1">男</span>
-                <span v-else-if="subItem.customer_sex === 0">女</span>
-                <span v-else>未知</span>
-              </el-button>
-            </span>
-            <span v-else>
-              <el-button size="mini" type="success" plain round @click="handleAddPatient(subItem.frame_bed)"><i class="el-icon-circle-plus-outline" /> 用户</el-button>
-            </span>
-            <span>
-              <el-dropdown size="mini" @command="handleGroupCommand">
-                <span class="el-dropdown-link">操作<i class="el-icon-arrow-down el-icon--right" /></span>
-                <el-dropdown-menu slot="dropdown">
-                  <el-dropdown-item :command="{type: 'edit', frame: subItem.frame_bed}">编辑</el-dropdown-item>
-                  <el-dropdown-item :command="{type: 'delete', frame: subItem.frame_bed}" style="color: #F56C6C">删除</el-dropdown-item>
-                  <el-dropdown-item :command="{type: 'device', frame: subItem.frame_bed}" divided><i class="el-icon-cpu" /> 设备 {{ subItem.device_count }}
-                  </el-dropdown-item>
-                </el-dropdown-menu>
-              </el-dropdown>
-            </span>
-          </div>
-          <el-button type="text" class="add-params-btn" @click="handleAddFrame(item.frame_room.id, item.frame_room.name)"><i class="el-icon-circle-plus" /> 添加床位</el-button>
-        </template>
-        <template v-else>
-          <div class="param-item empty">暂无数据...</div>
-          <el-button type="text" class="add-params-btn" @click="handleAddFrame(item.frame_room.id, item.frame_room.name)"><i class="el-icon-circle-plus" /> 添加床位</el-button>
-        </template>
-      </el-card>
-    </div>
-
-    <el-dialog
-      title="用户信息"
-      :visible.sync="dialogPatientVisible"
-      width="85%"
-    >
-      <customer-edit :customer-id="customerId" :frame-id="frameId" @saved="handlePatientFinished" />
-    </el-dialog>
-
-    <el-dialog title="科室结构" :visible.sync="dialogFrameVisible" width="500px">
-      <el-form ref="editForm" :model="frameInfo" :rules="rules" label-width="110px">
-        <el-row>
-          <el-col :span="24">
-            <!--医院结构名称-->
-            <el-form-item label="名称" prop="name">
-              <el-input v-model="frameInfo.name" :maxlength="20">
-                <template slot="append">{{ frameInfo.type === 4?"房":"床" }}</template>
-              </el-input>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <!--医院结构别名-->
-            <el-form-item label="别名" prop="alias">
-              <el-input v-model="frameInfo.alias" :maxlength="20" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row hidden>
-          <el-col :span="12">
-            <el-form-item label="类型">
-              <el-radio v-model="frameInfo.type" :label="1">客房</el-radio>
-              <el-radio v-model="frameInfo.type" :label="2">床位</el-radio>
-            </el-form-item>
-          </el-col>
-        </el-row>
-
-        <el-form-item>
-          <el-button type="primary" class="save" @click="handlerSubmit('editForm')">保存修改</el-button>
-        </el-form-item>
-      </el-form>
-    </el-dialog>
-
-    <el-drawer
-      :title="selectedFrame.full_name+' 设备'"
-      :visible.sync="deviceVisible"
-      :append-to-body="true"
-      size="60%"
-    >
-      <device-info :frame-id="frameId" :frame="selectedFrame" />
-    </el-drawer>
-  </div>
-</template>
-
-<script>
-import * as HospitalFrame_API from '@/api/ncs_hospitalFrame'
-import * as RegExp from '@/utils/RegExp'
-import customerEdit from '@/views/customer/customerEdit'
-import DeviceInfo from '@/views/ncs-device/deviceInfo'
-
-export default {
-  name: 'HospitalFrame',
-  components: { DeviceInfo, customerEdit },
-  data: function() {
-    return {
-      hospital_frame: null,
-      frameAddVisible: false,
-      frameName: '',
-      dialogPatientVisible: false,
-      customerId: null,
-      dialogFrameVisible: false,
-      frameInfo: {},
-      deviceVisible: false,
-      frameId: 0,
-      selectedFrame: {},
-      rules: {
-        name: [
-          this.MixinRequired('请输入名称!'),
-          { min: 1, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
-          {
-            validator: (rule, value, callback) => {
-              if (!RegExp.userName.test(value)) {
-                callback(new Error('只支持汉字、字母、数字、“-”、“_”的组合!'))
-              } else {
-                callback()
-              }
-            }
-          }
-        ],
-        alias: [
-          { min: 1, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
-          {
-            validator: (rule, value, callback) => {
-              if (!value) {
-                callback()
-              }
-              if (!RegExp.userName.test(value)) {
-                callback(new Error('只支持汉字、字母、数字、“-”、“_”的组合!'))
-              } else {
-                callback()
-              }
-            }
-          }
-        ]
-      },
-      fullName: null
-    }
-  },
-  watch: {
-    deviceVisible: function(newData) {
-      if (!newData) {
-        this.GET_All()
-      }
-    }
-  },
-  mounted() {
-    this.GET_All()
-  },
-  methods: {
-    GET_All() {
-      HospitalFrame_API.getHospitalFrameList(this.$store.getters.userInfo.last_login_shopid).then(response => {
-        if (response) {
-          console.log(response)
-          this.hospital_frame = response
-        }
-      }).catch(response => {
-        this.$message({
-          type: 'info',
-          message: response.message
-        })
-      })
-    },
-    /** 下拉触发 */
-    handleGroupCommand(object) {
-      console.log(object)
-      this.selectedFrame = object.frame
-      switch (object.type) {
-        case 'edit':
-          this.handelEditFrame(object.frame)
-          break
-        case 'delete':
-          this.handlerDeleteFrame(object.frame.id)
-          break
-        case 'device':
-          this.frameId = object.frame.id
-          this.openDeviceList()
-          break
-      }
-    },
-    handleAddPatient(bedFrame) {
-      this.customerId = 0
-      this.frameId = bedFrame.id
-      this.dialogPatientVisible = true
-    },
-    handlePatientFinished() {
-      this.dialogPatientVisible = false
-      this.GET_All()
-    },
-    handleEditPatient(id, frameId) {
-      this.dialogPatientVisible = true
-      this.customerId = id
-      this.frameId = frameId
-    },
-    // frame handle
-    handleAddRoom() {
-      let parent_id = null
-      if (this.hospital_frame) {
-        parent_id = this.hospital_frame.frame_part.id
-      }
-      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.$t('action.addSuccess2'))
-        this.GET_All()
-      })
-    },
-    handleAddFrame(id, name) { // 新增床位
-      this.frameInfo = {}
-      this.frameInfo = { parent_id: id, type: 5 }
-      this.fullName = name
-      this.dialogFrameVisible = true
-    },
-    handelEditFrame(frame) {
-      this.frameInfo = { id: frame.id, type: frame.type, name: frame.name, alias: frame.alias, full_name: frame.full_name }
-      this.dialogFrameVisible = true
-    },
-    handleFrameFinished() {
-      this.dialogFrameVisible = false
-      this.GET_All()
-    },
-    /** 单条数据删除处理 */
-    handlerDeleteFrame(ids) {
-      this.$confirm('确定要删除此结构及其所有下级吗?', this.$t('action.waring'), {
-        confirmButtonText: this.$t('action.yes'),
-        cancelButtonText: this.$t('action.cancel'),
-        type: 'warning'
-      }).then(() => {
-        HospitalFrame_API.deleteHospitalFrame(ids).then(response => {
-          this.$message({
-            type: 'success',
-            message: '已删除!'
-          })
-          this.GET_All()
-        }).catch(response => {
-          this.$message({
-            type: 'info',
-            message: response.message
-          })
-        })
-      })
-    },
-
-    // --------------------设备管理
-    handlePartDevice() {
-      this.frameId = this.hospital_frame.frame_part.id
-      this.selectedFrame = this.hospital_frame.frame_part
-      this.openDeviceList()
-    },
-    openDeviceList() {
-      this.deviceVisible = true
-    },
-    handlerSubmit(formName) {
-      this.$refs[formName].validate(valid => {
-        if (valid) {
-          const params = this.MixinClone(this.frameInfo)
-          if (params.id) {
-            if (params.type === 5) {
-              const name = params.full_name.split('-')
-              params.full_name = name[0] + '-' + params.name + '床'
-            } else if (params.type === 4) {
-              params.full_name = params.name + '房'
-            }
-            HospitalFrame_API.updateHospitalFrame(params.id, params).then(response => {
-              this.$message.success(this.$t('action.editSuccess'))
-              this.handleFrameFinished()
-            })
-          } else {
-            if (!params.part_id) {
-              params.part_id = this.$store.getters.partId
-            }
-            params.full_name = this.fullName + '房-' + params.name + '床'
-            HospitalFrame_API.addHospitalFrame(params).then(response => {
-              this.$message.success(this.$t('action.addSuccess2'))
-              this.handleFrameFinished()
-            })
-          }
-        } else {
-          this.$message.error(this.$t('action.fromError'))
-          return false
-        }
-      })
-    }
-
-  }
-}
-</script>
-
-<style type="text/scss" lang="scss" scoped>
-  #params-container {
-    display: flex;
-    flex-wrap: wrap;
-    position: relative;
-    background-color: #fff;
-    padding: 10px;
-    min-height: 150px;
-
-    .el-card {
-      min-width: 350px;
-      max-width: 500px;
-      min-height: 100px;
-      margin: 10px;
-      overflow: hidden;
-    }
-
-    .el-card__header {
-      padding: 10px 15px;
-      background-color: #f5f7fa;
-    }
-
-    .el-card__body {
-      padding: 10px !important;
-    }
-
-    .el-dropdown-link {
-      cursor: pointer;
-      color: #409eff
-    }
-
-    .el-icon-arrow-down {
-      font-size: 12px
-    }
-  }
-
-  #add-new-group {
-    position: absolute;
-    left: 10px;
-    top: 10px;
-    z-index: 10;
-    min-width: 30px;
-    height: 30px;
-    background: #475669;
-    border-radius: 50%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    transition: background-color .3s ease;
-
-    &:hover {
-      background-color: rgb(192, 204, 218);
-      cursor: pointer;
-
-      .add-btn {
-        color: rgb(71, 86, 105)
-      }
-    }
-
-    .add-btn {
-      display: block;
-      width: 30px;
-      text-align: center;
-      font-size: 30px;
-      font-weight: bold;
-      color: white;
-      margin-top: -7px;
-    }
-
-    .add-div {
-      display: flex;
-      background: #324057;
-      align-items: center;
-      justify-content: space-around;
-      min-width: 330px;
-      height: 40px;
-      position: absolute;
-      top: -5px;
-      left: 50px;
-      padding: 2px 5px;
-      color: #F9FAFC;
-      box-shadow: 0 0 10px 0 #303133;
-
-      .add-div-title {
-        font-size: 12px
-      }
-    }
-  }
-
-  .add-params-btn {
-    width: 100%;
-  }
-
-  .el-tag + .el-tag {
-    margin-left: 10px;
-  }
-
-  .button-new-tag {
-    margin-left: 10px;
-    height: 32px;
-    line-height: 30px;
-    padding-top: 0;
-    padding-bottom: 0;
-  }
-
-  .input-new-tag {
-    width: 90px;
-    margin-left: 10px;
-    vertical-align: bottom;
-  }
-
-  .el-checkbox + .el-checkbox {
-    margin-left: 20px
-  }
-
-  .el-button + .el-button {
-    margin-left: 0
-  }
-
-  .param-item {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    padding: 7px;
-    background-color: #f5f7fa;
-    font-size: 14px;
-
-    &.empty {
-      background-color: #fff
-    }
-  }
-
-  .line {
-    line-height: 32px;
-  }
-</style>

+ 14 - 12
src/views/hospitalFrame/nurse_watch_frame.vue

@@ -3,24 +3,24 @@
 
       <el-form ref="editform" label-width="80px">
         <el-tabs v-model="activeName" style="margin:0px;" type="border-card">
-          <el-tab-pane label="所有房间" name="frameInfo">
+          <el-tab-pane :label="$t('watch.allFrame')" name="frameInfo">
 <!--        <fieldset class="margin-top-sm">-->
 <!--          <legend>{{ watchDeviceFrame }}</legend>-->
           <el-row v-if="rooms.length > 1" :gutter="20" type="flex">
             <el-col v-for="(item,index) in rooms" :key="index" :xs="8" :sm="8" :md="6" :lg="6" :xl="6">
               <el-card class="box-card">
-                <div v-if="roleName !== '护士组长'" slot="header" class="clearfix">
+                <div v-if="roleId !== 8" slot="header" class="clearfix">
                   <el-checkbox v-if="uiVersion === 1" v-model="item.checked" @change="handleCheckboxChanged(item)"><svg-icon icon-class="sickroom" style="color: #9aaabf;margin-right: 5px" /><span>{{ item.name }}</span></el-checkbox>
                   <span v-if="uiVersion !== 1"><svg-icon icon-class="sickroom" style="color: #9aaabf;margin-right: 5px" /><span>{{ item.name }}</span></span>
                   <el-checkbox v-model="item.allCkeck" style="float: right" :indeterminate="item.indeterminate" @change="(checked)=>{handleCheckAll(checked,item)}">
                     {{ $t('action.choiceAll') }}</el-checkbox>
                 </div>
                 <div v-for="(bed,_index) in item.children" :key="_index" class="text item">
-                  <el-checkbox  v-if="roleName !== '护士组长'" v-model="bed.checked" @change="handleCheckboxChanged(item)"><svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />
+                  <el-checkbox  v-if="roleId !== 8" v-model="bed.checked" @change="handleCheckboxChanged(item)"><svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />
                     <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
                     <span v-else>{{ bed.full_name }}</span>
                   </el-checkbox>
-                  <div v-if="roleName === '护士组长'">
+                  <div v-if="roleId === 8">
                     <svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />
                     <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
                     <span v-else>{{ bed.full_name }}</span>
@@ -32,19 +32,19 @@
           <el-row v-if="rooms.length === 1" :gutter="20" type="flex">
             <el-col :span="24">
               <div class="text item">
-                <div v-if="roleName !== '护士组长'" style="margin: 10px;">
+                <div v-if="roleId !== 8" style="margin: 10px;">
                   <el-checkbox v-if="uiVersion === 1" v-model="rooms[0].checked" @change="handleCheckboxChanged(rooms[0])"><svg-icon icon-class="sickroom" style="color: #9aaabf;margin-right: 5px" /><span>{{ rooms[0].name }}</span></el-checkbox>
                   <span v-if="uiVersion !== 1"><svg-icon icon-class="sickroom" style="color: #9aaabf;margin-right: 5px" /><span>{{ rooms[0].name }}</span></span>
                   <el-checkbox v-model="rooms[0].allCkeck" style="margin-left: 30px;" :indeterminate="rooms[0].indeterminate" @change="(checked)=>{handleCheckAll(checked,rooms[0])}">{{ $t('action.choiceAll') }}</el-checkbox>
                 </div>
                 <el-row>
                   <el-col v-for="(bed,_index) in rooms[0].children" :key="_index" :xs="8" :sm="8" :md="6" :lg="6" :xl="6">
-                    <el-checkbox v-if="roleName !== '护士组长'" v-model="bed.checked" @change="handleCheckboxChanged(rooms[0])">
+                    <el-checkbox v-if="roleId !== 8" v-model="bed.checked" @change="handleCheckboxChanged(rooms[0])">
                       <svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />
                       <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
                       <span v-else>{{ bed.full_name }}</span>
                     </el-checkbox>
-                    <div v-if="roleName === '护士组长'">
+                    <div v-if="roleId !== 8">
                       <svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />
                       <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
                       <span v-else>{{ bed.full_name }}</span>
@@ -60,18 +60,18 @@
             <el-row v-if="group[1].length > 1" :gutter="20" type="flex">
               <el-col v-for="(item,index) in group[1]" :key="index" :xs="8" :sm="8" :md="6" :lg="6" :xl="6">
                 <el-card class="box-card">
-                  <div v-if="roleName !== '护士组长'" slot="header" class="clearfix">
+                  <div v-if="roleId !== 8" slot="header" class="clearfix">
                     <el-checkbox v-if="uiVersion === 1" v-model="item.checked" @change="handleCheckboxChanged(item)"><svg-icon icon-class="sickroom" style="color: #9aaabf;margin-right: 5px" /><span>{{ item.name }}</span></el-checkbox>
                     <span v-if="uiVersion !== 1"><svg-icon icon-class="sickroom" style="color: #9aaabf;margin-right: 5px" /><span>{{ item.name }}</span></span>
                     <el-checkbox v-model="item.allCkeck" style="float: right" :indeterminate="item.indeterminate" @change="(checked)=>{handleCheckAll(checked,item)}">
                       {{ $t('action.choiceAll') }}</el-checkbox>
                   </div>
                   <div v-for="(bed,_index) in item.children" :key="_index" class="text item">
-                    <el-checkbox  v-if="roleName !== '护士组长'" v-model="bed.checked" @change="handleCheckboxChanged(item)"><svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />
+                    <el-checkbox  v-if="roleId !== 8" v-model="bed.checked" @change="handleCheckboxChanged(item)"><svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />
                       <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
                       <span v-else>{{ bed.full_name }}</span>
                     </el-checkbox>
-                    <div v-if="roleName === '护士组长'">
+                    <div v-if="roleId === 8">
                       <svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />
                       <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
                       <span v-else>{{ bed.full_name }}</span>
@@ -82,7 +82,7 @@
             </el-row>
           </el-tab-pane>
         </el-tabs>
-        <el-form-item v-if="roleName !== '护士组长'" align="center" class="margin-top-sm">
+        <el-form-item v-if="roleId !== 8" align="center" class="margin-top-sm">
           <el-button type="success" @click="onSubmit">{{ $t('action.saveSettings') }}</el-button>
           <el-button type="primary" @click="onQK">{{ $t('action.deleteSettings') }}</el-button>
           <el-button @click="back">{{ $t('action.back') }}</el-button>
@@ -178,9 +178,10 @@ export default {
                 return acc
               }, {})
 
-      if (this.roleName === '护士组长') {
+      if (this.roleId === 8) {
         API_hospitalFrame.getFrameByRoleGroupId(this.$store.getters.partId, this.memberId).then(res => {
           _this.rooms = _this.filterGroupFrames(res)
+
           const room_group = groupBy(_this.rooms, item => item.group_name)
           _this.roomGroup = Object.entries(room_group)
           console.log(_this.roomGroup)
@@ -188,6 +189,7 @@ export default {
       } else {
         API_hospitalFrame.getFrameByRoleId(this.$store.getters.partId, this.roleId).then(res => {
           _this.rooms = _this.filterGroupFrames(res)
+          console.log('rooms',_this.rooms)
           const room_group = groupBy(_this.rooms, item => item.group_name)
           _this.roomGroup = Object.entries(room_group)
         })

+ 552 - 0
src/views/interaction-chain/index.vue

@@ -0,0 +1,552 @@
+<template>
+    <div>
+        <ag-grid-layout
+                toolbar
+                :table-height="tableHeight"
+                theme="ag-theme-alpine"
+                :column-defs="columnDefs"
+                :row-data="rowData"
+                :locale-text="localeText"
+                :grid-options="gridOptions"
+                :default-col-def="defaultColDef"
+                :animate-rows="true"
+                :row-selection="rowSelection"
+                :enable-cell-change-flash="true"
+                @filterChanged="filterModifed"
+                @sortChanged="gridSortChange"
+        >
+            <!--        @rowDoubleClicked="getList"-->
+            <div slot="toolbar" class="inner-toolbar">
+                <div class="toolbar-search">
+                    <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
+                </div>
+                <div class="toolbar-btns">
+                    <el-button type="primary" size="mini" @click="createBroadcast">{{ this.$t('action.add') }}</el-button>
+                </div>
+            </div>
+            <el-pagination
+                    v-if="pageData"
+                    slot="pagination"
+                    :current-page="pageData.page_no"
+                    :page-sizes="[10, 20, 50, 100]"
+                    :page-size="pageData.page_size"
+                    layout="total, sizes, prev, pager, next, jumper"
+                    :total="pageData.data_total"
+                    @size-change="handlePageSizeChange"
+                    @current-change="handlePageCurrentChange"
+            />
+        </ag-grid-layout>
+
+
+
+        <el-dialog :title.sync="formtitle" :visible.sync="formshow" width="55%">
+            <div>
+                <el-form ref="editform" :rules="rules" label-width="120px" :model="formmodel">
+
+                    <el-form-item :label="this.$t('interactionChain.ActionType')" prop="action_type">
+                        <el-select v-model="formmodel.action_type"
+                                   clearable >
+                            <el-option v-for="(item,index) in interactionTypes" :key="index" :label="item.key" :value="item.value"/>
+                        </el-select>
+                    </el-form-item>
+                    <el-row>
+                        <el-col :span="24" >
+                            <el-form-item :label="this.$t('interactionChain.AcceptSequence')" prop="role_path">
+                            <el-transfer
+                                    filterable
+                                    :filter-method="filterMethod"
+                                    :titles="[this.$t('interactionChain.AllRoles'), this.$t('interactionChain.AcceptRoles')+'('+this.$t('interactionChain.NoticeSequence')+')']"
+                                    :filter-placeholder="this.$t('interactionChain.SearchPlaceHolder')"
+                                    v-model="role_path"
+                                    :props="{key:'role_id',label:'role_name'}"
+                                    :data="role_data"
+                                    target-order="push"
+                            @change="roleDataChange"
+                            >
+                            </el-transfer>
+
+
+</el-form-item>
+                        </el-col>
+
+                    </el-row>
+                    <el-row>
+                        <el-col :span="24">
+                            <h3>{{this.$t('interactionChain.sketchMap')}}</h3>
+                            <el-steps  finish-status="success">
+
+                                <el-step :title="item.role_name" v-for="(item,index) in role_path_step" :key="index" status="finish"></el-step>
+
+                            </el-steps>
+                        </el-col>
+                    </el-row>
+                </el-form>
+
+            </div>
+            <div slot="footer" class="dialog-footer">
+                <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>
+
+</template>
+
+<script>
+    import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
+    import ButtonCellRenderList from '@/components/AgGridCellRender/ButtonCellRenderList'
+    import * as API_InteractionChain from '@/api/ncs_interaction-chain'
+    import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
+    import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
+    const serverUrl = domain.serverUrl
+    const DeviceUrl = domain.DeviceUrl
+    import * as API_FunctionRoleMapping from '@/api/ncs_functions_role_mapping'
+    import * as API_Role from '@/api/role'
+    import i18n from "../../utils/i18n";
+    const customer={role_name:i18n.t('interactionChain.Customer') ,role_id:0}
+    const nurse_host={role_name:i18n.t('interactionChain.NURSE_HOST'),role_id:-1}
+    export default {
+        name: 'Index',
+        components: { ButtonCellRenderList, ListFilter, RadioFilter },
+        data() {
+            return {
+                tableData: [],
+                role_data:[],
+                role_path:[],
+                role_path_step:[customer,nurse_host],
+                /** 列表参数 */
+                params: {
+                    page_size: 20,
+                    page_no: 1,
+                    fixedCondition: ' part_id = ' + this.$store.getters.partId
+                },
+                /** 新建组织弹出参数 **/
+                formtitle: this.$t('interactionChain.AddInteractionSpreadPath'),
+                formshow: false,
+                formmodel: {
+                    repeat_times: 1,
+                    group_ids: []
+                },
+                rules: {
+                    action_type: [
+                        { required: true, message: this.$t('interactionChain.chooseActionTypeTip'), trigger: 'blur' }
+                    ],
+                    role_path:[{
+                        required: true,
+                        validator: (rule, value, callback) => {
+                            console.log('rule',value)
+                            if (this.role_path.length>0) {
+                                callback()
+                            } else {
+                                callback(new Error(this.$t('interactionChain.chooseRoleSquence')))
+                            }
+                        },
+                        trigger: 'change'
+                    }]
+                },
+                /** ag-grid参数 **/
+                pageData: [],
+                loading: false,
+                errorId: null,
+                columnDefs: null,
+                rowData: null,
+                defaultColDef: null,
+                gridOptions: null,
+                gridApi: null,
+                columnApi: null,
+                localeText: AG_GRID_LOCALE_CN,
+                filterState: null,
+                rowSelection: null,
+                frameworkComponents: null,
+                manageBedRole:{},
+                canManageBedRoleIds:[],
+                canManageBedRole:[],
+                interactionTypes:[{
+                    key:this.$t('tcpType.EVENT'),
+                    value:'EVENT'
+                },{
+                    key:this.$t('tcpType.VOICE'),
+                    value:'VOICE'
+                },{
+                    key:this.$t('tcpType.VIDEO'),
+                    value:'VIDEO'
+                },{
+                    key:this.$t('tcpType.IM'),
+                    value:'IM'
+                }]
+            }
+        },
+        computed: {
+            tableHeight() {
+                return this.mainAreaHeight - 130
+            }
+        },
+        beforeMount() {
+            this.gridOptions = {}
+            this.columnDefs = [
+                {
+                    headerName: '#',
+                    headerCheckboxSelection: true,
+                    headerCheckboxSelectionFilteredOnly: true,
+                    checkboxSelection: true,
+                    sortable: false, filter: false,
+                    width: 100,
+                    resizable: false,
+                    valueGetter: this.hashValueGetter
+                },
+                { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 130 },
+                {
+                    headerName: this.$t('interactionChain.ActionType'), field: 'action_type', sortable: true, filterFramework: 'ListFilter', filterParams: {
+                        listData: this.interactionTypes
+                    }, width: 180,
+                    valueGetter: this.actionTypeGetter
+
+                },
+                {
+                    headerName: this.$t('interactionChain.FirstRole'), field: 'first_role_id', sortable: true, filterFramework: 'ListFilter', filterParams: {
+                        listData: this.canManageBedRole
+                    }, width: 180, cellRenderer: this.firstRoleFormatter
+                },
+                {
+                    headerName: this.$t('interactionChain.SpreadRoleNamePath'), field: 'spread_role_name_path', sortable: true, filter: 'agTextColumnFilter',
+                    flex:1,
+                    cellRenderer: this.chainFormatter
+                },
+
+                {
+                    headerName: this.$t('action.edit'), field: 'shop_id',
+                    cellRendererFramework: 'ButtonCellRenderList',
+                    cellRendererParams: param => {
+                        return {
+                            list: [
+                                {
+                                    onClick: this.handEdit,
+                                    label: this.$t('action.edit'),
+                                    buttonType: 'primary',
+                                    buttonSize: 'mini'
+                                },
+                                {
+                                    onClick: this.deleteSingle,
+                                    label: this.$t('action.delete'),
+                                    buttonType: 'danger',
+                                    buttonSize: 'mini'
+                                }
+                            ]}
+                    },
+                    filter: false,
+                    pinned: 'right',
+                    lockPinned: true,
+                    width: this.$i18n.locale === 'zh' ? 290 : 300,
+                    resizable: false,
+                    sortable: false
+                }
+            ]
+            this.defaultColDef = {
+                sortable: true,
+                resizable: true,
+                comparator: this.dateCustomComparator,
+                filterParams: {
+                    debounceMs: 200,
+                    newRowsAction: 'keep',
+                    textCustomComparator: this.textCustomComparator,
+                    comparator: this.dateCustomComparator
+                }
+            }
+            this.rowSelection = 'multiple'
+        },
+       async mounted() {
+
+           this.manageBedRole = await API_FunctionRoleMapping.getFunctionsRoleMappingByCodeAndPartId('MANAGE_BED', this.$store.getters.partId)
+           const {role_ids} = this.manageBedRole
+           if(role_ids!==undefined){
+               this.canManageBedRoleIds = role_ids.split(',').map(p=>Number(p))
+           }
+            window.onresize = this.windowResize
+            this.gridApi = this.gridOptions.api
+            this.gridColumnApi = this.gridOptions.columnApi
+            // 设置默认排序字段,应用列状态之后会触发 gridSortChange 函数,会调用getlist,后面不需要再调用this.getlist
+            this.gridColumnApi.applyColumnState({
+                state: [
+                    {
+                        colId: 'id',
+                        sort: 'asc'
+                    }
+                ]
+            })
+            this.getRoleList()
+
+
+
+        },
+        methods: {
+            windowResize() {
+                this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+            },
+           getRoleList(){
+               API_Role.getRoleList(-1).then(res => {
+
+                    res.forEach(item=>{
+                        this.$set(item,'can_manage_bed',this.canManageBedRoleIds.includes(item.role_id))
+                        })
+                   this.role_data=[...res]
+                   this.canManageBedRole =[...res.filter(p=>p['can_manage_bed']).map(p=>{return {'key':p.role_name,'value':p.role_id}})]
+                   this.columnDefs[3].filterParams.listData=this.canManageBedRole
+                   this.gridApi.setColumnDefs(this.columnDefs);
+                   this.setRoleStatus()
+                    console.log(this.role_data)
+               })
+           },
+           setRoleStatus(){
+               let allRoleIds= this.role_data.map(p=>p.role_id)
+               let disabledRoleIds=[] //要被禁止的ids
+               if(this.role_path.length==0){ //没有选择任何项,只需把不管床的角色禁用
+                   disabledRoleIds = this.role_data.filter(p=>!p['can_manage_bed']).map(p=>p.role_id)
+               }else{
+                   let choosedNoManageBed = this.role_path.filter(p=>!new Set(this.canManageBedRoleIds).has(p))
+                   let choosedManageBed = this.role_path.filter(p=>new Set(this.canManageBedRoleIds).has(p))
+                   if(choosedNoManageBed.length===this.role_path){ //选择的都不能管床,有问题
+                       disabledRoleIds=[]
+                       this.role_path=[]
+                   }else if(choosedNoManageBed.length>0){
+                     disabledRoleIds=[...choosedManageBed]
+                   }
+
+               }
+
+                this.role_data.forEach(item=>{
+                        this.$set(item,'disabled',disabledRoleIds.includes(item.role_id))
+                })
+           },
+            handlerDelete(ids) {
+                this.$confirm(this.$t('action.sureDelete'), this.$t('action.waring'), {
+                    confirmButtonText: this.$t('action.yes'),
+                    cancelButtonText: this.$t('action.cancel'),
+                    type: 'warning'
+                }).then(() => {
+                    API_InteractionChain.remove(ids).then(
+                        response => {
+                            this.$message({
+                                type: 'success',
+                                message: this.$t('action.deleted')
+                            })
+                            this.getList()
+                        }
+                    ).catch(response => {
+                        this.$message({
+                            type: 'info',
+                            message: response.message
+                        })
+                    })
+                }).catch(() => {
+                    this.$message({
+                        type: 'info',
+                        message: this.$t('action.cancelDelete')
+                    })
+                })
+            },
+            filterMethod(query,item){
+                return item.role_name.indexOf(query) > -1;
+            },
+            deleteSingle(row) {
+                this.handlerDelete(row.id)
+            },
+
+
+            /** 获取交互类型文字显示,从deviceTypeTransfer 中找出value值对应的key显示出来 */
+            actionTypeGetter(params) {
+                const gridVal = params.data.action_type
+                // return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
+                return this.interactionTypes.filter(p=>p.value===gridVal).map(p=>p.key)[0]
+            },
+            /**
+             * 创建接收顺序
+             */
+            createBroadcast() {
+                delete this.formmodel.id
+                this.formmodel={
+
+                }
+                this.role_path=[]
+                this.role_path_step=[customer,nurse_host]
+                this.setRoleStatus()
+                this.formshow = true
+            },
+            /** 分页大小发生改变 */
+            handlePageSizeChange(size) {
+                this.params.page_size = size
+                this.getList()
+            },
+            /** 分页页数发生改变 */
+            handlePageCurrentChange(page) {
+                this.params.page_no = page
+                this.getList()
+            },
+            /** 加载列表数据 */
+            getList() {
+                this.loading = true
+                const param = this.MixinClone(this.params)
+                this.gridApi.showLoadingOverlay()
+                API_InteractionChain.getList(param).then(response => {
+                    this.loading = false
+                    // this.tableData = [...response.data]
+                    this.pageData = {
+                        page_no: response.page_no,
+                        page_size: response.page_size,
+                        data_total: response.data_total
+                    }
+                    this.$nextTick(() => {
+                        const node = this.gridApi.getDisplayedRowAtIndex(0)
+                        if (node !== null && node !== undefined) {
+                            node.setSelected(true)
+                        }
+                    })
+                    this.rowData = [...response.data]
+                    this.refreshPlayStatus()
+                }).catch(() => {
+                    this.loading = false
+                })
+            },
+            /** 处理搜索 */
+            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()
+            },
+
+            chainFormatter(params){
+                return params.value.replaceAll(',','<i class="el-icon-right"></i>')
+            },
+            firstRoleFormatter(params) {
+                console.log('para', params)
+                // return
+               return params.data.spread_role_name_path.split(',')[0]
+
+            },
+
+            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()
+                // console.log(sortState)
+            },
+            filterModifed(param) { // todo 通过转换后的数值过滤,需要转回原始数值
+                // console.log(param)
+                var model = param.api.getFilterModel()
+                // console.log('model', JSON.stringify(model))
+                this.params.filter = JSON.stringify(model)
+                this.getList()
+            },
+            handEdit(row) {
+               this.formmodel ={
+                   ...row
+               }
+               this.role_path=row.spread_role_path.split(',').map(p=>Number(p))
+
+                this.roleDataChange(this.role_path)
+
+                this.setRoleStatus()
+               this.formshow=true
+
+            },
+            /**
+             * 提交新增表单
+             * @param formname
+             */
+            handlerFormSubmit(formName) {
+                this.$refs[formName].validate((valid) => {
+                    if (valid) {
+                        this.formmodel.part_id = this.$store.getters.partId
+                        this.formmodel.spread_role_path = this.role_path.join(',')
+                        this.formmodel.first_role_id = this.role_path[0]
+                        let chosedRoleName = []
+                        this.role_path.forEach(item => {
+                            chosedRoleName.push(this.role_data.filter(p => item === p.role_id).map(p => p.role_name))
+                        })
+                        this.formmodel.spread_role_name_path = chosedRoleName.join(',')
+                        if (this.formmodel.id === undefined) {
+                            /** 新增 */
+
+                            API_InteractionChain.add(this.formmodel).then(result => {
+                                console.log(result)
+                                this.formshow = false
+                                this.$message.success(this.$t('action.saveSuccess'))
+                                this.getList()
+                            })
+                        }else{
+                         API_InteractionChain.update(this.formmodel.id,this.formmodel).then(res=>{
+                             this.formshow = false
+                             this.$message.success(this.$t('action.saveSuccess'))
+                             this.getList()
+                         }).catch(err=>{
+                             this.$message.error(err.message)
+                         })
+                        }
+                    } else {
+                        this.$message.error(this.$t('action.fromError'))
+                    }
+
+                })
+            },
+
+            roleDataChange(val){
+                console.log(val)
+                let  chosedRole =[]
+                val.forEach(item=>{
+                    chosedRole.push(this.role_data.filter(p=>item===p.role_id)[0])
+                })
+                console.log(chosedRole)
+                this.role_path_step=[customer,...chosedRole,nurse_host]
+                this.setRoleStatus()
+            },
+
+
+        }
+    }
+    </script>
+
+<style scoped>
+
+/deep/
+.el-transfer-panel{
+    width:300px
+}
+
+</style>

+ 14 - 14
src/views/login/index.vue

@@ -9,14 +9,14 @@
             <h3 class="title">{{ this.$t('action.wdklCallingSystem') }}</h3>
           </div>
 
-          <el-form-item prop="username">
+          <el-form-item :prop="this.$t('action.usernameMsg')">
             <span class="svg-container">
               <svg-icon icon-class="user" />
             </span>
             <el-input
               ref="username"
               v-model="loginForm.username"
-              placeholder="Username"
+              :placeholder="this.$t('action.usernameMsg')"
               name="username"
               type="text"
               tabindex="1"
@@ -25,7 +25,7 @@
           </el-form-item>
 
           <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
-            <el-form-item prop="password">
+            <el-form-item :prop="this.$t('action.passwordMsg')">
               <span class="svg-container">
                 <svg-icon icon-class="password" />
               </span>
@@ -34,7 +34,7 @@
                 ref="password"
                 v-model="loginForm.password"
                 :type="passwordType"
-                placeholder="Password"
+                :placeholder="this.$t('action.passwordMsg')"
                 name="password"
                 tabindex="2"
                 autocomplete="on"
@@ -159,20 +159,20 @@ export default {
                 // this.$router.push({ path: '/' })
                 this.loading = false
               }).catch(err => {
-                Message({
-                  message: err,
-                  type: 'error',
-                  duration: 5 * 1000
-                })
+                // Message({
+                //   message: err,
+                //   type: 'error',
+                //   duration: 5 * 1000
+                // })
                 this.loading = false
               })
             })
             .catch((error) => {
-              Message({
-                message: error,
-                type: 'error',
-                duration: 5 * 1000
-              })
+              // Message({
+              //   message: error,
+              //   type: 'error',
+              //   duration: 5 * 1000
+              // })
               this.loading = false
             })
         } else {

+ 588 - 0
src/views/ncs-advice/index.vue

@@ -0,0 +1,588 @@
+<template>
+  <div>
+    <ag-grid-layout
+        toolbar
+        theme="ag-theme-alpine"
+        :column-defs="columnDefs"
+        :row-data="rowData"
+        :locale-text="localeText"
+        :grid-options="gridOptions"
+        :debounce-vertical-scrollbar="true"
+        :default-col-def="defaultColDef"
+        :animate-rows="true"
+        :row-selection="rowSelection"
+        :framework-components="frameworkComponents"
+        @filterChanged="filterModifed"
+        @sortChanged="gridSortChange"
+    >
+      <div slot="toolbar" class="inner-toolbar">
+        <div class="toolbar-search">
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
+        </div>
+
+        <div class="toolbar-btns">
+          <el-button type="primary" size="mini" @click="handleAdd">{{ this.$t('action.add') }}</el-button>
+          <el-button type="danger" size="mini" @click="batchDelete">{{ this.$t('action.deleteList') }}</el-button>
+        </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>
+
+    <!--添加医嘱 dialog-->
+    <el-dialog :title="adviceEditTitle" :visible.sync="dialogAddVisible"
+               width="50%" :close-on-click-modal="false" :close-on-press-escape="false"
+               append-to-body
+    >
+      <el-form ref="addAdviceForm" :model="addAdviceForm" :rules="addAdviceRules" label-width="80px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('adviceManage.adviceType')" prop="type">
+              <el-select v-model="addAdviceForm.type" :placeholder="this.$t('adviceManage.adviceType')" clearable>
+                <el-option v-for="(item, index) in Object.keys(adviceTypeEnum)" :key="index" :label="adviceTypeEnum[item]" :value="item" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('adviceManage.adviceStatus')" prop="status">
+              <el-radio v-model="addAdviceForm.status" :label="0">{{ this.$t('adviceManage.loseEfficacy') }}</el-radio>
+              <el-radio v-model="addAdviceForm.status" :label="1">{{ this.$t('adviceManage.takeEffect') }}</el-radio>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('action.startTime')" prop="start_time">
+              <el-date-picker
+                  v-model="addAdviceForm.start_time"
+                  type="date"
+                  :editable="false"
+                  value-format="timestamp"
+                  :default-value="new Date()"
+                  :placeholder="this.$t('customerManage.choiceDate')"
+                  :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('action.endTime')" prop="end_time">
+              <el-date-picker
+                  v-model="addAdviceForm.end_time"
+                  type="date"
+                  :editable="false"
+                  value-format="timestamp"
+                  :default-value="new Date()"
+                  :placeholder="this.$t('customerManage.choiceDate')"
+                  :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="24">
+            <el-form-item :label="this.$t('action.content')" prop="content">
+              <el-input
+                  v-model="addAdviceForm.content"
+                  type="textarea"
+                  :autosize="{ minRows: 2, maxRows: 4}"
+                  :minlength="2"
+                  :maxlength="50"
+                  :placeholder="this.$t('customerManage.inputAdvice')"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-form-item
+            v-for="(detail, index) in detailForm"
+            :label="$t('action.param')"
+            :key="detail.key"
+            :rules="{
+              required: false, trigger: 'blur'
+            }"
+          >
+            <el-col :span="8">
+              <el-input v-model="detailForm[index].name" :placeholder="$t('action.inputParamName')"></el-input>
+            </el-col>
+
+            <el-col :span="1">
+              <span style="margin-left: 10px">-</span>
+            </el-col>
+
+            <el-col :span="8">
+              <el-input v-model="detailForm[index].value" :placeholder="$t('action.inputParamValue')"></el-input>
+            </el-col>
+            <el-button style="margin-left: 20px" @click.prevent="removeDetail(detailForm[index])" type="danger" plain>
+              {{ $t('action.delete') }}</el-button>
+          </el-form-item>
+
+          <el-form-item>
+            <el-button @click="addDetail" type="primary" plain>{{ this.$t('action.addParam') }}</el-button>
+          </el-form-item>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogAddVisible = false">{{ this.$t('action.cancel') }}</el-button>
+        <el-button type="primary" @click="handlerFormSubmit('addAdviceForm')">{{ this.$t('action.yes') }}</el-button>
+      </div>
+    </el-dialog>
+  </div>
+
+</template>
+
+<script>
+import {AG_GRID_LOCALE_CN} from "@/utils/AgGridVueLocaleCn";
+import * as API_Advice from "@/api/ncs_advice";
+import {unix2Date, unixToDate} from "@/utils/Foundation";
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter";
+import {ADVICE_TYPE} from "@/utils/enum/AdviceTypeEnym";
+import {ADVICE_STATUS_TYPE} from "@/utils/enum/AdviceStatusTypeEnum";
+
+export default {
+  name: "Advice",
+  components: {ButtonCellRender, ListFilter, RadioFilter},
+  props: {
+    customerId: {
+      type: Number,
+      default: null
+    },
+    partId: {
+      type: Number,
+      default: null
+    },
+    activeName: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      /** ag-grid参数 **/
+      pageData: {}, // 翻页数据
+      errorId: null,
+      shopVisible: false,
+      columnDefs: null,
+      rowData: [],
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      filterState: null,
+      rowSelection: null,
+      frameworkComponents: null,
+      adviceEditTitle: this.$t('adviceManage.adviceEdit'),
+      /** 添加会员弹出框指示 */
+      dialogAddVisible: false,
+      /** 添加医嘱 表单数据 */
+      addAdviceForm: {},
+      /** 添加医嘱 表单规则 */
+      addAdviceRules: {
+        type: [
+          { required: true, message: '', trigger: 'blur' }
+        ],
+        content: [
+          { required: true, message: '', trigger: 'blur' }
+        ]
+      },
+      detailForm: [
+        {
+          name: '',
+          value: ''
+        }
+      ],
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+        fixedCondition: ' customer_id = ' + this.customerId,
+        sort: 'id',
+        dir: 'desc'
+      },
+      adviceTypeEnum: ADVICE_TYPE.getValueList(),
+    }
+  },
+  computed: {
+  },
+  watch: {},
+  beforeMount() {
+    this.gridOptions = {}
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 80,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      {headerName: this.$t('adviceManage.adviceType'), field: 'type', sortable: true, filter: 'agTextColumnFilter',
+        valueGetter: this.adviceTypeGetter,
+        width: 120,
+      },
+      {headerName: this.$t('adviceManage.adviceStatus'), field: 'status', sortable: true, filter: 'agNumberColumnFilter',
+        valueGetter: this.adviceStatusGetter,
+        width: 100,},
+      {
+        headerName: this.$t('action.startTime'),
+        field: 'start_time',
+        sortable: true,
+        filter: 'agDateColumnFilter',
+        valueFormatter: this.unixDateFormatter,
+        filterParams: {
+          comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
+            const celldate = unixToDate(cellValue, 'yyyy-MM-dd')
+            return (new Date(celldate).getTime() / 1000) - (filterLocalDateAtMidnight.getTime() / 1000)
+          }
+        }
+      },
+      {
+        headerName: this.$t('action.endTime'),
+        field: 'end_time',
+        sortable: true,
+        filter: 'agDateColumnFilter',
+        valueFormatter: this.unixDateFormatter,
+        filterParams: {
+          comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
+            const celldate = unixToDate(cellValue, 'yyyy-MM-dd')
+            return (new Date(celldate).getTime() / 1000) - (filterLocalDateAtMidnight.getTime() / 1000)
+          }
+        }
+      },
+      {headerName: this.$t('action.content'), field: 'content', sortable: true, filter: 'agTextColumnFilter'},
+      {headerName: this.$t('action.param'), field: 'detail', sortable: true, filter: 'agTextColumnFilter'},
+      {
+        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: 90,
+        resizable: false,
+        sortable: false
+      },
+      {
+        headerName: this.$t('action.delete'), field: 'id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.deleteSingle,
+            label: this.$t('action.delete'),
+            buttonType: 'danger',
+            buttonSize: 'mini',
+            disabled: param.data['member_name'] === 'superadmin'
+          }
+        },
+        pinned: 'right',
+        lockPinned: true,
+        width: 90,
+        resizable: false,
+        filter: false,
+        sortable: false
+      }
+    ]
+    this.defaultColDef = {
+      // filter: 'agTextColumnFilter',
+      sortable: true,
+      resizable: true,
+      enableValue: true,
+      filter: true,
+      // comparator: this.dateCustomComparator,
+      filterParams: {
+        debounceMs: 500,
+        newRowsAction: 'keep',
+        textCustomComparator: this.textCustomComparator
+      }
+    }
+    this.rowSelection = 'multiple'
+  },
+  mounted() {
+    window.onresize = this.windowResize
+    this.gridApi = this.gridOptions.api
+    // this.gridColumnApi = this.gridOptions.columnApi
+    this.getList()
+  },
+  methods: {
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    /** 加载列表数据 */
+    getList() {
+      const param = this.MixinClone(this.params)
+      this.gridApi.showLoadingOverlay()
+      API_Advice.getList(param).then(response => {
+        this.rowData = 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)
+          }
+        })
+      })
+    },
+
+    /**
+     * 过滤状态发生变化,发送到服务器检索数据
+     */
+    filterModifed(param) {
+      var 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()
+    },
+    /** 处理搜索 */
+    handlerSearch(keywords) {
+      this.params.query = keywords
+      this.getList()
+    },
+    /** 格式化时间函数 */
+    unixDateFormatter(param) {
+      if (!param.value) return ''
+      return unix2Date(param.value * 1000, 'yyyy-MM-dd')
+    },
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.getList()
+    },
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.getList()
+    },
+    formatterDate(params) {
+      return unixToDate(params.value)
+    },
+    /** 删除医嘱 **/
+    deleteSingle(row) {
+      this.handlerDelete(row.id)
+    },
+    /** 单条数据删除处理 */
+    handlerDelete(ids) {
+      this.$confirm(this.$t('action.sureDelete'), this.$t('action.waring'), {
+        confirmButtonText: this.$t('action.yes'),
+        cancelButtonText: this.$t('action.cancel'),
+        type: 'warning'
+      }).then(() => {
+        API_Advice.remove(ids).then(
+          response => {
+            this.getList()
+            this.$message({
+              type: 'success',
+              message: this.$t('action.deleted')
+            })
+          }
+        ).catch(response => {
+          this.$message({
+            type: 'info',
+            message: response.message
+          })
+        })
+      }).catch((response) => {
+        this.$message({
+          type: 'info',
+          message: this.$t('action.cancelDelete')
+        })
+      })
+    },
+    /** 批量数据删除处理(删除选中的行) */
+    batchDelete: function() {
+      const rows = this.gridApi.getSelectedRows()
+      if (rows.length === 0) {
+        this.$message({ type: 'info', message: this.$t('action.pleaseChoiceDelete') })
+        return
+      }
+      const ids = []
+      const uids = []
+      let isFounder = 0
+      rows.forEach(function(item) {
+        if (item.founder === 1) {
+          isFounder = 1
+          return
+        }
+        ids.push(item.clerk_id)
+        uids.push(item.member_id)
+      })
+      if (isFounder === 1) {
+        this.$message({ type: 'info', message: this.$t('action.cannotDeleteAdmin') })
+        return
+      }
+      this.handlerDelete(ids.join(','))
+    },
+    /** 添加医嘱事件 **/
+    handleAdd() {
+      this.adviceEditTitle = this.$t('adviceManage.adviceAdd')
+      this.dialogAddVisible = true
+      this.addAdviceForm = {
+        status: 1,
+        customer_id: this.customerId,
+        part_id: this.partId
+      }
+      this.detailForm = [
+        {
+          name: '',
+          value: ''
+        }
+      ]
+    },
+    /** 修改医嘱  **/
+    handleEdit(params) {
+      this.addAdviceForm = {
+        ...params
+      }
+      this.adviceEditTitle = this.$t('adviceManage.adviceEdit')
+      this.dialogAddVisible = true
+      if (this.addAdviceForm.start_time) {
+        this.$set(this.addAdviceForm, 'start_time', this.addAdviceForm.start_time * 1000)
+      }
+      if (this.addAdviceForm.end_time) {
+        this.$set(this.addAdviceForm, 'end_time', this.addAdviceForm.end_time * 1000)
+      }
+      if (this.addAdviceForm.detail) {
+        this.detailForm = JSON.parse(this.addAdviceForm.detail)
+      } else {
+        this.detailForm = [
+          {
+            name: '',
+            value: ''
+          }
+        ]
+      }
+    },
+    /** 新增 提交表单 */
+    handlerFormSubmit(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          const _this = this
+
+          // 判断是否存在参数,如果存在参数,就将值赋给this.addAdviceForm.detail
+          const detail = []
+          this.detailForm.forEach(v => {
+            console.log(v)
+            if (v.name && v.name !== "") {
+              detail.push(v)
+            }
+          })
+          if (detail.length > 0) {
+            this.addAdviceForm.detail = JSON.stringify(detail)
+          } else {
+            this.addAdviceForm.detail = ''
+          }
+          if (this.addAdviceForm.start_time) {
+            this.$set(this.addAdviceForm, 'start_time', this.addAdviceForm.start_time / 1000) // 将毫秒数转换成秒
+          }
+          if (this.addAdviceForm.end_time) {
+            this.$set(this.addAdviceForm, 'end_time', this.addAdviceForm.end_time / 1000) // 将毫秒数转换成秒
+          }
+          console.log('this.addAdviceForm', this.addAdviceForm)
+          /** 新增 */
+          if (!this.addAdviceForm.id) {
+            API_Advice.add(this.addAdviceForm).then(r => {
+              this.$message.success(this.$t('action.saveSuccess'))
+              this.dialogAddVisible = false
+              this.getList()
+            })
+          } else {
+            /** 修改 */
+            API_Advice.update(this.addAdviceForm.id, this.addAdviceForm).then(() => {
+              this.$message.success(this.$t('action.editSuccess'))
+              this.dialogAddVisible = false
+              this.getList()
+            })
+          }
+        }
+      })
+    },
+    /** 获取医嘱类型模式 */
+    adviceTypeGetter(params) {
+      const gridVal = params.data.type
+      return ADVICE_TYPE.getDescFromValue(gridVal)
+    },
+    adviceStatusGetter(params) {
+      const gridVal = params.data.status
+      return ADVICE_STATUS_TYPE.getDescFromValue(gridVal)
+    },
+    removeDetail(item) {
+      var index = this.detailForm.indexOf(item)
+      if (index !== -1) {
+        this.detailForm.splice(index, 1)
+      }
+    },
+    addDetail() {
+      this.detailForm.push({
+        name: '',
+        value: ''
+      });
+    }
+  }
+}
+</script>
+
+<style scoped>
+.el-input .el-button {
+  margin-left: 120px;
+}
+</style>

+ 31 - 2
src/views/ncs-auth/compontents/roleEdit.vue

@@ -51,6 +51,21 @@
           </el-row>
         </div>
       </el-form-item>
+
+      <el-form-item :label="this.$t('role.leaderRole')">
+        <el-select v-model="permissionForm.leader_role_id" :placeholder="this.$t('role.leaderRolePlaceholder')" clearable>
+          <!--                <el-option v-for="item in sosDeviceSettingsTypeOptions" :key="item.value" :label="item.key" :value="item.value" />-->
+          <el-option v-for="(item, index) in leaderRoles" :key="index" :label="item.role_name" :value="item.role_id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item :label="this.$t('role.roleEnum')">
+        <el-select v-model="permissionForm.role_type" :placeholder="this.$t('role.roleEnumPlaceholder')" clearable>
+          <!--                <el-option v-for="item in sosDeviceSettingsTypeOptions" :key="item.value" :label="item.key" :value="item.value" />-->
+          <el-option v-for="(item, index) in roleTypeEnums" :key="index" :label="item.key" :value="item.key" />
+        </el-select>
+      </el-form-item>
+
       <el-form-item label="">
         <el-button type="primary" size="small" style="margin-top: 15px" @click="saveRolePermission">{{ this.$t('action.saveSettings') }}</el-button>
       </el-form-item>
@@ -69,6 +84,11 @@ export default {
       type: Number,
       required: true,
       default: 0
+    },
+    allRoles:{
+      type:Array,
+      require:true,
+      default:()=>[]
     }
   },
   data() {
@@ -90,15 +110,22 @@ export default {
       // 全选状态
       allCheck: false,
       // 全选不确定状态
-      allIndeterminate: false
+      allIndeterminate: false,
+      roleTypeEnums:[]
     }
   },
   watch: {
     role_id: 'GET_RolePermission'
   },
-  mounted() {
+  async mounted() {
     // this.role_id = Number(this.$route.params.id)
     this.GET_RolePermission()
+    this.roleTypeEnums = await API_Auth.getRoleEnums()
+  },
+  computed:{
+    leaderRoles(){
+      return this.allRoles.filter(p=>p.role_id!==this.role_id)
+    }
   },
   methods: {
     /** 全选 */
@@ -193,6 +220,8 @@ export default {
           API_Auth.getRolePermission(this.role_id).then(response => {
             this.permissionForm.role_name = response.role_name
             this.permissionForm.role_describe = response.role_describe
+            this.$set(this.permissionForm,'role_type',response.role_type)
+            this.$set(this.permissionForm,'leader_role_id',response.leader_role_id)
             // this.permissionForm.hidden_in_seller = response.hidden_in_seller
             const checkedIds = this.expandRouters(response.menus)
             this.$set(this, 'permissions', this.filterRoleRouter(res, checkedIds))

+ 2 - 1
src/views/ncs-auth/superadmin/defaultRoleManager.vue

@@ -23,7 +23,7 @@
           <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" />
+        <role-edit :role_id="role_id" :all-roles="tableData" @aftersave="getRoleList" />
       </el-main>
     </el-container>
     <el-dialog :title="this.$t('role.roleEdit')" :visible.sync="formShow" width="50%">
@@ -62,6 +62,7 @@ export default {
       allCheck: false,
       newCheckList: [],
       oldCheckList: []
+
     }
   },
   computed: {

+ 4 - 3
src/views/ncs-channel/index.vue

@@ -104,7 +104,7 @@ export default {
         fixedCondition: ' part_id = ' + this.$store.getters.partId
       },
       /** 新建组织弹出参数 **/
-      formtitle: '新增频道',
+      formtitle: this.$t('channel.channelAdd'),
       formshow: false,
       /** 频道订阅设置 */
       formSubscribe: false,
@@ -112,7 +112,7 @@ export default {
       frameGroups: [],
       rules: {
         channel_name: [
-          { required: true, message: '频道名称不能为空', trigger: 'blur' }
+          { required: true, message: this.$t('channel.inputChannelName'), trigger: 'blur' }
         ]
       },
       timeRange: [new Date(2020, 11, 11, 7, 0), new Date(2020, 11, 11, 8, 0)],
@@ -206,7 +206,7 @@ export default {
         filter: false,
         pinned: 'right',
         lockPinned: true,
-        minWidth: this.$i18n.locale === 'zh' ? 310 : 340,
+        minWidth: this.$i18n.locale === 'zh' ? 310 : 350,
         resizable: false,
         sortable: false
       }
@@ -532,6 +532,7 @@ export default {
         _this.nurses.forEach(item => {
           this.channelSubscribers.push({ 'roleName': item[0], 'clerks': item[1].map(i => { return { ...i, 'checked': false } }), 'allCheck': false, 'indeterminate': false })
         })
+
       })
     },
     handleCheckboxChanged(item) {

+ 9 - 4
src/views/ncs-chars/index.vue

@@ -102,6 +102,9 @@
       <el-tab-pane name="PHONE">
         <span slot="label"><i class="el-icon-mobile-phone" /> {{ this.$t('tcpType.PHONE') }}</span>
       </el-tab-pane>
+      <el-tab-pane name="SIDE">
+        <span slot="label"><i class="el-icon-first-aid-kit" /> {{ this.$t('tcpType.SIDE') }}</span>
+      </el-tab-pane>
     </el-tabs>
     <div v-if="sssparams.type">
       <el-card shadow="always" style="margin-top: 15px;">
@@ -193,7 +196,7 @@ export default {
         noCount: 0
       },
       tableData: [],
-      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'), this.$t('tcpType.PHONE')],
+      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'), this.$t('tcpType.PHONE'), this.$t('tcpType.SIDE')],
       activeName: 'ALL',
       userActionList: [],
       activeName2: 'user',
@@ -462,12 +465,12 @@ export default {
         this.sssparams.year = object.date_val.getFullYear()
         this.sssparams.month = this.checkTime(object.date_val.getMonth() + 1)
         this.sssparams.day = this.checkTime(object.date_val.getDate())
-        this.infoDay = this.sssparams.year + '年' + this.sssparams.month + '月' + this.sssparams.day + '日'
+        this.infoDay = this.sssparams.year + this.$t('interaction.year') + this.sssparams.month + this.$t('interaction.month') + this.sssparams.day + this.$t('interaction.day')
       } else {
         this.sssparams.year = object.year
         this.sssparams.month = object.month
         this.sssparams.cycle_type = object.type
-        this.infoDay = this.sssparams.year + '年' + this.sssparams.month
+        this.infoDay = this.sssparams.year + this.$t('interaction.year') + this.sssparams.month
       }
       this.getLogCharsJS()
       if (this.activeName !== 'ALL') {
@@ -498,6 +501,8 @@ export default {
           return this.$t('tcpType.SOS')
         case 'PHONE':
           return this.$t('tcpType.PHONE')
+        case 'SIDE':
+          return this.$t('tcpType.SIDE')
         default:
           return this.$t('tcpType.UNKNOWN')
       }
@@ -577,7 +582,7 @@ export default {
             tHeader.push(this.$t('interaction.SumNum'))
             filterVal.push('sum_num')
           }
-          const tit = _this.infoDay + _this.formatterType(_this.activeName) + '统计表'
+          const tit = _this.infoDay + _this.formatterType(_this.activeName) + $t('interaction.eventStatistics')
           const data = _this.formatJson(filterVal, _this.userActionList)
           excel.export_json_to_excel({
             header: tHeader,

+ 3 - 3
src/views/ncs-chars/info.vue

@@ -2,7 +2,7 @@
   <div>
     <div style="padding: 10px;margin: 10px;">
       <div style="padding: 10px;">
-        <el-button type="primary" @click="exportExcel">导出</el-button>
+        <el-button type="primary" @click="exportExcel">{{ this.$t('action.export') }}</el-button>
       </div>
       <div class="table-wrapper">
         <el-table :data="userActionList" stripe border :default-sort = "{prop: 'num', order: 'descending'}" style="width: 100%">
@@ -107,7 +107,7 @@ export default {
     },
     exportExcel() {
       const _this = this
-      this.$confirm('将导出Excel文件,是否继续?', '提示', {
+      this.$confirm(this.$t('action.excelFile'), this.$t('action.prompt'), {
         type: 'warning'
       }).then(() => {
         _this.loading = false
@@ -115,7 +115,7 @@ export default {
           const tHeader = [this.sssparams.eventType ? this.$t('member.name') : this.$t('tcpType.EVENT'), this.$t('interaction.actionTime'),
             this.$t('interaction.unSuccessTime'), this.$t('interaction.avgResponseNum'), this.$t('interaction.MinNum'), this.$t('interaction.MaxNum')] // 表头
           const filterVal = ['name', 'num', 'error_num', 'avg_num', 'min_num', 'max_num']
-          const tit = this.infoName + '事件统计表'
+          const tit = this.infoName + this.$t('action.eventStatistics')
           const data = _this.formatJson(filterVal, this.userActionList)
           excel.export_json_to_excel({
             header: tHeader,

+ 480 - 0
src/views/ncs-clerk-frame-manage/components/employeeView.vue

@@ -0,0 +1,480 @@
+<template>
+    <el-container :style="{height: asideHeight+'px'}">
+        <el-aside width="220px" style="overflow: hidden">
+            <el-scrollbar wrap-class="scrollbar-wrapper">
+                <el-menu
+                        default-active="0-0"
+                        class="el-menu-vertical-demo"
+                        @open="handleOpen"
+                        @select="handleSelect"
+                        @close="handleClose"
+                >
+                    <el-submenu v-for="(key,index) in Object.keys(clerks)" :index="index+''" :key="index">
+                        <template slot="title">
+                            <svg-icon icon-class="role"/>
+                            <span>{{key}}</span>
+                        </template>
+                        <el-menu-item-group v-if="clerks[key].length>0">
+                            <el-menu-item :index="index+'-'+_idx" v-for="(item,_idx) in clerks[key]" :key="_idx">
+                                {{item.clerk_name}}
+                            </el-menu-item>
+                        </el-menu-item-group>
+                    </el-submenu>
+                </el-menu>
+
+            </el-scrollbar>
+
+        </el-aside>
+        <el-main :style="{height: (asideHeight-16)+'px'}">
+            <el-tabs v-model="activeName" type="border-card">
+                <el-tab-pane :label="this.$t('clerkFrameManage.managedFrames')" name="first">
+                    <div class="inner-toolbar">
+                        <div class="toolbar-search">
+                            <en-table-search :placeholder="this.$t('action.keywords')" @search="(keyword)=>handlerSearchManaged(keyword,1)"/>
+                        </div>
+                    </div>
+                    <el-tabs v-model="activeName2" class="inner-tab-panel" tab-position="left">
+
+                        <el-tab-pane :label="$t('watch.allFrame')" name="allManaged">
+                            <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-171)+'px'}">
+                                <div style="padding: 0 15px">
+                                    <!--        <fieldset class="margin-top-sm">-->
+                                    <!--          <legend>{{ watchDeviceFrame }}</legend>-->
+                                    <el-row :gutter="20" type="flex">
+                                        <el-col v-for="(item,index) in clerkManageFrame.managed_frames" :key="index"
+                                                :xs="8" :sm="8" :md="6" :lg="4" :xl="4">
+                                            <el-card class="box-card">
+                                                <div  slot="header" class="clearfix">
+
+                                                        <svg-icon icon-class="sickroom"
+                                                                  style="color: #9aaabf;margin-right: 5px"/>
+                                                        <span>{{ item.name }}</span>
+
+                                                    <el-checkbox v-model="item.allCkeck" style="float: right"
+                                                                 :indeterminate="item.indeterminate"
+                                                                 :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')"
+                                                                 @change="(checked)=>{handleCheckAll(checked,item)}">
+                                                        {{ $t('action.choiceAll') }}
+                                                    </el-checkbox>
+                                                </div>
+                                                <div v-for="(bed,_index) in item.children" :key="_index"
+                                                     class="text item">
+                                                    <el-checkbox
+                                                            v-model="bed.checked"
+                                                                 :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')"
+                                                                 @change="handleCheckboxChanged(item)">
+                                                        <svg-icon icon-class="bed"
+                                                                  style="color: #9aaabf;margin-right: 5px"/>
+                                                        <span v-if="bed.device_id && !bed.checked"
+                                                              style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
+                                                        <span v-else>{{ bed.full_name }}</span>
+                                                    </el-checkbox>
+                                                </div>
+                                            </el-card>
+                                        </el-col>
+                                    </el-row>
+                                </div>
+                            </el-scrollbar>
+                        </el-tab-pane>
+
+                        <el-tab-pane v-for="(group,idx) in managedRoomGroup" v-if="group[0]!=='null'" :key="idx"
+                                     :label="group[0]" :name="'zone-'+idx">
+                            <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-171)+'px'}">
+                                <div style="padding: 0 15px">
+                            <el-row v-if="group[1].length > 1" :gutter="20" type="flex">
+                                <el-col v-for="(item,index) in group[1]" :key="index" :xs="6" :sm="6" :md="4" :lg="4"
+                                        :xl="4">
+                                    <el-card class="box-card">
+                                        <div slot="header" class="clearfix">
+
+                                                <svg-icon icon-class="sickroom"
+                                                          style="color: #9aaabf;margin-right: 5px"/>
+                                                <span>{{ item.name }}</span>
+
+                                            <el-checkbox v-model="item.allCkeck" style="float: right"
+                                                         :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')"
+                                                         :indeterminate="item.indeterminate"
+                                                         @change="(checked)=>{handleCheckAll(checked,item)}">
+                                                {{ $t('action.choiceAll') }}
+                                            </el-checkbox>
+                                        </div>
+                                        <div v-for="(bed,_index) in item.children" :key="_index" class="text item">
+                                            <el-checkbox v-model="bed.checked" :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')">
+                                                <svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px"/>
+                                                <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
+                                                <span v-else>{{ bed.full_name }}</span>
+                                            </el-checkbox>
+                                            <!--                                        <div v-if="roleId === 8">-->
+                                            <!--                                            <svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />-->
+                                            <!--                                            <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>-->
+                                            <!--                                            <span v-else>{{ bed.full_name }}</span>-->
+                                            <!--                                        </div>-->
+                                        </div>
+                                    </el-card>
+                                </el-col>
+                            </el-row>
+                                </div>
+                            </el-scrollbar>
+                        </el-tab-pane>
+                    </el-tabs>
+                    <div class="margin-top-xs text-center padding-content">
+                        <el-row>
+                            <el-col :span="8"> <el-checkbox v-if="clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')" v-model="clerkManageFrameSource.bool_phone_acceptor">{{this.$t('clerkFrameManage.phoneAcceptorTipsLeft')}}{{clerkManageFrameSource.clerk_name}}{{this.$t('clerkFrameManage.phoneAcceptorTipsMid')}},{{clerkManageFrameSource.clerk_name}}{{this.$t('clerkFrameManage.phoneAcceptorTipsRight')}}</el-checkbox></el-col>
+                            <el-col :span="8"> <el-button type="primary" :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')" @click="saveClerkManageFrame">{{this.$t('action.saveSettings')}}</el-button></el-col>
+                            <el-col :span="8"></el-col>
+                        </el-row>
+
+                    </div>
+                </el-tab-pane>
+                <el-tab-pane :label="this.$t('clerkFrameManage.notManagedFrames')" name="second">
+                    <div class="inner-toolbar">
+                        <div class="toolbar-search">
+                            <en-table-search :placeholder="this.$t('action.keywords')" @search="(keyword)=>handlerSearchManaged(keyword,2)"/>
+                        </div>
+                    </div>
+                    <el-tabs v-model="activeName1" class="inner-tab-panel" tab-position="left">
+
+                        <el-tab-pane :label="$t('watch.allFrame')" name="allNoManange">
+
+                            <!--        <fieldset class="margin-top-sm">-->
+                            <!--          <legend>{{ watchDeviceFrame }}</legend>-->
+                            <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-171)+'px'}">
+                                <div style="padding: 0 15px">
+                                    <el-row :gutter="20" type="flex">
+
+                                        <el-col v-for="(item,index) in clerkManageFrame.no_manage_frames" :key="index"
+                                                :xs="8" :sm="8" :md="6" :lg="4" :xl="4">
+                                            <el-card class="box-card">
+                                                <div slot="header" class="clearfix">
+                                                    <svg-icon icon-class="sickroom"
+                                                              style="color: #9aaabf;margin-right: 5px"/>
+                                                    <span>{{ item.name }}</span>
+                                                    <span v-if="uiVersion !== 1"><svg-icon icon-class="sickroom"
+                                                                                           style="color: #9aaabf;margin-right: 5px"/><span>{{ item.name }}</span></span>
+                                                    <el-checkbox v-model="item.allCkeck" style="float: right"
+                                                                 :indeterminate="item.indeterminate" :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')"
+                                                                 @change="(checked)=>{handleCheckAll(checked,item)}">
+                                                        {{ $t('action.choiceAll') }}
+                                                    </el-checkbox>
+                                                </div>
+                                                <div v-for="(bed,_index) in item.children" :key="_index"
+                                                     class="text item">
+                                                    <el-checkbox v-model="bed.checked"
+                                                                 :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')"
+                                                                 @change="handleCheckboxChanged(item)">
+                                                        <svg-icon icon-class="bed"
+                                                                  style="color: #9aaabf;margin-right: 5px"/>
+                                                        <span v-if="bed.device_id && !bed.checked"
+                                                              style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
+                                                        <span v-else>{{ bed.full_name }}</span>
+                                                    </el-checkbox>
+                                                    <!--                                            <div >-->
+                                                    <!--                                                <svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />-->
+                                                    <!--                                                <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>-->
+                                                    <!--                                                <span v-else>{{ bed.full_name }}</span>-->
+                                                    <!--                                            </div>-->
+                                                </div>
+                                            </el-card>
+                                        </el-col>
+
+                                    </el-row>
+                                </div>
+                            </el-scrollbar>
+                        </el-tab-pane>
+
+                        <el-tab-pane v-for="(group,idx) in noManagedRoomGroup" v-if="group[0]!=='null'" :key="idx"
+                                     :label="group[0]" :name="'zone-'+idx">
+                            <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-171)+'px'}">
+                                <div style="padding: 0 15px">
+                                    <el-row v-if="group[1].length > 1" :gutter="20" type="flex">
+                                        <el-col v-for="(item,index) in group[1]" :key="index" :xs="8" :sm="8" :md="6"
+                                                :lg="4" :xl="4">
+                                            <el-card class="box-card">
+                                                <div slot="header" class="clearfix">
+                                                    <svg-icon icon-class="sickroom"
+                                                              style="color: #9aaabf;margin-right: 5px"/>
+                                                    <span>{{ item.name }}</span>
+                                                    <span v-if="uiVersion !== 1"><svg-icon icon-class="sickroom"
+                                                                                           style="color: #9aaabf;margin-right: 5px"/><span>{{ item.name }}</span></span>
+                                                    <el-checkbox v-model="item.allCkeck" style="float: right"
+                                                                 :indeterminate="item.indeterminate"
+                                                                 :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')"
+                                                                 @change="(checked)=>{handleCheckAll(checked,item)}">
+                                                        {{ $t('action.choiceAll') }}
+                                                    </el-checkbox>
+                                                </div>
+                                                <div v-for="(bed,_index) in item.children" :key="_index"
+                                                     class="text item">
+                                                    <el-checkbox v-model="bed.checked"
+                                                                 :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')"
+                                                                 @change="handleCheckboxChanged(item)">
+                                                        <svg-icon icon-class="bed"
+                                                                  style="color: #9aaabf;margin-right: 5px"/>
+                                                        <span v-if="bed.device_id && !bed.checked"
+                                                              style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>
+                                                        <span v-else>{{ bed.full_name }}</span>
+                                                    </el-checkbox>
+                                                    <!--                                        <div v-if="roleId === 8">-->
+                                                    <!--                                            <svg-icon icon-class="bed" style="color: #9aaabf;margin-right: 5px" />-->
+                                                    <!--                                            <span v-if="bed.device_id && !bed.checked" style="color: #13ce66">{{ bed.full_name }} {{ bed.clerk_name }}</span>-->
+                                                    <!--                                            <span v-else>{{ bed.full_name }}</span>-->
+                                                    <!--                                        </div>-->
+                                                </div>
+                                            </el-card>
+                                        </el-col>
+                                    </el-row>
+                                </div>
+                            </el-scrollbar>
+                        </el-tab-pane>
+                    </el-tabs>
+                    <div class="margin-top-xs text-center padding-content">
+                        <el-row>
+                            <el-col :span="8"> <el-checkbox v-if="clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')" v-model="clerkManageFrameSource.bool_phone_acceptor">{{this.$t('clerkFrameManage.phoneAcceptorTipsLeft')}}{{clerkManageFrameSource.clerk_name}}{{this.$t('clerkFrameManage.phoneAcceptorTipsMid')}},{{clerkManageFrameSource.clerk_name}}{{this.$t('clerkFrameManage.phoneAcceptorTipsRight')}}</el-checkbox></el-col>
+                            <el-col :span="8"> <el-button type="primary" :disabled="!clerkManageFrame.permissions.some(k=>k==='MANAGE_BED')" @click="saveClerkManageFrame">{{this.$t('action.saveSettings')}}</el-button></el-col>
+                            <el-col :span="8"></el-col>
+                        </el-row>
+
+                    </div>
+
+                </el-tab-pane>
+            </el-tabs>
+
+        </el-main>
+    </el-container>
+
+</template>
+
+<script>
+    import * as API_Clerk from '@/api/ncs_clerk'
+
+    const uiVersion = domain.uiVersion
+    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
+        }, {})
+    export default {
+        name: "employeeView",
+        computed: {
+            asideHeight() {
+                return this.mainAreaHeight - 80
+            }
+        },
+        data() {
+            return {
+                clerks: {},
+                activeName: 'first',
+                testdata: [{key: 1, check: false},
+                    {key: 2, check: false},
+                    {key: 3, check: false},
+                    {key: 4, check: false}
+                ],
+                showdata: [],
+                clerkManageFrame: {
+                    permissions:[]
+                },
+                clerkManageFrameSource: {},
+                managedRoomGroup: [],
+                noManagedRoomGroup: [],
+                uiVersion: uiVersion,
+                activeName1: 'allNoManange',
+                activeName2: 'allManaged',
+                currentClerk:{}
+            }
+        },
+        mounted() {
+            this.getRoleGroupClerk()
+            this.showdata = this.testdata
+        },
+        methods: {
+            getRoleGroupClerk() {
+                API_Clerk.getRoleGroupClerk(this.$store.getters.partId).then(res => {
+                    this.clerks = {...res}
+                    this.currentClerk = {...this.clerks[Object.keys(this.clerks)[0]][0]}
+                    this.getClerkManageFrame(this.currentClerk.clerk_id, 4)
+                })
+            },
+            handleOpen() {
+
+            },
+            handleClose() {
+
+            },
+            handleSelect(val){
+                let path =val.split('-').map(p=>Number(p))
+                this.currentClerk = {...this.clerks[Object.keys(this.clerks)[path[0]]][path[1]]}
+                this.getClerkManageFrame(this.currentClerk.clerk_id, 4)
+            },
+
+            getClerkManageFrame(clerkId, rootType) {
+
+                API_Clerk.getClerkManageFrame(clerkId, rootType).then(res => {
+                    this.clerkManageFrameSource = {...res}
+                    this.clerkManageFrame = {...this.clerkManageFrameSource}
+                    this.clerkManageFrame.managed_frames.forEach(item=>{
+                        this.countAllFrame(item)
+                    })
+
+                    this.clerkManageFrame.no_manage_frames.forEach(item=>{
+                        this.countAllFrame(item)
+                    })
+
+                    const managedGroup = groupBy(this.clerkManageFrame.managed_frames, item => item.group_name)
+                    this.managedRoomGroup = Object.entries(managedGroup)
+                    const noManagedGroup = groupBy(this.clerkManageFrame.no_manage_frames, item => item.group_name)
+                    this.noManagedRoomGroup = Object.entries(noManagedGroup)
+                })
+            },
+            handleCheckAll(checked, item) {
+                this.$set(item, 'indeterminate', false)
+                this.setFrameCheck(item, checked)
+            },
+            /** 设置选择状态 */
+            setFrameCheck(item, checked) {
+                const perm = this.MixinClone(item)
+                if (!Array.isArray(perm)) {
+                    this.$set(item, 'checked', checked)
+                    if (item.children && item.children.length) {
+                        this.$set(item, 'children', this.setFrameCheck(item.children, checked))
+                    }
+                } else {
+                    perm.map(item => {
+                        item.checked = checked
+                        this.$set(item, 'checked', checked)
+                        if (item.children && item.children.length) {
+                            this.$set(item, 'children', this.setFrameCheck(item.children, checked))
+                        }
+                    })
+                }
+                return perm
+            },
+            /** 选择 */
+            handleCheckboxChanged(item) {
+                this.countAllFrame(item)
+            },
+            /** 获取所有frame的长度、被选中的长度 */
+            countAllFrame(frame) {
+                const _list = []
+                if (!Array.isArray(frame)) {
+                    // _list.push(frame)
+                    if (frame.children) _list.push(...this.countAllFrame(frame.children))
+                } else {
+                    frame.forEach(item => {
+                         _list.push(item)
+                        if (item.children) _list.push(...this.countAllFrame(item.children))
+                    })
+                }
+                const length = _list.length
+                const length_checked = _list.filter(_item => _item.checked).length
+                this.$set(frame, 'allCkeck', length === _list.filter(_item => _item.checked).length)
+                this.$set(frame, 'indeterminate', (length_checked !== 0) && (length !== length_checked))
+                return _list
+            },
+            handlerSearchManaged(keywords,view) {
+                if (keywords !== '') {
+                    if(view===1){
+                        this.clerkManageFrame.managed_frames =this.clerkManageFrameSource.managed_frames.filter(p => p.full_name.indexOf(keywords) > -1 || p.chidren !== null && p.children.length > 0 && p.children.some(k => k.full_name.indexOf(keywords) > -1))
+                    }else{
+                        this.clerkManageFrame.no_manage_frames = this.clerkManageFrameSource.no_manage_frames.filter(p => p.full_name.indexOf(keywords) > -1 || p.chidren !== null && p.children.length > 0 && p.children.some(k => k.full_name.indexOf(keywords) > -1))
+                    }
+                } else {
+                    if(view===1){
+                        this.clerkManageFrame.managed_frames = [...this.clerkManageFrameSource.managed_frames]
+                    }else{
+                        this.clerkManageFrame.no_manage_frames = [...this.clerkManageFrameSource.no_manage_frames]
+                    }
+
+
+                }
+                const managedGroup = groupBy(this.clerkManageFrame.managed_frames, item => item.group_name)
+                this.managedRoomGroup = Object.entries(managedGroup)
+                const noManagedGroup = groupBy(this.clerkManageFrame.no_manage_frames, item => item.group_name)
+                this.noManagedRoomGroup = Object.entries(noManagedGroup)
+
+            },
+            saveClerkManageFrame() {
+                API_Clerk.saveClerkManageFrame(this.clerkManageFrameSource).then(res => {
+                    this.getClerkManageFrame(this.currentClerk.clerk_id, 4)
+                    this.$message.success(this.$t('action.saveSuccess'))
+                })
+            }
+        }
+    }
+</script>
+
+<style scoped>
+
+    .el-aside {
+        margin: 8px;
+        padding: 8px;
+        /*border-width: 1px;*/
+        /*border-style: solid;*/
+        background: #fff;
+    }
+
+    .el-submenu .el-menu-item {
+        width: 100% !important;
+    }
+
+    .custom-tree-node {
+        flex: 1;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        font-size: 14px;
+        padding-right: 8px;
+    }
+
+    .el-tree {
+        margin-top: 8px
+    }
+
+    /deep/ .el-main {
+        margin: 8px;
+        padding: 0;
+        overflow: hidden;
+    }
+
+    /deep/ .scrollbar-wrapper {
+        height: 100%;
+        overflow-x: hidden;
+    }
+
+    /deep/ .inner-tab-panel .el-tabs__content {
+        /*height:calc(100vh - 260px)*/
+    }
+
+    /deep/ .el-menu-item-group__title {
+        display: none;
+    }
+
+    .el-scrollbar {
+        height: 100%;
+    }
+
+    /deep/ .svg-icon {
+        margin-right: 16px;
+    }
+
+    /deep/ .el-tabs--border-card > .el-tabs__content {
+        padding: 15px;
+        padding-right: 0;
+    }
+
+    .el-row--flex {
+        flex-wrap: wrap !important;
+        margin-top: 20px;
+    }
+
+    .el-col {
+        margin-bottom: 20px !important;
+    }
+
+    /deep/.el-checkbox__input.is-disabled.is-checked + span.el-checkbox__label{
+        color: #1890ff;
+    }
+ /deep/ .el-checkbox__label{
+     white-space: normal;
+     text-align: left;
+ }
+</style>

+ 500 - 0
src/views/ncs-clerk-frame-manage/components/frameView.vue

@@ -0,0 +1,500 @@
+<template>
+
+    <el-container :style="{height: asideHeight+'px'}">
+        <el-aside width="280px" style="border-color: rgb(238, 241, 246)">
+            <div class="el-row--flex">
+                <el-input
+                        v-model="filterText"
+                        :placeholder="this.$t('frameManage.keywordsFilter')"
+                        clearable
+                />
+            </div>
+            <el-tree
+                    ref="frameTree"
+                    :data="treeData"
+                    :show-checkbox="false"
+                    node-key="id"
+                    :default-expand-all="true"
+                    :auto-expand-parent="true"
+                    :expand-on-click-node="false"
+                    :highlight-current="true"
+                    :current-node-key="selectedNodeId"
+                    :accordion="true"
+                    :filter-node-method="filterNode"
+                    @node-click="nodeClick"
+            >
+          <span slot-scope="{ node, data }" class="custom-tree-node">
+
+            <!--            <span><svg-icon :icon-class="data.type===4?'sickroom':data.type===5?'bed':'area'" />{{ data.full_name }}</span>-->
+              <span
+              ><svg-icon
+                      :style="data.customer_id ? 'color: #0a901c' : ''"
+                      :icon-class="data.type===4?'sickroom':data.type===5?'bed':'area'"
+              />{{ data.full_name }}</span>
+
+
+          </span>
+            </el-tree>
+        </el-aside>
+        <el-main>
+
+            <el-card :style="{height: asideHeight -20 +'px'}">
+                <el-form>
+                    <el-tabs v-model="activeName">
+                        <el-tab-pane :label="this.$t('clerkFrameManage.settableEmployee')" name="first">
+
+                            <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-160)+'px'}">
+                                <div style="padding: 0 15px">
+
+
+                                    <el-row v-if="frameManagedClerk.settable!==undefined && Object.keys(frameManagedClerk.settable).length>0">
+                                        <el-col :span="24">
+
+                                            <div class="text item">
+
+                                                <fieldset style="margin-bottom: 10px"
+                                                          v-for="(roleName,_index) in Object.keys(frameManagedClerk.settable)"
+                                                          :key="_index">
+                                                    <legend><span
+                                                            style="margin-right: 10px">{{roleName}}</span>
+                                                    </legend>
+                                                    <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                        <el-col :span="24">
+                                                            <el-checkbox
+                                                                    v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                    @change="(val)=>{checkChange(val,roleName)}"
+                                                                    :key="index" v-model="clerk.checked"
+                                                            >{{ clerk.clerk_name }}
+                                                            </el-checkbox>
+                                                        </el-col>
+                                                    </el-row>
+                                                    <el-divider
+                                                            v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)"></el-divider>
+                                                    <el-row type="flex" :gutter="20" class="margin-top-sm"
+                                                            v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)">
+                                                        <el-col :span="24">
+                                                            <el-form-item
+                                                                    :label="i18n.t('clerkFrameManage.phoneAcceptorLabel')">
+                                                                <el-select
+                                                                        v-model="frameManagedClerk.phone_acceptor[roleName]"
+                                                                        @change="(val)=>{phoneAcceptorChange(val,roleName)}"
+                                                                        >
+                                                                    <el-option
+                                                                            v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                            v-if="clerk.checked"
+                                                                            :key="clerk.clerk_id"
+                                                                            :label="clerk.clerk_name"
+                                                                            :value="clerk.clerk_id">
+                                                                    </el-option>
+                                                                </el-select>
+                                                            </el-form-item>
+                                                        </el-col>
+                                                    </el-row>
+                                                </fieldset>
+                                            </div>
+
+
+                                        </el-col>
+                                    </el-row>
+
+
+                                </div>
+                            </el-scrollbar>
+                        </el-tab-pane>
+                        <el-tab-pane :label="this.$t('clerkFrameManage.settedEmployee')" name="second">
+
+                            <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-160)+'px'}">
+                                <div style="padding: 0 15px">
+
+
+                                    <el-row v-if="frameManagedClerk.settable!==undefined && Object.keys(frameManagedClerk.settable).length>0">
+                                        <el-col :span="24">
+
+                                            <div class="text item">
+
+                                                <fieldset style="margin-bottom: 10px"
+                                                          v-for="(roleName,_index) in Object.keys(frameManagedClerk.settable)"
+                                                          v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)"
+                                                          :key="_index">
+                                                    <legend><span
+                                                            style="margin-right: 10px">{{roleName}}</span>
+                                                    </legend>
+                                                    <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                        <el-col :span="24">
+                                                            <el-checkbox
+                                                                    v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                    v-if="clerk.checked"
+                                                                    @change="(val)=>{checkChange(val,roleName)}"
+                                                                    :key="index" v-model="clerk.checked">{{
+                                                                clerk.clerk_name }}
+                                                            </el-checkbox>
+                                                        </el-col>
+                                                    </el-row>
+                                                    <el-divider
+                                                            v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)"></el-divider>
+                                                    <el-row type="flex" :gutter="20" class="margin-top-sm"
+                                                            v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)">
+                                                        <el-col :span="24">
+                                                            <el-form-item
+                                                                    :label="i18n.t('clerkFrameManage.phoneAcceptorLabel')">
+                                                                <el-select
+                                                                        v-model="frameManagedClerk.phone_acceptor[roleName]"
+                                                                        @change="(val)=>{phoneAcceptorChange(val,roleName)}"
+                                                                       >
+                                                                    <el-option
+                                                                            v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                            v-if="clerk.checked"
+                                                                            :key="clerk.clerk_id"
+                                                                            :label="clerk.clerk_name"
+                                                                            :value="clerk.clerk_id">
+                                                                    </el-option>
+                                                                </el-select>
+                                                            </el-form-item>
+                                                        </el-col>
+                                                    </el-row>
+                                                </fieldset>
+                                            </div>
+
+
+                                        </el-col>
+                                    </el-row>
+
+
+                                    <el-row class="margin-top-sm"
+                                            v-if="frameManagedClerk.un_settable!==undefined && Object.keys(frameManagedClerk.un_settable).length>0">
+                                        <el-col :span="24">
+
+                                            <div class="text item">
+
+                                                <fieldset style="margin-bottom: 10px"
+                                                          v-for="(roleName,_index) in Object.keys(frameManagedClerk.un_settable)"
+                                                          :key="_index"
+                                                          v-if="frameManagedClerk.un_settable[roleName].length>0&&frameManagedClerk.un_settable[roleName].some(p=>p.checked)">
+                                                    <legend><span
+                                                            style="margin-right: 10px">{{roleName}}</span>
+                                                    </legend>
+                                                    <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                        <el-col :span="24">
+                                                            <el-checkbox
+                                                                    v-for="(clerk,index) in frameManagedClerk.un_settable[roleName]"
+                                                                    v-if="clerk.checked" disabled :key="index"
+                                                                    v-model="clerk.checked"
+                                                            >{{ clerk.clerk_name }}
+                                                            </el-checkbox>
+                                                        </el-col>
+                                                    </el-row>
+                                                </fieldset>
+                                            </div>
+
+
+                                        </el-col>
+                                    </el-row>
+
+                                </div>
+                            </el-scrollbar>
+                        </el-tab-pane>
+
+                        <el-tab-pane :label="this.$t('clerkFrameManage.allEmployee')" name="third">
+                            <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-160)+'px'}">
+                                <div style="padding: 0 15px">
+
+
+                                    <el-row v-if="frameManagedClerk.settable!==undefined && Object.keys(frameManagedClerk.settable).length>0">
+                                        <el-col :span="24">
+
+                                            <div class="text item">
+
+                                                <fieldset style="margin-bottom: 10px"
+                                                          v-for="(roleName,_index) in Object.keys(frameManagedClerk.settable)"
+                                                          :key="_index">
+                                                    <legend><span
+                                                            style="margin-right: 10px">{{roleName}}</span>
+                                                    </legend>
+                                                    <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                        <el-col :span="24">
+                                                            <el-checkbox
+                                                                    v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                    :key="index" v-model="clerk.checked"
+                                                                    @change="(val)=>{checkChange(val,roleName)}"
+                                                            >{{ clerk.clerk_name }}
+                                                            </el-checkbox>
+                                                        </el-col>
+                                                    </el-row>
+                                                    <el-divider
+                                                            v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)"></el-divider>
+                                                    <el-row type="flex" :gutter="20" class="margin-top-sm"
+                                                            v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)">
+                                                        <el-col :span="24">
+                                                            <el-form-item
+                                                                    :label="i18n.t('clerkFrameManage.phoneAcceptorLabel')">
+                                                                <el-select
+                                                                        v-model="frameManagedClerk.phone_acceptor[roleName]"
+                                                                        @change="(val)=>{phoneAcceptorChange(val,roleName)}"
+                                                                       >
+                                                                    <el-option
+                                                                            v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                            v-if="clerk.checked"
+                                                                            :key="clerk.clerk_id"
+                                                                            :label="clerk.clerk_name"
+                                                                            :value="clerk.clerk_id">
+                                                                    </el-option>
+                                                                </el-select>
+                                                            </el-form-item>
+                                                        </el-col>
+                                                    </el-row>
+                                                </fieldset>
+                                            </div>
+
+
+                                        </el-col>
+                                    </el-row>
+
+
+                                    <el-row class="margin-top-sm"
+                                            v-if="frameManagedClerk.un_settable!==undefined && Object.keys(frameManagedClerk.un_settable).length>0">
+                                        <el-col :span="24">
+
+                                            <div class="text item">
+
+                                                <fieldset style="margin-bottom: 10px"
+                                                          v-for="(roleName,_index) in Object.keys(frameManagedClerk.un_settable)"
+                                                          :key="_index">
+                                                    <legend><span
+                                                            style="margin-right: 10px">{{roleName}}</span>
+                                                    </legend>
+                                                    <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                        <el-col :span="24">
+                                                            <el-checkbox
+                                                                    v-for="(clerk,index) in frameManagedClerk.un_settable[roleName]"
+                                                                    disabled :key="index" v-model="clerk.checked"
+                                                            >{{ clerk.clerk_name }}
+                                                            </el-checkbox>
+                                                        </el-col>
+                                                    </el-row>
+                                                    <el-divider
+                                                            v-if="frameManagedClerk.un_settable[roleName].length>0&&frameManagedClerk.un_settable[roleName].some(p=>p.checked)"></el-divider>
+                                                    <el-row type="flex" :gutter="20" class="margin-top-sm"
+                                                            v-if="frameManagedClerk.un_settable[roleName].length>0&&frameManagedClerk.un_settable[roleName].some(p=>p.checked)">
+                                                        <el-col :span="24">
+                                                            <el-form-item
+                                                                    :label="i18n.t('clerkFrameManage.phoneAcceptorLabel')">
+                                                                <el-select
+                                                                        v-model="frameManagedClerk.phone_acceptor[roleName]"
+                                                                        @change="(val)=>{phoneAcceptorChange(val,roleName)}"
+                                                                        disabled>
+                                                                    <el-option
+                                                                            v-for="(clerk,index) in frameManagedClerk.un_settable[roleName]"
+                                                                            v-if="clerk.checked"
+                                                                            :key="clerk.clerk_id"
+                                                                            :label="clerk.clerk_name"
+                                                                            :value="clerk.clerk_id">
+                                                                    </el-option>
+                                                                </el-select>
+                                                            </el-form-item>
+                                                        </el-col>
+                                                    </el-row>
+                                                </fieldset>
+                                            </div>
+
+
+                                        </el-col>
+                                    </el-row>
+
+                                </div>
+                            </el-scrollbar>
+                        </el-tab-pane>
+                    </el-tabs>
+
+                </el-form>
+                <div class="margin-top-xs text-center padding-content">
+                    <el-button type="primary" :disabled="frameManagedClerk['type']!==5" @click="saveFrameManagedClerk">
+                        {{this.$t('action.saveSettings')}}
+                    </el-button>
+                </div>
+            </el-card>
+
+        </el-main>
+    </el-container>
+</template>
+
+<script>
+    import * as API_FrameGroup from '@/api/ncs_frameGroup'
+    import {FRAME_TYPE} from '@/utils/enum/FrameTypeEnum'
+    import i18n from "../../../utils/i18n"
+
+    export default {
+        name: "frameView",
+        computed: {
+            asideHeight() {
+                return this.mainAreaHeight - 80
+            }
+        },
+        watch: {
+            selectedNodeId(newval, old) {
+                // this.selectedNode = this.findNodeById(this.treeData, newval)
+            },
+            filterText(val) {
+                this.$refs.frameTree.filter(val)
+            }
+        },
+        mounted() {
+            this.getFrameTree().then(() => {
+                this.selectedNodeId = this.treeData[0].id
+                this.$refs.frameTree.setCurrentKey(this.selectedNodeId)
+            }).catch(err => {
+                this.$message.error(err.message)
+            })
+        },
+        data() {
+            return {
+                treeData: [],
+                treeDataClone: [],
+                isShowTooltip: false,
+                /** 当前选中的树节点 */
+                selectedNodeId: 0,
+                selectedNode: {},
+                filterText: '',
+                abc: [],
+                frameManagedClerk: {},
+                activeName: 'first',
+                i18n:i18n
+            }
+        },
+        methods: {
+            /**
+             * 获取空间结构树形数据
+             * */
+            getFrameTree() {
+                return new Promise((resolve, reject) => {
+                    API_FrameGroup.getframestruct(this.$store.getters.partId, FRAME_TYPE.PART).then(res => {
+                        this.treeData = res.frameTree
+                        resolve()
+                    }).catch(err => {
+                        reject(err)
+                    })
+                })
+            },
+            checkChange(val, roleName) {
+
+                const roleCheckedClerk = this.frameManagedClerk.settable[roleName].filter(p => p.checked)
+
+                if (roleCheckedClerk.length === 0) {
+                    this.frameManagedClerk.phone_acceptor[roleName]=null
+                    this.frameManagedClerk.settable[roleName].forEach(item => {
+                        item.bool_phone_acceptor = false
+                    })
+                } else if (roleCheckedClerk.length === 1) {  //角色群组中只选中了一个职员,把该职员设为默认的电话接收人
+                    this.frameManagedClerk.phone_acceptor[roleName] = roleCheckedClerk[0].clerk_id
+                    this.frameManagedClerk.settable[roleName].forEach(item => {
+                        if (item.clerk_id === roleCheckedClerk[0].clerk_id) {
+                            item.bool_phone_acceptor = true
+                        } else {
+                            item.bool_phone_acceptor = false
+                        }
+                    })
+                } else if (roleCheckedClerk.length > 1) {//查看当前电话接收人是否是选中状态,如果不是选中状态,修改电话接收人
+                    const currentPhoneAcceptor = this.frameManagedClerk.settable[roleName].filter(p => p.clerk_id === this.frameManagedClerk.phone_acceptor[roleName])[0]
+                    if (currentPhoneAcceptor !== undefined && !currentPhoneAcceptor.checked) {
+                        this.frameManagedClerk.phone_acceptor[roleName] = roleCheckedClerk[0].clerk_id
+                        this.frameManagedClerk.settable[roleName].forEach(item => {
+                            if (item.clerk_id === roleCheckedClerk[0].clerk_id) {
+                                item.bool_phone_acceptor = true
+                            } else {
+                                item.bool_phone_acceptor = false
+                            }
+                        })
+                    }
+
+                }
+            },
+            phoneAcceptorChange(val, roleName) {
+                const phoneAcceptor = this.frameManagedClerk.phone_acceptor[roleName]
+                this.frameManagedClerk.settable[roleName].forEach(item => {
+                    if (item.clerk_id === phoneAcceptor) {
+                        item.bool_phone_acceptor = true
+                    } else {
+                        item.bool_phone_acceptor = false
+                    }
+                })
+            },
+            getFrameManagedClerk(frameId) {
+                API_FrameGroup.getFrameManagedClerk(frameId).then(res => {
+                    this.frameManagedClerk = {...res}
+                }).catch(err => {
+
+                })
+            },
+
+
+            /** 节点过滤方法 **/
+            filterNode(value, data) {
+                if (!value) return true
+                return data.full_name.indexOf(value) !== -1
+            },
+            /** 点击树形节点  **/
+            nodeClick(data, node, leaf) {
+                this.$set(this, 'selectedNodeId', data.id)
+                this.getFrameManagedClerk(data.id)
+            },
+
+            saveFrameManagedClerk() {
+                API_FrameGroup.saveFrameManagedClerk(this.frameManagedClerk).then(res => {
+
+                    this.getFrameManagedClerk(res.id)
+                    this.$message.success(this.$t('action.saveSuccess'))
+                }).catch(err => {
+                    this.$message.error(err.message)
+                })
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .el-aside {
+        margin: 8px;
+        padding: 8px;
+        border-width: 1px;
+        border-style: solid;
+        background: #fff;
+    }
+
+    .custom-tree-node {
+        flex: 1;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        font-size: 14px;
+        padding-right: 8px;
+    }
+
+    .el-tree {
+        margin-top: 8px
+    }
+
+    .el-main {
+        margin: 8px;
+        padding: 0;
+    }
+
+    fieldset {
+        border: 1px solid #DCDFE6;
+        border-radius: 5px;
+    }
+
+    .margin-top-sm {
+        margin-top: 10px
+    }
+
+    /deep/ .el-checkbox__input.is-disabled.is-checked + span.el-checkbox__label {
+        color: #1890ff;
+    }
+
+    /deep/ .el-scrollbar__wrap {
+        overflow-x: hidden;
+    }
+
+    /deep/ .el-form-item {
+        margin-bottom: 10px;
+    }
+</style>

+ 500 - 0
src/views/ncs-clerk-frame-manage/components/multiClerkManageFrame.vue

@@ -0,0 +1,500 @@
+<template>
+    <el-container :style="{height: asideHeight+'px'}">
+        <el-aside width="280px" style="border-color: rgb(238, 241, 246)">
+            <div class="el-row--flex">
+                <el-input
+                        v-model="filterText"
+                        :placeholder="this.$t('frameManage.keywordsFilter')"
+                        clearable
+                />
+            </div>
+            <el-tree
+                    ref="frameTree"
+                    :data="treeData"
+                    :show-checkbox="false"
+                    node-key="id"
+                    :default-expand-all="true"
+                    :auto-expand-parent="true"
+                    :expand-on-click-node="false"
+                    :highlight-current="true"
+                    :current-node-key="selectedNodeId"
+                    :accordion="true"
+                    :filter-node-method="filterNode"
+                    @node-click="nodeClick"
+            >
+          <span slot-scope="{ node, data }" class="custom-tree-node">
+
+            <!--            <span><svg-icon :icon-class="data.type===4?'sickroom':data.type===5?'bed':'area'" />{{ data.full_name }}</span>-->
+              <span
+              ><svg-icon
+                      :style="data.customer_id ? 'color: #0a901c' : ''"
+                      :icon-class="data.type===4?'sickroom':data.type===5?'bed':'area'"
+              />{{ data.full_name }}</span>
+
+
+          </span>
+            </el-tree>
+        </el-aside>
+        <el-main>
+
+            <el-card :style="{height: asideHeight -20 +'px'}">
+                <el-form>
+                <el-tabs v-model="activeName" >
+                    <el-tab-pane :label="this.$t('clerkFrameManage.settableEmployee')" name="first">
+
+                        <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-160)+'px'}">
+                            <div style="padding: 0 15px">
+
+
+                                <el-row v-if="frameManagedClerk.settable!==undefined && Object.keys(frameManagedClerk.settable).length>0">
+                                    <el-col :span="24">
+
+                                        <div class="text item">
+
+                                            <fieldset style="margin-bottom: 10px"  v-for="(roleName,_index) in Object.keys(frameManagedClerk.settable)"  :key="_index">
+                                                <legend><span
+                                                        style="margin-right: 10px">{{roleName}}</span>
+                                                </legend>
+                                                <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                    <el-col :span="24">
+                                                        <el-checkbox v-for="(clerk,index) in frameManagedClerk.settable[roleName]"  :key="index" v-model="clerk.checked"
+                                                                     @change="(val)=>{checkChange(val,roleName)}"
+                                                        >{{ clerk.clerk_name }}
+                                                        </el-checkbox>
+                                                    </el-col>
+                                                </el-row>
+                                                <el-divider
+                                                        v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)"></el-divider>
+                                                <el-row type="flex" :gutter="20" class="margin-top-sm"
+                                                        v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)">
+                                                    <el-col :span="24">
+                                                        <el-form-item
+                                                                :label="i18n.t('clerkFrameManage.phoneAcceptorLabel')">
+                                                            <el-select
+                                                                    v-model="frameManagedClerk.phone_acceptor[roleName]"
+                                                                    @change="(val)=>{phoneAcceptorChange(val,roleName)}"
+                                                                    >
+                                                                <el-option
+                                                                        v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                        v-if="clerk.checked"
+                                                                        :key="clerk.clerk_id"
+                                                                        :label="clerk.clerk_name"
+                                                                        :value="clerk.clerk_id">
+                                                                </el-option>
+                                                            </el-select>
+                                                        </el-form-item>
+                                                    </el-col>
+                                                </el-row>
+                                            </fieldset>
+                                        </div>
+
+
+                                    </el-col>
+                                </el-row>
+
+
+
+
+                            </div>
+                        </el-scrollbar>
+                    </el-tab-pane>
+                    <el-tab-pane :label="this.$t('clerkFrameManage.settedEmployee')" name="second">
+
+                        <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-160)+'px'}">
+                            <div style="padding: 0 15px">
+
+
+                                <el-row v-if="frameManagedClerk.settable!==undefined && Object.keys(frameManagedClerk.settable).length>0">
+                                    <el-col :span="24">
+
+                                        <div class="text item">
+
+                                            <fieldset style="margin-bottom: 10px"  v-for="(roleName,_index) in Object.keys(frameManagedClerk.settable)" v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)" :key="_index">
+                                                <legend><span
+                                                        style="margin-right: 10px">{{roleName}}</span>
+                                                </legend>
+                                                <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                    <el-col :span="24">
+                                                        <el-checkbox v-for="(clerk,index) in frameManagedClerk.settable[roleName]" v-if="clerk.checked" :key="index" v-model="clerk.checked"
+                                                                     @change="(val)=>{checkChange(val,roleName)}"
+                                                        >{{ clerk.clerk_name }}
+                                                        </el-checkbox>
+                                                    </el-col>
+                                                </el-row>
+                                                <el-divider
+                                                        v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)"></el-divider>
+                                                <el-row type="flex" :gutter="20" class="margin-top-sm"
+                                                        v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)">
+                                                    <el-col :span="24">
+                                                        <el-form-item
+                                                                :label="i18n.t('clerkFrameManage.phoneAcceptorLabel')">
+                                                            <el-select
+                                                                    v-model="frameManagedClerk.phone_acceptor[roleName]"
+                                                                    @change="(val)=>{phoneAcceptorChange(val,roleName)}"
+                                                                    >
+                                                                <el-option
+                                                                        v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                        v-if="clerk.checked"
+                                                                        :key="clerk.clerk_id"
+                                                                        :label="clerk.clerk_name"
+                                                                        :value="clerk.clerk_id">
+                                                                </el-option>
+                                                            </el-select>
+                                                        </el-form-item>
+                                                    </el-col>
+                                                </el-row>
+                                            </fieldset>
+                                        </div>
+
+
+                                    </el-col>
+                                </el-row>
+
+
+                                <el-row class="margin-top-sm" v-if="frameManagedClerk.un_settable!==undefined && Object.keys(frameManagedClerk.un_settable).length>0" >
+                                    <el-col :span="24">
+
+                                        <div class="text item">
+
+                                            <fieldset style="margin-bottom: 10px"  v-for="(roleName,_index) in Object.keys(frameManagedClerk.un_settable)" :key="_index" v-if="frameManagedClerk.un_settable[roleName].length>0&&frameManagedClerk.un_settable[roleName].some(p=>p.checked)">
+                                                <legend><span
+                                                        style="margin-right: 10px">{{roleName}}</span>
+                                                </legend>
+                                                <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                    <el-col :span="24">
+                                                        <el-checkbox v-for="(clerk,index) in frameManagedClerk.un_settable[roleName]" v-if="clerk.checked" disabled :key="index" v-model="clerk.checked"
+                                                        >{{ clerk.clerk_name }}
+                                                        </el-checkbox>
+                                                    </el-col>
+                                                </el-row>
+                                                <el-divider
+                                                        v-if="frameManagedClerk.un_settable[roleName].length>0&&frameManagedClerk.un_settable[roleName].some(p=>p.checked)"></el-divider>
+                                                <el-row type="flex" :gutter="20" class="margin-top-sm"
+                                                        v-if="frameManagedClerk.un_settable[roleName].length>0&&frameManagedClerk.un_settable[roleName].some(p=>p.checked)">
+                                                    <el-col :span="24">
+                                                        <el-form-item
+                                                                :label="i18n.t('clerkFrameManage.phoneAcceptorLabel')">
+                                                            <el-select
+                                                                    v-model="frameManagedClerk.phone_acceptor[roleName]"
+                                                                    @change="(val)=>{phoneAcceptorChange(val,roleName)}"
+                                                                    disabled>
+                                                                <el-option
+                                                                        v-for="(clerk,index) in frameManagedClerk.un_settable[roleName]"
+                                                                        v-if="clerk.checked"
+                                                                        :key="clerk.clerk_id"
+                                                                        :label="clerk.clerk_name"
+                                                                        :value="clerk.clerk_id">
+                                                                </el-option>
+                                                            </el-select>
+                                                        </el-form-item>
+                                                    </el-col>
+                                                </el-row>
+                                            </fieldset>
+                                        </div>
+
+
+                                    </el-col>
+                                </el-row>
+
+                            </div>
+                        </el-scrollbar>
+                    </el-tab-pane>
+
+                    <el-tab-pane :label="this.$t('clerkFrameManage.allEmployee')" name="third">
+                        <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight-160)+'px'}">
+                            <div style="padding: 0 15px">
+
+
+                                <el-row v-if="frameManagedClerk.settable!==undefined && Object.keys(frameManagedClerk.settable).length>0">
+                                    <el-col :span="24">
+
+                                        <div class="text item">
+
+                                            <fieldset style="margin-bottom: 10px"  v-for="(roleName,_index) in Object.keys(frameManagedClerk.settable)" :key="_index">
+                                                <legend><span
+                                                        style="margin-right: 10px">{{roleName}}</span>
+                                                </legend>
+                                                <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                    <el-col :span="24">
+                                                        <el-checkbox v-for="(clerk,index) in frameManagedClerk.settable[roleName]" :key="index" v-model="clerk.checked"
+                                                                     @change="(val)=>{checkChange(val,roleName)}"
+                                                        >{{ clerk.clerk_name }}
+                                                        </el-checkbox>
+                                                    </el-col>
+                                                </el-row>
+                                                <el-divider
+                                                        v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)"></el-divider>
+                                                <el-row type="flex" :gutter="20" class="margin-top-sm"
+                                                        v-if="frameManagedClerk.settable[roleName].length>0&&frameManagedClerk.settable[roleName].some(p=>p.checked)">
+                                                    <el-col :span="24">
+                                                        <el-form-item
+                                                                :label="i18n.t('clerkFrameManage.phoneAcceptorLabel')">
+                                                            <el-select
+                                                                    v-model="frameManagedClerk.phone_acceptor[roleName]"
+                                                                    @change="(val)=>{phoneAcceptorChange(val,roleName)}"
+                                                                    >
+                                                                <el-option
+                                                                        v-for="(clerk,index) in frameManagedClerk.settable[roleName]"
+                                                                        v-if="clerk.checked"
+                                                                        :key="clerk.clerk_id"
+                                                                        :label="clerk.clerk_name"
+                                                                        :value="clerk.clerk_id">
+                                                                </el-option>
+                                                            </el-select>
+                                                        </el-form-item>
+                                                    </el-col>
+                                                </el-row>
+                                            </fieldset>
+                                        </div>
+
+
+                                    </el-col>
+                                </el-row>
+
+
+                                <el-row class="margin-top-sm" v-if="frameManagedClerk.un_settable!==undefined && Object.keys(frameManagedClerk.un_settable).length>0">
+                                    <el-col :span="24">
+
+                                        <div class="text item">
+
+                                            <fieldset style="margin-bottom: 10px"  v-for="(roleName,_index) in Object.keys(frameManagedClerk.un_settable)" :key="_index">
+                                                <legend><span
+                                                        style="margin-right: 10px">{{roleName}}</span>
+                                                </legend>
+                                                <el-row :gutter="20" type="flex" style="padding: 10px">
+                                                    <el-col :span="24">
+                                                        <el-checkbox v-for="(clerk,index) in frameManagedClerk.un_settable[roleName]" disabled :key="index" v-model="clerk.checked"
+                                                        >{{ clerk.clerk_name }}
+                                                        </el-checkbox>
+                                                    </el-col>
+                                                </el-row>
+                                            </fieldset>
+                                        </div>
+
+
+                                    </el-col>
+                                </el-row>
+
+                            </div>
+                        </el-scrollbar></el-tab-pane>
+                </el-tabs>
+
+
+                <div class="margin-top-xs text-center padding-content">
+                    <el-button type="primary"  :disabled="frameManagedClerk['type']===4" @click="saveFrameManagedClerk">{{this.$t('action.saveSettings')}}</el-button>
+                </div>
+                </el-form>
+            </el-card>
+
+        </el-main>
+    </el-container>
+</template>
+
+<script>
+    import * as API_FrameGroup from '@/api/ncs_frameGroup'
+    import {FRAME_TYPE} from '@/utils/enum/FrameTypeEnum'
+    import i18n from "../../../utils/i18n"
+    export default {
+        name: "multiClerkManageFrame",
+        computed: {
+            asideHeight() {
+                return this.mainAreaHeight - 80
+            }
+        },
+        watch: {
+            selectedNodeId(newval, old) {
+                // this.selectedNode = this.findNodeById(this.treeData, newval)
+            },
+            filterText(val) {
+                this.$refs.frameTree.filter(val)
+            }
+        },
+        mounted() {
+            this.getFrameTree().then(() => {
+                if(this.treeData[0]!=null){
+                    this.selectedNodeId = this.treeData[0].children[0].children[0].id
+                    this.$refs.frameTree.setCurrentKey(this.selectedNodeId)
+                    this.getFrameManagedClerk(this.selectedNodeId)
+                }else{
+                    this.frameManagedClerk={}
+                }
+            }).catch(err => {
+                this.$message.error(err.message)
+            })
+        },
+        data() {
+            return {
+                treeData: [],
+                treeDataClone: [],
+                isShowTooltip: false,
+                /** 当前选中的树节点 */
+                selectedNodeId: 0,
+                selectedNode: {},
+                filterText: '',
+                frameManagedClerk:{
+
+                },
+                activeName:'first',
+                i18n:i18n
+            }
+        },
+        methods: {
+            /**
+             * 获取空间结构树形数据
+             * */
+            getFrameTree() {
+                return new Promise((resolve, reject) => {
+                    API_FrameGroup.getframemultimanagedstruct(this.$store.getters.partId, FRAME_TYPE.PART).then(res => {
+                        this.treeData = [...res]
+                        resolve()
+                    }).catch(err => {
+                        reject(err)
+                    })
+                })
+            },
+
+            getFrameManagedClerk(frameId) {
+                API_FrameGroup.getFrameManagedClerk(frameId).then(res => {
+                    this.frameManagedClerk={...res}
+                }).catch(err => {
+
+                })
+            },
+            checkChange(val, roleName) {
+                const roleCheckedClerk = this.frameManagedClerk.settable[roleName].filter(p => p.checked)
+                if (roleCheckedClerk.length === 0) {
+                    this.frameManagedClerk.phone_acceptor[roleName]=null
+                    this.frameManagedClerk.settable[roleName].forEach(item => {
+                        item.bool_phone_acceptor = false
+                    })
+                } else if (roleCheckedClerk.length === 1) {  //角色群组中只选中了一个职员,把该职员设为默认的电话接收人
+                    this.frameManagedClerk.phone_acceptor[roleName] = roleCheckedClerk[0].clerk_id
+                    this.frameManagedClerk.settable[roleName].forEach(item => {
+                        if (item.clerk_id === roleCheckedClerk[0].clerk_id) {
+                            item.bool_phone_acceptor = true
+                        } else {
+                            item.bool_phone_acceptor = false
+                        }
+                    })
+                } else if (roleCheckedClerk.length > 1) {//查看当前电话接收人是否是选中状态,如果不是选中状态,修改电话接收人
+                    const currentPhoneAcceptor = this.frameManagedClerk.settable[roleName].filter(p => p.clerk_id === this.frameManagedClerk.phone_acceptor[roleName])[0]
+                    if (currentPhoneAcceptor !== undefined && !currentPhoneAcceptor.checked) {
+                        this.frameManagedClerk.phone_acceptor[roleName] = roleCheckedClerk[0].clerk_id
+                        this.frameManagedClerk.settable[roleName].forEach(item => {
+                            if (item.clerk_id === roleCheckedClerk[0].clerk_id) {
+                                item.bool_phone_acceptor = true
+                            } else {
+                                item.bool_phone_acceptor = false
+                            }
+                        })
+                    }
+
+                }
+            },
+            phoneAcceptorChange(val, roleName) {
+                const phoneAcceptor = this.frameManagedClerk.phone_acceptor[roleName]
+                this.frameManagedClerk.settable[roleName].forEach(item => {
+                    if (item.clerk_id === phoneAcceptor) {
+                        item.bool_phone_acceptor = true
+                    } else {
+                        item.bool_phone_acceptor = false
+                    }
+                })
+            },
+
+            /** 节点过滤方法 **/
+            filterNode(value, data) {
+                if (!value) return true
+                return data.full_name.indexOf(value) !== -1
+            },
+            /** 点击树形节点  **/
+            nodeClick(data, node, leaf) {
+                this.$set(this, 'selectedNodeId', data.id)
+                this.getFrameManagedClerk(data.id)
+            },
+
+            saveFrameManagedClerk(){
+                API_FrameGroup.saveFrameManagedClerk(this.frameManagedClerk).then(res=>{
+                    this.getFrameTree().then(() => {
+                        if(this.treeData[0]!=null){
+                            let node = this.findNodeById(this.treeData,this.selectedNodeId)
+                            if(node!=null){ //原来选选择的node没有了
+                            this.$refs.frameTree.setCurrentKey(this.selectedNodeId)
+                            }else{
+                                this.selectedNodeId = this.treeData[0].children[0].children[0].id
+                                this.$refs.frameTree.setCurrentKey(this.selectedNodeId)
+                            }
+                            this.getFrameManagedClerk(this.selectedNodeId)
+                        }else{
+                            this.frameManagedClerk={}
+                        }})
+                    this.$message.success(this.$t('action.saveSuccess'))
+                }).catch(err=>{
+                    this.$message.error(err.message)
+                })
+            },
+            /** 树形结构中查找指定Id节点 */
+            findNodeById(data, id) {
+                let node = null
+                if (data.length > 0) {
+                    for (var i = 0; i < data.length; i++) {
+                        if (data[i].id === id) {
+                            node = data[i]
+                            break
+                        }
+                        if (data[i].children && data[i].children.length > 0) {
+                            const subresult = this.findNodeById(data[i].children, id)
+                            if (subresult !== null) {
+                                node = subresult
+                                break
+                            }
+                        }
+                    }
+                }
+                return node
+            },
+        }
+    }
+
+</script>
+
+<style scoped>
+    .el-aside {
+        margin: 8px;
+        padding: 8px;
+        border-width: 1px;
+        border-style: solid;
+        background: #fff;
+    }
+
+    .custom-tree-node {
+        flex: 1;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        font-size: 14px;
+        padding-right: 8px;
+    }
+
+    .el-tree {
+        margin-top: 8px
+    }
+
+    .el-main {
+        margin: 8px;
+        padding: 0;
+    }
+
+    fieldset {
+        border: 1px solid #DCDFE6;
+        border-radius: 5px;
+    }
+    .margin-top-sm{margin-top: 20px}
+    /deep/.el-checkbox__input.is-disabled.is-checked + span.el-checkbox__label{
+        color: #1890ff;
+    }
+    /deep/ .el-scrollbar__wrap{
+        overflow-x: hidden;
+    }
+
+</style>

+ 49 - 0
src/views/ncs-clerk-frame-manage/index.vue

@@ -0,0 +1,49 @@
+<template>
+    <div class="container">
+        <el-container>
+            <el-header height="36px" align="center" style="padding: 10px">
+                        <el-radio-group v-model="radio1">
+                            <el-radio-button :label="1">{{this.$t('clerkFrameManage.employeeView')}}</el-radio-button>
+                            <el-radio-button :label="2">{{this.$t('clerkFrameManage.frameView')}}</el-radio-button>
+                            <el-radio-button :label="3">{{this.$t('clerkFrameManage.multiClerkView')}}</el-radio-button>
+                        </el-radio-group>
+
+            </el-header>
+            <el-divider></el-divider>
+            <el-main>
+                <employee-view v-if="radio1===1"></employee-view>
+                <frame-view v-if="radio1===2"></frame-view>
+                <multi-clerk-manage-frame v-if="radio1===3"></multi-clerk-manage-frame>
+            </el-main>
+        </el-container>
+    </div>
+</template>
+
+<script>
+    import EmployeeView from "./components/employeeView";
+    import FrameView from "./components/frameView";
+    import MultiClerkManageFrame from "./components/multiClerkManageFrame";
+
+    export default {
+        name: "index",
+        components: {MultiClerkManageFrame, FrameView, EmployeeView},
+        data() {
+            return {
+                radio1: 1
+            }
+        }
+
+    }
+</script>
+
+<style scoped>
+/deep/ .el-divider--horizontal{
+    margin:0;
+    margin-top: 20px;
+}
+
+/deep/ .el-main{
+    margin: 8px;
+    padding: 0;
+}
+</style>

+ 139 - 50
src/views/ncs-clerk/components/clerkList.vue

@@ -24,7 +24,7 @@
 <!--        </div>-->
         <div class="toolbar-btns">
           <el-button v-if="part_view" type="primary" size="mini" @click="handleAddMember">{{ this.$t('action.add') }}</el-button>
-<!--          <el-button v-if="part_view" type="danger" size="mini" @click="batchDelete">批量删除</el-button>-->
+          <el-button v-if="!part_view" type="danger" size="mini" @click="batchDelete">{{ this.$t('action.deleteList') }}</el-button>
         </div>
       </div>
       <el-pagination
@@ -147,26 +147,41 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-row v-if="nurseList.length > 0">
+        <el-row v-if="addMemberForm.subordinate!==undefined && Object.keys(addMemberForm.subordinate).length>0">
           <el-col :span="24">
             <el-form-item :label="this.$t('clerkManage.clerkList')">
               <div class="text item">
-                <el-row>
-                  <el-checkbox-group v-model="newCheckList">
-                    <el-col v-for="(bed,_index) in nurseClerkList" :key="_index" :xs="8" :sm="8" :md="6" :lg="6" :xl="6">
-                      <el-checkbox :label="bed.clerk_id" @change="handleCheckboxChanged(bed)">
-                        <span v-if="bed.group_id && !bed.checked" style="color: #13ce66">{{ bed.clerk_name }}  <span style="color: #302db4">{{ bed.group_name }}</span></span>
-                        <span v-else>{{ bed.clerk_name }}</span>
+
+                <fieldset style="margin-bottom: 10px"  v-for="(roleName,_index) in Object.keys(addMemberForm.subordinate)" :key="_index">
+                  <legend><span
+                          style="margin-right: 10px">{{roleName}}</span>
+                  </legend>
+                  <el-row :gutter="20" type="flex" style="padding: 10px">
+                    <el-col :span="24">
+                      <el-checkbox v-for="(clerk,index) in addMemberForm.subordinate[roleName]" :key="index" v-model="clerk.checked"
+                                   >{{ clerk.clerk_name }}<span v-if="!clerk.checked&&clerk.leader_id!==addMemberForm.clerk_id" style="color: #67C23A;margin-left: 10px;">{{ clerk.leader_name }}</span>
                       </el-checkbox>
                     </el-col>
-                  </el-checkbox-group>
-                  <el-col v-for="(bed,_index) in nurseClerkList" :key="_index" :xs="8" :sm="8" :md="6" :lg="6" :xl="6">
-                    <!--                    <el-checkbox v-model="bed.checked">-->
-                    <!--                      <span v-if="bed.group_id && !bed.checked" style="color: #13ce66">{{ bed.clerk_name }}  <span style="color: #302db4">{{ bed.group_name }}</span></span>-->
-                    <!--                      <span v-else>{{ bed.clerk_name }}</span>-->
-                    <!--                    </el-checkbox>-->
-                  </el-col>
-                </el-row>
+                  </el-row>
+                </fieldset>
+
+
+<!--                <el-row>-->
+<!--                  <el-checkbox-group v-model="newCheckList">-->
+<!--                    <el-col v-for="(bed,_index) in addMemberForm.subordinate" :key="_index" :xs="8" :sm="8" :md="6" :lg="6" :xl="6">-->
+<!--                      <el-checkbox :label="bed.clerk_id" @change="handleCheckboxChanged(bed)">-->
+<!--                        <span v-if="bed.group_id && !bed.checked" style="color: #13ce66">{{ bed.clerk_name }}  <span style="color: #302db4">{{ bed.group_name }}</span></span>-->
+<!--                        <span v-else>{{ bed.clerk_name }}</span>-->
+<!--                      </el-checkbox>-->
+<!--                    </el-col>-->
+<!--                  </el-checkbox-group>-->
+<!--                  <el-col v-for="(bed,_index) in nurseClerkList" :key="_index" :xs="8" :sm="8" :md="6" :lg="6" :xl="6">-->
+<!--                    &lt;!&ndash;                    <el-checkbox v-model="bed.checked">&ndash;&gt;-->
+<!--                    &lt;!&ndash;                      <span v-if="bed.group_id && !bed.checked" style="color: #13ce66">{{ bed.clerk_name }}  <span style="color: #302db4">{{ bed.group_name }}</span></span>&ndash;&gt;-->
+<!--                    &lt;!&ndash;                      <span v-else>{{ bed.clerk_name }}</span>&ndash;&gt;-->
+<!--                    &lt;!&ndash;                    </el-checkbox>&ndash;&gt;-->
+<!--                  </el-col>-->
+<!--                </el-row>-->
               </div>
             </el-form-item>
 
@@ -204,20 +219,23 @@
 
 <script>
 // import { serverUrl } from '@/utils/domain'
-import * as clerk_API from '@/api/ncs_clerk'
+import * as API_Clerk from '@/api/ncs_clerk'
 import * as RegExp from '@/utils/RegExp'
 import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
 import ButtonCellRender from '@/components/AgGridCellRender/ButtonCellRender'
 import AgGridImg from '@/components/AgGridImg/AgGridImg'
 import ImageViewer from 'element-ui/packages/image/src/image-viewer'
 import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
+import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
 import * as API_User from "@/api/user";
 import {ROLE_TYPE} from "@/utils/enum/RoleTypeEnum";
+import ButtonCellRenderList from "@/components/AgGridCellRender/ButtonCellRenderList";
 let prevOverflow = ''
 const serverUrl = domain.serverUrl
 export default {
   name: 'CareDoctorManager',
-  components: { ButtonCellRender, AgGridImg, ImageViewer, RadioFilter },
+  components: { ButtonCellRenderList, ButtonCellRender, AgGridImg, ImageViewer, RadioFilter,ListFilter },
+
   props: {
     partId: {
       type: Number,
@@ -238,7 +256,7 @@ export default {
       params: {
         page_size: 10,
         page_no: 1,
-        sort: 'nc.member_id',
+        sort: 'member_id',
         dir: 'asc'
       },
       /** 列表数据 */
@@ -309,6 +327,7 @@ export default {
         { key: this.$t('member.man'), value: 1 },
         { key: this.$t('member.woman'), value: 0 }
       ],
+      roleTransfer:[],
       roleId: null,
       roleZzId: null,
       newCheckList: [],
@@ -330,7 +349,7 @@ export default {
       } else {
         this.shopId = val
       }
-      this.params.fixedCondition = this.part_view ? 'nc.shop_id=' + this.shopId : '1 = 1'
+      this.params.fixedCondition = this.part_view ? 'shop_id=' + this.shopId : '1 = 1'
       this.GET_MemberList()
     }
   },
@@ -344,11 +363,11 @@ export default {
         headerCheckboxSelectionFilteredOnly: true,
         checkboxSelection: true,
         sortable: false, filter: false,
-        width: 50,
+        width: 100,
         resizable: false,
         valueGetter: this.hashValueGetter
       },
-      { headerName: this.$t('member.face'), field: 'face', sortable: true, filter: false, width: 70,
+      { headerName: this.$t('member.face'), field: 'face', sortable: true, filter: false, width: 180,
         cellRendererFramework: 'AgGridImg',
         cellRendererParams: param => {
           return {
@@ -357,15 +376,19 @@ export default {
           }
         }
       },
-      { 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',
+      { headerName: this.$t('member.uname'), field: 'uname', sortable: true, filter: true, width: 180 },
+      { headerName: this.$t('member.nickname'), field: 'clerk_name', sortable: true, filter: true, width: 180 },
+      { headerName: this.$t('member.sex'), field: 'sex', sortable: true, valueFormatter: this.formatterSex, width: 180, filterFramework: 'RadioFilter',
         filterParams: {
           listData: this.sexTransfer
         }
       },
-      { 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('member.mobile'), field: 'mobile', sortable: true, filter: true, width: 200 },
+      { headerName: this.$t('clerkManage.role'), field: 'role_name', sortable: true, filter: false, valueFormatter: this.formatterRole,   filterFramework: 'ListFilter', flex:1,
+        filterParams: {
+          listData: this.roleTransfer
+        } },
+      { headerName: this.$t('member.leaderName'), field: 'leader_name', sortable: true, filter: true, width: 180 },
       { headerName: this.$t('action.handle'), field: 'id',
         cellRendererFramework: 'ButtonCellRender',
         cellRendererParams: param => {
@@ -379,13 +402,59 @@ export default {
         filter: false,
         pinned: 'right',
         lockPinned: true,
-        width: 100,
+        width: 160,
         resizable: false,
         sortable: false
+      },
+      {
+        headerName: this.$t('action.delete'), field: 'id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.deleteSingle,
+            label: this.$t('action.delete'),
+            buttonType: 'danger',
+            buttonSize: 'mini'
+          }
+        },
+        pinned: 'right',
+        lockPinned: true,
+        width: 90,
+        resizable: false,
+        filter: false,
+        sortable: false,
+        hide: this.part_view
       }
+      // { 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'
+      //         },
+      //         {
+      //           onClick: this.deleteSingle,
+      //           label: this.$t('action.delete'),
+      //           buttonType: 'danger',
+      //           buttonSize: 'mini',
+      //           show: !this.part_view
+      //         }
+      //       ]}
+      //   },
+      //   filter: false,
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   minWidth: this.$i18n.locale === 'zh' ? 60 : 180,
+      //   resizable: false,
+      //   sortable: false
+      // },
     ]
     this.defaultColDef = {
-      filter: 'agTextColumnFilter',
+      // filter: 'agTextColumnFilter',
       sortable: true,
       resizable: true,
       comparator: this.testComparator,
@@ -398,16 +467,20 @@ export default {
     }
     this.rowSelection = 'multiple'
   },
-  mounted() {
+  async mounted() {
     this.gridApi = this.gridOptions.api
-    this.getRoles({ page_size: 200, page_no: 1, fixedCondition: ' shop_id = -1', sort: ' role_id', dir: 'desc' })
+    this.gridApi = this.gridOptions.api
+    this.gridColumnApi = this.gridOptions.columnApi
+
     if (this.partId === 0) {
       this.shopId = this.$store.getters.partId
     } else {
       this.shopId = this.partId
     }
-    this.params.fixedCondition = this.part_view ? 'nc.shop_id=' + this.shopId : '1 = 1'
+    this.params.fixedCondition = this.part_view ? 'shop_id=' + this.shopId : '1 = 1'
     this.GET_MemberList()
+    this.getRoles({ page_size: 200, page_no: 1, fixedCondition: ' shop_id = -1', sort: ' role_id', dir: 'desc' })
+
   },
   activated() {
     this.GET_MemberList()
@@ -421,8 +494,8 @@ export default {
     GET_MemberList() {
       this.loading = true
       this.gridApi.showLoadingOverlay()
-      this.gridApi.sizeColumnsToFit()
-      clerk_API.getList(this.params).then(response => {
+      // this.gridApi.sizeColumnsToFit()
+      API_Clerk.getList(this.params).then(response => {
         this.loading = false
         const size = 0
         // response.data.forEach((item, index) => {
@@ -446,6 +519,10 @@ export default {
       this.params.query = keywords
       this.GET_MemberList()
     },
+    /** 删除设备 **/
+    deleteSingle(row) {
+      this.handlerDelete(row.clerk_id)
+    },
     /** 单条数据删除处理 */
     handlerDelete(ids) {
       this.$confirm(this.$t('member.disableClerk'), this.$t('action.waring'), {
@@ -453,7 +530,7 @@ export default {
         cancelButtonText: this.$t('action.cancel'),
         type: 'warning'
       }).then(() => {
-        clerk_API.remove(ids).then(
+        API_Clerk.remove(ids).then(
           response => {
             this.GET_MemberList()
             this.$message({
@@ -476,8 +553,14 @@ export default {
     },
     getRoles(param) {
       // 获取角色
-      clerk_API.getRoles(param).then(res => {
+      API_Clerk.getRoles(param).then(res => {
         this.rolesOptions = res.data
+        this.roleTransfer =[...res.data.map(p=>{return {'key':p.role_name,'value':p.role_name}})]
+        this.columnDefs[6].filterParams.listData=this.roleTransfer
+        console.log(this.columnDefs)
+        this.gridApi.setColumnDefs(this.columnDefs);
+        this.gridApi.redrawRows()
+        console.log(this.roleTransfer)
         const nurseZz = res.data.find(item => item.role_name === '护士组长')
         if (nurseZz) {
           this.roleZzId = nurseZz.role_id
@@ -541,25 +624,26 @@ export default {
           if (this.imageUrl) {
             params.face = this.imageUrl
           }
+          params.role_name = this.rolesOptions.filter( p => p.role_id === params.role_id)[0].role_name
           if (params.member_id) {
-            if (this.roleZzId === params.role_id) {
-              const addIds = this.newCheckList.filter(function(val) { return _this.oldCheckList.indexOf(val) === -1 })
-              const delIds = this.oldCheckList.filter(function(val) { return _this.newCheckList.indexOf(val) === -1 })
-              const data = {
-                clerkId: params.clerk_id,
-                addIds: addIds.join(','),
-                delIds: delIds.join(',')
-              }
-              clerk_API.updateParentById(data)
-            }
-            clerk_API.update(params.clerk_id, params).then(response => {
+            // if (this.roleZzId === params.role_id) {
+            //   const addIds = this.newCheckList.filter(function(val) { return _this.oldCheckList.indexOf(val) === -1 })
+            //   const delIds = this.oldCheckList.filter(function(val) { return _this.newCheckList.indexOf(val) === -1 })
+            //   const data = {
+            //     clerkId: params.clerk_id,
+            //     addIds: addIds.join(','),
+            //     delIds: delIds.join(',')
+            //   }
+            //   API_Clerk.updateParentById(data)
+            // }
+            API_Clerk.update(params.clerk_id, params).then(response => {
               this.dialogAddMemberVisible = false
               this.imageUrl = null
               this.GET_MemberList()
             })
           } else {
             params.shop_id = this.shopId
-            clerk_API.add(params).then(response => {
+            API_Clerk.add(params).then(response => {
               this.dialogAddMemberVisible = false
               this.imageUrl = null
               this.GET_MemberList()
@@ -603,7 +687,7 @@ export default {
       const _this = this
       this.newCheckList = []
       this.oldCheckList = []
-      clerk_API.getNurseByRoleId(_this.roleId, this.shopId).then(r => {
+      API_Clerk.getNurseByRoleId(_this.roleId, this.shopId).then(r => {
         _this.nurseList = r
         _this.getNurseIds(id)
         // r.forEach(item => {
@@ -616,7 +700,7 @@ export default {
     },
     getNurseIds(id) {
       const _this = this
-      clerk_API.getNurseIdsByPartId(this.shopId).then(r => {
+      API_Clerk.getNurseIdsByPartId(this.shopId).then(r => {
         r.forEach(item => {
           _this.nurseList.forEach(t => {
             if (t.clerk_id === item.nurse_id) {
@@ -756,6 +840,11 @@ export default {
     cursor: pointer;
   }
 
+  fieldset {
+    border: 1px solid #DCDFE6;
+    border-radius: 5px;
+  }
+
   .formwrap /deep/ .el-tabs__content {
     overflow: visible !important;
   }

Разлика између датотеке није приказан због своје велике величине
+ 1224 - 1076
src/views/ncs-device/components/deviceManager.vue


+ 0 - 1
src/views/ncs-device/deviceInfo.vue

@@ -111,7 +111,6 @@ export default {
   mounted() {
     this.GET_List()
     console.log('frame=', this.frame)
-    console.log(this.frameId)
   },
   methods: {
     formatterDeviceType(row, column, cellValue) {

+ 283 - 0
src/views/ncs-his/his-clerk/hisClerkManager.vue

@@ -0,0 +1,283 @@
+<template>
+  <div class="app-container">
+
+    <ag-grid-layout
+        :table-height="tableHeight"
+        theme="ag-theme-alpine"
+        :column-defs="columnDefs"
+        :row-data="tableData"
+        :locale-text="localeText"
+        :grid-options="gridOptions"
+        :default-col-def="defaultColDef"
+        :animate-rows="true"
+        :row-selection="rowSelection"
+        row-height="50"
+        @filterChanged="filterModifed"
+        @sortChanged="gridSortChange"
+    >
+      <div slot="toolbar" class="inner-toolbar">
+        <div class="toolbar-search">
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
+        </div>
+      </div>
+      <el-pagination
+          v-if="pageData"
+          slot="pagination"
+          :current-page="pageData.page_no"
+          :page-sizes="[20, 50, 100, 200]"
+          :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>
+  </div>
+</template>
+
+<script>
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter";
+import RecordButtonCellRender from "@/components/AgGridCellRender/RecordButtonCellRender";
+import {AG_GRID_LOCALE_CN} from "@/utils/AgGridVueLocaleCn";
+import * as API_his from "@/api/ncs_his";
+import {unixToDate} from "@/utils/Foundation";
+
+export default {
+  name: "hisClerkManager",
+  components: { ButtonCellRender, RadioFilter, ListFilter, RecordButtonCellRender },
+  data() {
+    return {
+      pickerOptions: {
+      },
+      tableData: [],
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+      },
+      pageData: [],
+      loading: false,
+      searchDateRange: [],
+      callingType: null,
+      columnDefs: null, // 新表格
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      rowSelection: null,
+      showViewer: false,
+      queryResult: '-1',
+      srcStreaming1: '',
+      srcStreaming2: '',
+      stream1: '',
+      stream2: '',
+      beginSeconds: 0,
+      buttonStr: this.$t('action.play'),
+      dialogVisible: false,
+      streamingType: true,
+      recordDir: '',
+      sexTransfer: [
+        { key: this.$t('member.man'), value: '1', color: 'green' },
+        { key: this.$t('member.woman'), value: '0', color: 'red' }
+      ],
+      roleTypeTransfer: [
+        { key: '医生', value: '1' },
+        { key: '护士', value: '2' },
+        { key: '护工', value: '3' },
+      ],
+      partKeyval: this.$route.params.id
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 130
+    }
+  },
+  beforeMount() {
+    this.gridOptions = {
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 50,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      { headerName: this.$t('his.hisClerkKeyval'), field: 'keyval', sortable: false, minWidth: 120 },
+      { headerName: this.$t('his.hisPartKeyval'), field: 'part_keyval', sortable: false, minWidth: 120 },
+      { headerName: this.$t('member.uname'), field: 'name', sortable: false, minWidth: 120 },
+      { headerName: this.$t('role.roleName'), field: 'type', sortable: false, minWidth: 120,
+        filterParams: {
+          listData: this.roleTypeTransfer
+        },
+        cellRenderer: this.roleTypeRenderer },
+      { headerName: this.$t('member.sex'), field: 'sex', sortable: true, filterFramework: 'RadioFilter', minWidth: 80,
+        filterParams: {
+          listData: this.sexTransfer
+        },
+        cellRenderer: this.sexRenderer },
+      { headerName: this.$t('member.birthday'), field: 'birthday', sortable: false, minWidth: 150 },
+      { headerName: this.$t('customerManage.idNo'), field: 'id_no', sortable: true, filter: 'agNumberColumnFilter' },
+      { headerName: this.$t('member.mobile'), field: 'mobile', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('his.passNo'), field: 'pass_no', sortable: false, minWidth: 150 },
+    ]
+    this.defaultColDef = {
+      filter: false,
+      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.$refs.video2.addEventListener("pause", this.pause)
+  },
+  methods: {
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    /** 分页大小发生改变 */
+    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()
+      if (this.partKeyval !== undefined) {
+        this.params.fixedCondition = 'part_keyval = "' + this.partKeyval + '"'
+      }
+
+      const param = this.MixinClone(this.params)
+      API_his.getClerkList(param).then(response => {
+        this.loading = false
+        this.tableData = [...response.data]
+        this.pageData = {
+          page_no: response.page_no,
+          page_size: response.page_size,
+          data_total: response.data_total
+        }
+      }).catch((error) => {
+        this.loading = false
+      })
+    },
+    /** 处理搜索 */
+    handlerSearch(value) {
+      this.params.page_no = 1
+      this.params.query = value
+      this.getList()
+    },
+    formatterCreateTime(row, column, cellValue) {
+      return unixToDate(row.create_time)
+    },
+    /** 处理字段排序 */
+    tableSort(column) {
+      if (column.order !== null) {
+        this.params.sort = column.prop
+        this.params.dir = column.order === 'ascending' ? 'asc' : 'desc'
+      } else {
+        this.params.sort = null
+        this.params.dir = null
+      }
+      this.getList()
+    },
+    filterModifed(param) {
+      const model = param.api.getFilterModel()
+      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()
+    },
+    changeResult() {
+      this.params.query_result = this.queryResult
+      this.params.page_no = 1
+      this.getList()
+    },
+    /** 性别格式化 **/
+    sexRenderer(params) {
+      if (params.value === null || params.value === undefined) return ''
+      const item = this.sexTransfer.filter(p => p.value === params.value)[0]
+      if (item) {
+        return '<span style="color:' + item.color + ';">' + item.key + '</span>'
+      } else {
+        return this.$t('member.unknown')
+      }
+    },
+    /** 性别格式化 **/
+    roleTypeRenderer(params) {
+      if (params.value === null || params.value === undefined) return ''
+      const item = this.roleTypeTransfer.filter(p => p.value === params.value)[0]
+      if (item) {
+        return item.key
+      } else {
+        return this.$t('member.unknown')
+      }
+    },
+    formatterPartName(param) {
+      let partName = ''
+      API_his.getPartByKeyval(param.value).then(response => {
+        partName = response.name
+      })
+      return partName
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 306 - 0
src/views/ncs-his/his-nurse-config/hisNurseConfigManager.vue

@@ -0,0 +1,306 @@
+<template>
+  <div class="app-container">
+    <el-container :style="{height: tableHeight+'px'}">
+
+      <el-aside width="300px" style="background-color: rgb(238, 241, 246)">
+        <el-table
+            ref="nurseConfigTable"
+            v-loading="listLoading"
+            :data="tagList1"
+            highlight-current-row
+            :height="tableHeight-40"
+            stripe
+            @row-click="tableClick"
+        >
+          <el-table-column prop="name" :label="this.$t('nurseConfig.configName')" width="120px" />
+          <el-table-column
+              width="160px"
+              align="right"
+          >
+
+          </el-table-column>
+        </el-table>
+      </el-aside>
+      <el-main>
+
+        <ag-grid-layout
+            toolbar
+            :table-height="tableHeight-130"
+            theme="ag-theme-alpine"
+            :column-defs="columnDefs"
+            :row-data="tagList2"
+            :locale-text="localeText"
+            :grid-options="gridOptions"
+            :default-col-def="defaultColDef"
+            :animate-rows="true"
+            :row-selection="rowSelection"
+            @filterChanged="filterModifed"
+            @sortChanged="gridSortChange"
+        >
+          <!--        @rowDoubleClicked="getList"-->
+          <div slot="toolbar" class="inner-toolbar">
+            <div class="toolbar-search">
+              <en-table-search :placeholder="this.$t('action.keywords')" @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-main>
+    </el-container>
+  </div>
+</template>
+
+<script>
+import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
+import * as API_his from "@/api/ncs_his";
+
+export default {
+  name: 'hisNurseConfig',
+  components: {},
+  data() {
+    return {
+      listLoading: false,
+      tagList1: [],
+      tagList2: [],
+      pKeyval: '',
+      type: '',
+      myTitle: '',
+      shopVisible: false,
+      member_tags: null,
+      params: {
+        page_size: 20,
+        page_no: 1,
+        sort: 'id',
+        dir: 'desc'
+      },
+      partId: this.$store.getters.partId,
+      pName: null,
+      /** ag-grid参数 **/
+      pageData: [],
+      loading: false,
+      errorId: null,
+      columnDefs: null,
+      rowData: null,
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      filterState: null,
+      rowSelection: null,
+      partKeyval: this.$route.params.id,
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 40
+    }
+  },
+  beforeMount() {
+    this.gridOptions = {
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 100,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      { headerName: this.$t('his.hisNurseOptionsKeyval'), field: 'keyval', sortable: true, filter: 'agNumberColumnFilter', width: 80 },
+      { headerName: this.$t('nurseConfig.optionName'), field: 'name', sortable: true, flex: 1, filter: 'agTextColumnFilter', filterParams: {
+          debounceMs: 200,
+          newRowsAction: 'keep'
+        }
+      },
+      // lockPosition 锁定位置,会在第一列
+      // lockPinned = true 不能拖动然后固定
+      // resizeable 单元个大小是否可以调整
+      { headerName: this.$t('nurseConfig.colorRgb'), field: 'color', sortable: true, filter: false,
+        cellRenderer: this.colorFormatter
+      },
+    ]
+    this.defaultColDef = {
+      filter: 'agTextColumnFilter',
+      sortable: true,
+      resizable: true,
+      comparator: this.dateCustomComparator,
+      filterParams: {
+        debounceMs: 200,
+        newRowsAction: 'keep',
+        textCustomComparator: this.textCustomComparator,
+        comparator: this.dateCustomComparator
+      }
+    }
+    this.rowSelection = 'multiple'
+  },
+  mounted() {
+    window.onresize = this.windowResize()
+    this.gettagList1()
+  },
+  methods: {
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    gettagList1() {
+      this.params.sort = 'index_no'
+      this.params.dir = 'asc'
+      if (this.partKeyval !== undefined && this.partKeyval.length > 0) {
+        this.params.fixedCondition = 'part_keyval= "' + this.partKeyval + '"'
+      }
+
+      API_his.getNurseConfigList(this.params).then(response => {
+        this.listLoading = false
+        this.tagList1 = response.data
+
+        if (this.tagList1.length > 0) {
+          if (this.pKeyval === '') {
+            this.pKeyval = this.tagList1[0].keyval
+          }
+          this.pName = this.tagList1[0].name
+          this.gettagList2(this.pKeyval)
+          const currentRow = this.tagList1.find(p => p.keyval === this.pKeyval)
+          this.$refs.nurseConfigTable.setCurrentRow(currentRow)
+        }
+      }).catch(() => {
+        this.listLoading = false
+      })
+    },
+    gettagList2() {
+      if (this.pKeyval !== undefined && this.pKeyval.length > 0) {
+        this.params.fixedCondition = ' category_keyval = "' + this.pKeyval + '"'
+      }
+
+      this.params.sort = 'id'
+      this.params.dir = 'desc'
+      API_his.getNurseOptionsList(this.params).then(response => {
+        this.tagList2 = response.data
+      }).catch(() => {
+      })
+    },
+    tableClick(row, column, event, cell) {
+      if (column.property === 'name') {
+        this.pKeyval = row.keyval
+        this.pName = row.name
+        this.gettagList2()
+      }
+    },
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.gettagList2()
+    },
+
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.gettagList2()
+    },
+    memberInit() {
+    },
+    openAdvert(index, row) {
+      this.member_tags = row.tag
+      this.shopVisible = true
+    },
+    colorFormatter(param) {
+      console.log('aa', param)
+      return '<button style="width: 120px;height: 30px;vertical-align:middle;border:0;background-color: #' + param.value + '"/>'
+    },
+    /** 处理搜索 */
+    handlerSearch(keywords) {
+      this.params.query = keywords
+      this.gettagList2()
+    },
+    /** 处理字段排序 */
+    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.gettagList2()
+    },
+    gridSortChange(param) {
+      console.log('sortparam', 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.gettagList2()
+      console.log(sortState)
+    },
+    filterModifed(param) {
+      console.log(param)
+      var model = param.api.getFilterModel()
+      console.log('model', JSON.stringify(model))
+      this.params.filter = JSON.stringify(model)
+      this.gettagList2()
+    },
+  }
+}
+</script>
+
+<style scoped>
+.permission-container {
+  padding: 10px;
+  background-color: #fff;
+}
+.el-aside{
+  padding: 8px 10px;
+}
+.mytable {
+  width: 100%;
+  padding: 20px;
+  min-height: 480px;
+  cursor: pointer;
+  font-size: 16px;
+}
+/deep/ .colorBtn {
+  width: 80px !important;
+  height: 40px !important;
+}
+/deep/ .m-colorPicker .box.open{
+  z-index: 1000 !important;
+}
+</style>

+ 272 - 0
src/views/ncs-his/his-part/hisPartManager.vue

@@ -0,0 +1,272 @@
+<template>
+  <div class="app-container">
+
+    <ag-grid-layout
+        :table-height="tableHeight"
+        theme="ag-theme-alpine"
+        :column-defs="columnDefs"
+        :row-data="tableData"
+        :locale-text="localeText"
+        :grid-options="gridOptions"
+        :default-col-def="defaultColDef"
+        :animate-rows="true"
+        :row-selection="rowSelection"
+        row-height="50"
+        @filterChanged="filterModifed"
+        @sortChanged="gridSortChange"
+    >
+      <div slot="toolbar" class="inner-toolbar">
+        <div class="toolbar-search">
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
+        </div>
+      </div>
+      <el-pagination
+          v-if="pageData"
+          slot="pagination"
+          :current-page="pageData.page_no"
+          :page-sizes="[20, 50, 100, 200]"
+          :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>
+  </div>
+</template>
+
+<script>
+import * as API_his from '@/api/ncs_his'
+import { unixToDate } from '@/utils/Foundation'
+import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
+import RecordButtonCellRender from "@/components/AgGridCellRender/RecordButtonCellRender";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter";
+import ButtonCellRenderList from "@/components/AgGridCellRender/ButtonCellRenderList";
+const DeviceUrl = domain.DeviceUrl
+
+export default {
+  name: 'hisPartManager',
+  components: { ButtonCellRenderList, ButtonCellRender, RadioFilter, ListFilter, RecordButtonCellRender },
+  data() {
+    return {
+      pickerOptions: {
+      },
+      tableData: [],
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+      },
+      pageData: [],
+      loading: false,
+      searchDateRange: [],
+      callingType: null,
+      columnDefs: null, // 新表格
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      rowSelection: null,
+      showViewer: false,
+      queryResult: '-1',
+      srcStreaming1: '',
+      srcStreaming2: '',
+      stream1: '',
+      stream2: '',
+      beginSeconds: 0,
+      buttonStr: this.$t('action.play'),
+      dialogVisible: false,
+      streamingType: true,
+      recordDir: '',
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 130
+    }
+  },
+  beforeMount() {
+    this.gridOptions = {
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 50,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      { headerName: this.$t('his.hisPartKeyval'), field: 'keyval', sortable: false, minWidth: 150 },
+      { headerName: this.$t('his.hisPartName'), field: 'name', sortable: false, minWidth: 150 },
+      { headerName: this.$t('his.summary'), field: 'summary', sortable: false, minWidth: 150 },
+      { headerName: this.$t('his.tel'), field: 'tel', sortable: false, minWidth: 150 },
+      { headerName: this.$t('action.handle'), field: 'id',
+        cellRendererFramework: 'ButtonCellRenderList',
+        cellRendererParams: param => {
+          return {
+            list: [
+              {
+                onClick: this.getHisPatient,
+                label: this.$t('his.hisPatient'),
+                buttonType: 'primary',
+                buttonSize: 'mini'
+              },
+              {
+                onClick: this.getHisClerk,
+                label: this.$t('his.hisClerk'),
+                buttonType: 'warning',
+                buttonSize: 'mini',
+              },
+              {
+                onClick: this.getHisNurseConfig,
+                label: this.$t('his.hisNurseConfig'),
+                buttonType: 'success',
+                buttonSize: 'mini',
+              }
+            ]}
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        minWidth: this.$i18n.locale === 'zh' ? 240 : 350,
+        resizable: false,
+        sortable: false
+      }
+    ]
+    this.defaultColDef = {
+      filter: false,
+      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.$refs.video2.addEventListener("pause", this.pause)
+  },
+  methods: {
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    /** 分页大小发生改变 */
+    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()
+      const param = this.MixinClone(this.params)
+      API_his.getList(param).then(response => {
+        this.loading = false
+        this.tableData = [...response.data]
+        this.pageData = {
+          page_no: response.page_no,
+          page_size: response.page_size,
+          data_total: response.data_total
+        }
+      }).catch((error) => {
+        this.loading = false
+      })
+    },
+    getHisPatient(row) {
+      this.$router.push({ name: 'hisPatientManage', params: { id: row.keyval, callback: this.getList() }})
+    },
+    getHisClerk(row) {
+      this.$router.push({ name: 'hisClerkManage', params: { id: row.keyval, callback: this.getList() }})
+    },
+    getHisNurseConfig(row) {
+      this.$router.push({ name: 'hisNurseConfigManage', params: { id: row.keyval, callback: this.getList() }})
+    },
+    /** 处理搜索 */
+    handlerSearch(value) {
+      this.params.page_no = 1
+      this.params.query = value
+      this.getList()
+    },
+    formatterCreateTime(row, column, cellValue) {
+      return unixToDate(row.create_time)
+    },
+    /** 处理字段排序 */
+    tableSort(column) {
+      if (column.order !== null) {
+        this.params.sort = column.prop
+        this.params.dir = column.order === 'ascending' ? 'asc' : 'desc'
+      } else {
+        this.params.sort = null
+        this.params.dir = null
+      }
+      this.getList()
+    },
+    filterModifed(param) {
+      const model = param.api.getFilterModel()
+      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()
+    },
+    changeResult() {
+      this.params.query_result = this.queryResult
+      this.params.page_no = 1
+      this.getList()
+    },
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 495 - 0
src/views/ncs-his/his-patient/hisPatientManage.vue

@@ -0,0 +1,495 @@
+<template>
+  <div class="app-container">
+
+    <ag-grid-layout
+        :table-height="tableHeight"
+        theme="ag-theme-alpine"
+        :column-defs="columnDefs"
+        :row-data="tableData"
+        :locale-text="localeText"
+        :grid-options="gridOptions"
+        :default-col-def="defaultColDef"
+        :animate-rows="true"
+        :row-selection="rowSelection"
+        row-height="50"
+        @filterChanged="filterModifed"
+        @sortChanged="gridSortChange"
+    >
+      <div slot="toolbar" class="inner-toolbar">
+        <div class="toolbar-search">
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
+        </div>
+      </div>
+      <el-pagination
+          v-if="pageData"
+          slot="pagination"
+          :current-page="pageData.page_no"
+          :page-sizes="[20, 50, 100, 200]"
+          :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 :visible.sync="customerFormVisible" :title="this.$t('customerManage.customerInfo')" class="customer-dialog" width="60%">
+      <el-form ref="editForm" :model="formmodel" :label-width="this.$i18n.locale === 'zh' ? '120px' : '145px'">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('customerManage.named')" prop="name">
+              {{ this.formmodel.name }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('customerManage.cardNo')">
+              {{ this.formmodel.card_no }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('member.sex')" class="form-item-sex">
+              {{ getSex(this.formmodel.sex) }}
+            </el-form-item>
+          </el-col>
+
+          <el-col :span="12">
+            <el-form-item :label="this.$t('customerManage.age')" prop="age">
+              {{ this.formmodel.age + this.formmodel.age_unit }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('member.mobile')" prop="mobile">
+              {{ this.formmodel.mobile }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('member.homeAddress')" prop="address">
+              {{ this.formmodel.address }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('member.birthday')" prop="birthday">
+              {{ this.formmodel.birthday }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="this.$t('customerManage.inDate')" prop="in_date">
+              {{ this.formmodel.indate }}
+            </el-form-item>
+          </el-col>
+
+          <el-col :span="12">
+            <el-form-item :label="this.$t('customerManage.idCard')">
+              {{ this.formmodel.id_no }}
+            </el-form-item>
+          </el-col>
+
+          <el-col :span="12">
+            <el-form-item :label="this.$t('customerManage.frame')" prop="frame_id">
+              {{ this.formmodel.bed_no }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="16">
+            <el-form-item :label="this.$t('customerManage.patientIllnessDesc')">
+              {{ this.formmodel.illness_description }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="8">
+            <el-form-item :label="this.$t('customerManage.doctor')">
+              {{ this.formmodel.doctor_name }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item :label="this.$t('customerManage.nurse')">
+              {{ this.formmodel.nurse_name }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item :label="this.$t('customerManage.worker')">
+              {{ this.formmodel.worker_name }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row v-if="hisPatientMappingList.length > 0">
+          <el-col v-for="(item, index) in hisPatientMappingList" :key="index" :span="8">
+            <el-form-item :label="item.category_name">
+              <span :style="'color: #' + item.color">{{ item.options_name }}</span>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+
+        <el-row>
+
+          <el-col :span="8">
+            <el-form-item :label="this.$t('customerManage.babyName')">
+              {{ this.formmodel.baby_name }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item :label="this.$t('customerManage.babySex')">
+              {{ getSex(this.formmodel.baby_sex) }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item :label="this.$t('customerManage.babyBirthday')">
+              {{ this.formmodel.baby_birthday  }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import * as API_his from '@/api/ncs_his'
+import { unixToDate } from '@/utils/Foundation'
+import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
+import RecordButtonCellRender from "@/components/AgGridCellRender/RecordButtonCellRender";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter";
+import {getDevicesByUuid} from "@/api/initialize";
+import * as API_NurseConfig from "@/api/ncs_nurse_config";
+const DeviceUrl = domain.DeviceUrl
+
+export default {
+  name: 'hisPatientManage',
+  components: { ButtonCellRender, RadioFilter, ListFilter, RecordButtonCellRender },
+  data() {
+    return {
+      pickerOptions: {
+      },
+      tableData: [],
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+      },
+      activeName: 'customerBaseInfo',
+      formmodel: {},
+      pageData: [],
+      nurseconfigSelection: [],
+      loading: false,
+      searchDateRange: [],
+      callingType: null,
+      columnDefs: null, // 新表格
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      rowSelection: null,
+      showViewer: false,
+      queryResult: '-1',
+      srcStreaming1: '',
+      srcStreaming2: '',
+      stream1: '',
+      stream2: '',
+      beginSeconds: 0,
+      buttonStr: this.$t('action.play'),
+      dialogVisible: false,
+      streamingType: true,
+      recordDir: '',
+      sexTransfer: [
+        { key: this.$t('member.man'), value: '1', color: 'green' },
+        { key: this.$t('member.woman'), value: '0', color: 'red' }
+      ],
+      customerStatusTransfer: [
+        { key: this.$t('customerManage.customerStatusTrue'), value: '0', color: 'green' },
+        { key: this.$t('customerManage.customerStatusFalse'), value: '1', color: 'red' }
+      ],
+      partKeyval: this.$route.params.id,
+      partName: '',
+      customerFormVisible: false,
+      hisNurseOptionsList: [],
+      hisPatientMappingList: []
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 130
+    }
+  },
+  beforeMount() {
+    this.gridOptions = {
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 50,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      { headerName: this.$t('his.hisPatientKeyval'), field: 'keyval', sortable: false, minWidth: 120 },
+      { headerName: this.$t('his.hisPartKeyval'), field: 'part_keyval', sortable: false, minWidth: 120 },
+      { headerName: this.$t('customerManage.named'), field: 'name', sortable: false, minWidth: 120 },
+      { headerName: this.$t('customerManage.frame'), field: 'bed_no', sortable: false, minWidth: 120 },
+      { headerName: this.$t('member.sex'), field: 'sex', sortable: true, filterFramework: 'RadioFilter', minWidth: 120,
+        filterParams: {
+          listData: this.sexTransfer
+        },
+        cellRenderer: this.sexRenderer },
+      { headerName: this.$t('customerManage.customerStatus'), field: 'status', sortable: true, filterFramework: 'RadioFilter', minWidth: 80,
+        filterParams: {
+          listData: this.customerStatusTransfer
+        },
+        cellRenderer: this.customerStatusRenderer },
+      { headerName: this.$t('member.mobile'), field: 'mobile', sortable: true, filter: 'agTextColumnFilter', minWidth: 120 },
+      { headerName: this.$t('customerManage.age'), field: 'age', sortable: true, filter: 'agNumberColumnFilter', minWidth: 80 },
+      { headerName: this.$t('customerManage.ageUnit'), field: 'age_unit', sortable: true, filter: 'agTextColumnFilter', minWidth: 80 },
+      { headerName: this.$t('member.birthday'), field: 'birthday', sortable: false, minWidth: 120 },
+      { headerName: this.$t('customerManage.cardNo'), field: 'card_no', sortable: false, minWidth: 120 },
+      { headerName: this.$t('customerManage.inDate'), field: 'indate', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: this.$t('action.handle'), field: 'id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: {
+          onClick: this.handleInfo,
+          label: this.$t('his.hisPatientInfo'),
+          buttonType: 'primary',
+          buttonSize: 'mini'
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        minWidth: 120,
+        resizable: false,
+        sortable: false
+      }
+    ]
+    this.defaultColDef = {
+      filter: false,
+      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.$refs.video2.addEventListener("pause", this.pause)
+  },
+  methods: {
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    /** 分页大小发生改变 */
+    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()
+
+      if (this.partKeyval !== undefined) {
+        this.params.fixedCondition = 'part_keyval = "' + this.partKeyval + '"'
+      }
+
+      const param = this.MixinClone(this.params)
+      API_his.getPatientList(param).then(response => {
+        this.loading = false
+        this.tableData = [...response.data]
+        this.pageData = {
+          page_no: response.page_no,
+          page_size: response.page_size,
+          data_total: response.data_total
+        }
+      }).catch((error) => {
+        this.loading = false
+      })
+    },
+    /** 处理搜索 */
+    handlerSearch(value) {
+      this.params.page_no = 1
+      this.params.query = value
+      this.getList()
+    },
+    formatterCreateTime(row, column, cellValue) {
+      return unixToDate(row.create_time)
+    },
+    /** 处理字段排序 */
+    tableSort(column) {
+      if (column.order !== null) {
+        this.params.sort = column.prop
+        this.params.dir = column.order === 'ascending' ? 'asc' : 'desc'
+      } else {
+        this.params.sort = null
+        this.params.dir = null
+      }
+      this.getList()
+    },
+    filterModifed(param) {
+      const model = param.api.getFilterModel()
+      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()
+    },
+    changeResult() {
+      this.params.query_result = this.queryResult
+      this.params.page_no = 1
+      this.getList()
+    },
+    /** 性别格式化 **/
+    sexRenderer(params) {
+      if (params.value === null || params.value === undefined) return ''
+      const item = this.sexTransfer.filter(p => p.value === params.value)[0]
+      if (item) {
+        return '<span style="color:' + item.color + ';">' + item.key + '</span>'
+      } else {
+        return this.$t('member.unknown')
+      }
+    },
+    getSex(value) {
+      if (value === null || value === undefined) return ''
+      const item = this.sexTransfer.filter(p => p.value ===value)[0]
+      if (item) {
+        return item.key
+      } else {
+        return this.$t('member.unknown')
+      }
+    },
+    /** 状态格式化 **/
+    customerStatusRenderer(params) {
+      if (params.value === null || params.value === undefined) return ''
+      const item = this.customerStatusTransfer.filter(p => p.value === params.value)[0]
+      if (item) {
+        return '<span style="color:' + item.color + ';">' + item.key + '</span>'
+      } else {
+        return this.$t('member.unknown')
+      }
+    },
+    handleInfo(row) {
+      this.boolDevice = false
+      this.formmodel = {
+        ...row
+      }
+
+      console.log(this.formmodel)
+      this.getPatientNurseMappingByPatientKeyval(this.formmodel.keyval)
+      // // 处理护理项已选择内容
+      // const nurseconfigs = this.formmodel.nurseconfigs
+      // for (let i = 0; i < this.nurseconfigSelection.length; i++) {
+      //   delete this.nurseconfigSelection[i].selected_id
+      //   delete this.nurseconfigSelection[i].mapping_id
+      // }
+      // if (nurseconfigs) {
+      //   nurseconfigs.forEach(item => {
+      //     const nurseconfigselect = this.nurseconfigSelection.find(p => p.config.id === item.nurseconfig_id)
+      //     if (nurseconfigselect) {
+      //       nurseconfigselect.selected_id = item.nurseconfig_option_id
+      //       nurseconfigselect.mapping_id = item.mapping_id
+      //     }
+      //   })
+      // }
+      this.customerFormVisible = true
+      // this.handNusreColor()
+    },
+
+    /**
+     * 加载护理参数
+     */
+    getNurseConfigs() {
+      this.nurseData = []
+      API_NurseConfig.getConfigSelectionByPartId(this.$store.getters.partId).then(res => {
+        this.nurseconfigSelection = [...res]
+      })
+    },
+    // 护理项选择 设置选中项的颜色
+    changeNurseData(val, configid, index) {
+      const currentCfg = this.nurseconfigSelection.find(p => p.config.id === configid).options.find(p => p.id === val)
+      if (currentCfg) {
+        this.$refs['patient_nurse_' + configid][0].$el.getElementsByClassName('el-input__inner')[0].style = 'color:#' + currentCfg.color_rgb + ' !important'
+      }
+      this.$set(this, 'nurseconfigSelection', this.nurseconfigSelection)
+      this.$set(this.nurseconfigSelection, index, this.nurseconfigSelection[index])
+    },
+    // 初始化护理参数选中项颜色
+    handNusreColor() {
+      // 处理护理等级颜色
+      this.$nextTick(() => {
+        this.nurseconfigSelection.forEach(item => {
+          const currentCfg = this.nurseconfigSelection.find(p => p.config.id === item.config.id).options.find(p => p.id === item.selected_id)
+          if (currentCfg) {
+            this.$refs['patient_nurse_' + item.config.id][0].$el.getElementsByClassName('el-input__inner')[0].style = 'color:#' + currentCfg.color_rgb + ' !important'
+          }
+        })
+      })
+    },
+    getPatientNurseMappingByPatientKeyval(patientKeyval) {
+      API_his.getPatientNurseMappingByPatientKeyval(patientKeyval).then(res => {
+        this.hisPatientMappingList = res
+        console.log(this.hisPatientMappingList)
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 48 - 0
src/views/ncs-his/hisManagement.vue

@@ -0,0 +1,48 @@
+<template>
+  <el-tabs v-model="activeName" style="margin:0;" type="border-card">
+    <el-tab-pane :label="this.$t('his.hisPart')" name="hisPart">
+      <keep-alive>
+        <his-part-manager :frame="frame" />
+      </keep-alive>
+    </el-tab-pane>
+    <el-tab-pane :label="this.$t('his.hisPatient')" name="hisPatient">
+      <keep-alive>
+        <his-patient-manager :frame="frame" />
+      </keep-alive>
+    </el-tab-pane>
+    <el-tab-pane :label="this.$t('his.hisClerk')" name="hisClerk">
+      <keep-alive>
+        <his-clerk-manager :frame="frame" />
+      </keep-alive>
+    </el-tab-pane>
+    <el-tab-pane :label="this.$t('his.hisNurseConfig')" name="hisNurseConfig">
+      <keep-alive>
+        <his-nurse-config-manager :frame="frame" />
+      </keep-alive>
+    </el-tab-pane>
+  </el-tabs>
+</template>
+
+<script>
+import HisPartManager from './his-part/hisPartManager'
+import HisPatientManager from './his-patient/hisPatientManage'
+import HisClerkManager from './his-clerk/hisClerkManager'
+import HisNurseConfigManager from './his-nurse-config/hisNurseConfigManager'
+export default {
+  name: 'hisManager',
+  components: { HisPartManager, HisPatientManager, HisClerkManager, HisNurseConfigManager },
+  data() {
+    return {
+      frame: {},
+      activeName: 'hisPart',
+      loading: false
+    }
+  },
+  methods: {
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 71 - 8
src/views/ncs-interaction/index.vue

@@ -251,6 +251,7 @@ export default {
         width: 120
       },
       { headerName: this.$t('interaction.createDate'), field: 'create_date', sortable: true, valueFormatter: this.formatterDate, width: 150 },
+      { headerName: this.$t('interaction.responseTime'), sortable: true, valueFormatter: this.formatterResponseTime, width: 150 },
       { headerName: this.$t('interaction.fromDevice'), field: 'from_device_type', sortable: true, valueFormatter: this.formatterDeviceType, width: 120 },
       { headerName: this.$t('interaction.toDevice'), field: 'to_device_type', sortable: true, valueFormatter: this.formatterDeviceType, width: 120 },
     ]
@@ -397,7 +398,7 @@ export default {
         }
         return named
       } else {
-        return row.data.from_member_name + '的' + row.data.relative_name
+        return row.data.from_member_name + this.$t('action.of') + row.data.relative_name
       }
     },
     formatterToName(row) {
@@ -443,6 +444,64 @@ export default {
         }
       }
     },
+    formatterResponseTime(params) {
+      console.log(params.data)
+      let responseTime = 0;
+      if (params.data.action_end !== null) {
+        if (params.data.action_type === TCP_TYPE.VOICE ||
+            params.data.action_type === TCP_TYPE.VIDEO ||
+            params.data.action_type === TCP_TYPE.PHONE
+        ) {
+          if (params.data.action_start !== null && params.data.action_accept !== null) {
+            responseTime = params.data.action_accept - params.data.action_start
+            return this.formateSeconds(responseTime)
+          }
+        } else {
+          responseTime = params.data.action_end - params.data.action_start
+          return this.formateSeconds(responseTime)
+        }
+      }
+    },
+    formatterResponseTimeToExcel(params) {
+      let responseTime = 0;
+      if (params.data.action_end !== null) {
+        if (params.data.action_type === TCP_TYPE.VOICE ||
+            params.data.action_type === TCP_TYPE.VIDEO ||
+            params.data.action_type === TCP_TYPE.PHONE
+        ) {
+          if (params.data.action_start !== null && params.data.action_accept !== null) {
+            responseTime = params.data.action_accept - params.data.action_start
+            return responseTime
+          }
+        } else {
+          responseTime = params.data.action_end - params.data.action_start
+          return responseTime
+        }
+      }
+    },
+    formateSeconds(endTime){
+      if (endTime === 0) {
+        return this.$t('action.oneSecond')
+      } else if (endTime === -1) {
+        return this.$t('action.null')
+      }
+      let secondTime = endTime//将传入的秒的值转化为Number
+      let min = 0// 初始化分
+      let h =0// 初始化小时
+      if(secondTime>60){//如果秒数大于60,将秒数转换成整数
+        min=parseInt(secondTime/60)//获取分钟,除以60取整数,得到整数分钟
+        secondTime=parseInt(secondTime%60)//获取秒数,秒数取佘,得到整数秒数
+        if(min>60){//如果分钟大于60,将分钟转换成小时
+          h=parseInt(min/60)//获取小时,获取分钟除以60,得到整数小时
+          min=parseInt(min%60) //获取小时后取佘的分,获取分钟除以60取佘的分
+          return h + this.$t('action.time2') + min + this.$t('action.minute2') + secondTime + this.$t('action.second')
+        } else {
+          return min +this.$t('action.minute2') + secondTime + this.$t('action.second')
+        }
+      } else {
+        return secondTime + this.$t('action.second')
+      }
+    },
     formatterDate(params) {
       return unixToDate(params.value)
     },
@@ -490,24 +549,25 @@ export default {
     },
     daochu() {
       const _this = this
-      this.$confirm('将导出交互信息Excel文件,是否继续?', '提示', {
+      this.$confirm(this.$t('action.excelFile'), this.$t('action.prompt'), {
         type: 'warning'
       }).then(() => {
         _this.loading = true
         const params = _this.MixinClone(_this.params)
         if (!params.start_date || !params.end_date) {
-          _this.$message.info('请选择时间范围!')
+          _this.$message.info(this.$t('action.timeMsg'))
           return
         }
-        params.page_size = 1000
+        params.page_size = this.pageData.data_total
         params.page_no = 1
         API_interaction.getList(params).then(res => {
           _this.loading = false
           import('@/vendor/Export2Excel').then(excel => {
-            const tHeader = [this.$t('interaction.fromMemberName'), this.$t('interaction.toMemberName'), this.$t('interaction.actionType'), this.$t('interaction.actionEnd'), this.$t('interaction.data'),
+            const tHeader = [this.$t('interaction.fromMemberName'), this.$t('interaction.toMemberName'), this.$t('interaction.actionType'),
+              this.$t('interaction.actionEnd'), this.$t('interaction.data'), this.$t('interaction.responseTime'),
               this.$t('interaction.createDate')] // 表头
-            const filterVal = ['fromMemberName', 'toMemberName', 'action_type', 'action_end', 'data', 'create_date']
-            const tit = params.start_date + '至' + params.end_date + '交互记录'
+            const filterVal = ['fromMemberName', 'toMemberName', 'action_type', 'action_end', 'data', 'responseTime', 'create_date']
+            const tit = params.start_date + this.$t('action.to') + params.end_date + this.$t('interaction.interactionRecord')
             const data = _this.formatJson(filterVal, res.data)
             excel.export_json_to_excel({
               header: tHeader,
@@ -531,6 +591,9 @@ export default {
           return this.formatterResult2(v[j])
         }else if (j === 'create_date') {
           return this.formatterDate({value: v[j]})
+        } else if (j === 'responseTime') {
+          console.log(v)
+          return this.formatterResponseTimeToExcel({data: v})
         } else {
           return v[j]
         }
@@ -546,7 +609,7 @@ export default {
         if (res.length !== 0) {
           if (res[0].endsWith("webm")) {
             this.streamingType = true
-          } else if (resp[0].endsWith("opus")) {
+          } else if (res[0].endsWith("opus")) {
             this.streamingType = false
           }
 

+ 13 - 5
src/views/ncs-orginazition/components/AppVersionManager.vue

@@ -85,12 +85,20 @@ export default {
     /** 文件上传之前的校验 */
     handleShopLogoBefore(file) {
       const isImg = file.type === 'application/vnd.android.package-archive'
-      const ext = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase() === 'apk'
-      const isapk = isImg || ext
-      if (!isapk) {
-        this.$message.error(this.$t('action.uploadFileMsg5'))
+      if (isImg) {
+        const ext = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase() === 'apk'
+        const isapk = isImg || ext
+        if (!isapk) {
+          this.$message.error(this.$t('action.uploadFileMsg5'))
+        }
+        return isapk
+      } else {
+        const ext = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase() === 'img'
+        if (!ext) {
+          this.$message.error(this.$t('action.uploadFileMsg5'))
+        }
+        return ext
       }
-      return isapk
     },
     getAppVersion() {
       const params = {

+ 77 - 24
src/views/ncs-orginazition/components/partInfoEdit.vue

@@ -308,17 +308,22 @@
             </el-col>
 
             <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.channelImHistoryStoreDays')" prop="channel_im_history_store_days">
+                <el-input-number v-model="formmodel.channel_im_history_store_days" :min="1" :max="1000" :label="this.$t('partInfo.channelImHistoryStoreDays')" />
+              </el-form-item>
+            </el-col>
+
+            <el-col :span="8">
               <el-form-item :label="this.$t('partInfo.customerNameHidden')" prop="customer_name_hidden">
                 <el-checkbox v-model="formmodel.customer_name_hidden" :true-label="1" :false-label="0">{{ this.$t('partInfo.hidden') }}</el-checkbox>
               </el-form-item>
             </el-col>
-          </el-row>
-
 
-          <el-row>
-            <el-form-item :label="this.$t('partInfo.channelImHistoryStoreDays')" prop="channel_im_history_store_days">
-              <el-input-number v-model="formmodel.channel_im_history_store_days" :min="1" :max="1000" :label="this.$t('partInfo.channelImHistoryStoreDays')" />
-            </el-form-item>
+            <el-col :span="8">
+              <el-form-item :label="this.$t('partInfo.clerkNameHidden')" prop="clerk_name_hidden">
+                <el-checkbox v-model="formmodel.clerk_name_hidden" :true-label="1" :false-label="0">{{ this.$t('partInfo.hidden') }}</el-checkbox>
+              </el-form-item>
+            </el-col>
 
             <el-col :span="8">
               <el-form-item :label="this.$t('partInfo.recordEnabled')" prop="record_enabled">
@@ -328,7 +333,6 @@
           </el-row>
 
 
-
           <el-row>
             <el-col :span="8">
               <el-form-item :label="this.$t('partInfo.communicationModeBed')" prop="communication_mode_bed">
@@ -511,19 +515,39 @@
               </el-form-item>
             </el-col>
           </el-row>
-          <el-form-item :label="this.$t('action.icon')">
-            <el-upload
-                class="avatar-uploader"
-                :action="`${uploadurl}?scene=avatar`"
-                :show-file-list="false"
-                :on-success="uploaded"
-                :before-upload="handleShopLogoBefore"
-            >
-              <img v-if="imageUrl" :src="imageUrl" class="avatar">
-              <i v-else class="el-icon-plus avatar-uploader-icon" />
-            </el-upload>
-          </el-form-item>
 
+          <el-row>
+            <el-col :span="8">
+              <el-form-item :label="this.$t('action.icon')">
+                <el-upload
+                    class="avatar-uploader"
+                    :action="`${uploadurl}?scene=avatar`"
+                    :show-file-list="false"
+                    :on-success="uploaded"
+                    :before-upload="handleShopLogoBefore"
+                >
+                  <img v-if="imageUrl" :src="imageUrl" class="avatar">
+                  <i v-else class="el-icon-plus avatar-uploader-icon" />
+                </el-upload>
+              </el-form-item>
+            </el-col>
+
+            <el-col :span="8" v-if="isShow">
+              <el-form-item :label="this.$t('action.excelUpload')">
+                <el-upload
+                    class="excel-uploader"
+                    :action="`${excelUploadUrl}`"
+                    :show-file-list="false"
+                    :on-success="excelUploaded"
+                    :before-upload="handleExcelBefore"
+                    :limit="1"
+                >
+                  <el-button size="small" type="primary">{{ this.$t('action.uploadFile') }}</el-button>
+                </el-upload>
+                <el-link :href="excelUploadDemo" type="primary" target="_blank" icon="el-icon-download" :underline="false">excel表格模板</el-link>
+              </el-form-item>
+            </el-col>
+          </el-row>
         </fieldset>
 
         <el-form-item align="center" class="margin-top-sm">
@@ -547,12 +571,14 @@ import {bindDeviceTransAudio, init485Device, initData, initDeviceList} from '@/a
 import * as API_Clerk from '@/api/ncs_clerk'
 import * as API_SystemConfig from '@/api/ncs_systemconfig'
 import * as API_Device from '@/api/ncs_device'
+import * as API_Excel from "@/api/ncs_excel";
 const serverUrl = domain.serverUrl
+const DeviceUrl = domain.DeviceUrl
 export default {
   name: 'PartInfoEdit',
   props: {
     partId: {
-      type: String,
+      type: Number,
       default: null
     }
   },
@@ -578,15 +604,18 @@ export default {
       otherHostDevice: [],
       uploadurl: serverUrl + '/ncs/upload/uploadFile',
       imageUrl: '',
+      excelUploadUrl: DeviceUrl + '/ncs/excel/upload/' + this.partId,
+      excelUploadDemo: serverUrl + '/upload/excel/demo/excel_demo.xlsx',
     }
   },
   async mounted() {
     this.isShow = JSON.parse(Storage.getItem('calling_user')).username === 'superadmin'
     // this.nurseLevel0Config = await API_Nurse.getNurseConfigs(this.partId, 0)
     this.getPartInfo()
-    this.getPartents()
+    this.getParents()
     this.getRoles({ page_size: 200, page_no: 1, fixedCondition: ' shop_id = -1 and role_name<>"护士"', sort: ' role_id', dir: 'desc' })
-    this.getOtherHostDevice(this.$store.getters.partId)
+    this.getOtherHostDevice(this.partId)
+    console.log(this.excelUploadUrl)
   },
   methods: {
     getPartInfo() {
@@ -644,6 +673,7 @@ export default {
                 customize_role_call_fourth: 0,
                 customize_role_call_fifth: 0,
                 customer_name_hidden: 0,
+                clerk_name_hidden: 0,
                 channel_im_history_store_days: 30,
                 record_enabled: false,
                 auto_accept: 0,
@@ -741,7 +771,7 @@ export default {
       })
     },
     /** 获取上级机构数组 特指医院 **/
-    getPartents() {
+    getParents() {
       API_Part.listByType(6).then(res => {
         this.parents = [...res]
       })
@@ -814,7 +844,6 @@ export default {
       }
     },
     getOtherHostDevice(part_id) {
-      console.log("111111111")
       const _this = this
       API_Device.getOtherHostDevice(part_id).then(r => {
         _this.otherHostDevice = r
@@ -870,6 +899,30 @@ export default {
         reader.readAsDataURL(file)
       })
     },
+    excelUploaded(res) {
+      console.log(res)
+      let param = {}
+      param.part_id = this.partId
+      param.filename = res
+      API_Excel.getExcelFile(param).then(r => {
+        console.log(r)
+      })
+    },
+    handleExcelBefore(file) {
+      console.log(file)
+      const extension = file.name.split('.')[1] === 'xls'
+      const extension2 = file.name.split('.')[1] === 'xlsx'
+      const isLt5M = file.size / 1024 / 1024 < 5
+      if (!extension && !extension2) {
+        this.$message.info("上传文件只能是xls、xlsx格式!")
+        return false
+      }
+      if (!isLt5M) {
+        this.$message.info("上传文件大小不能超过5M!")
+        return false
+      }
+      return true
+    }
   }
 }
 </script>

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

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

+ 15 - 0
src/views/ncs-orginazition/partInfoSetting.vue

@@ -59,6 +59,11 @@
           <app-version-manager :part-id="part_id" :device-type="104" />
         </keep-alive>
       </el-tab-pane>
+      <el-tab-pane :label="this.$t('partInfo.linuxsickbed')" name="linuxsickbed">
+        <keep-alive>
+          <app-version-manager :part-id="part_id" :device-type="304" />
+        </keep-alive>
+      </el-tab-pane>
       <el-tab-pane :label="this.$t('partInfo.mobiledevice')" name="mobiledevice">
         <keep-alive>
           <app-version-manager :part-id="part_id" :device-type="7" />
@@ -79,6 +84,16 @@
           <app-version-manager :part-id="part_id" :device-type="5" />
         </keep-alive>
       </el-tab-pane>
+      <el-tab-pane :label="this.$t('deviceType.EMERGENCY_GATEWAY')" name="emergencyGateway">
+        <keep-alive>
+          <app-version-manager :part-id="part_id" :device-type="131" />
+        </keep-alive>
+      </el-tab-pane>
+      <el-tab-pane :label="this.$t('partInfo.entraceguard_device')" name="entraceguardDevice">
+        <keep-alive>
+          <app-version-manager :part-id="part_id" :device-type="18" />
+        </keep-alive>
+      </el-tab-pane>
     </el-tabs>
   </div>
 </template>

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

@@ -107,7 +107,7 @@
                 userInfo: this.$store.getters.userInfo,
                 content: null,
                 rules: {
-                    content: [{required: true, message: '请输入备注内容', trigger: 'blur'}],
+                    content: [{required: true, message: this.$t('customerManage.inputRemarks'), trigger: 'blur'}],
                 },
               remarkContent: this.$t('remark.remarkContent'),
               remarkCreateTime: this.$t('remark.remarkCreateTime'),
@@ -212,11 +212,11 @@
                     const isImg = hz === 'jpeg' || hz === 'png' || hz === 'jpg' || hz === 'txt'  || hz === 'doc' || hz === 'docx' || hz === 'xls' || hz === 'xlsx'
                     const isLt5M = file.size / 1024 / 1024 < 5
                     if (!isImg) {
-                        _this.$message.error('上传附件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!')
+                        _this.$message.error(this.$t('action.uploaderImg'))
                         reject()
                     }
                     if (!isLt5M) {
-                        _this.$message.error('上传附件大小不能超过 5MB!')
+                        _this.$message.error(this.$t('action.uploaderSize'))
                         reject()
                     }
                     resolve()
@@ -224,7 +224,7 @@
             },
             addRemark() {
                 if (!this.content) {
-                    this.$message.info('请输入内容!')
+                    this.$message.info(this.$t('action.inputMsg'))
                     return
                 }
                 if (!this.filePath) {

+ 0 - 0
src/views/ncs_fee/index.vue


Неке датотеке нису приказане због велике количине промена