Explorar o código

添加质控环节比例

xiaochan %!s(int64=2) %!d(string=hai) anos
pai
achega
d549b8873b

+ 18 - 0
src/api/emr-control/emr-control.ts

@@ -1,4 +1,5 @@
 import request from "./request";
+import {Axios, AxiosPromise} from "axios";
 
 export function linkQualityControl(startDate, endDate, sid) {
     return request({
@@ -8,6 +9,15 @@ export function linkQualityControl(startDate, endDate, sid) {
     })
 }
 
+export function obtainTheProportionOfMedicalRecords(startDate, endDate, finalControl) {
+    return request({
+        url: '/emrQualityControl/obtainTheProportionOfMedicalRecords',
+        method: 'get',
+        params: {startDate, endDate, finalControl}
+    })
+}
+
+
 export function finalControl(data: any) {
     return request({
         url: '/emrQualityControl/finalControl',
@@ -15,3 +25,11 @@ export function finalControl(data: any) {
         data
     })
 }
+
+export function selectControlByPatNo(patNo: string, times: number) {
+    return request({
+        url: '/emrQualityControl/selectControlByPatNo',
+        method: 'get',
+        params: {patNo, times}
+    })
+}

+ 9 - 0
src/api/zhu-yuan-yi-sheng/emr-audit.js

@@ -42,3 +42,12 @@ export function updateFinalControl(patNo, times) {
         params: {patNo, times}
     })
 }
+
+export function updateControlLevel(patNo, times, bazl) {
+    return request({
+        url: url + '/updateControlLevel',
+        method: 'get',
+        params: {patNo, times, bazl}
+    })
+}
+

+ 52 - 9
src/components/xiao-chan/combo-grid/XcComboGridV2.vue

@@ -17,6 +17,10 @@ const props = defineProps({
     twoWayBinding: true,
     default: null
   },
+  filterable: {
+    type: Boolean,
+    default: false,
+  },
   code: String,
   name: String,
   clearable: {
@@ -49,12 +53,38 @@ const inputRef = ref()
 const isShow = ref()
 
 const computedData = computed(() => {
-  return props.data === null ? tempData.value : props.data
+  if (props.filterable) {
+    currentIndex.value = -1
+    return XEUtils.isEmpty(inputData.value) ? props.data : XEUtils.filter(props.data, (item) => {
+      return notNullAndLike(item, ['code', 'name'], inputData.value)
+    })
+  } else {
+    return props.data === null ? tempData.value : props.data;
+  }
 })
 
+const notNullAndLike = (data: any, keyName: Array<string>, likeValue: string) => {
+  for (let i = 0; i < keyName.length; i++) {
+    let itemKey = keyName[i];
+    let tempVal = data[itemKey]
+    if (tempVal) {
+      try {
+        if (tempVal.indexOf(likeValue) > -1) {
+          return true
+        }
+      } catch {
+        return false
+      }
+    }
+  }
+}
+
 const change = XEUtils.debounce(async (value) => {
   emits('input', value)
   if (XEUtils.isEmpty(value)) return
+  if (props.filterable) {
+    return
+  }
   if (props.queryDataFunc === null) return
   try {
     let res = await props.queryDataFunc(value)
@@ -119,9 +149,13 @@ const handleBlur = () => {
 }
 
 const keyUp = () => {
-  currentIndex.value -= 1
+  let len = computedData.value.length
+  if (len === 0) {
+    return
+  }
+  currentIndex.value -= 1;
   if (currentIndex.value <= -1) {
-    currentIndex.value = computedData.value.length - 1
+    currentIndex.value = len - 1
   }
   let tempData = computedData.value[currentIndex.value]
   vxeTableRef.value.setCurrentRow(computedData.value[currentIndex.value])
@@ -129,8 +163,12 @@ const keyUp = () => {
 }
 
 const keyDown = () => {
+  let len = computedData.value.length
+  if (len === 0) {
+    return
+  }
   currentIndex.value += 1
-  if (computedData.value.length === currentIndex.value) {
+  if (len === currentIndex.value) {
     currentIndex.value = 0
   }
   let tempData = computedData.value[currentIndex.value]
@@ -151,6 +189,8 @@ const enterToSelect = () => {
     }
   } else {
     pulldownRef.value.showPanel()
+    handleFocus()
+    vxeTableRef.value.scrollToRow(theRowIsCurrentlySelected.value.row)
   }
 }
 
@@ -164,8 +204,7 @@ const handleClear = () => {
   placeholder.value = ''
 }
 
-
-onMounted(() => {
+onMounted(async () => {
   if (isObj) {
     watch(() => props.modelValue[props.code], () => {
       inputData.value = props.modelValue[props.name]
@@ -175,6 +214,13 @@ onMounted(() => {
       inputData.value = <string>props.modelValue
     }, {immediate: true, deep: true})
   }
+
+  if (props.filterable && props.data === null) {
+    console.error('开启本地搜索,data属性不能为空。')
+  }
+  if (props.filterable && props.queryDataFunc !== null) {
+    console.warn('开启本地搜索后,远程搜索无效。')
+  }
 })
 
 </script>
@@ -225,7 +271,4 @@ onMounted(() => {
 </template>
 
 <style lang="scss">
-.popover_padding_zero {
-  padding: 0 !important;
-}
 </style>

+ 0 - 12
src/components/xiao-chan/dialog/XcDialogV2.vue

@@ -12,9 +12,6 @@
                :fullscreen="fullScreen">
       <template #header="{ close, titleId, titleClass }">
         <div class="xc-dialog-v2__header">
-          <!--          <div class="xc-dialog-v2__img">-->
-          <!--            <img :src="imgIcon()" :alt="title">-->
-          <!--          </div>-->
           <div class="xc-dialog-v2__title">
             {{ title }}
           </div>
@@ -48,8 +45,6 @@
 </template>
 
 <script setup name='XcDialogV2'>
-import {genTextPortrait} from '@/utils/portrait'
-
 const props = defineProps({
   modelValue: {
     type: Boolean,
@@ -95,13 +90,6 @@ const props = defineProps({
 
 const emit = defineEmits(['closed', 'update:modelValue', 'cancel', 'confirm'])
 
-
-const imgIcon = () => {
-  if (props.iconImg === null) {
-    return genTextPortrait(props.title)
-  }
-}
-
 let fullScreen = $ref(props.maximize)
 const clickFullScreen = () => {
   if (props.allowMaximization) {

+ 0 - 1
src/components/zhu-yuan-yi-sheng/yi-zhu-lu-ru/yz-edit/YzEditor.vue

@@ -356,7 +356,6 @@ const xuanZhongFeiYong = async (row, laiyuan = 1) => {
         yiZhuData.value.superiorDoctor = authorization.code
         yiZhuData.value.instruction = `由【${authorization.name}】医生授权。`
       }
-
       // 加载药品计量
       yaoPinJiLiangData.value = res.yaoPingJiLiang;
       if (newData) {

+ 69 - 8
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/components/EmrAudit.vue

@@ -9,7 +9,8 @@
     <el-button @click="finalControl">标记终末质控</el-button>
   </template>
   <template v-else-if="permissions()">
-    <el-button>病历评分</el-button>
+    <el-divider direction="vertical"/>
+    <el-button @click="ratingClick">病历评分</el-button>
   </template>
 
   <el-table :data="data"
@@ -76,7 +77,11 @@
     </el-table-column>
     <el-table-column prop="remark" label="备注">
       <template #default="{row}" v-if="permissions()">
-        <el-input v-model="row.remark" :maxlength="100"></el-input>
+        <el-input v-model="row.remark"
+                  :maxlength="100"
+                  :title="row.remark"
+                  type="textarea"
+                  :rows="2"/>
       </template>
     </el-table-column>
     <el-table-column prop="numberOfDefects" label="缺陷数">
@@ -90,11 +95,40 @@
     <el-table-column type="selection" v-if="permissions()"/>
   </el-table>
   <right-click-menu v-if="!permissions()" :config="opt" :mouse-position="mousePosition"/>
+
+  <xc-dialog-v2 title="系统自动评级" v-model="scoreDialog"
+                @confirm="confirmTheQuality"
+                show-button
+                @cancel="scoreDialog = false"
+                manual-shutdown
+  >
+    <span style="color: red">
+      注:此功能会直接修改病案首页中
+      病案质量、质控医师、质控日期
+    </span>
+    <br>
+    <br>
+    病案质控等级:
+    <el-select v-model="scoreLevel" style="width: 60px">
+      <xc-el-option :data="scoreList"/>
+    </el-select>
+
+    质控人: {{ userInfoStore.name }}
+
+
+  </xc-dialog-v2>
+
 </template>
 
 <script setup name='EmrAudit'>
 import {emrMitt} from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init";
-import {getAuditMessages, rectifyMedicalRecords, setAudit, updateFinalControl} from "@/api/zhu-yuan-yi-sheng/emr-audit";
+import {
+  getAuditMessages,
+  rectifyMedicalRecords,
+  setAudit,
+  updateControlLevel,
+  updateFinalControl
+} from "@/api/zhu-yuan-yi-sheng/emr-audit";
 import {needRule} from "@/utils/public";
 import {getWindowSize} from "@/utils/window-size";
 import RightClickMenu from "@/components/menu-item/RightClickMenu.vue";
@@ -107,6 +141,10 @@ import {BizException, ExceptionEnum} from "@/utils/BizException";
 import {uuid} from "@/utils/getUuid";
 import {scoringCriteriaList} from "@/data";
 import {ElMessageBox} from "element-plus";
+import {selectControlByPatNo} from "@/api/emr-control/emr-control";
+import XcElOption from "@/components/xiao-chan/xc-el-option/XcElOption.vue";
+import {userInfoStore} from "../../../../../../utils/store-public";
+import XcDialogV2 from "@/components/xiao-chan/dialog/XcDialogV2.vue";
 
 const elTableRef = ref(null)
 
@@ -203,7 +241,7 @@ const queryAudit = (val) => {
     elTableRef.value.clearSelection()
     await nextTick()
     let tempList = []
-    console.log(res)
+    console.log('质控数据', res)
     for (let i = 0, len = data.value.length; i < len; i++) {
       let item = data.value[i]
       item.rowId = i;
@@ -226,7 +264,7 @@ const queryAudit = (val) => {
 
 }
 
-const addAudit = () => {
+const addAudit = async () => {
   let editor = emrMitt.emit('editor')
   if (stringIsBlank(editor?.documentData._id)) {
     BizException(ExceptionEnum.MESSAGE_ERROR, "请先选择病历。");
@@ -242,27 +280,50 @@ const addAudit = () => {
   }
   data.value.push(tempData)
   elTableRef.value.toggleRowSelection(tempData);
+  await nextTick();
+  elTableRef.value.setScrollTop(elTableRef.value.$el.querySelector('.el-scrollbar__view').scrollHeight)
 }
 
-const finalControl = () => {
+const scoreDialog = ref(false)
+const scoreLevel = ref(1)
+const ratingClick = async () => {
+  let res = await selectControlByPatNo(patInfo.value.inpatientNo, patInfo.value.admissTimes)
+  scoreDialog.value = true
+  scoreLevel.value = res.patient[0].score
+}
 
+const finalControl = () => {
   ElMessageBox.confirm('是否标记此患者为终末质控。', '提示', {
     type: 'warning'
   }).then(() => {
-    updateFinalControl(emrInfo.value.patNo, emrInfo.value.times).then(res => {
+    updateFinalControl(patInfo.value.inpatientNo, patInfo.value.admissTimes).then(res => {
       emrMitt.emit('setPatInfo', 'finalControl', 1)
       queryAudit(emrInfo.value)
     })
   }).catch(() => {
-
   })
+}
 
+const confirmTheQuality = async () => {
+  await ElMessageBox.alert('是否改变病案质量,点击后病案首页会改变。', '提示', {
+    type: "warning"
+  })
+  updateControlLevel(patInfo.value.inpatientNo, patInfo.value.admissTimes, scoreLevel.value)
+  scoreDialog.value = false
 }
 
 onMounted(() => {
   patInfo.value = emrMitt.emit('getPatInfo')
   emrMitt.on('audit', queryAudit)
 })
+
+let scoreList = [
+  {code: 1, name: 'Ⅰ'},
+  {code: 2, name: 'Ⅱ'},
+  {code: 3, name: 'Ⅲ'},
+  {code: 4, name: 'Ⅳ'},
+  {code: 5, name: 'Ⅴ'},
+]
 </script>
 
 <style scoped lang="scss">

+ 13 - 41
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr_control_rule/EmrControlRule.vue

@@ -11,6 +11,10 @@
                  :loading="load"
                  @click="queryQualityControlData">查询质控数据
       </el-button>
+
+      <el-button @click="queryScale">
+        {{ proportion }} 比例
+      </el-button>
     </template>
 
     <template #main>
@@ -51,20 +55,17 @@ import PageLayer from "@/layout/PageLayer.vue";
 import {shortcuts} from "@/data/shortcuts";
 import RuleSift
   from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr_control_rule/RuleSift.vue";
-import {uuid} from "@/utils/getUuid";
 import {setCallback} from "@/utils/websocket";
-import {userInfoStore} from "@/utils/store-public";
-import {linkQualityControl} from "@/api/emr-control/emr-control";
+import {linkQualityControl, obtainTheProportionOfMedicalRecords} from "@/api/emr-control/emr-control";
 import {makePercentage} from "@/components/progress/progUtils";
 import {getWindowSize} from "@/utils/window-size";
 import {BizException, ExceptionEnum} from "@/utils/BizException";
 import XcTable from "@/components/xiao-chan/xc-table/XcTable.vue";
-import {openSocket} from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/emr-socket";
+import {openSocket, sid} from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/emr-socket";
 
 const intervalPatients = ref([])
 const load = ref(false)
 
-const sid = userInfoStore.value.code + '_' + uuid(8, 62);
 const percentage = ref(0)
 const numberToArray = ref([])
 const tabsModel = ref('质控数量')
@@ -82,6 +83,7 @@ const queryQualityControlData = async () => {
   siftData.value = {}
   let res = await linkQualityControl(startTime, endTime, sid)
   ruleReturnData.value = res
+  proportion.value = res.proportion
   numberToArrayFunc()
   load.value = false
 }
@@ -118,6 +120,12 @@ const detailClick = ({name, total}) => {
   tabsModel.value = name;
 }
 
+const proportion = ref('0%')
+const queryScale = async () => {
+  let {startTime, endTime} = getDateRangeFormatDate(intervalPatients.value)
+  proportion.value = await obtainTheProportionOfMedicalRecords(startTime, endTime, 0)
+}
+
 onMounted(() => {
   intervalPatients.value = shortcuts[2].value
   openSocket()
@@ -129,41 +137,5 @@ onMounted(() => {
 </script>
 
 <style lang="scss">
-.tree-select {
-  .el-select-dropdown__item.hover,
-  .el-select-dropdown__item:hover {
-    background-color: #f5f7fa !important;
-    color: black;
-  }
-}
 
-.select_div {
-  min-height: 20px;
-  width: 100%;
-  border: 1px solid;
-  border-radius: 4px;
-
-  table-layout: fixed;
-  word-break: break-all;
-  overflow: hidden;
-
-  .select_input {
-    margin-left: 3px;
-  }
-
-  span {
-    border-radius: 2px;
-    background-color: #f0f2f5;
-    padding: 0 5px;
-    margin: 4px;
-
-    i {
-      cursor: pointer;
-      font-size: 12px;
-      width: 14px;
-      height: 14px;
-      border-radius: 50%;
-    }
-  }
-}
 </style>

+ 14 - 3
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/final-quality-control/FinalQualityControl.vue

@@ -1,7 +1,7 @@
 <script setup>
 import {onMounted, ref} from "vue";
-import {currentAndAFewDaysAgo, dateRangeAddTime} from "@/utils/date";
-import {finalControl} from "@/api/emr-control/emr-control";
+import {currentAndAFewDaysAgo, dateRangeAddTime, getDateRangeFormatDate} from "@/utils/date";
+import {finalControl, obtainTheProportionOfMedicalRecords} from "@/api/emr-control/emr-control";
 import XcTable from "@/components/xiao-chan/xc-table/XcTable.vue";
 import {setCallback} from "@/utils/websocket";
 import {Export} from "@/utils/ExportExcel";
@@ -24,11 +24,19 @@ const queryClick = () => {
     socketId: sid
   }
   finalControl(temp).then((res) => {
-    let {patient} = res
+    let {patient, proportion: p} = res
     data.value = patient
+    console.log(p)
+    proportion.value = p
   })
 }
 
+const proportion = ref('0%')
+const queryScale = async () => {
+  let {startTime, endTime} = getDateRangeFormatDate(dateRange.value)
+  proportion.value = await obtainTheProportionOfMedicalRecords(startTime, endTime, 1)
+}
+
 const exportExcelClick = () => {
   let title = {
     inpatientNo: '住院号',
@@ -89,6 +97,9 @@ onMounted(async () => {
                       value-format="YYYY-MM-DD"/>
       <el-divider direction="vertical"/>
       <el-button @click="queryClick">查询</el-button>
+      <el-button @click="queryScale">
+        {{ proportion }} 比例
+      </el-button>
       <el-button @click="exportExcelClick">导出Excel</el-button>
     </el-header>
     <el-main>

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 486 - 484
src/views/hospitalization/zhu-yuan-yi-sheng/yi-zhu-lu-ru/TemplateMaintenance.vue


+ 10 - 3
src/views/settings/Test.vue

@@ -1,11 +1,12 @@
 <template>
-  {{ obj}}
+  {{ obj }}
   <xc-combo-grid-v2
       v-model="obj"
       clearable
+      filterable
       code="codesd"
       name="namead"
-      :query-data-func="queryOperation"/>
+      :data="data"/>
 </template>
 
 <script setup>
@@ -16,7 +17,7 @@ import {obtainSurgicalItems} from "@/api/zhu-yuan-yi-sheng/shou-shu-shen-qing";
 const model = ref('')
 
 const obj = ref({
-  codesd : '',
+  codesd: '',
   namead: ''
 })
 
@@ -25,6 +26,12 @@ const data = ref([])
 const queryOperation = (val) => {
   return obtainSurgicalItems(val, 0)
 }
+
+
+onMounted(async () => {
+  data.value = await obtainSurgicalItems('12', 0)
+  // console.log(data.value)
+})
 </script>
 
 <style lang="scss">

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio