Forráskód Böngészése

空间位置,用户,设备管理

wuyunfeng 4 éve
szülő
commit
4098ef1986

+ 8 - 0
src/api/ncs_hospitalFrame.js

@@ -81,3 +81,11 @@ export function sort(source_id, target_id, relation) {
     }
   })
 }
+
+export function getFramesPartId(part_id) {
+  return request({
+    url: `/ncs/frame/frames/${part_id}`,
+    method: 'GET',
+    loading: false
+  })
+}

+ 2 - 2
src/api/ncs_remark.js

@@ -4,7 +4,7 @@ export function getRemarks(params) {
   return request({
     url: '/ncs/remark/page',
     method: 'POST',
-    loading: true,
+    loading: false,
     data: params
   })
 }
@@ -14,7 +14,7 @@ export function save(params) {
   return request({
     url: '/ncs/remark',
     method: 'POST',
-    loading: true,
+    loading: false,
     data: params
   })
 }

+ 3 - 2
src/api/user.js

@@ -29,6 +29,7 @@ export function refreshToken(data) {
   return request({
     url: '/Mgr/refresh_token',
     method: 'post',
+    loading: false,
     data: {
       refresh_token: Storage.getItem('calling_refresh_token')
     }
@@ -48,7 +49,7 @@ export function getList(data) {
     url: '/Mgr/member/page',
     method: 'POST',
     params: data,
-    loading: true
+    loading: false
   })
 }
 
@@ -65,7 +66,7 @@ export function remove(params) {
   return request({
     url: `/Mgr/member/${ids}`,
     method: 'DELETE',
-    loading: true,
+    loading: false,
     data: params
   })
 }

+ 18 - 4
src/router/index.js

@@ -93,7 +93,8 @@ export const partRoutes = [
     children: [
       {
         path: 'index',
-        component: () => import('@/views/ncs-device/index'),
+        // component: () => import('@/views/ncs-device/index'),
+        component: () => import('@/views/ncs-device/deviceManagement'),
         name: 'CallingDevice',
         meta: { title: '设备管理', icon: 'component', noCache: true }
       }
@@ -121,7 +122,7 @@ export const partRoutes = [
         path: 'frameTreeView',
         component: () => import('@/views/hospitalFrame/frameTreeView'),
         name: 'hospitalFrame',
-        meta: { title: '医院结构', icon: 'el-icon-s-shop', noCache: true }
+        meta: { title: '空间位置', icon: 'el-icon-s-shop', noCache: true }
       }
     ]
   },
@@ -152,6 +153,19 @@ export const partRoutes = [
     ]
   },
   {
+    path: '/customerlist',
+    component: Layout,
+    redirect: '/customerlist/index',
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/customer/customerManagement'),
+        name: 'customerManager',
+        meta: { title: '用户管理', icon: 'el-icon-s-custom', noCache: true }
+      }
+    ]
+  },
+  {
     path: '/ncs-nurse-watch',
     component: Layout,
     redirect: '/ncs-device/nurse_watch',
@@ -226,13 +240,13 @@ export const partRoutes = [
         path: '/frameGroup/index',
         component: () => import('@/views/hospitalFrame/frameGroup'),
         name: 'frameGroup',
-        meta: { title: '区管理', icon: 'area', noCache: true }
+        meta: { title: '区管理', icon: 'area', noCache: true }
       },
       {
         path: 'edit/:id?',
         component: () => import('@/views/hospitalFrame/frameGroupEdit'),
         name: 'frameGroupEdit',
-        meta: { title: '编辑区信息', icon: 'area', noCache: true },
+        meta: { title: '编辑区信息', icon: 'area', noCache: true },
         hidden: true
       }
     ]

+ 513 - 98
src/views/customer/components/customerManager.vue

@@ -38,7 +38,8 @@
       />
     </ag-grid-layout>
 
-    <el-dialog :visible.sync="customerFormVisible" title="用户信息">
+    <!-- 用户信息 -->
+    <el-dialog :visible.sync="customerFormVisible" title="用户信息" class="customer-dialog">
       <el-tabs v-model="activeName" type="border-card" tab-position="bottom" width="50%" @tab-click="handleClick">
         <el-tab-pane label="基本信息" name="customerBaseInfo">
           <div style="height: 450px">
@@ -139,7 +140,7 @@
                     </el-col>
                     <el-col :span="12">
                       <el-form-item label="入住床位" prop="frame_id">
-                        <el-select v-model="formmodel.frame_id" placeholder="请选择床位">
+                        <el-select v-model="formmodel.frame_id" :disabled="bedSelectabled" placeholder="请选择床位">
                           <el-option v-for="(item,index) in emptyBeds" :key="index" :label="item.full_name" :value="item.id" />
                         </el-select>
                       </el-form-item>
@@ -213,94 +214,207 @@
                 <el-button type="primary" :disabled="isDisabled" class="save" @click="handlerSubmit('editForm')">保存</el-button>
               </el-form-item>
             </el-form>
-            <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>
           </div>
         </el-tab-pane>
-        <el-tab-pane v-if="customerId != 0" label="备注" name="customerRemark">
-          <div style="height: 450px">
-            <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">
+        <el-tab-pane v-if="formmodel.id" label="备注" name="customerRemark">
+          <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>
-                  <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"
-                  />
+                  <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>{{ item.create_time | unixDateFilter }}
+                      <span style="font-weight:bold;margin-left: 10px;">备注人:</span>{{ item.create_name }}
+                    </p>
+                  </div>
                 </div>
-              </div>
-            </el-card>
+              </el-card>
+
+            </div>
+            <div style="height: 100px;">
+              <el-form ref="remarkForm" :model="remarkFormModel" :rules="remarkRules" label-width="100px" style="margin-right: 10px">
+                <el-row>
+                  <el-col :span="16">
+                    <el-form-item label="内容" prop="content">
+                      <el-input
+                        v-model="remarkFormModel.content"
+                        type="textarea"
+                        :autosize="{ minRows: 2, maxRows: 6}"
+                        :minlength="2"
+                        :maxlength="300"
+                        show-word-limit
+                        :placeholder="'请输入文本内容,长度300'"
+                      />
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="8">
+                    <el-form-item label="附件" style="margin-bottom: 0">
+                      <el-upload
+                        v-if="!attachFilePath"
+                        class="attach-uploader"
+                        :action="`${uploadServer}/ncs/upload/uploadFile?scene=attach`"
+                        :show-file-list="false"
+                        :on-success="attachUploaded"
+                        :before-upload="handleAttachUploadBefore"
+                      >
+                        <i class="el-icon-plus attach-uploader-icon" />
+                      </el-upload>
+                      <span v-if="attachFilePath">{{ remarkFormModel.fileName }}</span>
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-form-item>
+                  <el-button type="primary" @click="addRemark">添加备注</el-button>
+                </el-form-item>
+              </el-form>
+            </div>
           </div>
         </el-tab-pane>
-        <el-tab-pane v-if="customerId != 0" label="用户亲属" name="customerRelative">
+        <el-tab-pane v-if="formmodel.id" label="用户亲属" name="customerRelative">
           <div style="height: 450px">
-            <customer-relative :member-id="memberId" />
+            <!--            <customer-relative :member-id="memberId" />-->
+            <el-table
+              :data="relativeData"
+              height="250"
+              border
+              style="width: 100%"
+            >
+              <el-table-column
+                prop="true_name"
+                label="亲属姓名"
+                width="180"
+              />
+              <el-table-column
+                prop="sex"
+                label="性别"
+                width="180"
+                :formatter="formatterSex"
+              />
+              <el-table-column
+                prop="relative_name"
+                label="关系"
+                width="180"
+              />
+              <el-table-column
+                prop="mobile"
+                label="手机号码"
+              />
+              <el-table-column
+                label="操作"
+                width="100"
+              >
+                <template slot-scope="scope">
+                  <el-button type="danger" size="mini" @click="handlerDeleteRelative(scope.row.member_id)">删除</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+
+            <el-form ref="relativeForm" :model="relativeFormModel" :rules="relativeRules" label-width="120px" style="margin-top:20px">
+              <el-row>
+                <el-col :span="12">
+                  <el-form-item label="姓名" prop="true_name">
+                    <el-input v-model="relativeFormModel.true_name" clearable placeholder="请输入姓名" :maxlength="20" />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="亲属关系" prop="relative_name">
+                    <el-input v-model="relativeFormModel.relative_name" clearable placeholder="请输入亲属关系 如:朋友" :maxlength="20" />
+                  </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="relativeFormModel.sex" :label="0">女</el-radio>
+                    <el-radio v-model="relativeFormModel.sex" :label="1">男</el-radio>
+                    <el-radio v-model="relativeFormModel.sex" :label="2">未知</el-radio>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="手机号码" prop="mobile">
+                    <el-input v-model="relativeFormModel.mobile" clearable placeholder="请输入手机号码" :maxlength="20" />
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <el-form-item>
+                <el-button type="primary" @click="addRelative">添加</el-button>
+              </el-form-item>
+            </el-form>
+
           </div>
 
         </el-tab-pane>
       </el-tabs>
     </el-dialog>
+    <!-- 用户信息 -->
+    <!-- 用户换床-->
+    <el-dialog :visible.sync="changeBedFormVisible" title="用户换床">
+      <el-form ref="changeBedForm" :model="changeBedFormModel" :rules="changeBedRules" label-width="120px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="用户姓名" prop="named">
+              <el-input v-model="changeBedFormModel.named" clearable placeholder="请输入姓名" readonly :maxlength="20" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="入住编号">
+              <el-input v-model="changeBedFormModel.card_no" clearable placeholder="请输入病人编号" readonly :maxlength="20" />
+            </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="changeBedFormModel.sex" :label="0" disabled>女</el-radio>
+              <el-radio v-model="changeBedFormModel.sex" :label="1" disabled>男</el-radio>
+              <el-radio v-model="changeBedFormModel.sex" :label="2" disabled>未知</el-radio>
+            </el-form-item>
+          </el-col>
+
+          <el-col :span="12">
+            <el-form-item label="年龄" prop="age">
+              <el-input v-model="changeBedFormModel.age" clearable :maxlength="4" readonly placeholder="请输入年龄">
+                <el-select slot="append" v-model="changeBedFormModel.age_unit" disabled 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="12">
+            <el-form-item label="当前床位" prop="nickname">
+              <el-input v-model="changeBedFormModel.current_bed" clearable readonly :maxlength="20" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="换到床位" prop="frame_id">
+              <el-select v-model="changeBedFormModel.frame_id" clearable filterable placeholder="请选择床位">
+                <el-option v-for="(item,index) in emptyBeds" :key="index" :label="item.full_name" :value="item.id" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+
+        </el-row>
+
+        <el-form-item>
+          <el-button type="primary" class="save" @click="handleChangeBedSubmit('changeBedForm')">确定</el-button>
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+    <!-- 用户换床-->
   </div>
 
 </template>
@@ -312,13 +426,20 @@ import ButtonCellRender from '@/components/AgGridCellRender/ButtonCellRender'
 import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
 import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
 import * as API_Customer from '@/api/ncs_customer'
-import { unix2Date } from '@/utils/Foundation'
+import { unix2Date, unixToDate } from '@/utils/Foundation'
 import * as API_Frame from '@/api/ncs_hospitalFrame'
 import * as RegExp from '@/utils/RegExp'
 import { serverUrl } from '@/utils/domain'
+import * as API_Remark from '@/api/ncs_remark'
+import * as API_User from '@/api/user'
 export default {
   name: 'CustomerManager',
   components: { ButtonCellRender, ListFilter, RadioFilter },
+  filters: {
+    unixDateFilter(val) {
+      return unixToDate(val)
+    }
+  },
   props: {
     frame: {
       type: Object,
@@ -359,6 +480,63 @@ export default {
       imageUrl: null,
       /** 是否禁用保存按钮 **/
       isDisabled: false,
+      /** 备注 */
+      remarks: [],
+      remarkParams: {
+        page_size: 100,
+        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 frame_id =' + this.formmodel.member_id
+      },
+      remarkFormModel: {
+        content: ''
+      },
+      remarkRules: {
+        content: [{ required: true, message: '请输入备注内容', trigger: 'blur' }]
+      },
+      attachFilePath: null,
+      /** 亲属表单 **/
+      relativeData: [],
+      relativeFormModel: {
+        sex: 0,
+        true_name: null,
+        relative_name: null,
+        mobile: null
+      },
+      relativeParams: {
+        page_size: 100,
+        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: '请输入姓名', trigger: 'blur' }],
+        relative_name: [{ required: true, message: '请输入亲属关系', trigger: 'blur' }],
+        mobile: [
+          {
+            validator: (rule, value, callback) => {
+              if (value === null || value === '') { // 手机号可为空
+                callback()
+              }
+              if (!RegExp.mobile.test(value)) {
+                callback(new Error('手机格式有误!'))
+              } else {
+                callback()
+              }
+            }
+          }
+        ]
+      },
+      /** 换床 */
+      changeBedFormVisible: false,
+      changeBedFormModel: {
+
+      },
+      changeBedRules: {
+        frame_id: [{ required: true, message: '请选择床位!', trigger: 'blur' }]
+      },
       /** 空床位 **/
       emptyBeds: [],
       /** frame 是否为空床位 */
@@ -381,6 +559,9 @@ export default {
               }
             }
           }
+        ],
+        frame_id: [
+          { required: Object.keys(this.frame).length === 0, message: '请选床位!', trigger: 'blur' } // 没有传入frame 属性,必须选择床位
         ]
       },
       doctors: [],
@@ -399,17 +580,16 @@ export default {
   },
   computed: {
     tableHeight() {
-      return Object.keys(this.frame).length === 0 ? this.mainAreaHeight : this.mainAreaHeight - 174
-    }
+      return Object.keys(this.frame).length === 0 ? this.mainAreaHeight - 130 : this.mainAreaHeight - 174
+    },
+    /** 床位是否允许选择,如果已限定空间结构,则不可选 */
+    bedSelectabled() { return Object.keys(this.frame).length > 0 }
   },
   watch: {
     frame(val, oldvalue) {
       this.params.fixedCondition = Object.keys(this.frame).length === 0 ? 'part_id=' + this.$store.getters.partId : 'part_id=' + this.$store.getters.partId + ' and frame_id =' + this.frame.id
       this.getList()
-      // 传入结构是否为空床位
-      if (Object.keys(this.frame).length > 0) {
-        this.isEmptyFrame = this.emptyBeds.filter(p => p.id === this.frame.id).length > 0
-      }
+      this.infoChanged()
     }
   },
   beforeMount() {
@@ -469,7 +649,7 @@ export default {
           return 0
         }
       }},
-      { headerName: '编辑', field: 'shop_id',
+      { headerName: '编辑', field: 'id',
         cellRendererFramework: 'ButtonCellRender',
         cellRendererParams: {
           onClick: this.handleEdit,
@@ -480,7 +660,41 @@ export default {
         filter: false,
         pinned: 'right',
         lockPinned: true,
-        width: 90,
+        width: 80,
+        resizable: false,
+        sortable: false },
+      { headerName: '退床', field: 'id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.handleOut,
+            label: '退床',
+            buttonType: 'warning',
+            buttonSize: 'mini',
+            disabled: param.data['status'] !== 0
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        width: 80,
+        resizable: false,
+        sortable: false },
+      { headerName: '换床', field: 'id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.handleChangeBed,
+            label: '换床',
+            buttonType: 'success',
+            buttonSize: 'mini',
+            disabled: param.data['status'] !== 0
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        width: 80,
         resizable: false,
         sortable: false },
       { headerName: '删除', field: 'shop_id',
@@ -496,7 +710,7 @@ export default {
         },
         pinned: 'right',
         lockPinned: true,
-        width: 90,
+        width: 80,
         resizable: false,
         filter: false,
         sortable: false }
@@ -520,7 +734,7 @@ export default {
     this.gridColumnApi.applyColumnState({
       state: [
         {
-          colId: 'id',
+          colId: 'status',
           sort: 'asc'
         }
       ]
@@ -547,7 +761,7 @@ export default {
   methods: {
 
     getEmptyBeds() {
-      new Promise((resolve, reject) => {
+      return new Promise((resolve, reject) => {
         API_Frame.getSickbedByPartId(this.$store.getters.partId).then(res => {
           this.emptyBeds = [...res]
           resolve()
@@ -769,12 +983,9 @@ export default {
             API_Customer.addAll(this.formmodel).then(res => {
               this.$message.success('添加成功!')
               this.customerFormVisible = false
+              this.isDisabled = false
               this.getList()
-              if (Object.keys(this.frame).length > 0) {
-                this.getEmptyBeds().then(() => {
-                  this.isEmptyFrame = this.emptyBeds.filter(p => p.id === this.frame.id).length > 0
-                })
-              }
+              this.infoChanged()
             }).catch(e => {
               this.$message.error(e)
               this.isDisabled = false
@@ -782,6 +993,7 @@ export default {
           } else {
             API_Customer.updateAll(this.formmodel).then(res => {
               this.$message.success('修改成功!')
+              this.customerFormVisible = false
               this.isDisabled = false
               this.$emit('saved')
             })
@@ -808,6 +1020,175 @@ export default {
         API_Customer.remove(ids).then(
           response => {
             this.getList()
+            this.infoChanged()
+          }
+        ).catch(response => {
+          this.$message({
+            type: 'info',
+            message: response.message
+          })
+        })
+      })
+    },
+
+    handleEdit(row) {
+      this.formmodel = {
+        ...row
+      }
+      // 编辑时把当前用户床位加入到空床位,否则会显示一个床位Id号
+      this.emptyBeds.push({ id: this.formmodel.frame_id, full_name: this.formmodel.full_name })
+      if (this.formmodel.in_date) {
+        this.$set(this.formmodel, 'in_date', this.formmodel.in_date * 1000)
+      }
+      if (this.formmodel.birthday) {
+        this.$set(this.formmodel, 'birthday', this.formmodel.birthday * 1000)
+      }
+      this.customerFormVisible = true
+      this.getRemarks()
+      this.getRelatives()
+    },
+    /** 出院 退床 **/
+    handleOut(row) {
+      this.formmodel = {
+        ...row,
+        status: 1
+      }
+      this.$confirm('确定退床吗?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        API_Customer.updateAll(this.formmodel).then(res => {
+          this.$message.success('退床成功!')
+          this.getList()
+          this.infoChanged()
+        })
+      }).catch(err => {
+        this.$message.error(err)
+      })
+    },
+    /** 换床 **/
+    handleChangeBed(row) {
+      this.changeBedFormVisible = true
+      this.changeBedFormModel = {
+        ...row,
+        current_bed: row.full_name,
+        frame_id: null
+      }
+    },
+    /** 提交换床 */
+    handleChangeBedSubmit(formName) {
+      this.$refs[formName].validate(valid => {
+        if (valid) {
+          API_Customer.updateAll(this.changeBedFormModel).then(res => {
+            this.$message.success('换床成功!')
+            this.getList()
+            this.infoChanged()
+            this.changeBedFormVisible = false
+          })
+        } else {
+          this.$message.error('表单填写有误,请检查!')
+          return false
+        }
+      })
+    },
+    /** 获取用户备注 */
+    getRemarks() {
+      this.remarkParams.fixedCondition = 'part_id=' + this.$store.getters.partId + ' and type=1 and member_id =' + this.formmodel.member_id
+      API_Remark.getRemarks(this.remarkParams).then(res => {
+        this.remarks = [...res.data]
+        console.log('remarks', this.remarks)
+      })
+    },
+    /** 添加备注 */
+    addRemark() {
+      this.$refs['remarkForm'].validate(valid => {
+        if (valid) {
+          if (!this.filePath) {
+            this.fileName = null
+          }
+          const data = {
+            ...this.remarkFormModel,
+            partId: this.$store.getters.partId,
+            type: 1,
+            memberId: this.formmodel.member_id,
+            createName: this.$store.getters.userInfo.username
+          }
+
+          API_Remark.save(data).then(res => {
+            this.$message.success('添加成功!')
+            this.remarkFormModel = {}
+            this.attachFilePath = null
+            this.getRemarks()
+          })
+        } else {
+          this.$message.error('表单填写有误,请检查!')
+          return false
+        }
+      })
+    },
+    /** 附件上传成功 */
+    attachUploaded(res) {
+      this.attachFilePath = serverUrl + '/' + res
+      this.remarkFormModel.filePath = serverUrl + '/' + res
+    },
+    /** 附件上传之前校验 */
+    handleAttachUploadBefore(file) {
+      return new Promise((resolve, reject) => {
+        const filename = file.name
+        this.remarkFormModel.fileName = filename
+        const index = filename.lastIndexOf('.')
+        const extension = filename.substring(index + 1)
+        const isImg = extension === 'jpeg' || extension === 'png' || extension === 'jpg' || extension === 'txt' || extension === 'doc' || extension === 'docx' || extension === 'xls' || extension === '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()
+      })
+    },
+    /** 添加亲属 */
+    addRelative() {
+      this.$refs['relativeForm'].validate(valid => {
+        if (valid) {
+          this.relativeFormModel.relative_id = this.formmodel.member_id
+          API_User.add(this.relativeFormModel).then(res => {
+            this.relativeFormModel = {
+              sex: 0,
+              true_name: null,
+              relative_name: null,
+              mobile: null
+            }
+            this.getRelatives()
+          })
+        }
+      })
+    },
+    /** 拉取亲属列表 **/
+    getRelatives() {
+      this.relativeParams.fixedCondition = ' relative_id=' + this.formmodel.member_id
+      API_User.getList(this.relativeParams).then(res => {
+        this.relativeData = res.data
+      }).catch(() => {
+
+      })
+    },
+    /** 单条数据删除处理 */
+    handlerDeleteRelative(ids) {
+      const test = '你确定要删除此病人亲属信息?'
+      this.$confirm(test, '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        API_User.remove(ids).then(
+          response => {
+            this.getRelatives()
           }
         ).catch(response => {
           this.$message({
@@ -816,13 +1197,33 @@ export default {
           })
         })
       })
+    },
+    formatterSex(row, column, cellValue) {
+      if (row.sex === 1) {
+        return '男'
+      } else if (row.sex === 0) {
+        return '女'
+      } else {
+        return '未知'
+      }
+    },
+    /** 信息变化后操作,如床位状态改变,传入的空间结构变化了 **/
+    infoChanged() {
+      this.getEmptyBeds().then(() => {
+        // 传入结构是否为空床位
+        if (Object.keys(this.frame).length > 0) {
+          this.isEmptyFrame = this.emptyBeds.filter(p => p.id === this.frame.id).length > 0
+        }
+      }).catch(() => {
+
+      })
     }
   }
 }
 </script>
 
    <style scoped type="text/scss">
-                                 /deep/ .el-dialog__body{
+                                 /deep/ .customer-dialog .el-dialog__body{
                                      padding: 1px;
                                  }
 
@@ -832,10 +1233,10 @@ export default {
    /*/deep/ .el-input-group__append {*/
    /*    background-color: #fff;*/
    /*}*/
-                                 /deep/ .avatar-uploader{
+                                 /deep/ .avatar-uploader,/deep/ .attach-uploader{
                                      line-height: 0;
                                  }
-                                 /deep/ .avatar-uploader .el-upload {
+                                 /deep/ .avatar-uploader .el-upload,/deep/.attach-uploader .el-upload {
                                      border: 1px dashed #d9d9d9;
                                      border-radius: 6px;
                                      cursor: pointer;
@@ -859,4 +1260,18 @@ export default {
                                      height: 110px;
                                      display: block;
                                  }
+
+                                 .attach-uploader-icon {
+                                   font-size: 28px;
+                                   color: #8c939d;
+                                   width: 60px;
+                                   height: 60px;
+                                   line-height: 60px;
+                                   text-align: center;
+                                 }
+                                 .attach {
+                                   width: 60px;
+                                   height: 60px;
+                                   display: block;
+                                 }
 </style>

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

@@ -0,0 +1,22 @@
+<template>
+  <div>
+    <customer-manager :frame="frame" />
+  </div>
+</template>
+
+<script>
+import CustomerManager from './components/customerManager'
+export default {
+  name: 'CustomerManagement',
+  components: { CustomerManager },
+  data() {
+    return {
+      frame: {}
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 1 - 1
src/views/hospitalFrame/frameGroup.vue

@@ -20,7 +20,7 @@
           <en-table-search placeholder="请输入搜索关键字" @search="handlerSearch" />
         </div>
         <div class="toolbar-btns">
-          <el-button type="primary" size="mini" @click="createOrginazition">新建区</el-button>
+          <el-button type="primary" size="mini" @click="createOrginazition">新建区</el-button>
         </div>
       </div>
       <el-pagination

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

@@ -16,7 +16,7 @@
           </el-col>
         </el-row>
         <fieldset class="margin-top-sm">
-          <legend>区管辖空间</legend>
+          <legend>区管辖空间</legend>
           <el-row :gutter="20">
             <el-col v-for="(item,index) in rooms" :key="index" gut :xs="8" :sm="6" :md="4" :lg="4" :xl="4">
               <el-card class="box-card">
@@ -171,6 +171,7 @@ export default {
   .item {
     margin-bottom: 10px;
   }
+  .box-card{margin-bottom: 10px}
   /deep/ .el-card__body {
       min-height: 130px;
     }

+ 12 - 541
src/views/hospitalFrame/frameTreeView.vue

@@ -64,48 +64,13 @@
         <el-tabs v-model="activeName" style="margin:0px;" type="border-card">
           <el-tab-pane label="设备列表" name="deviceList">
             <keep-alive>
-              <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"
-              >
-                <!--        @rowDoubleClicked="getList"-->
-                <div slot="toolbar" class="inner-toolbar">
-                  <div class="toolbar-search">
-                    <en-table-search placeholder="请输入搜索关键字" @search="handlerSearch" />
-                  </div>
-                  <div class="toolbar-btns">
-                    <el-button type="primary" size="mini" @click="handleAdd">新增设备</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>
+              <device-manager :frame="selectedNode" />
             </keep-alive>
           </el-tab-pane>
-          <el-tab-pane label="用户列表" name="frameInfo" >
-     <keep-alive>
-       <customer-manager :frame="selectedNode"></customer-manager>
-     </keep-alive>
+          <el-tab-pane label="用户列表" name="frameInfo">
+            <keep-alive>
+              <customer-manager :frame="selectedNode" />
+            </keep-alive>
           </el-tab-pane>
         </el-tabs>
       </el-main>
@@ -148,118 +113,6 @@
     </el-dialog>
     <!---添加空间结构弹窗 -->
 
-    <!-- 设备编辑弹窗 -->
-    <el-dialog :title="deviceEditTitle" :visible.sync="deviceDialogVisible" width="60%">
-      <el-form ref="deviceEditForm" :rules="deviceRules" label-width="120px" :model="deviceModel">
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="设备类型" prop="device_type">
-              <el-select v-model="deviceModel.device_type" placeholder="请选择设备类型" :disabled="deviceTypeDisabled" clearable @change="deviceTypeChange">
-                <el-option v-for="(item,index) in deviceTypeTransfer" :key="index" :label="item.key" :value="item.value" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="设备别名" prop="name">
-              <el-input v-model="deviceModel.name" clearable :maxlength="20" placeholder="请输入设备别名" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="出厂编号" prop="code">
-              <el-input v-model="deviceModel.code" clearable placeholder="请输入出厂编号" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="设备型号" prop="model">
-              <el-input v-model="deviceModel.model" clearable placeholder="请输入设备型号" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="有线物理地址" prop="eth_mac">
-              <el-input v-model="deviceModel.eth_mac" clearable placeholder="请输入物理MAC地址" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="有线IP地址" prop="eth_ip">
-              <el-input v-model="deviceModel.eth_ip" clearable placeholder="请输入IP地址" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="WIFI物理地址" prop="wifi_mac">
-              <el-input v-model="deviceModel.wifi_mac" clearable placeholder="请输入WIFI MAC地址" readonly />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="WIFIIP地址" prop="wifi_ip">
-              <el-input v-model="deviceModel.wifi_ip" clearable placeholder="请输入WIFI IP地址" readonly />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="软件版本" prop="soft_ver">
-              <el-input v-model="deviceModel.soft_ver" clearable placeholder="请输入软件版本号" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="硬件版本" prop="hard_ver">
-              <el-input v-model="deviceModel.hard_ver" clearable placeholder="请输入硬件版本号" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="WIFI热点">
-              <el-input v-model="deviceModel.wifi_hostname" :readonly="true" clearable placeholder="请输入WIFI热点名称" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="WIFI密码">
-              <el-input v-model="deviceModel.wifi_password" :readonly="true" clearable placeholder="请输入WIFI热点密码" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="设备位置">
-              <el-input v-model="deviceModel.full_name" :readonly="true" clearable placeholder="" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="后备设备ID">
-              <el-input v-model="deviceModel.backup_id" clearable placeholder="" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="设备优先级">
-              <el-input-number v-model="deviceModel.priority" controls-position="right" :min="1" :max="99" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="是否启用">
-              <el-checkbox v-model="deviceModel.status" :true-label="1" :false-label="0">启用设备</el-checkbox>
-              <!--              <el-radio v-model="formmodel.status" :label="1">启用</el-radio>-->
-              <!--              <el-radio v-model="formmodel.status" :label="0">不启用</el-radio>-->
-            </el-form-item>
-          </el-col>
-        </el-row>
-
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="handlerFormSubmit('deviceEditForm')">确 定</el-button>
-      </div>
-    </el-dialog>
-    <!-- 设备编辑弹窗 -->
-
     <!---快速创建结构弹窗 -->
     <el-dialog title="快速构建结构" :visible.sync="frameQuickCreateVisible" width="500px">
       <el-form ref="createFrameForm" :model="createFrameModel" :rules="createFrameRules" label-width="110px">
@@ -326,18 +179,13 @@
   </div></template>
 
 <script>
-import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
 import * as HospitalFrame_API from '@/api/ncs_hospitalFrame'
-import { unix2Date } from '@/utils/Foundation'
 import * as API_FrameGroup from '@/api/ncs_frameGroup'
-import ButtonCellRender from '@/components/AgGridCellRender/ButtonCellRender'
-import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
-import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
-import * as API_Device from '@/api/ncs_device'
-import CustomerManager from "../customer/components/customerManager";
+import CustomerManager from '../customer/components/customerManager'
+import DeviceManager from '../ncs-device/components/deviceManager'
 export default {
   name: 'FrameTreeView',
-  components: { CustomerManager, ButtonCellRender, ListFilter, RadioFilter },
+  components: { DeviceManager, CustomerManager },
   data() {
     return {
       treeData: [],
@@ -349,26 +197,6 @@ export default {
       activeName: 'deviceList',
       /** 上级机构数组 **/
       parents: [],
-      /** ag-grid参数 **/
-      pageData: {}, // 翻页数据
-      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,
-      /** 列表参数 */
-      params: {
-        page_size: 20,
-        page_no: 1,
-        fixedCondition: 'part_id=' + this.$store.getters.partId
-      },
       /** frame 编辑弹窗 **/
       frameEditTitle: '添加',
       frameDialogVisible: false,
@@ -382,29 +210,6 @@ export default {
           { min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }
         ]
       },
-      /** device 弹窗 **/
-      deviceDialogVisible: false,
-      deviceEditTitle: '添加设备',
-      deviceModel: {},
-      deviceTypeDisabled: false,
-      deviceRules: {
-        name: [
-          this.MixinRequired('请输入设备别名!')
-        ],
-        device_type: [
-          { required: true, message: '请选择设备类型', trigger: 'blur' }
-        ],
-        code: [
-          { required: true, message: '请输入设备编码', trigger: 'blur' }
-        ],
-        model: [
-          { required: true, message: '请输入设备型号', trigger: 'blur' }
-        ],
-        eth_mac: [
-          { required: true, message: '请输入设备MAC地址', trigger: 'blur' },
-          { pattern: /^([0-9A-Fa-f]{2}:?){6}/gi, message: '请输入正确的MAC地址', trigger: 'blur' }
-        ]
-      },
       /** 快速创建空间结构弹窗 **/
       frameQuickCreateVisible: false,
       createFrameModel: {
@@ -418,182 +223,31 @@ export default {
       room_num_demo: '01',
       createFrameRules: {
 
-      },
-      /** 设备类型转换数组 **/
-      deviceTypeTransfer: [
-        { key: '护士主机', value: 1 },
-        { key: '医生主机', value: 2 },
-        { key: '门口机', value: 3 },
-        { key: '病床分机', value: 4 },
-        { key: 'LCD走廊屏', value: 5 },
-        { key: 'LED点阵屏', value: 6 },
-        { key: '护士腕表', value: 7 },
-        { key: '护工腕表', value: 8 },
-        { key: '病人腕表', value: 9 },
-        { key: '手机App', value: 10 },
-        { key: '总线转换盒', value: 11 },
-        { key: '模拟分机', value: 12 },
-        { key: '模拟紧急按钮', value: 13 },
-        { key: '模拟门灯', value: 14 },
-        { key: '遥控器', value: 15 },
-        { key: '信标', value: 16 },
-        { key: '看板', value: 17 }
-      ],
-      deviceStatusTransfer: [
-        { key: '启用', value: 1, color: 'green' },
-        { key: '未启用', value: 0, color: 'red' }
-      ]
+      }
 
     }
   },
   computed: {
     asideHeight() {
       return this.mainAreaHeight
-    },
-    tableHeight() {
-      return this.mainAreaHeight - 174
     }
   },
   watch: {
     selectedNodeId(newval, old) {
-      this.params.fixedCondition = ' part_id=' + this.$store.getters.partId + ' and frame_id = ' + newval
+      console.log('watch',newval)
       this.selectedNode = this.findNodeById(this.treeData, newval)
-      this.getList()
     },
     filterText(val) {
       this.$refs.frameTree.filter(val)
     }
   },
-  beforeMount() {
-    this.gridOptions = {
-    }
-    this.columnDefs = [
-      {
-        headerName: '#',
-        headerCheckboxSelection: true,
-        headerCheckboxSelectionFilteredOnly: true,
-        checkboxSelection: true,
-        sortable: false, filter: false,
-        width: 80,
-        resizable: false,
-        valueGetter: this.hashValueGetter
-      },
-      { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 100 },
-      { headerName: '设备类型', field: 'device_type', sortable: true, filterFramework: 'ListFilter', width: 160,
-        filterParams: {
-          listData: this.deviceTypeTransfer
-        },
-        valueGetter: this.deviceTypeGetter
-      },
-      // lockPosition 锁定位置,会在第一列
-      // lockPinned = true 不能拖动然后固定
-      // resizeable 单元个大小是否可以调整
-      { headerName: '设备别名', field: 'name', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '设备状态', field: 'status', sortable: true, filterFramework: 'RadioFilter',
-        filterParams: {
-          listData: this.deviceStatusTransfer
-        },
-        cellRenderer: this.deviceStatusFormatter
-      },
-
-      { headerName: '部署位置', field: 'full_name', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '以太网MAC地址', field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '以太网IP地址', field: 'eth_ip', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '通讯端口', field: 'eth_ip_port', sortable: true, filter: 'agNumberColumnFilter' },
-      { headerName: '设备型号', field: 'model', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '出厂编号', field: 'code', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '软件版本', field: 'soft_ver', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '硬件版本', field: 'hard_ver', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '无线MAC地址', field: 'wifi_mac', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '无线IP地址', field: 'wifi_ip', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: 'SIP账号', field: 'sip_id', sortable: true, filter: 'agTextColumnFilter' },
-      { headerName: '更新时间', field: 'update_time', sortable: true, filter: 'agDateColumnFilter', valueFormatter: this.unixDateFormatter, filterParams: {
-        comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
-          return 0
-        }
-      }},
-      { headerName: '编辑', field: 'shop_id',
-        cellRendererFramework: 'ButtonCellRender',
-        cellRendererParams: {
-          onClick: this.handleEdit,
-          label: '编辑',
-          buttonType: 'primary',
-          buttonSize: 'mini'
-        },
-        filter: false,
-        pinned: 'right',
-        lockPinned: true,
-        width: 90,
-        resizable: false,
-        sortable: false },
-      { headerName: '删除', field: 'shop_id',
-        cellRendererFramework: 'ButtonCellRender',
-        cellRendererParams: param => {
-          return {
-            onClick: this.deleteSingle,
-            label: '删除',
-            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,
-      // comparator: this.dateCustomComparator,
-      filterParams: {
-        debounceMs: 500,
-        newRowsAction: 'keep',
-        textCustomComparator: this.textCustomComparator
-      }
-    }
-    this.rowSelection = 'multiple'
-  },
   mounted() {
-    this.gridApi = this.gridOptions.api
-    this.gridColumnApi = this.gridOptions.columnApi
-
     this.getFrameTree().then(() => {
       this.selectedNodeId = this.treeData[0].id
       this.$refs.frameTree.setCurrentKey(this.selectedNodeId)
-      // 设置默认排序字段,应用列状态之后会触发 gridSortChange 函数,会调用getlist,后面不需要再调用this.getlist
-      this.gridColumnApi.applyColumnState({
-        state: [
-          {
-            colId: 'id',
-            sort: 'asc'
-          }
-        ]
-      })
     }).catch(err => {
       this.$message.error(err)
     })
-
-    // var column = this.gridColumnApi.getColumn('id')
-    // const _this = this
-    // column.addEventListener('sortChanged', function(event) {
-    //   console.log(event)
-    //   // _this.rowData = []
-    //   if (event.column.sort !== null && event.column.sort !== '') {
-    //     _this.params.sort = event.column.colId
-    //     _this.params.dir = event.column.sort
-    //   } else {
-    //     delete _this.params.sort
-    //     delete _this.params.dir
-    //   }
-    //   _this.getList()
-    //   // event.columnApi.applyColumnState({ defaultState: { sort: null }})
-    //   // console.log('Column visibility changed', event)
-    // })
-    // this.getList()
   },
   methods: {
     /**
@@ -609,6 +263,7 @@ export default {
         })
       })
     },
+
     append(data) {
       if (data.type === 4) {
         this.frameEditTitle = '【' + data.full_name + '】添加床位'
@@ -774,180 +429,7 @@ export default {
     },
     /** 点击树形节点  **/
     nodeClick(data, node, leaf) {
-      this.selectedNodeId = data.id
-    },
-
-    /** 加载列表数据 */
-    getList() {
-      const param = this.MixinClone(this.params)
-      this.gridApi.showLoadingOverlay()
-      API_Device.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
-        }
-      }).catch(err => {
-        this.$message.error(err)
-      })
-    },
-    /**
- * 过滤状态发生变化,发送到服务器检索数据
- */
-    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()
-    },
-    /** 获取设备类型文字显示,从deviceTypeTransfer 中找出value值对应的key显示出来 */
-    deviceTypeGetter(params) {
-      const gridVal = params.data.device_type
-      return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
-    },
-    /** 格式化时间函数 */
-    unixDateFormatter(param) {
-      if (!param.value) return ''
-      return unix2Date(param.value * 1000)
-    },
-    /** 设备状态格式化 **/
-    deviceStatusFormatter(params) {
-      if (params.value === null || params.value === undefined) return ''
-      const item = this.deviceStatusTransfer.filter(p => p.value === params.value)[0]
-      console.log('item', item)
-      if (item) {
-        return '<span style="color:' + item.color + ';">' + item.key + '</span>'
-      } else {
-        return ''
-      }
-    },
-    /** 删除设备 **/
-    deleteSingle(row) {
-      this.handlerDelete(row.id)
-    },
-    /** 删除设备 **/
-    handlerDelete(id) {
-      this.$confirm('删除操作后数据不可复原,您确定要删除此数据?', '警告', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        API_Device.remove(id).then(
-          response => {
-            this.getList()
-          }
-        ).catch(response => {
-          this.$message({
-            type: 'info',
-            message: response.message
-          })
-        })
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: '已取消删除'
-        })
-      })
-    },
-    /** 设备类型选中变化  **/
-    deviceTypeChange(val) {
-      if (val === 12 || val === 13 || val === 14) { // 模拟设备不需要mac地址
-        this.deviceRules.eth_mac[0].required = false
-      } else {
-        this.deviceRules.eth_mac[0].required = true
-      }
-    },
-    /** 添加设备事件 **/
-    handleAdd() {
-      const node = this.findNodeById(this.treeData, this.selectedNodeId)
-      this.deviceModel = {
-        frame_id: this.selectedNodeId,
-        full_name: node.full_name,
-        soft_ver: 'SV1.0',
-        hard_ver: 'HV1.0',
-        code: 'C' + parseInt(Math.random() * 100000),
-        model: 'M' + parseInt(Math.random() * 100000),
-        part_id: this.$store.getters.partId
-      }
-      delete this.deviceModel.id
-      this.deviceEditTitle = '添加设备'
-      this.deviceDialogVisible = true
-      this.deviceTypeDisabled = false // 新增设备可以选择设备类型
-    },
-    /** 修改设备  **/
-    handleEdit(params) {
-      console.log('param', params)
-      this.deviceModel = {
-        ...params
-      }
-      this.deviceEditTitle = '修改设备'
-      this.deviceDialogVisible = true
-      this.deviceTypeDisabled = true // 修改设备时,不能改变设备类型
-    },
-    /** 新增 提交表单 */
-    handlerFormSubmit(formName) {
-      this.$refs[formName].validate((valid) => {
-        if (valid) {
-          /** 新增 */
-          if (!this.deviceModel.id) {
-            API_Device.add(this.deviceModel).then(() => {
-              this.$message.success('保存成功!')
-              this.deviceDialogVisible = false
-              this.getList()
-            }).catch(err => {
-              this.$message.error(err)
-            })
-          } else {
-            /** 修改 */
-            API_Device.update(this.deviceModel.id, this.deviceModel).then(() => {
-              this.$message.success('修改成功!')
-              this.deviceDialogVisible = false
-              this.getList()
-            }).catch(error => {
-              this.$message.error(error)
-            })
-          }
-        }
-      })
+      this.$set(this, 'selectedNodeId', data.id)
     },
     /** 快速创建空间结构弹窗 **/
     quickCreateFrame() {
@@ -983,17 +465,6 @@ export default {
       if (val > this.createFrameModel.room_end_no) {
         this.createFrameModel.room_end_no = val
       }
-    },
-    /** 分页大小发生改变 */
-    handlePageSizeChange(size) {
-      this.params.page_size = size
-      this.getList()
-    },
-
-    /** 分页页数发生改变 */
-    handlePageCurrentChange(page) {
-      this.params.page_no = page
-      this.getList()
     }
   }
 }

+ 565 - 0
src/views/ncs-device/components/deviceManager.vue

@@ -0,0 +1,565 @@
+<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="请输入搜索关键字" @search="handlerSearch" />
+        </div>
+        <div class="toolbar-btns">
+          <el-button type="primary" size="mini" @click="handleAdd">新增设备</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="deviceEditTitle" :visible.sync="deviceDialogVisible" width="60%">
+      <el-form ref="deviceEditForm" :rules="deviceRules" label-width="120px" :model="deviceModel">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="设备类型" prop="device_type">
+              <el-select v-model="deviceModel.device_type" placeholder="请选择设备类型" :disabled="deviceTypeDisabled" clearable @change="deviceTypeChange">
+                <el-option v-for="(item,index) in deviceTypeTransfer" :key="index" :label="item.key" :value="item.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="设备别名" prop="name">
+              <el-input v-model="deviceModel.name" clearable :maxlength="20" placeholder="请输入设备别名" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="出厂编号" prop="code">
+              <el-input v-model="deviceModel.code" clearable placeholder="请输入出厂编号" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="设备型号" prop="model">
+              <el-input v-model="deviceModel.model" clearable placeholder="请输入设备型号" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="有线物理地址" prop="eth_mac">
+              <el-input v-model="deviceModel.eth_mac" clearable placeholder="请输入物理MAC地址" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="有线IP地址" prop="eth_ip">
+              <el-input v-model="deviceModel.eth_ip" clearable placeholder="请输入IP地址" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="WIFI物理地址" prop="wifi_mac">
+              <el-input v-model="deviceModel.wifi_mac" clearable placeholder="请输入WIFI MAC地址" readonly />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="WIFIIP地址" prop="wifi_ip">
+              <el-input v-model="deviceModel.wifi_ip" clearable placeholder="请输入WIFI IP地址" readonly />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="软件版本" prop="soft_ver">
+              <el-input v-model="deviceModel.soft_ver" clearable placeholder="请输入软件版本号" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="硬件版本" prop="hard_ver">
+              <el-input v-model="deviceModel.hard_ver" clearable placeholder="请输入硬件版本号" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="WIFI热点">
+              <el-input v-model="deviceModel.wifi_hostname" :readonly="true" clearable placeholder="请输入WIFI热点名称" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="WIFI密码">
+              <el-input v-model="deviceModel.wifi_password" :readonly="true" clearable placeholder="请输入WIFI热点密码" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="设备位置" prop="frame_id">
+              <el-select v-model="deviceModel.frame_id" filterable clearable :disabled="frameSelectabled" placeholder="请选择安装位置">
+                <el-option v-for="(item,index) in partFrames" :key="index" :label="item.full_name" :value="item.id" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="后备设备ID">
+              <el-input v-model="deviceModel.backup_id" clearable placeholder="" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="设备优先级">
+              <el-input-number v-model="deviceModel.priority" controls-position="right" :min="1" :max="99" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="是否启用">
+              <el-checkbox v-model="deviceModel.status" :true-label="1" :false-label="0">启用设备</el-checkbox>
+              <!--              <el-radio v-model="formmodel.status" :label="1">启用</el-radio>-->
+              <!--              <el-radio v-model="formmodel.status" :label="0">不启用</el-radio>-->
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="handlerFormSubmit('deviceEditForm')">确 定</el-button>
+      </div>
+    </el-dialog>
+    <!-- 设备编辑弹窗 -->
+  </div>
+</template>
+
+<script>
+import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
+import { unix2Date } from '@/utils/Foundation'
+import ButtonCellRender from '@/components/AgGridCellRender/ButtonCellRender'
+import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
+import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
+import * as API_Device from '@/api/ncs_device'
+import * as API_Frame from '@/api/ncs_hospitalFrame'
+export default {
+  name: 'DeviceManager',
+  components: { ButtonCellRender, ListFilter, RadioFilter },
+  props: {
+    frame: {
+      type: Object,
+      default: () => {}
+    }
+  },
+  data() {
+    return {
+      /** ag-grid参数 **/
+      pageData: {}, // 翻页数据
+      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,
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+        fixedCondition: 'part_id=' + this.$store.getters.partId
+      },
+      /** device 弹窗 **/
+      deviceDialogVisible: false,
+      deviceEditTitle: '添加设备',
+      deviceModel: {},
+      deviceTypeDisabled: false,
+      deviceRules: {
+        name: [
+          this.MixinRequired('请输入设备别名!')
+        ],
+        device_type: [
+          { required: true, message: '请选择设备类型', trigger: 'blur' }
+        ],
+        code: [
+          { required: true, message: '请输入设备编码', trigger: 'blur' }
+        ],
+        model: [
+          { required: true, message: '请输入设备型号', trigger: 'blur' }
+        ],
+        eth_mac: [
+          { required: true, message: '请输入设备MAC地址', trigger: 'blur' },
+          { pattern: /^([0-9A-Fa-f]{2}:?){6}/gi, message: '请输入正确的MAC地址', trigger: 'blur' }
+        ],
+        frame_id: [
+          { required: Object.keys(this.frame).length === 0, message: '请选安装位置!', trigger: 'blur' } // 没有传入frame 属性,必须选择安装位置
+        ]
+      },
+      partFrames: [],
+      /** 设备类型转换数组 **/
+      deviceTypeTransfer: [
+        { key: '护士主机', value: 1 },
+        { key: '医生主机', value: 2 },
+        { key: '门口机', value: 3 },
+        { key: '病床分机', value: 4 },
+        { key: 'LCD走廊屏', value: 5 },
+        { key: 'LED点阵屏', value: 6 },
+        { key: '护士腕表', value: 7 },
+        { key: '护工腕表', value: 8 },
+        { key: '病人腕表', value: 9 },
+        { key: '手机App', value: 10 },
+        { key: '总线转换盒', value: 11 },
+        { key: '模拟分机', value: 12 },
+        { key: '模拟紧急按钮', value: 13 },
+        { key: '模拟门灯', value: 14 },
+        { key: '遥控器', value: 15 },
+        { key: '信标', value: 16 },
+        { key: '看板', value: 17 }
+      ],
+      deviceStatusTransfer: [
+        { key: '启用', value: 1, color: 'green' },
+        { key: '未启用', value: 0, color: 'red' }
+      ]
+    }
+  },
+  computed: {
+    tableHeight() {
+      return Object.keys(this.frame).length === 0 ? this.mainAreaHeight - 130 : this.mainAreaHeight - 174
+    },
+    frameSelectabled() { return Object.keys(this.frame).length > 0 }
+  },
+  watch: {
+    frame(val, oldvalue) {
+      console.log('watch',val)
+      this.params.fixedCondition = Object.keys(this.frame).length === 0 ? 'part_id=' + this.$store.getters.partId : 'part_id=' + this.$store.getters.partId + ' and frame_id =' + this.frame.id
+      this.getList()
+    }
+  },
+  beforeMount() {
+    this.gridOptions = {
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 80,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 100 },
+      { headerName: '设备类型', field: 'device_type', sortable: true, filterFramework: 'ListFilter', width: 160,
+        filterParams: {
+          listData: this.deviceTypeTransfer
+        },
+        valueGetter: this.deviceTypeGetter
+      },
+      // lockPosition 锁定位置,会在第一列
+      // lockPinned = true 不能拖动然后固定
+      // resizeable 单元个大小是否可以调整
+      { headerName: '设备别名', field: 'name', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '设备状态', field: 'status', sortable: true, filterFramework: 'RadioFilter',
+        filterParams: {
+          listData: this.deviceStatusTransfer
+        },
+        cellRenderer: this.deviceStatusFormatter
+      },
+
+      { headerName: '部署位置', field: 'full_name', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '以太网MAC地址', field: 'eth_mac', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '以太网IP地址', field: 'eth_ip', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '通讯端口', field: 'eth_ip_port', sortable: true, filter: 'agNumberColumnFilter' },
+      { headerName: '设备型号', field: 'model', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '出厂编号', field: 'code', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '软件版本', field: 'soft_ver', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '硬件版本', field: 'hard_ver', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '无线MAC地址', field: 'wifi_mac', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '无线IP地址', field: 'wifi_ip', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: 'SIP账号', field: 'sip_id', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '更新时间', field: 'update_time', sortable: true, filter: 'agDateColumnFilter', valueFormatter: this.unixDateFormatter, filterParams: {
+        comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
+          return 0
+        }
+      }},
+      { headerName: '编辑', field: 'shop_id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: {
+          onClick: this.handleEdit,
+          label: '编辑',
+          buttonType: 'primary',
+          buttonSize: 'mini'
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        width: 90,
+        resizable: false,
+        sortable: false },
+      { headerName: '删除', field: 'shop_id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.deleteSingle,
+            label: '删除',
+            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,
+      // comparator: this.dateCustomComparator,
+      filterParams: {
+        debounceMs: 500,
+        newRowsAction: 'keep',
+        textCustomComparator: this.textCustomComparator
+      }
+    }
+    this.rowSelection = 'multiple'
+  },
+  mounted() {
+    this.gridApi = this.gridOptions.api
+    this.gridColumnApi = this.gridOptions.columnApi
+    this.gridColumnApi.applyColumnState({
+      state: [
+        {
+          colId: 'status',
+          sort: 'asc'
+        }
+      ]
+    })
+    /** 加载科室空间节点  **/
+    this.getPartFrames()
+  },
+  methods: {
+    /** 加载列表数据 */
+    getList() {
+      const param = this.MixinClone(this.params)
+      this.gridApi.showLoadingOverlay()
+      API_Device.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
+        }
+      }).catch(err => {
+        this.$message.error(err)
+      })
+    },
+    /** 获取科室的所有空间节点 */
+    getPartFrames() {
+      API_Frame.getFramesPartId(this.$store.getters.partId).then(res => {
+        this.partFrames = [...res]
+      })
+    },
+
+    /**
+         * 过滤状态发生变化,发送到服务器检索数据
+         */
+    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()
+    },
+    /** 获取设备类型文字显示,从deviceTypeTransfer 中找出value值对应的key显示出来 */
+    deviceTypeGetter(params) {
+      const gridVal = params.data.device_type
+      return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
+    },
+    /** 格式化时间函数 */
+    unixDateFormatter(param) {
+      if (!param.value) return ''
+      return unix2Date(param.value * 1000)
+    },
+    /** 设备状态格式化 **/
+    deviceStatusFormatter(params) {
+      if (params.value === null || params.value === undefined) return ''
+      const item = this.deviceStatusTransfer.filter(p => p.value === params.value)[0]
+      console.log('item', item)
+      if (item) {
+        return '<span style="color:' + item.color + ';">' + item.key + '</span>'
+      } else {
+        return ''
+      }
+    },
+    /** 删除设备 **/
+    deleteSingle(row) {
+      this.handlerDelete(row.id)
+    },
+    /** 删除设备 **/
+    handlerDelete(id) {
+      this.$confirm('删除操作后数据不可复原,您确定要删除此数据?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        API_Device.remove(id).then(
+          response => {
+            this.getList()
+          }
+        ).catch(response => {
+          this.$message({
+            type: 'info',
+            message: response.message
+          })
+        })
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消删除'
+        })
+      })
+    },
+    /** 设备类型选中变化  **/
+    deviceTypeChange(val) {
+      if (val === 12 || val === 13 || val === 14) { // 模拟设备不需要mac地址
+        this.deviceRules.eth_mac[0].required = false
+      } else {
+        this.deviceRules.eth_mac[0].required = true
+      }
+    },
+    /** 添加设备事件 **/
+    handleAdd() {
+      this.deviceModel = {
+        soft_ver: 'SV1.0',
+        hard_ver: 'HV1.0',
+        code: 'C' + parseInt(Math.random() * 100000),
+        model: 'M' + parseInt(Math.random() * 100000),
+        part_id: this.$store.getters.partId
+      }
+      if (Object.keys(this.frame).length > 0) {
+        this.$set(this.deviceModel, 'frame_id', this.frame.id)
+      }
+      delete this.deviceModel.id
+      this.deviceEditTitle = '添加设备'
+      this.deviceDialogVisible = true
+      this.deviceTypeDisabled = false // 新增设备可以选择设备类型
+    },
+    /** 修改设备  **/
+    handleEdit(params) {
+      console.log('param', params)
+      this.deviceModel = {
+        ...params
+      }
+      this.deviceEditTitle = '修改设备'
+      this.deviceDialogVisible = true
+      this.deviceTypeDisabled = true // 修改设备时,不能改变设备类型
+    },
+    /** 新增 提交表单 */
+    handlerFormSubmit(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          /** 新增 */
+          if (!this.deviceModel.id) {
+            API_Device.add(this.deviceModel).then(() => {
+              this.$message.success('保存成功!')
+              this.deviceDialogVisible = false
+              this.getList()
+            }).catch(err => {
+              this.$message.error(err)
+            })
+          } else {
+            /** 修改 */
+            API_Device.update(this.deviceModel.id, this.deviceModel).then(() => {
+              this.$message.success('修改成功!')
+              this.deviceDialogVisible = false
+              this.getList()
+            }).catch(error => {
+              this.$message.error(error)
+            })
+          }
+        }
+      })
+    },
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.getList()
+    },
+
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.getList()
+    }
+
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 22 - 0
src/views/ncs-device/deviceManagement.vue

@@ -0,0 +1,22 @@
+<template>
+  <div>
+    <device-manager :frame="frame" />
+  </div>
+</template>
+
+<script>
+import DeviceManager from './components/deviceManager'
+export default {
+  name: 'DeviceManagement',
+  components: { DeviceManager },
+  data() {
+    return {
+      frame: {}
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>