Răsfoiți Sursa

fix:增加送样预约

LYK 2 zile în urmă
părinte
comite
5f65666ae7
2 a modificat fișierele cu 251 adăugiri și 68 ștergeri
  1. 14 0
      components.d.ts
  2. 237 68
      src/view/instr/detail.vue

+ 14 - 0
components.d.ts

@@ -13,12 +13,22 @@ declare module 'vue' {
     RouterView: typeof import('vue-router')['RouterView']
     SelectInst: typeof import('./src/components/select-inst.vue')['default']
     SelectInstAppointRecord: typeof import('./src/components/select-inst-appoint-record.vue')['default']
+    VanActionBar: typeof import('vant/es')['ActionBar']
+    VanActionBarButton: typeof import('vant/es')['ActionBarButton']
+    VanActionBarIcon: typeof import('vant/es')['ActionBarIcon']
+    VanBackTop: typeof import('vant/es')['BackTop']
     VanButton: typeof import('vant/es')['Button']
     VanCalendar: typeof import('vant/es')['Calendar']
     VanCell: typeof import('vant/es')['Cell']
     VanCellGroup: typeof import('vant/es')['CellGroup']
     VanCheckbox: typeof import('vant/es')['Checkbox']
+    VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
+    VanCol: typeof import('vant/es')['Col']
+    VanCollapse: typeof import('vant/es')['Collapse']
+    VanCollapseItem: typeof import('vant/es')['CollapseItem']
+    VanDatePicker: typeof import('vant/es')['DatePicker']
     VanDialog: typeof import('vant/es')['Dialog']
+    VanEmpty: typeof import('vant/es')['Empty']
     VanField: typeof import('vant/es')['Field']
     VanFloatingBubble: typeof import('vant/es')['FloatingBubble']
     VanForm: typeof import('vant/es')['Form']
@@ -27,9 +37,12 @@ declare module 'vue' {
     VanList: typeof import('vant/es')['List']
     VanNotify: typeof import('vant/es')['Notify']
     VanPicker: typeof import('vant/es')['Picker']
+    VanPickerGroup: typeof import('vant/es')['PickerGroup']
     VanPopup: typeof import('vant/es')['Popup']
     VanRadio: typeof import('vant/es')['Radio']
     VanRadioGroup: typeof import('vant/es')['RadioGroup']
+    VanRow: typeof import('vant/es')['Row']
+    VanSearch: typeof import('vant/es')['Search']
     VanStep: typeof import('vant/es')['Step']
     VanStepper: typeof import('vant/es')['Stepper']
     VanSteps: typeof import('vant/es')['Steps']
@@ -41,6 +54,7 @@ declare module 'vue' {
     VanTabs: typeof import('vant/es')['Tabs']
     VanTag: typeof import('vant/es')['Tag']
     VanTextEllipsis: typeof import('vant/es')['TextEllipsis']
+    VanTimePicker: typeof import('vant/es')['TimePicker']
     VanUploader: typeof import('vant/es')['Uploader']
   }
 }

+ 237 - 68
src/view/instr/detail.vue

@@ -45,7 +45,8 @@
     <van-tabs v-model:active="active" @change="tabChange">
       <van-tab title="仪器信息" name="info"></van-tab>
       <van-tab title="待审核" name="approval"></van-tab>
-      <van-tab title="历史申请" name="history"></van-tab>
+      <van-tab title="预约申请" name="history"></van-tab>
+      <van-tab title="送样申请" name="sample"></van-tab>
     </van-tabs>
     <div v-if="active === 'info'" class="content">
       <div class="card">
@@ -112,76 +113,165 @@
       <van-cell v-for="item in state.list" :key="item.id">
         <template #default>
           <div class="list">
-            <header class="flex justify-between">
-              <strong class="title">{{ item.userName }}的预约</strong>
-              <van-tag v-if="item.appointStatus == '10'" type="default">
-                待审核
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '11'" type="warning">
-                已退回
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '20'" type="success">
-                已通过
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '30'" type="danger">
-                已驳回
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '40'" type="warning">
-                已取消
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '50'" type="default">
-                已上机
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '60'" type="primary">
-                已完成
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '70'" type="warning">
-                审核超时
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '80'" type="danger">
-                超时取消
-              </van-tag>
-              <van-tag v-else-if="item.appointStatus == '90'" type="danger">
-                超时未上机
-              </van-tag>
-            </header>
-            <p class="inst-title">
-              <span>预约仪器</span>
-              <span class="title ml8">{{ item.instName }}({{ item.instCode }})</span>
-            </p>
-            <p class="inst-title">
-              <span>预约时间</span>
-              <span class="title ml8">
-                {{ formatDate(new Date(item.startTime), 'YYYY-mm-dd HH:MM') }}~{{
-                  formatDate(new Date(item.endTime), 'YYYY-mm-dd HH:MM')
-                }}
-              </span>
-            </p>
-            <p class="inst-title">
-              <span>预约时长</span>
-              <span class="title ml8">{{ getAppointTime(item) }}</span>
-            </p>
-            <p class="inst-title">
-              <span>违约情况</span>
-              <span class="title ml8">{{ getBreachTypes(item) }}</span>
-            </p>
-            <p class="inst-title">
-              <span>扣分明细</span>
-              <span class="title ml8">{{ item.breachScore }}分</span>
-            </p>
-            <p class="inst-title">
-              <span>备注</span>
-              <span class="title ml8">{{ item.remark }}</span>
-            </p>
-            <footer class="flex justify-between mt4">
-              <span class="title">{{ item.userName }}</span>
-              <span class="time">{{ formatDate(new Date(item.createdTime), 'mm-dd HH:MM') }}</span>
-            </footer>
+            <template v-if="active === 'sample'">
+              <header class="flex justify-between">
+                <strong class="title">{{ item.userName }}的送样</strong>
+                <van-tag :type="getSampleStatusType(item.deliverStatus)">
+                  {{ getSampleStatusText(item.deliverStatus) }}
+                </van-tag>
+              </header>
+              <p class="inst-title">
+                <span>送样时间</span>
+                <span class="title ml8">{{ formatDate(new Date(item.deliverTime), 'YYYY-mm-dd HH:MM') }}</span>
+              </p>
+              <p class="inst-title">
+                <span>检测时间</span>
+                <span class="title ml8">{{ formatDate(new Date(item.testTime), 'YYYY-mm-dd HH:MM') }}</span>
+              </p>
+              <p class="inst-title">
+                <span>样品数</span>
+                <span class="title ml8">{{ item.sampleNum }}</span>
+              </p>
+              
+              <!-- 检测信息 -->
+              <div class="inst-title" v-if="item.sampleItem !== '[]' || item.testSampleItem">
+                <span>检测信息</span>
+                <div class="ml8" style="display: inline-block;">
+                  <span v-if="item.sampleItem" class="primary-color pointer mr10"
+                    @click.stop="showSampleItem(item.sampleItem, '预约信息')">预约检测项目</span>
+                  <span v-if="item.testSampleItem" class="primary-color pointer"
+                    @click.stop="showSampleItem(item.testSampleItem, '实测信息')">实测检测项目</span>
+                </div>
+              </div>
+
+              <!-- 检测结果 -->
+              <div class="inst-title" v-if="item.testResultName">
+                <span>检测结果</span>
+                <span class="title ml8">
+                  <a :href="item.testResult" target="_blank" class="file-link" @click.stop>
+                    {{ item.testResultName }}
+                  </a>
+                </span>
+              </div>
+
+              <!-- 收费明细 -->
+              <div v-if="item.order" class="mt8" @click.stop>
+                <van-collapse v-model="activeNames">
+                  <van-collapse-item title="收费明细" :name="item.id">
+                    <div class="flex mb10">
+                      <div class="equ-tit">
+                        <span class="fontSize14 bold">计费编号:</span>
+                      </div>
+                      <div>
+                        <span class="fontSize14">{{ item.order.fboCode }}</span>
+                      </div>
+                    </div>
+                    <div class="flex mb10">
+                      <div class="equ-tit">
+                        <span class="fontSize14 bold">收费:</span>
+                      </div>
+                      <div>
+                        <span class="fontSize14 price">¥{{ item.order.fboActualAmount }}</span>
+                      </div>
+                    </div>
+                    <div class="flex mb10">
+                      <div class="equ-tit">
+                        <span class="fontSize14 bold">预估费用:</span>
+                      </div>
+                      <div>
+                        <span class="fontSize14 price">¥{{ item.order.fboExpectedAmount }}</span>
+                      </div>
+                    </div>
+                  </van-collapse-item>
+                </van-collapse>
+              </div>
+
+              <footer class="flex justify-between mt4">
+                <span class="title">{{ item.userName }}</span>
+              </footer>
+            </template>
+            <template v-else>
+              <header class="flex justify-between">
+                <strong class="title">{{ item.userName }}的预约</strong>
+                <van-tag v-if="item.appointStatus == '10'" type="default">
+                  待审核
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '11'" type="warning">
+                  已退回
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '20'" type="success">
+                  已通过
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '30'" type="danger">
+                  已驳回
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '40'" type="warning">
+                  已取消
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '50'" type="default">
+                  已上机
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '60'" type="primary">
+                  已完成
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '70'" type="warning">
+                  审核超时
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '80'" type="danger">
+                  超时取消
+                </van-tag>
+                <van-tag v-else-if="item.appointStatus == '90'" type="danger">
+                  超时未上机
+                </van-tag>
+              </header>
+              <p class="inst-title">
+                <span>预约仪器</span>
+                <span class="title ml8">{{ item.instName }}({{ item.instCode }})</span>
+              </p>
+              <p class="inst-title">
+                <span>预约时间</span>
+                <span class="title ml8">
+                  {{ formatDate(new Date(item.startTime), 'YYYY-mm-dd HH:MM') }}~{{
+                    formatDate(new Date(item.endTime), 'YYYY-mm-dd HH:MM')
+                  }}
+                </span>
+              </p>
+              <p class="inst-title">
+                <span>预约时长</span>
+                <span class="title ml8">{{ getAppointTime(item) }}</span>
+              </p>
+              <p class="inst-title">
+                <span>违约情况</span>
+                <span class="title ml8">{{ getBreachTypes(item) }}</span>
+              </p>
+              <p class="inst-title">
+                <span>扣分明细</span>
+                <span class="title ml8">{{ item.breachScore }}分</span>
+              </p>
+              <p class="inst-title">
+                <span>备注</span>
+                <span class="title ml8">{{ item.remark }}</span>
+              </p>
+              <footer class="flex justify-between mt4">
+                <span class="title">{{ item.userName }}</span>
+                <span class="time">{{ formatDate(new Date(item.createdTime), 'mm-dd HH:MM') }}</span>
+              </footer>
+            </template>
           </div>
         </template>
       </van-cell>
     </van-list>
     <van-back-top target=".instr-detail" bottom="10vh" />
+    <!-- Dialog for Sample Items -->
+    <van-dialog v-model:show="itemsDialogShow" :title="dialogTitle">
+      <div class="dialog-content">
+        <div class="flex mb10 flex-column" style="padding: 10px;">
+          <div class="flex mb4" v-for="(test, idx) in currentSampleItems" :key="idx">
+            <span class="fontSize14">{{ testItemInfo(test) }}</span>
+          </div>
+        </div>
+      </div>
+    </van-dialog>
   </div>
   <van-action-bar placeholder>
     <van-action-bar-icon icon="wap-home-o" text="首页" @click="onRouterPush('/home')" />
@@ -226,6 +316,7 @@ import { showNotify } from 'vant'
 import download from 'downloadjs'
 import { useNoticeApi } from '/@/api/instr/notice'
 import { useUseAppointApi } from '/@/api/instr/useAppoint'
+import { useSampleApi } from '/@/api/instr/sample'
 import { useBlackApi } from '/@/api/blacklist'
 import AddAuthDialog from './addAuthorization/index.vue'
 import { useUserInfos } from '/@/hooks/useUserInfos'
@@ -238,6 +329,7 @@ const instApi = useInstrApi()
 const instDocApi = useInstDocApi()
 const noticeApi = useNoticeApi()
 const useAppointApi = useUseAppointApi()
+const sampleApi = useSampleApi()
 const blacklistApi = useBlackApi()
 const trainingApi = useTrainingApi()
 const active = ref('info')
@@ -268,9 +360,31 @@ const noticeInfo = ref({ noticeTitle: '', noticeContent: '' })
 const isNeedGrant = ref(false)
 
 const addAuthDialogRef = ref()
+const activeNames = ref([])
+const itemsDialogShow = ref(false)
+const currentSampleItems = ref<any[]>([])
+const dialogTitle = ref('检测信息')
 
 const { userInfos } = useUserInfos()
 
+const toParse = (str: string) => {
+  try {
+    return JSON.parse(str) || []
+  } catch (e) {
+    return []
+  }
+}
+
+const testItemInfo = (test: any) => {
+  return `检测项:${test.name},数量:${test.count}`
+}
+
+const showSampleItem = (itemsStr: string, title: string = '检测信息') => {
+  currentSampleItems.value = toParse(itemsStr)
+  dialogTitle.value = title
+  itemsDialogShow.value = true
+}
+
 const getNeedGrant = async (instId: number) => {
   const [err, res]: ToResponse = await to(useAppointApi.getNeedGrant({ instId }))
   if (err) return
@@ -338,7 +452,7 @@ const setLaboratoryName = (name) => {
   return name ? `(${name})` : ''
 }
 const tabChange = (name: string) => {
-  if (name === 'history' || name === 'approval') {
+  if (name === 'history' || name === 'approval' || name === 'sample') {
     state.finished = false
     state.list = []
     state.queryParams = {
@@ -352,7 +466,13 @@ const tabChange = (name: string) => {
 }
 const onLoad = async () => {
   state.loading = true
-  const [err, res]: ToResponse = await to(useAppointApi.getListByPermission(state.queryParams))
+  let err, res
+  if (active.value === 'sample') {
+    [err, res] = await to(sampleApi.getList(state.queryParams))
+  } else {
+    [err, res] = await to(useAppointApi.getListByPermission(state.queryParams))
+  }
+  
   if (err) return
   const list = res?.data?.list || []
   for (const item of list) {
@@ -389,6 +509,55 @@ const getAppointTime = (row: any) => {
   const minutes = Math.floor(remainingMillisecondsAfterHours / (1000 * 60))
   return `${days}天${hours}小时${minutes}分`
 }
+
+const getSampleStatusType = (key: string) => {
+  let type = 'default'
+  switch (key) {
+    case '10': // 待审核
+      type = 'warning'
+      break
+    case '20': // 已通过
+      type = 'success'
+      break
+    case '30': // 已驳回
+      type = 'danger'
+      break
+    case '50': // 已检测
+      type = 'primary'
+      break
+    case '40': // 已取消
+    case '11': // 已退回
+      type = 'default'
+      break
+  }
+  return type as 'primary' | 'success' | 'warning' | 'danger' | 'default'
+}
+
+const getSampleStatusText = (key: string) => {
+  let str = ''
+  switch (key) {
+    case '10':
+      str = '待审核'
+      break
+    case '11':
+      str = '已退回'
+      break
+    case '20':
+      str = '已通过'
+      break
+    case '30':
+      str = '已驳回'
+      break
+    case '40':
+      str = '已取消'
+      break
+    case '50':
+      str = '已检测'
+      break
+  }
+  return str
+}
+
 // 关注/取关
 const handleFollowInst = async () => {
   const [err] = state.instDetail.following