Browse Source

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

* 'master' of http://git.wdklian.com/allen/ncs_ui:
  1、首页开发;2、任务功能开发;3、空间结构优化
wuyunfeng 4 years ago
parent
commit
b9032b5dc6

+ 13 - 0
package-lock.json

@@ -5046,6 +5046,11 @@
         }
       }
     },
+    "comutils": {
+      "version": "1.1.19",
+      "resolved": "https://registry.npm.taobao.org/comutils/download/comutils-1.1.19.tgz",
+      "integrity": "sha1-PgfzBqv0joNyZRFxOnKyBWUDREM="
+    },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -17103,6 +17108,14 @@
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.2.tgz",
       "integrity": "sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg=="
     },
+    "vue-seamless-scroll": {
+      "version": "1.1.23",
+      "resolved": "https://registry.npm.taobao.org/vue-seamless-scroll/download/vue-seamless-scroll-1.1.23.tgz",
+      "integrity": "sha1-3egbPHmqSZeRs8O//Q/bIv8+Wac=",
+      "requires": {
+        "comutils": "^1.1.9"
+      }
+    },
     "vue-splitpane": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/vue-splitpane/-/vue-splitpane-1.0.4.tgz",

+ 1 - 0
package.json

@@ -47,6 +47,7 @@
     "vue-count-to": "1.0.13",
     "vue-property-decorator": "^9.1.2",
     "vue-router": "3.0.2",
+    "vue-seamless-scroll": "^1.1.23",
     "vue-splitpane": "1.0.4",
     "vuedraggable": "2.20.0",
     "vuex": "3.1.0",

+ 8 - 0
src/api/ncs_task.js

@@ -38,3 +38,11 @@ export function listByPartId(params) {
     data: params
   })
 }
+/** 修改 */
+export function updateOrSave(id, params) {
+  return request({
+    url: `/ncs/task/updateOrSave/${id}`,
+    method: 'put',
+    data: params
+  })
+}

+ 8 - 4
src/components/AgGridCellRender/ButtonCellRender.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <el-button :type="buttonType" :size="buttonSize" :disabled="disabled" @click="buttonClick">{{ label }}</el-button>
+    <el-button v-if="show" :type="buttonType" :size="buttonSize" :disabled="disabled" @click="buttonClick">{{ label }}</el-button>
   </div>
 </template>
 
@@ -12,13 +12,14 @@ export default {
       buttonType: 'primary',
       buttonSize: 'mini',
       label: 'button',
-      disabled: false
+      disabled: false,
+      show: true
     }
   },
   beforeMount() {
   },
   mounted() {
-    const { buttonType, buttonSize, label, disabled } = this.params
+    const { buttonType, buttonSize, label, disabled, show } = this.params
     if (buttonType) {
       this.buttonType = buttonType
     }
@@ -31,13 +32,16 @@ export default {
     if (disabled !== undefined) {
       this.disabled = disabled
     }
+    if (show !== undefined) {
+      this.show = show
+    }
   },
   methods: {
     buttonClick() {
       console.log('click', typeof this.params.onClick === 'function')
 
       if (typeof this.params.onClick === 'function') {
-          console.log(this.params.node.data)
+        console.log(this.params.node.data)
         this.params.onClick(this.params.node.data)
         // this.params.context.componentParent.showDetail(this.params.node.data)
       }

+ 2 - 0
src/main.js

@@ -26,6 +26,7 @@ import * as filters from './filters' // global filters
 import mixin from './utils/mixin'
 import Components from './components'
 import vcolorpicker from 'vcolorpicker'
+import scroll from 'vue-seamless-scroll/src'
 /**
  * If you don't want to use mock-server
  * you want to use MockJs for mock api
@@ -42,6 +43,7 @@ if (process.env.NODE_ENV === 'production') {
 Vue.component('AgGridVue', AgGridVue)
 Vue.use(vcolorpicker)
 Vue.use(Components)
+Vue.use(scroll)
 Vue.mixin(mixin)
 Vue.use(Element, {
   size: Cookies.get('size') || 'medium' // set element-ui default size

+ 3 - 3
src/router/index.js

@@ -133,7 +133,7 @@ export const partRoutes = [
       {
         path: 'customer',
         component: () => import('@/views/customer/list'),
-        name: 'customer',
+        name: 'customerList',
         meta: { title: '病人管理', icon: 'el-icon-s-custom', noCache: true }
       }
     ]
@@ -146,7 +146,7 @@ export const partRoutes = [
       {
         path: 'remark',
         component: () => import('@/views/ncs-remark/index'),
-        name: 'customer',
+        name: 'remarkList',
         meta: { title: '便签管理', icon: 'el-icon-s-order', noCache: true }
       }
     ]
@@ -159,7 +159,7 @@ export const partRoutes = [
       {
         path: 'task',
         component: () => import('@/views/ncs-task/index'),
-        name: 'customer',
+        name: 'taskList',
         meta: { title: '任务管理', icon: 'table', noCache: true }
       }
     ]

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

@@ -194,7 +194,7 @@
                       v-model="content">
               </el-input>
             </el-form-item>
-            <el-form-item label="件">
+            <el-form-item label="件">
               <el-upload v-if="!filePath"
                          class="avatar-uploader"
                          :action="`${uploadServer}?scene=avatar`"
@@ -508,11 +508,11 @@
           const isImg = hz === 'jpeg' || hz === 'png' || hz === 'jpg' || hz === 'txt'  || hz === 'doc' || hz === 'docx' || hz === 'xls' || hz === 'xlsx'
           const isLt5M = file.size / 1024 / 1024 < 5
           if (!isImg) {
-            _this.$message.error('上传件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!')
+            _this.$message.error('上传件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!')
             reject()
           }
           if (!isLt5M) {
-            _this.$message.error('上传件大小不能超过 5MB!')
+            _this.$message.error('上传件大小不能超过 5MB!')
             reject()
           }
           resolve()

+ 37 - 19
src/views/customer/list.vue

@@ -1,7 +1,26 @@
 <template>
   <div>
+    <!--工具栏-->
+    <div class="toolbar" style="padding-left: 20px">
+      <el-form :inline="true" label-width="120px">
+        <el-form-item>
+          <el-input v-model="searchStr" placeholder="请输入病人姓名或编号" clearable>
+            <el-button slot="append" icon="el-icon-search" @click="clickSearch"></el-button>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="病人状态">
+          <el-select v-model="callingType" placeholder="请选择病人状态" clearable @change="changeStatus">
+            <el-option label="在院" :value="0" />
+            <el-option label="已出院" :value="1" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="danger" :disabled="multipleSelection.length === 0" @click="batchDelete">批量删除</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
     <en-table-layout
-      toolbar
+      :toolbar = false
       @selection-change="selectFun"
       pagination
       :tableData="tableData"
@@ -9,27 +28,13 @@
       :loading="loading"
       :default-sort="{prop: 'id', order: 'ascending'}"
     >
-      <!--工具栏-->
-      <div slot="toolbar" class="inner-toolbar">
-        <div style="float: left">
-          <el-select v-model="callingType" placeholder="请选择病人状态" clearable @change="changeStatus">
-            <el-option label="在院" :value="0" />
-            <el-option label="已出院" :value="1" />
-          </el-select>
-        </div>
-        <div class="toolbar-search">
-          <en-table-search @search="handlerSearch" placeholder="请输入病人姓名或编号"/>
-        </div>
-        <div class="toolbar-btns">
-           <el-button type="danger" :disabled="multipleSelection.length === 0" @click="batchDelete">批量删除</el-button>
-        </div>
-      </div>
       <!--表头-->
       <template slot="table-columns">
         <el-table-column type="selection" width="55" align="center"></el-table-column>
         <el-table-column prop="named" label="姓名" align="center" min-width="160"></el-table-column>
         <el-table-column prop="card_no" label="病人编号" align="center" min-width="160"></el-table-column>
         <el-table-column prop="relative_name" label="年龄" align="center" :formatter="formatterAge" width="100"></el-table-column>
+        <el-table-column prop="sex" label="性别" align="center" width="70" :formatter="formatterSex"></el-table-column>
         <el-table-column prop="in_date" label="住院时间" align="center" :formatter="formatterDate" min-width="190"></el-table-column>
         <el-table-column prop="status" label="状态" align="center" :formatter="formatterStatus" width="100"></el-table-column>
         <el-table-column label="操作" width="220">
@@ -109,7 +114,8 @@
         customerId: null,
         frameId: null,
         callingType: null,
-        frameList: []
+        frameList: [],
+        searchStr: null
       }
     },
     mounted() {
@@ -264,7 +270,20 @@
           this.formshow = false
           this.GET_List()
         })
-      }
+      },
+      clickSearch() {
+        delete this.params.fixedCondition
+        if (this.searchStr != null && this.searchStr != '') {
+          this.params.fixedCondition = " ( named like concat('%','" + this.searchStr + "','%') or card_no like concat('%','" + this.searchStr + "','%')) "
+        } else {
+          this.params.fixedCondition = ' 1 = 1'
+        }
+        this.GET_List()
+      },
+      /** 性别格式化 */
+      formatterSex(row, column, cellValue) {
+        return row.sex === 1 ? '男' :  row.sex === 2 ? '女' : '未知'
+      },
     }
   }
 </script>
@@ -284,5 +303,4 @@
       text-align: center;
     }
   }
-
 </style>

+ 248 - 30
src/views/dashboard/calling/index.vue

@@ -1,56 +1,274 @@
 <template>
   <div class="dashboard-editor-container" :style="{'min-height': minDashboadHeight+'px'}">
-    <panel-group :bed-board="bedBoard" />
-    <sick-bed-board :bed-board="bedBoard" :part-info="partInfo" @change="searchChange" />
+    <el-row :gutter="20">
+      <el-col :span="12">
+        <el-card style="maring:10px">
+          <div slot="header" class="clearfix">
+            <span style="float: left">今日任务</span>
+            <el-link type="primary" style="float: right" @click="goMove('taskList')">更多</el-link>
+          </div>
+          <div style="clear:both;font-size: 14px;height: 300px;">
+            <el-scrollbar wrapClass="scrollbar-wrapper" style="min-height: 250px">
+              <vue-seamless-scroll :data="todayList" :class-option="defaultOption" class="seamless-warp">
+                <el-card v-for="(item, index) in todayList" :key="index">
+                  <div>
+                    <span>计划执行时间:{{forDate(item.task_plan_time)}}</span>
+                  </div>
+                  <div style="margin-top: 5px;" @click="showArticleContext(item.task_content)">
+                    <span style="margin-left: 20px; line-height:1.2"><a>{{item.task_content}}</a></span>
+                  </div>
+                  <div style="margin: 5px">
+                    <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>
+              </vue-seamless-scroll>
+            </el-scrollbar>
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="12">
+        <el-card>
+          <div slot="header" class="clearfix">
+            <span style="float: left">最近便签</span>
+            <el-link type="primary" style="float: right" @click="goMove('remarkList')">更多</el-link>
+          </div>
+          <div style="clear:both;font-size: 14px;height: 300px;">
+            <el-scrollbar wrapClass="scrollbar-wrapper" style="min-height: 250px">
+              <vue-seamless-scroll :data="noteList" :class-option="defaultOption" class="seamless-warp">
+                <el-card v-for="(item, index) in noteList" :key="index">
+                  <div style="margin-top: 5px;" @click="showArticleContext(item.content)">
+                    <span style="margin-left: 20px; line-height:1.2"><a>{{item.content}}</a></span>
+                  </div>
+                  <div style="margin: 5px">
+                    <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>
+              </vue-seamless-scroll>
+            </el-scrollbar>
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <el-row :gutter="20">
+      <el-col :span="16">
+        <el-card style="maring:10px">
+          <div slot="header" class="clearfix">
+            <span style="float: left">最近呼叫</span>
+            <el-link type="primary" style="float: right" @click="goMove('CallingList')">更多</el-link>
+          </div>
+          <div style="height: 300px">
+<!--            <el-scrollbar wrapClass="scrollbar-wrapper" style="min-height: 250px">-->
+<!--              <vue-seamless-scroll :data="callingHistoryList" :class-option="defaultOption" class="seamless-warp">-->
+<!--                <el-card v-for="(item, index) in callingHistoryList" :key="index">-->
+<!--                  <a>-->
+<!--                    <div style="margin-top: 5px;">-->
+<!--                      <span style="margin-left: 20px; line-height:1.2">{{item.content}}</span>-->
+<!--                    </div>-->
+<!--                  </a>-->
+<!--                </el-card>-->
+<!--              </vue-seamless-scroll>-->
+<!--            </el-scrollbar>-->
+            <el-table :data="callingHistoryList" height="300px">
+                <el-table-column prop="calllist_type" label="呼叫类型" width="120" align="center" :formatter="formatterCallType" />
+                <el-table-column prop="content" label="呼叫内容" width="320" align="center" />
+                <el-table-column prop="create_time" label="呼叫时间" width="170" align="center" :formatter="formatterCreateTime" />
+                <el-table-column prop="calling_direct" label="呼叫方向" align="center" :formatter="formatterCallDirect" />
+                <el-table-column prop="nickname" label="呼叫人" align="center" />
+            </el-table>
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="8">
+        <el-card>
+          <div slot="header" class="clearfix">
+            <span style="float: left">最近患者备注</span>
+            <el-link type="primary" style="float: right" @click="goMove('customerList')">更多</el-link>
+          </div>
+          <div style="clear:both;font-size: 14px;height: 300px;">
+            <el-scrollbar wrapClass="scrollbar-wrapper" style="min-height: 250px">
+              <vue-seamless-scroll :data="remarkList" :class-option="defaultOption" class="seamless-warp">
+                <el-card v-for="(item, index) in remarkList" :key="index">
+                  <div style="margin-top: 5px;" @click="showArticleContext(item.content)">
+                    <span style="margin-left: 20px; line-height:1.2"><a>{{item.content}}</a></span>
+                  </div>
+                  <div style="margin: 5px">
+                    <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>
+              </vue-seamless-scroll>
+            </el-scrollbar>
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+    <el-dialog title="详情" :visible.sync="isShowArticle" width="50%" align="center">
+      <p style="text-align: left;" v-html="currentContent.replace(/\n/g, '<br>')" class="current-content"></p>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import PanelGroup from './components/PanelGroup'
-import * as API_Part from '@/api/calling-part'
-import * as API_Nurse from '@/api/calling-nurse'
-import SickBedBoard from './components/SickBedBoard'
+  import * as API_task from '@/api/ncs_task'
+  import * as API_Remark from '@/api/ncs_remark'
+  import {unixToDate} from '@/utils/Foundation'
+  import * as API_CallingList from '@/api/ncs_calling_history'
+
 export default {
   name: 'Index',
-  components: { SickBedBoard, PanelGroup },
   data() {
     return {
-      /** 床位信息 */
-      bedBoard: {},
-      /** 护理参数一配置项 */
-      nurseLevel0Config: [],
-      /** 科室信息 */
-      partInfo: {},
-      searchParams: {
-        bed_status: 0,
-        bed_care: 0,
-        query: ''
-      }
+      todayList: [],
+      params: {
+        page_no: 1,
+        page_size: 100,
+        sort: 'create_time',
+        dir: 'desc',
+      },
+      noteList: [],
+      callingHistoryList: [],
+      remarkList: [],
+      isShowArticle: false,
+      currentContent: ''
     }
   },
   computed: {
     minDashboadHeight() {
       return this.mainAreaHeight
+    },
+    // 滚动自定义
+    defaultOption() {
+      return {
+        step: 0.4, // 数值越大速度滚动越快
+        limitMoveNum: 2, // 开始无缝滚动的数据量 this.dataList.length
+        hoverStop: true, // 是否开启鼠标悬停stop
+        direction: 1, // 0向下 1向上 2向左 3向右 默认1
+        openWatch: true, // 开启数据实时监控刷新dom
+        singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
+        singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
+        waitTime: 1000 // 单步运动停止的时间(默认值1000ms)
+      }
     }
   },
-  async mounted() {
+  mounted() {
     if (this.$store.getters.partId) {
-      await this.getBedBoard()
-      this.nurseLevel0Config = await API_Nurse.getNurseConfigs(this.$store.getters.partId, 0)
-      this.partInfo = await API_Part.get(this.$store.getters.partId)
+      this.getTodayList()
+      this.getNoteList()
+      this.getCallingHistoryList()
+      this.getRemarkList()
     }
   },
   methods: {
-    searchChange(searchObj) {
-      this.searchParams = { ...searchObj }
-      this.getBedBoard()
+    getTodayList() {
+      const param = this.MixinClone(this.params)
+      param.fixedCondition = ' part_id = ' + this.$store.getters.partId
+      let _this = this
+      _this.todayList = []
+      API_task.getList(param).then(response => {
+        const today = (new Date().setHours(0, 0, 0, 0)) / 1000
+        const todayend = (today * 1000 + 86400000) / 1000
+        response.data.forEach((item, index) =>{
+          if (item.task_plan_time >= today && item.task_plan_time < todayend) {
+            _this.todayList.push(item)
+          }
+        })
+      })
     },
-
-    getBedBoard() {
-      API_Part.getBedInfos(this.$store.getters.partId, { ...this.searchParams }).then(res => {
-        this.bedBoard = { ...res }
+    getNoteList() {
+      const param = this.MixinClone(this.params)
+      param.fixedCondition = ' type = 2 and part_id=' + this.$store.getters.partId
+      let _this = this
+      API_Remark.getRemarks(param).then(response => {
+        _this.noteList = response.data
       })
-    }
+    },
+    getRemarkList() {
+      const param = this.MixinClone(this.params)
+      param.fixedCondition = ' type = 1 and part_id=' + this.$store.getters.partId
+      let _this = this
+      API_Remark.getRemarks(param).then(response => {
+        _this.remarkList = response.data
+      })
+    },
+    getCallingHistoryList() {
+      const param = this.MixinClone(this.params)
+      param.fixedCondition = ' nch.part_id=' + this.$store.getters.partId
+      param.sort = 'nch.id'
+      let _this = this
+      API_CallingList.getList(param).then(response => {
+        _this.callingHistoryList = response.data
+      })
+    },
+    forDate(date) {
+      return unixToDate(date)
+    },
+    showArticleContext(conent) {
+      this.currentContent = conent
+      this.isShowArticle = true
+    },
+    goMove(path) {
+      this.$router.push({name: path})
+    },
+    formatterCallType(row, column, cellValue) {
+      switch (row.calling_type) {
+        case 1:
+          return '病房普通呼叫'
+        case 2:
+          return '门口机呼叫'
+        case 3:
+          return '卫生间紧急呼叫'
+        case 4:
+          return '请求增援'
+        case 5:
+          return '优先呼叫'
+        case 6:
+          return '关系人电话呼叫'
+        default:
+          return '未知呼叫'
+      }
+    },
+    formatterCallDirect(row, column, cellValue) {
+      if (row.calling_direct === 0) {
+        return '呼出'
+      } else {
+        return '呼入'
+      }
+    },
+    formatterCreateTime(row, column, cellValue) {
+      return unixToDate(row.create_time)
+    },
   }
 
 }

+ 15 - 4
src/views/hospitalFrame/hospitalFrame.vue

@@ -56,11 +56,11 @@
               </el-dropdown>
             </span>
           </div>
-          <el-button type="text" class="add-params-btn" @click="handleAddFrame(item.frame_room.id)"><i class="el-icon-circle-plus"></i> 添加床位</el-button>
+          <el-button type="text" class="add-params-btn" @click="handleAddFrame(item.frame_room.id, item.frame_room.name)"><i class="el-icon-circle-plus"></i> 添加床位</el-button>
         </template>
         <template v-else>
           <div class="param-item empty">暂无数据...</div>
-          <el-button type="text" class="add-params-btn" @click="handleAddFrame(item.frame_room.id)"><i class="el-icon-circle-plus"></i> 添加床位</el-button>
+          <el-button type="text" class="add-params-btn" @click="handleAddFrame(item.frame_room.id, item.frame_room.name)"><i class="el-icon-circle-plus"></i> 添加床位</el-button>
         </template>
       </el-card>
     </div>
@@ -169,6 +169,7 @@
             }
           ]
         },
+        fullName: null
       }
     },
     mounted() {
@@ -197,6 +198,7 @@
       },
       /** 下拉触发 */
       handleGroupCommand(object) {
+        console.log(object)
         switch (object.type) {
           case 'edit':
             this.handelEditFrame(object.frame)
@@ -231,18 +233,20 @@
           parent_id = this.hospital_frame.frame_part.id
         }
         const params = { type: 4, name: this.frameName, part_id: this.$store.getters.partId, parent_id: parent_id}
+        params.full_name = params.name + '房'
         HospitalFrame_API.addHospitalFrame(params).then(response => {
           this.$message.success('添加成功!')
           this.GET_All()
         })
       },
-      handleAddFrame(id) { // 新增床位
+      handleAddFrame(id, name) { // 新增床位
         this.frameInfo = {}
         this.frameInfo = { parent_id: id, type: 5 }
+        this.fullName = name
         this.dialogFrameVisible = true
       },
       handelEditFrame(frame) {
-        this.frameInfo = { id: frame.id, type: frame.type, name: frame.name, alias: frame.alias }
+        this.frameInfo = { id: frame.id, type: frame.type, name: frame.name, alias: frame.alias, full_name: frame.full_name }
         this.dialogFrameVisible = true
       },
       handleFrameFinished() {
@@ -284,6 +288,12 @@
           if (valid) {
             const params = this.MixinClone(this.frameInfo)
             if (params.id) {
+              if (params.type === 5) {
+                const name = params.full_name.split('-')
+                params.full_name = name[0] + '-' + params.name + '床'
+              } else if (params.type === 4) {
+                params.full_name = params.name + '房'
+              }
               HospitalFrame_API.updateHospitalFrame(params.id, params).then(response => {
                 this.$message.success('修改成功!')
                 this.handleFrameFinished()
@@ -292,6 +302,7 @@
               if (!params.part_id) {
                 params.part_id = this.$store.getters.partId
               }
+              params.full_name = this.fullName + '房-' + params.name + '床'
               HospitalFrame_API.addHospitalFrame(params).then(response => {
                 this.$message.success('添加成功!')
                 this.handleFrameFinished()

+ 1 - 2
src/views/ncs-clerk/clerkList.vue

@@ -366,7 +366,7 @@
 
       /** 性别格式化 */
       formatterSex(row, column, cellValue) {
-        return row.sex === 1 ? '男' : '女'
+        return row.sex === 1 ? '男' :  row.sex === 2 ? '女' : '未知'
       },
 
       formatterRole(row, column, cellValue) {
@@ -425,7 +425,6 @@
         if (row.birthday) {
           this.addMemberForm.birthday *= 1000
         }
-        console.log(this.addMemberForm)
         this.dialogAddMemberVisible = true
       },
       /** 分页大小发生改变 */

+ 5 - 6
src/views/ncs-remark/index.vue

@@ -58,7 +58,7 @@
                             v-model="content">
                     </el-input>
                 </el-form-item>
-                <el-form-item label="件">
+                <el-form-item label="件">
                     <el-upload v-if="!filePath"
                                class="avatar-uploader"
                                :action="`${uploadServer}?scene=avatar`"
@@ -82,9 +82,8 @@
 <script>
     import * as API_Remark from '@/api/ncs_remark'
     import {unixToDate} from '@/utils/Foundation'
-    import {serverUrl} from "@/utils/domain";
-    import * as RegExp from "@/utils/RegExp";
-    import * as remark_API from "@/api/ncs_remark";
+    import {serverUrl} from "@/utils/domain"
+    import * as RegExp from "@/utils/RegExp"
 
     export default {
         name: 'Index',
@@ -209,11 +208,11 @@
                     const isImg = hz === 'jpeg' || hz === 'png' || hz === 'jpg' || hz === 'txt'  || hz === 'doc' || hz === 'docx' || hz === 'xls' || hz === 'xlsx'
                     const isLt5M = file.size / 1024 / 1024 < 5
                     if (!isImg) {
-                        _this.$message.error('上传件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!')
+                        _this.$message.error('上传件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!')
                         reject()
                     }
                     if (!isLt5M) {
-                        _this.$message.error('上传件大小不能超过 5MB!')
+                        _this.$message.error('上传件大小不能超过 5MB!')
                         reject()
                     }
                     resolve()

+ 235 - 86
src/views/ncs-task/index.vue

@@ -1,5 +1,5 @@
 <template>
-    <div>
+    <div class="formwrap">
 <!--        <en-table-layout-->
 <!--                toolbar-->
 <!--                @selection-change="selectFun"-->
@@ -67,6 +67,12 @@
 <!--                    :total="pageData.data_total">-->
 <!--            </el-pagination>-->
 <!--        </en-table-layout>-->
+        <el-tabs v-model="activeName" @tab-click="handleClick">
+            <el-tab-pane label="全部" name="all"></el-tab-pane>
+            <el-tab-pane label="未操作" name="not_operating"></el-tab-pane>
+            <el-tab-pane label="任务失败" name="fail"></el-tab-pane>
+            <el-tab-pane label="任务成功" name="success"></el-tab-pane>
+        </el-tabs>
 
         <ag-grid-layout
                 toolbar
@@ -83,9 +89,9 @@
                 @sortChanged="gridSortChange"
         >
             <div slot="toolbar" class="inner-toolbar">
-                <div class="toolbar-search">
-                    <en-table-search placeholder="请输入搜索关键字" @search="handlerSearch" />
-                </div>
+<!--                <div class="toolbar-search">-->
+<!--                    <en-table-search placeholder="请输入搜索关键字" @search="handlerSearch" />-->
+<!--                </div>-->
                 <div class="toolbar-btns">
                     <el-button type="primary" @click="handlerAdd">新增</el-button>
                     <el-button type="danger" @click="batchDelete">删除</el-button>
@@ -106,25 +112,49 @@
         <!--编辑表单-->
         <el-dialog title="通知/任务" :visible.sync="formshow" width="50%">
             <div>
-                <el-form ref="editform" :rules="rules" label-width="110px" :model="formmodel">
-                    <el-form-item label="发布/计划时间" prop="publish_time">
-                        <el-date-picker
-                                v-model="formmodel.publish_time"
-                                type="datetime"
-                                value-format="timestamp"
-                                placeholder="选择日期时间"
-                                align="right"
-                        >
-                        </el-date-picker>
-                    </el-form-item>
-
-                    <el-form-item label="概要" prop="subject">
-                        <el-input clearable v-model="formmodel.subject" :maxlength="30" placeholder="请输入概要"></el-input>
-                    </el-form-item>
-
-                    <el-form-item label="内容" prop="content">
-                        <el-input v-model="formmodel.content" type="textarea" rows="10" placeholder="请选输入内容"></el-input>
-                    </el-form-item>
+                <el-form ref="editform" :rules="rules" label-width="140px" :model="formmodel">
+                    <div v-if="editflag === 1">
+                        <el-form-item label="任务完成?">
+                            <el-switch
+                                    v-model="task_success"
+                                    active-text="成功"
+                                    inactive-text="失败">
+                            </el-switch>
+                        </el-form-item>
+                        <el-form-item label="实际回访时间" prop="task_do_time">
+                            <el-date-picker
+                                    v-model="formmodel.task_do_time"
+                                    type="datetime"
+                                    value-format="timestamp"
+                                    placeholder="实际回访时间"
+                            ></el-date-picker>
+                        </el-form-item>
+                    </div>
+                    <div v-if="!task_success">
+                        <el-form-item label="计划任务执行时间" prop="task_plan_time">
+                            <el-date-picker
+                                    v-model="formmodel.task_plan_time"
+                                    type="datetime"
+                                    value-format="timestamp"
+                                    placeholder="计划任务执行时间"
+                            ></el-date-picker>
+                        </el-form-item>
+                        <el-form-item label="内容" prop="task_content">
+                            <el-input v-model="formmodel.task_content" type="textarea" rows="10" placeholder="请选输入内容"></el-input>
+                        </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>
+                    </div>
 
                 </el-form>
 
@@ -143,6 +173,8 @@
     import { AG_GRID_LOCALE_CN } from '@/utils/AgGridVueLocaleCn'
     import Tooltip from '../../components/Tooltip/Tooltip'
     import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
+    import {serverUrl} from "@/utils/domain";
+    import {param} from "@/utils";
     export default {
         name: 'index',
         components: { Tooltip, ButtonCellRender },
@@ -155,11 +187,14 @@
                 formshow: false, // 编辑表单显示开关
                 /** 表单校验 */
                 rules: {
-                    subject: [
-                        {required: true, message: '请输入概要', trigger: 'blur'}
+                    task_plan_time: [
+                        {required: true, message: '请选择计划任务执行时间', trigger: 'blur'}
+                    ],
+                    task_content: [
+                        {required: true, message: '请输入任务内容', trigger: 'blur'}
                     ],
-                    content: [
-                        {required: true, message: '请输入内容', trigger: 'blur'}
+                    task_do_time: [
+                        {required: true, message: '请选择实际任务时间', trigger: 'blur'}
                     ]
                 },
                 pageData: [],
@@ -170,6 +205,7 @@
                     page_size: 10,
                     sort: 'create_time',
                     dir: 'desc',
+                    fixedCondition: ' part_id = ' + this.$store.getters.partId
                 },
                 doctors: [],
                 memberusers: [],
@@ -182,7 +218,12 @@
                 columnApi: null,
                 localeText: AG_GRID_LOCALE_CN,
                 filterState: null,
-                rowSelection: null
+                rowSelection: null,
+                fileName: null,
+                filePath: null,
+                uploadServer: serverUrl + '/ncs/upload/uploadFile',
+                task_success: false,
+                activeName: 'all'
             }
         },
         computed: {
@@ -213,21 +254,41 @@
                 { headerName: '计划任务时间', field: 'task_plan_time', valueFormatter: this.formatterDate, sortable: true, filter: false, width: 170 },
                 { headerName: '实际任务时间', field: 'task_do_time', valueFormatter: this.formatterDate, sortable: true, filter: false, width: 170 },
                 { headerName: '任务状态', field: 'task_success', filter: false, cellRenderer: this.formatterStasus, width: 100 },
-                { headerName: '任务结果', field: 'task_result', sortable: true, filter: false, width: 220,
-                    cellRendererFramework: 'Tooltip',
-                    cellRendererParams: {
-                        content: 'task_result'
-                    },
-                },
+                // { headerName: '任务结果', field: 'task_result', sortable: true, filter: false, width: 220,
+                //     cellRendererFramework: 'Tooltip',
+                //     cellRendererParams: {
+                //         content: 'task_result'
+                //     },
+                // },
                 { headerName: '任务操作人', field: 'task_do_name', sortable: true, filter: true, width: 120 },
-                { headerName: '创建人', field: 'create_name', sortable: true, filter: true, width: 120},
+                { headerName: '创建人', field: 'create_name', valueFormatter: this.formatterName, sortable: true, filter: true, width: 120},
                 { headerName: '操作任务', field: 'id',
                     cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: {
-                        onClick: this.handlerEdit,
-                        label: '操作任务',
-                        buttonType: 'primary',
-                        buttonSize: 'mini'
+                    cellRendererParams: param => {
+                        return {
+                            onClick: this.handlerEdit,
+                            label: '操作任务',
+                            buttonType: 'primary',
+                            buttonSize: 'mini',
+                            show: param.data['task_do_time'] === null
+                        }
+                    },
+                    filter: false,
+                    pinned: 'right',
+                    lockPinned: true,
+                    width: 100,
+                    resizable: false,
+                    sortable: false },
+                { headerName: '附件', field: 'id',
+                    cellRendererFramework: 'ButtonCellRender',
+                    cellRendererParams: param => {
+                        return {
+                            onClick: this.xzfj,
+                            label: '下载',
+                            buttonType: 'success',
+                            buttonSize: 'mini',
+                            show: param.data['file_path'] !== '' && param.data['file_path'] !== null
+                        }
                     },
                     filter: false,
                     pinned: 'right',
@@ -237,11 +298,13 @@
                     sortable: false },
                 { headerName: '删除', field: 'id',
                     cellRendererFramework: 'ButtonCellRender',
-                    cellRendererParams: {
-                        onClick: this.deleteSingle,
-                        label: '删除',
-                        buttonType: 'danger',
-                        buttonSize: 'mini'
+                    cellRendererParams: param => {
+                        return {
+                            onClick: this.deleteSingle,
+                            label: '删除',
+                            buttonType: 'danger',
+                            buttonSize: 'mini'
+                        }
                     },
                     pinned: 'right',
                     lockPinned: true,
@@ -271,22 +334,18 @@
         methods: {
             handlerAdd: function () {
                 this.formmodel = {}
-
                 if (this.$refs.editform) {
                     this.$refs.editform.resetFields()
                 }
+                this.task_success = false
                 this.editflag = 0
                 this.formshow = true
             },
-            handlerEdit: function (index, row) {
-                if (this.$refs.editform) {
-                    this.$refs.editform.resetFields()
-                }
-                this.formmodel = {
-                    ...row
-                }
-                this.formmodel.publish_time *= 1000
-                this.formmodel.create_time *= 1000
+            handlerEdit: function (row) {
+                this.formmodel = {}
+                this.formmodel.id = row.id
+                this.formmodel.task_do_time = Date.now()
+                this.task_success = true
                 this.editflag = 1
                 this.formshow = true
             },
@@ -294,6 +353,9 @@
             selectFun(val) {
                 this.multipleSelection = val
             },
+            deleteSingle(row) {
+                this.handlerDelete(row.id)
+            },
             /** 单条数据删除处理 */
             handlerDelete(ids) {
                 this.$confirm('删除操作后数据不可复原,您确定要删除此数据?', '警告', {
@@ -324,21 +386,16 @@
             },
             /** 批量数据删除处理(删除选中的行) */
             batchDelete: function () {
-                if (this.multipleSelection.length === 0) {
-                    this.$alert('没有选择任何记录!', '系统提示', {
-                        confirmButtonText: '确定',
-                        callback: action => {
-
-                        }
-                    })
-                } else {
-                    const ids = []
-                    this.multipleSelection.forEach(function (item) {
-                        ids.push(item.id)
-                    })
-
-                    this.handlerDelete(ids.join(','))
+                let rows = this.gridApi.getSelectedRows()
+                if (rows.length === 0) {
+                    this.$message({ type: 'info', message: '请先勾选需要删除的数据' })
+                    return
                 }
+                const ids = []
+                rows.forEach(function (item) {
+                    ids.push(item.id)
+                })
+                this.handlerDelete(ids.join(','))
             },
             /** 分页大小发生改变 */
             handlePageSizeChange(size) {
@@ -372,26 +429,42 @@
                     if (valid) {
                         /** 新增通知 */
                         if (this.editflag === 0) {
-                            this.formmodel.create_time = Date.parse(new Date()) / 1000
-                            this.formmodel.publish_time = this.formmodel.publish_time / 1000
+                            this.formmodel.task_plan_time = Date.parse(new Date()) / 1000
+                            this.formmodel.file_name = this.fileName
+                            this.formmodel.file_path = this.filePath
+                            this.formmodel.create_id = this.$store.getters.userInfo.uid
+                            this.formmodel.part_id = this.$store.getters.partId
                             API_task.add(this.formmodel).then(() => {
                                 this.formshow = false
                                 this.$message.success('保存成功!')
                                 this.getList()
+                                this.fileName = null
+                                this.filePath = null
                             })
                         } else {
                             /** 修改通知 */
-                            this.formmodel.create_time /= 1000
-                            this.formmodel.publish_time /= 1000
-                            API_task.update(this.formmodel.id, this.formmodel).then(() => {
-                                this.formshow = false
-                                this.$message.success('修改成功!')
-                                this.getList()
-                            }).catch(response => {
-                                this.formshow = false
-                                this.$message.warning(response.message)
-                                this.getList()
-                            })
+                            this.formmodel.task_do_time = Math.floor(this.formmodel.task_do_time /= 1000)
+                            this.formmodel.task_do_member_id = this.$store.getters.userInfo.uid
+                            this.formmodel.task_success = this.task_success
+                            if (this.task_success) {
+                                API_task.update(this.formmodel.id, this.formmodel).then(() => {
+                                    this.formshow = false
+                                    this.$message.success('修改成功!')
+                                    this.getList()
+                                })
+                            } else {
+                                this.formmodel.task_plan_time = Date.parse(new Date()) / 1000
+                                this.formmodel.file_name = this.fileName
+                                this.formmodel.file_path = this.filePath
+                                this.formmodel.create_id = this.$store.getters.userInfo.uid
+                                this.formmodel.part_id = this.$store.getters.partId
+                                API_task.updateOrSave(this.formmodel.id, this.formmodel).then(() => {
+                                    this.formshow = false
+                                    this.$message.success('修改成功!')
+                                    this.getList()
+                                })
+                            }
+
                         }
                     }
                 })
@@ -436,15 +509,19 @@
                     return '<span style="color:orange">暂未操作</span>'
                 }
             },
+            formatterName(param) {
+                if (param.data.create_id === 0) {
+                    return '系统创建'
+                } else {
+                    return param.value
+                }
+            },
             filterModifed(param) {
-                console.log('filterModifed===',param)
                 let model = param.api.getFilterModel()
-                console.log('model', JSON.stringify(model))
                 this.params.filter = JSON.stringify(model)
                 this.getList()
             },
             gridSortChange(param) {
-                console.log('gridSortChange===', param)
                 const columnState = param.columnApi.getColumnState()
                 // 排序状态
                 const sortState = columnState.filter(function(s) {
@@ -476,16 +553,62 @@
                 }
 
                 this.getList()
-                console.log(sortState)
             },
             formatterDate(params) {
                 return unixToDate(params.value)
+            },
+            /** 上传成功后的钩子 更换图片 置空存储数组*/
+            uploaded(res) {
+                this.filePath = serverUrl + '/' + res
+            },
+            /** 图片上传之前的校验 */
+            handleShopLogoBefore(file) {
+                let _this = this
+                return new Promise((resolve, reject) => {
+                    let hz = file.name
+                    _this.fileName = hz
+                    let index = hz .lastIndexOf(".");
+                    hz  = hz .substring(index + 1, hz .length);
+                    const isImg = hz === 'jpeg' || hz === 'png' || hz === 'jpg' || hz === 'txt'  || hz === 'doc' || hz === 'docx' || hz === 'xls' || hz === 'xlsx'
+                    const isLt5M = file.size / 1024 / 1024 < 5
+                    if (!isImg) {
+                        _this.$message.error('上传附件只能是txt,doc,docx,xls,xlsx,jpg,png,jpeg格式!')
+                        reject()
+                    }
+                    if (!isLt5M) {
+                        _this.$message.error('上传附件大小不能超过 5MB!')
+                        reject()
+                    }
+                    resolve()
+                })
+            },
+            handleClick(tab, event) {
+                this.params.fixedCondition = ' part_id = ' + this.$store.getters.partId
+                if (tab.name === 'not_operating') {
+                    this.params.fixedCondition += ' and isNull(task_success) '
+                } else if (tab.name === 'fail') {
+                    this.params.fixedCondition += ' and task_success = false '
+                } else if (tab.name === 'success') {
+                    this.params.fixedCondition += ' and task_success = true '
+                }
+                this.getList()
+            },
+            xzfj(row) {
+                window.open(row.file_path)
+
             }
         }
     }
 </script>
 
 <style type="text/scss" scoped>
+    .formwrap {
+        border: 1px solid #ebebeb;
+        border-radius: 3px;
+        background: #fff;
+        padding: 24px;
+        min-height: 500px;
+    }
     /deep/ div.toolbar {
         height: 70px;
         padding: 20px 0;
@@ -503,4 +626,30 @@
         justify-content: space-between;
         align-items: center;
     }
+    /deep/ .avatar-uploader .el-upload {
+        border: 1px dashed #d9d9d9;
+        border-radius: 6px;
+        cursor: pointer;
+        position: relative;
+        overflow: hidden;
+    }
+
+    /deep/ .avatar-uploader .el-upload:hover {
+        border-color: #409EFF;
+    }
+
+    /deep/ .avatar-uploader-icon {
+        font-size: 28px;
+        color: #8c939d;
+        width: 100px;
+        height: 100px;
+        line-height: 100px;
+        text-align: center;
+    }
+
+    /deep/ .avatar {
+        width: 100px;
+        height: 100px;
+        display: block;
+    }
 </style>