Przeglądaj źródła

重做空间结构管理,设备,用户管理

wuyunfeng 4 lat temu
rodzic
commit
fec28e4232

+ 3 - 2
src/api/ncs_frameGroup.js

@@ -57,10 +57,11 @@ export function get(id, params) {
 }
 
 /** 查询某科室下的房间结构 */
-export function getRoomStruct(id) {
+export function getframestruct(part_id, frame_type) {
   return request({
-    url: `/ncs/frame/getroomstruct/${id}`,
+    url: `/ncs/frame/getframestruct/${part_id}/${frame_type}`,
     method: 'get',
     loading: false
   })
 }
+

+ 22 - 0
src/api/ncs_hospitalFrame.js

@@ -59,3 +59,25 @@ export function getSickbedByPartId(id) {
   })
 }
 
+export function quickCreate(params) {
+  return request({
+    url: '/ncs/frame/quickcreate',
+    method: 'POST',
+    loading: false,
+    data: params
+  })
+}
+
+/** 拖拽排序frame */
+export function sort(source_id, target_id, relation) {
+  return request({
+    url: `/ncs/frame/sort`,
+    method: 'post',
+    loading: false,
+    data: {
+      frame_id: source_id,
+      target_id: target_id,
+      relation: relation
+    }
+  })
+}

+ 108 - 0
src/components/AgGridCustomFilter/ListFilter.vue

@@ -0,0 +1,108 @@
+<template>
+  <div class="el-transfer-panel">
+    <div class="el-transfer-panel__header">
+      <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">全选
+      </el-checkbox>
+    </div>
+    <div class="el-transfer-panel__body">
+      <el-checkbox-group v-model="checkData" class="el-transfer-panel__list" @change="handleCheckChange">
+        <div v-for="(item,_index) in listData" :key="_index" class="text item">
+          <el-checkbox :label="item.value" class="el-transfer-panel__item">{{ item.key }}</el-checkbox>
+        </div>
+      </el-checkbox-group>
+    </div>
+  </div>
+</template>
+
+<script>
+/**
+     * 可选择多项过滤的组件
+     * 通过参数传入可选择项的数组,每个项包含key value 属性 key为可选项的展示文字,value 表示真实要过滤的值
+     * 此过滤器用与数据库中的值与列表展示不一致时,并且列表项可穷尽的数据。
+     */
+export default {
+  name: 'ListFilter',
+  data() {
+    return {
+      isIndeterminate: false,
+      checkAll: false,
+      /** 可选择的项数组 {key:'护士主机',value:1} **/
+      listData: [],
+      checkData: []
+    }
+  },
+  beforeMount() {
+
+  },
+  mounted() {
+    const { listData } = this.params
+    if (listData) {
+      this.listData = listData
+    }
+  },
+  methods: {
+
+    handleCheckAllChange(val) {
+      this.checkData = val ? this.listData.map(p => p.value) : []
+      this.isIndeterminate = false
+      this.params.filterChangedCallback()
+    },
+    handleCheckChange() {
+      if (this.checkData.length === this.listData.length) { // 选中所有
+        this.isIndeterminate = false
+        this.checkAll = true
+      } else if (this.checkData.length === 0) { // 一个没选
+        this.isIndeterminate = false
+        this.checkAll = false
+      } else { // 部分选中
+        this.isIndeterminate = true
+        this.checkAll = false
+      }
+      this.params.filterChangedCallback()
+    },
+    /**
+             * 组装过滤对象,GridApi 可以通过getFilterModel 函数获取设置状态
+             **/
+    getModel() {
+      const model = {
+        'filterType': 'list',
+        'type': this.checkData.length === 1 ? 'equals' : 'in',
+        'filter': this.checkData.join(',')
+      }
+      if (this.checkData.length === 0) {
+        return null
+      } else {
+        return model
+      }
+    },
+
+    setModel() {
+    },
+
+    doesFilterPass(params) {
+      return this.checkData.indexOf(params.data.year)
+    },
+    /**
+             * filter 接口方法,返回true 列头显示过滤图标,返回false,不显示
+             * @returns {boolean}
+             */
+    isFilterActive() {
+      return this.checkData.length > 0
+    }
+  }
+}
+</script>
+
+<style scoped>
+    .el-transfer-panel {
+        width: 160px;
+    }
+
+    .el-transfer-panel__header {
+        background: #f8f8f8;
+    }
+
+    .el-transfer-panel__body {
+        height: 180px;
+    }
+</style>

+ 94 - 0
src/components/AgGridCustomFilter/RadioFilter.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="el-transfer-panel">
+    <div class="el-transfer-panel__body">
+      <el-radio-group v-model="checkData" class="el-transfer-panel__list" @change="handleCheckChange">
+        <div v-for="(item,_index) in listData" :key="_index" class="text item">
+          <el-radio :label="item.value" class="el-transfer-panel__item">{{ item.key }}</el-radio>
+        </div>
+      </el-radio-group>
+    </div>
+    <div style="text-align: center;margin-bottom: 10px">
+      <el-button size="mini" type="primary" @click="resetStatus">重置</el-button>
+    </div>
+
+  </div>
+</template>
+
+<script>
+/**
+     * 此过滤器用于快速过滤某一个类型数据,用法与ListFilter 相似
+     */
+export default {
+  name: 'RadioFilter',
+  data() {
+    return {
+      listData: [],
+      checkData: null
+    }
+  },
+  beforeMount() {
+
+  },
+  mounted() {
+    const { listData } = this.params
+    if (listData) {
+      this.listData = listData
+    }
+  },
+  methods: {
+    handleCheckChange() {
+      this.params.filterChangedCallback()
+    },
+    /**
+       * 组装过滤对象,GridApi 可以通过getFilterModel 函数获取设置状态
+       **/
+    getModel() {
+      const model = {
+        'filterType': 'list',
+        'type': 'equals',
+        'filter': this.checkData
+      }
+      if (this.checkData === null) {
+        return null
+      } else {
+        return model
+      }
+    },
+
+    setModel() {
+    },
+
+    doesFilterPass(params) {
+      return true
+    },
+    /**
+       * filter 接口方法,返回true 列头显示过滤图标,返回false,不显示
+       * @returns {boolean}
+       */
+    isFilterActive() {
+      return this.checkData !== null
+    },
+    /** 重置选择 radio选择后一定有一个被选中,需提供一个按钮把选中状态全置为空  */
+    resetStatus() {
+      this.checkData = null
+      this.params.filterChangedCallback()
+    }
+  }
+}
+</script>
+
+<style scoped>
+    .el-transfer-panel {
+        width: 160px;
+    }
+
+    .el-transfer-panel__header {
+        background: #f8f8f8;
+    }
+
+    .el-transfer-panel__body {
+        padding: 10px 0 0;
+        height: auto;
+    }
+    .el-transfer-panel__list{height: auto}
+</style>

+ 2 - 0
src/layout/components/Navbar.vue

@@ -94,6 +94,8 @@ export default {
             this.licence = '授权剩余有效期:' + days + '天,请联系售后获得授权'
           }
         }
+      }).catch(err => {
+        this.$message.error(err)
       })
     }
   },

+ 21 - 18
src/layout/mixin/ResizeHandler.js

@@ -56,25 +56,28 @@ export default {
       return unix2Date(params.value)
     },
     dateCustomComparator(valueA, valueB, nodeA, nodeB, isInverted) {
-      console.log('a', new Date(valueA))
+      console.log('a', valueA)
+      return 0
 
-      if (valueB === null) {
-        return 0
-      }
-      const cellDate = new Date(valueB)
-
-      const day = cellDate.getDate()
-      const month = cellDate.getMonth()
-      const year = cellDate.getFullYear()
-      const cellDateMidNight = new Date(year, month, day)
-      console.log('b', cellDateMidNight)
-      if (new Date(valueA) < cellDateMidNight) {
-        return 1
-      } else if (new Date(valueA) > cellDateMidNight) {
-        return -1
-      } else {
-        return 0
-      }
+      // console.log('a', new Date(valueA))
+      //
+      // if (valueB === null) {
+      //   return 0
+      // }
+      // const cellDate = new Date(valueB)
+      //
+      // const day = cellDate.getDate()
+      // const month = cellDate.getMonth()
+      // const year = cellDate.getFullYear()
+      // const cellDateMidNight = new Date(year, month, day)
+      // console.log('b', cellDateMidNight)
+      // if (new Date(valueA) < cellDateMidNight) {
+      //   return 1
+      // } else if (new Date(valueA) > cellDateMidNight) {
+      //   return -1
+      // } else {
+      //   return 0
+      // }
     }
   }
 }

+ 13 - 0
src/router/index.js

@@ -113,6 +113,19 @@ export const partRoutes = [
     ]
   },
   {
+    path: '/frameTreeView',
+    component: Layout,
+    redirect: '/hospitalFrame/frameTreeView',
+    children: [
+      {
+        path: 'frameTreeView',
+        component: () => import('@/views/hospitalFrame/frameTreeView'),
+        name: 'hospitalFrame',
+        meta: { title: '医院结构', icon: 'el-icon-s-shop', noCache: true }
+      }
+    ]
+  },
+  {
     path: '/ncs-clerk',
     component: Layout,
     redirect: '/ncs-clerk/clerkList',

+ 4 - 4
src/styles/index.scss

@@ -191,9 +191,9 @@ aside {
 }
 
 
- .el-select .el-input__inner[type="text"][readonly]{
-  background: #fff;
-}
- .el-input__inner[type="text"][readonly]{
+// .el-select .el-input__inner[type="text"][readonly]{
+//  background: #fff;
+//}
+.el-form-item__content>.el-input>.el-input__inner[type="text"][readonly]{
   background: #F5F7FA;
 }

+ 862 - 0
src/views/customer/components/customerManager.vue

@@ -0,0 +1,862 @@
+<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"
+    >
+      <!--        @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" :disabled="!isEmptyFrame" @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 :visible.sync="customerFormVisible" title="用户信息">
+      <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">
+            <el-form ref="editForm" :model="formmodel" :rules="rules" label-width="120px">
+              <el-row>
+                <el-col :span="12">
+                  <el-form-item label="用户姓名" prop="named">
+                    <el-input v-model="formmodel.named" clearable placeholder="请输入姓名" :maxlength="20" />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="入住编号">
+                    <el-input v-model="formmodel.card_no" 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="formmodel.sex" :label="0">女</el-radio>
+                    <el-radio v-model="formmodel.sex" :label="1">男</el-radio>
+                    <el-radio v-model="formmodel.sex" :label="2">未知</el-radio>
+                  </el-form-item>
+                </el-col>
+
+                <el-col :span="12">
+                  <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="12">
+                  <el-form-item label="手机号码" prop="mobile">
+                    <el-input v-model="formmodel.mobile" clearable placeholder="请输入手机号码" :maxlength="20" />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="家庭住址" prop="address">
+                    <el-input v-model="formmodel.address" clearable :maxlength="20" placeholder="请输入家庭住址" />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="生日" prop="birthday">
+                    <el-date-picker
+                      v-model="formmodel.birthday"
+                      type="date"
+                      :editable="false"
+                      value-format="timestamp"
+                      placeholder="选择日期"
+                      :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+                      @change="birthdayChange"
+                    />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="入住日期" prop="in_date">
+                    <el-date-picker
+                      v-model="formmodel.in_date"
+                      type="date"
+                      :editable="false"
+                      value-format="timestamp"
+                      :default-value="new Date()"
+                      placeholder="选择日期"
+                      :picker-options="{disabledDate(time) { return time.getTime() > Date.now() }}"
+                    />
+                  </el-form-item>
+                </el-col>
+
+                <el-col :span="12">
+                  <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-col :span="12">
+                  <el-form-item label="证件号码">
+                    <el-input v-model="formmodel.id_no" clearable placeholder="请输入证件号" :maxlength="20" />
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <el-row>
+
+                <el-col :span="16">
+                  <el-row>
+                    <el-col :span="12">
+                      <el-form-item label="昵称" prop="nickname">
+                        <el-input v-model="formmodel.nickname" clearable placeholder="请输入用户其他称呼" :maxlength="20" />
+                      </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                      <el-form-item label="入住床位" prop="frame_id">
+                        <el-select v-model="formmodel.frame_id" 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 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-col :span="8">
+                  <el-form-item label="头像">
+                    <el-upload
+                      class="avatar-uploader"
+                      :action="`${uploadServer}/ncs/upload/uploadFile?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-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 workers" :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-form-item>
+                <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">
+                <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>
+          </div>
+        </el-tab-pane>
+        <el-tab-pane v-if="customerId != 0" label="用户亲属" name="customerRelative">
+          <div style="height: 450px">
+            <customer-relative :member-id="memberId" />
+          </div>
+
+        </el-tab-pane>
+      </el-tabs>
+    </el-dialog>
+  </div>
+
+</template>
+
+<script>
+// 月子中心版,没有责任医生,责任护士,责任护工选项 也没有护理项参数
+import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
+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 * as API_Frame from '@/api/ncs_hospitalFrame'
+import * as RegExp from '@/utils/RegExp'
+import { serverUrl } from '@/utils/domain'
+export default {
+  name: 'CustomerManager',
+  components: { ButtonCellRender, ListFilter, RadioFilter },
+  props: {
+    frame: {
+      type: Object,
+      default: () => {}
+    }
+  },
+  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,
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+        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
+      },
+      customerFormVisible: false,
+      activeName: 'customerBaseInfo',
+      formmodel: {
+        sex: 0,
+        id_type: '身份证',
+        age_unit: '岁',
+        in_date: (new Date()).valueOf(),
+        mobile: ''
+      },
+      /** 上传接口 **/
+      uploadServer: serverUrl,
+      imageUrl: null,
+      /** 是否禁用保存按钮 **/
+      isDisabled: false,
+      /** 空床位 **/
+      emptyBeds: [],
+      /** frame 是否为空床位 */
+      isEmptyFrame: true,
+      rules: {
+        named: [
+          this.MixinRequired('请输入用户姓名!')
+        ],
+        age: [
+          { required: true, message: '请输入年龄', trigger: 'blur' }
+        ],
+        mobile: [
+          this.MixinRequired('请输入手机号!'),
+          {
+            validator: (rule, value, callback) => {
+              if (!RegExp.mobile.test(value)) {
+                callback(new Error('手机格式有误!'))
+              } else {
+                callback()
+              }
+            }
+          }
+        ]
+      },
+      doctors: [],
+      nurses: [],
+      workers: [],
+      nurseData: [],
+      sexTransfer: [
+        { key: '男', value: 1, color: 'green' },
+        { key: '女', value: 0, color: 'red' }
+      ],
+      customerStatusTransfer: [
+        { key: '入住中', value: 0, color: 'green' },
+        { key: '已离开', value: 1, color: 'red' }
+      ]
+    }
+  },
+  computed: {
+    tableHeight() {
+      return Object.keys(this.frame).length === 0 ? this.mainAreaHeight : this.mainAreaHeight - 174
+    }
+  },
+  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
+      }
+    }
+  },
+  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: 'named', sortable: true, filter: 'agTextColumnFilter', width: 160 },
+      { headerName: '昵称', field: 'nickname', sortable: true, filter: 'agTextColumnFilter', width: 130 },
+      { headerName: '当前状态', field: 'status', sortable: true, filterFramework: 'RadioFilter', width: 130,
+        filterParams: {
+          listData: this.customerStatusTransfer
+        },
+        cellRenderer: this.customerStatusRenderer },
+      // lockPosition 锁定位置,会在第一列
+      // lockPinned = true 不能拖动然后固定
+      // resizeable 单元个大小是否可以调整
+      { headerName: '性别', field: 'sex', sortable: true, filterFramework: 'RadioFilter', width: 130,
+        filterParams: {
+          listData: this.sexTransfer
+        },
+        cellRenderer: this.sexRenderer },
+
+      { headerName: '生日', field: 'birthday', sortable: true, filter: 'agDateColumnFilter', valueFormatter: this.unixDateFormatter, filterParams: {
+        comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
+          return 0
+        }
+      }},
+      { headerName: '年龄', field: 'age', sortable: true, filter: 'agNumberColumnFilter', width: 130
+      },
+      { headerName: '年龄单位', field: 'age_unit', sortable: true, filter: 'agTextColumnFilter', width: 130
+      },
+      { headerName: '入住编号', field: 'card_no', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '身份证件类型', field: 'id_type', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '证件号码', field: 'id_no', sortable: true, filter: 'agNumberColumnFilter', width: 160 },
+      { headerName: '入住床位', field: 'full_name', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '手机号码', field: 'mobile', sortable: true, filter: 'agTextColumnFilter' },
+      { headerName: '家庭住址', field: 'address', sortable: true, filter: 'agTextColumnFilter', width: 260 },
+
+      { headerName: '入住时间', field: 'in_date', sortable: true, filter: 'agDateColumnFilter', valueFormatter: this.unixDateFormatter, filterParams: {
+        comparator: (filterLocalDateAtMidnight, cellValue) => { // 所有数据都由服务器端过滤,此处只需返回0 即可
+          return 0
+        }
+      }},
+      { headerName: '离开时间', field: 'out_date', 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: 'id',
+          sort: 'asc'
+        }
+      ]
+    })
+    this.getEmptyBeds()
+    // 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: {
+
+    getEmptyBeds() {
+      new Promise((resolve, reject) => {
+        API_Frame.getSickbedByPartId(this.$store.getters.partId).then(res => {
+          this.emptyBeds = [...res]
+          resolve()
+        }).catch(err => {
+          this.$message.error('获取空床位:' + err)
+          reject()
+        })
+      })
+    },
+    /** 分页大小发生改变 */
+    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
+        }
+      }).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()
+    },
+    /** 入住登记 **/
+    handleAdd() {
+      this.customerFormVisible = true
+      this.formmodel = {
+        sex: 0,
+        id_type: '身份证',
+        age_unit: '岁',
+        in_date: (new Date()).valueOf(),
+        mobile: '',
+        part_id: this.$store.getters.partId
+      }
+      if (Object.keys(this.frame).length > 0) {
+        this.$set(this.formmodel, 'frame_id', this.frame.id)
+      }
+    },
+    /** 性别格式化 **/
+    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 '未知'
+      }
+    },
+    /** 状态格式化 **/
+    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 '未知'
+      }
+    },
+    /** 格式化时间函数 */
+    unixDateFormatter(param) {
+      if (!param.value) return ''
+      return unix2Date(param.value * 1000)
+    },
+    handleClick() {
+
+    },
+    /** 生日选择变化,修改年龄字段 */
+    birthdayChange(val) {
+      console.log(val)
+      const ageObj = this.getAge(val)
+      console.log('ageobj', ageObj)
+      this.$set(this.formmodel, 'age_unit', ageObj.ageunit)
+      this.$set(this.formmodel, 'age', ageObj.age)
+      // this.formmodel.age_unit = ageObj.ageunit
+      // this.formmodel.age = ageObj.age
+    },
+    getAge(birthday) {
+      const birth = new Date(birthday)
+      const birthYear = birth.getFullYear() // 出生年
+      const birthMonth = birth.getMonth() + 1 // 出生月
+      const birthDay = birth.getDate() // 出生日
+      const nowYear = new Date().getFullYear() // 出生年
+      const nowMonth = new Date().getMonth() + 1 // 出生月
+      const nowDay = new Date().getDate() // 出生日
+
+      if (nowYear === birthYear) { // 同年
+        if (nowMonth === birthMonth) { // 同月
+          return {
+            age: nowDay - birthDay,
+            ageunit: '天'
+          }
+        } else {
+          return {
+            age: nowMonth - birthMonth,
+            ageunit: '月'
+          }
+        }
+      } else { // 计算周岁
+        const ageDiff = nowYear - birthYear // 年之差
+        if (ageDiff > 0) {
+          if (nowMonth === birthMonth) { // 同月
+            const dayDiff = nowDay - birthDay// 日之差
+            if (dayDiff < 0) {
+              return {
+                age: ageDiff - 1,
+                ageunit: '岁'
+              }
+            } else {
+              return {
+                age: ageDiff,
+                ageunit: '岁'
+              }
+            }
+          } else {
+            const monthDiff = nowMonth - birthMonth // 月之差
+            if (monthDiff < 0) {
+              return {
+                age: ageDiff - 1,
+                ageunit: '岁'
+              }
+            } else {
+              return {
+                age: ageDiff,
+                ageunit: '岁'
+              }
+            }
+          }
+        }
+      }
+    },
+    /** 上传成功后的钩子 更换图片 置空存储数组*/
+    uploaded(response) {
+      this.imageUrl = serverUrl + '/' + response
+      this.formmodel.face = response
+    },
+    /** 图片上传之前的校验 */
+    handleShopLogoBefore(file) {
+      const isImg = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif'
+      const isLt2M = file.size / 1024 / 1024 < 2
+      if (!isImg) {
+        this.$message.error('上传头像图片只能是 JPG、PNG、GIF 格式!')
+      }
+      if (!isLt2M) {
+        this.$message.error('上传头像图片大小不能超过 2MB!')
+      }
+      return isImg && isLt2M
+    },
+    /** 入住登记 */
+    handlerSubmit(formName) {
+      this.$refs[formName].validate(valid => {
+        if (valid) {
+          this.isDisabled = true
+          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) // 将毫秒数转换成秒
+          }
+          if (!this.formmodel.id) {
+            API_Customer.addAll(this.formmodel).then(res => {
+              this.$message.success('添加成功!')
+              this.customerFormVisible = 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
+                })
+              }
+            }).catch(e => {
+              this.$message.error(e)
+              this.isDisabled = false
+            })
+          } else {
+            API_Customer.updateAll(this.formmodel).then(res => {
+              this.$message.success('修改成功!')
+              this.isDisabled = false
+              this.$emit('saved')
+            })
+          }
+        } else {
+          this.$message.error('表单填写有误,请检查!')
+          return false
+        }
+      })
+    },
+
+    /** 删除用户 **/
+    deleteSingle(row) {
+      this.handlerDelete(row.id)
+    },
+    /** 单条数据删除处理 */
+    handlerDelete(ids) {
+      const test = '你确定要删除此用户信息?'
+      this.$confirm(test, '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        API_Customer.remove(ids).then(
+          response => {
+            this.getList()
+          }
+        ).catch(response => {
+          this.$message({
+            type: 'info',
+            message: response.message
+          })
+        })
+      })
+    }
+  }
+}
+</script>
+
+   <style scoped type="text/scss">
+                                 /deep/ .el-dialog__body{
+                                     padding: 1px;
+                                 }
+
+    .el-input-group__append .el-select {
+       width: 60px;
+   }
+   /*/deep/ .el-input-group__append {*/
+   /*    background-color: #fff;*/
+   /*}*/
+                                 /deep/ .avatar-uploader{
+                                     line-height: 0;
+                                 }
+                                 /deep/ .avatar-uploader .el-upload {
+                                     border: 1px dashed #d9d9d9;
+                                     border-radius: 6px;
+                                     cursor: pointer;
+                                     position: static;
+                                     overflow: hidden;
+                                     display: inline-block;
+                                 }
+                                 .avatar-uploader .el-upload:hover {
+                                     border-color: #409EFF;
+                                 }
+                                 .avatar-uploader-icon {
+                                     font-size: 28px;
+                                     color: #8c939d;
+                                     width: 110px;
+                                     height: 110px;
+                                     line-height: 110px;
+                                     text-align: center;
+                                 }
+                                 .avatar {
+                                     width: 110px;
+                                     height: 110px;
+                                     display: block;
+                                 }
+</style>

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

@@ -141,7 +141,7 @@ export default {
         headerName: '创建时间',
         field: 'create_time',
         sortable: true,
-        filter: 'agNumberColumnFilter',
+        filter: 'agDateColumnFilter',
         width: 200,
         valueFormatter: this.unixDateFormatter
       },
@@ -149,7 +149,7 @@ export default {
         headerName: '更新时间',
         field: 'update_time',
         sortable: true,
-        filter: 'agNumberColumnFilter',
+        filter: 'agDateColumnFilter',
         width: 200,
         valueFormatter: this.unixDateFormatter
       },

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

@@ -73,7 +73,7 @@ export default {
     },
 
     getRoomStructs() {
-      API_FrameGroup.getRoomStruct(this.$store.getters.partId).then(res => {
+      API_FrameGroup.getframestruct(this.$store.getters.partId, 4).then(res => {
         this.rooms = this.filterGroupFrames(res, this.groupId)
         console.log('rooms', this.rooms)
       }).catch(err => {

Plik diff jest za duży
+ 1023 - 0
src/views/hospitalFrame/frameTreeView.vue


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

@@ -304,7 +304,7 @@ export default {
             if (!params.part_id) {
               params.part_id = this.$store.getters.partId
             }
-            params.full_name = this.fullName + '房-' + params.name + '床'
+            params.full_name = this.frameInfo.name + '房-' + params.name + '床'
             HospitalFrame_API.addHospitalFrame(params).then(response => {
               this.$message.success('添加成功!')
               this.handleFrameFinished()

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

@@ -42,7 +42,7 @@
             <span :class="scope.row.status===1?'green-text':'red-text'">{{ scope.row.status===1?'已启用':'未启用' }}</span>
           </template>
         </el-table-column>
-        <el-table-column prop="full_name" sortable="custom" label="所属位置" width="140" align="center" />
+        <el-table-column prop="full_name" sortable="custom" label="部署位置" width="140" align="center" />
         <el-table-column prop="eth_mac" sortable="custom" label="有线物理地址" width="160" align="center" />
         <el-table-column prop="eth_ip" sortable="custom" label="有线IP地址" width="160" align="center" />
         <el-table-column prop="model" sortable="custom" label="设备型号" width="160" align="center" />