|
@@ -45,7 +45,8 @@
|
|
|
<van-tabs v-model:active="active" @change="tabChange">
|
|
<van-tabs v-model:active="active" @change="tabChange">
|
|
|
<van-tab title="仪器信息" name="info"></van-tab>
|
|
<van-tab title="仪器信息" name="info"></van-tab>
|
|
|
<van-tab title="待审核" name="approval"></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>
|
|
</van-tabs>
|
|
|
<div v-if="active === 'info'" class="content">
|
|
<div v-if="active === 'info'" class="content">
|
|
|
<div class="card">
|
|
<div class="card">
|
|
@@ -112,76 +113,165 @@
|
|
|
<van-cell v-for="item in state.list" :key="item.id">
|
|
<van-cell v-for="item in state.list" :key="item.id">
|
|
|
<template #default>
|
|
<template #default>
|
|
|
<div class="list">
|
|
<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>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
</van-cell>
|
|
</van-cell>
|
|
|
</van-list>
|
|
</van-list>
|
|
|
<van-back-top target=".instr-detail" bottom="10vh" />
|
|
<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>
|
|
</div>
|
|
|
<van-action-bar placeholder>
|
|
<van-action-bar placeholder>
|
|
|
<van-action-bar-icon icon="wap-home-o" text="首页" @click="onRouterPush('/home')" />
|
|
<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 download from 'downloadjs'
|
|
|
import { useNoticeApi } from '/@/api/instr/notice'
|
|
import { useNoticeApi } from '/@/api/instr/notice'
|
|
|
import { useUseAppointApi } from '/@/api/instr/useAppoint'
|
|
import { useUseAppointApi } from '/@/api/instr/useAppoint'
|
|
|
|
|
+import { useSampleApi } from '/@/api/instr/sample'
|
|
|
import { useBlackApi } from '/@/api/blacklist'
|
|
import { useBlackApi } from '/@/api/blacklist'
|
|
|
import AddAuthDialog from './addAuthorization/index.vue'
|
|
import AddAuthDialog from './addAuthorization/index.vue'
|
|
|
import { useUserInfos } from '/@/hooks/useUserInfos'
|
|
import { useUserInfos } from '/@/hooks/useUserInfos'
|
|
@@ -238,6 +329,7 @@ const instApi = useInstrApi()
|
|
|
const instDocApi = useInstDocApi()
|
|
const instDocApi = useInstDocApi()
|
|
|
const noticeApi = useNoticeApi()
|
|
const noticeApi = useNoticeApi()
|
|
|
const useAppointApi = useUseAppointApi()
|
|
const useAppointApi = useUseAppointApi()
|
|
|
|
|
+const sampleApi = useSampleApi()
|
|
|
const blacklistApi = useBlackApi()
|
|
const blacklistApi = useBlackApi()
|
|
|
const trainingApi = useTrainingApi()
|
|
const trainingApi = useTrainingApi()
|
|
|
const active = ref('info')
|
|
const active = ref('info')
|
|
@@ -268,9 +360,31 @@ const noticeInfo = ref({ noticeTitle: '', noticeContent: '' })
|
|
|
const isNeedGrant = ref(false)
|
|
const isNeedGrant = ref(false)
|
|
|
|
|
|
|
|
const addAuthDialogRef = ref()
|
|
const addAuthDialogRef = ref()
|
|
|
|
|
+const activeNames = ref([])
|
|
|
|
|
+const itemsDialogShow = ref(false)
|
|
|
|
|
+const currentSampleItems = ref<any[]>([])
|
|
|
|
|
+const dialogTitle = ref('检测信息')
|
|
|
|
|
|
|
|
const { userInfos } = useUserInfos()
|
|
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 getNeedGrant = async (instId: number) => {
|
|
|
const [err, res]: ToResponse = await to(useAppointApi.getNeedGrant({ instId }))
|
|
const [err, res]: ToResponse = await to(useAppointApi.getNeedGrant({ instId }))
|
|
|
if (err) return
|
|
if (err) return
|
|
@@ -338,7 +452,7 @@ const setLaboratoryName = (name) => {
|
|
|
return name ? `(${name})` : ''
|
|
return name ? `(${name})` : ''
|
|
|
}
|
|
}
|
|
|
const tabChange = (name: string) => {
|
|
const tabChange = (name: string) => {
|
|
|
- if (name === 'history' || name === 'approval') {
|
|
|
|
|
|
|
+ if (name === 'history' || name === 'approval' || name === 'sample') {
|
|
|
state.finished = false
|
|
state.finished = false
|
|
|
state.list = []
|
|
state.list = []
|
|
|
state.queryParams = {
|
|
state.queryParams = {
|
|
@@ -352,7 +466,13 @@ const tabChange = (name: string) => {
|
|
|
}
|
|
}
|
|
|
const onLoad = async () => {
|
|
const onLoad = async () => {
|
|
|
state.loading = true
|
|
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
|
|
if (err) return
|
|
|
const list = res?.data?.list || []
|
|
const list = res?.data?.list || []
|
|
|
for (const item of list) {
|
|
for (const item of list) {
|
|
@@ -389,6 +509,55 @@ const getAppointTime = (row: any) => {
|
|
|
const minutes = Math.floor(remainingMillisecondsAfterHours / (1000 * 60))
|
|
const minutes = Math.floor(remainingMillisecondsAfterHours / (1000 * 60))
|
|
|
return `${days}天${hours}小时${minutes}分`
|
|
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 handleFollowInst = async () => {
|
|
|
const [err] = state.instDetail.following
|
|
const [err] = state.instDetail.following
|