| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- <template>
- <div class="panel-wrap">
- <van-empty v-if="state.appointList.length === 0 && state.finished" description="暂无预约记录" />
- <van-list v-else v-model:loading="state.loading" :finished="state.finished" finished-text="没有更多了" @load="onLoad"
- class="data-list">
- <div class="inst-item mb20" v-for="(v, index) in state.appointList" :key="index">
- <div class="flex flex-between mb20">
- <div>
- <div class="mr10">
- <span class="fontSize14 primary-color bold">{{ v.instName }}</span>
- </div>
- </div>
- <!-- Status Tag moved here -->
- </div>
- <div class="flex mb20">
- <div class="equ-tit">
- <span class="fontSize14 bold">送样时间:</span>
- </div>
- <div>
- <span class="fontSize14">{{ formatDate(new Date(v.deliverTime), 'YYYY-mm-dd HH:MM') }}</span>
- </div>
- </div>
- <div class="flex mb20">
- <div class="equ-tit">
- <span class="fontSize14 bold">检测时间:</span>
- </div>
- <div>
- <span class="fontSize14">{{ formatDate(new Date(v.testTime), 'YYYY-mm-dd HH:MM') }}</span>
- </div>
- </div>
- <div class="flex mb20">
- <div class="equ-tit">
- <span class="fontSize14 bold">样品数:</span>
- </div>
- <div>
- <span class="fontSize14">{{ v.sampleNum }}</span>
- </div>
- </div>
- <div class="flex mb20">
- <div class="equ-tit">
- <span class="fontSize14 bold">申请人:</span>
- </div>
- <div>
- <span class="fontSize14">{{ v.userName }}</span>
- </div>
- </div>
- <div class="flex mb20">
- <div class="equ-tit">
- <span class="fontSize14 bold">状态:</span>
- </div>
- <van-tag :type="getStatusType(v.deliverStatus)">{{ setStatus(v.deliverStatus) }}</van-tag>
- </div>
- <!-- Detection Info Clickable -->
- <div class="flex mb20" v-if="v.sampleItem !== '[]' || v.testSampleItem">
- <div class="equ-tit">
- <span class="fontSize14 bold">检测信息:</span>
- </div>
- <div>
- <span v-if="v.sampleItem" class="fontSize14 primary-color pointer mr10"
- @click="showSampleItem(v.sampleItem, '预约信息')">预约检测项目</span>
- <span v-if="v.testSampleItem" class="fontSize14 primary-color pointer"
- @click="showSampleItem(v.testSampleItem, '实测信息')">实测检测项目</span>
- </div>
- </div>
- <div class="flex mb20" v-if="v.testResultName">
- <div class="equ-tit">
- <span class="fontSize14 bold">检测结果:</span>
- </div>
- <div style="flex: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
- <span class="fontSize14 primary-color pointer">
- <a :href="v.testResult" target="_blank" class="file-link">
- {{ v.testResultName }}
- </a>
- </span>
- </div>
- </div>
- <div v-if="v.order">
- <van-collapse v-model="activeNames">
- <van-collapse-item title="收费明细" :name="v.id">
- <div class="flex mb10">
- <div class="equ-tit">
- <span class="fontSize14 bold">计费编号:</span>
- </div>
- <div>
- <span class="fontSize14">{{ v.order.fboCode }}</span>
- </div>
- </div>
- <div class="flex mb10">
- <div class="equ-tit">
- <span class="fontSize14 bold">收费:</span>
- </div>
- <div>
- <span class="fontSize14 price">¥{{ v.order.fboActualAmount }}</span>
- </div>
- </div>
- <div class="flex mb10">
- <div class="equ-tit">
- <span class="fontSize14 bold">预估费用:</span>
- </div>
- <div>
- <span class="fontSize14 price">¥{{ v.order.fboExpectedAmount }}</span>
- </div>
- </div>
- </van-collapse-item>
- </van-collapse>
- </div>
- <!-- Cancel Button moved to bottom -->
- <div class="flex mt20" style="justify-content: flex-end;"
- v-if="v.deliverStatus == '10'">
- <van-button class="scan-txt" plain type="danger" size="small" @click.stop="handleCancelAppoint(v)">
- 取消预约
- </van-button>
- </div>
- </div>
- </van-list>
- <!-- Dialog for Sample Items -->
- <van-dialog v-model:show="itemsDialogShow" :title="dialogTitle">
- <div class="dialog-content">
- <div class="flex mb10 flex-col" 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>
- </template>
- <script lang="ts" setup>
- import { reactive, ref, onMounted } from 'vue'
- import { useSampleApi } from '/@/api/instr/sample'
- import to from 'await-to-js'
- import { formatDate } from '/@/utils/formatTime'
- import { showDialog, showNotify } from 'vant'
- const props = defineProps({
- instId: {
- type: Number,
- default: 0
- }
- })
- const sampleApi = useSampleApi()
- const activeNames = ref([])
- const state = reactive({
- loading: false,
- finished: false,
- appointList: [] as any[],
- queryForm: {
- pageNum: 1,
- pageSize: 10,
- instId: props.instId
- },
- total: 0,
- })
- const toParse = (str: string) => {
- try {
- return JSON.parse(str) || []
- } catch (e) {
- return []
- }
- }
- const testItemInfo = (test: any) => {
- return `检测项:${test.name},数量:${test.count}`
- }
- const itemsDialogShow = ref(false)
- const currentSampleItems = ref<any[]>([])
- const dialogTitle = ref('检测信息')
- const showSampleItem = (itemsStr: string, title: string = '检测信息') => {
- currentSampleItems.value = toParse(itemsStr)
- dialogTitle.value = title
- itemsDialogShow.value = true
- }
- const getStatusType = (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 setStatus = (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 handleCancelAppoint = (row: any) => {
- showDialog({
- title: '提示',
- message: '确认取消预约?',
- showCancelButton: true,
- })
- .then(async () => {
- const params = { id: row.id }
- const [err, res]: any = await to(sampleApi.userCancelAppoint(params))
- if (err) return
- if (res?.code === 200) {
- showNotify({ type: 'success', message: '取消成功' })
- state.queryForm.pageNum = 1
- state.appointList = []
- state.finished = false
- onLoad()
- }
- })
- .catch(() => {
- // on cancel
- })
- }
- const onLoad = async () => {
- state.loading = true
- state.queryForm.instId = props.instId
- const [err, res]: any = await to(sampleApi.getList(state.queryForm))
- state.loading = false
- if (err) {
- state.finished = true
- return
- }
- if (res?.code === 200) {
- const list = res?.data?.list || []
- if (state.queryForm.pageNum === 1) {
- state.appointList = list
- } else {
- state.appointList = [...state.appointList, ...list]
- }
- state.total = res?.data?.total || 0
- state.queryForm.pageNum++
- if (state.appointList.length >= state.total) {
- state.finished = true
- }
- } else {
- state.finished = true
- }
- }
- onMounted(() => {
- // onLoad will be triggered by van-list automatically initially
- })
- // Expose onLoad for parent component to call
- defineExpose({
- onLoad: () => {
- state.queryForm.pageNum = 1
- state.finished = false
- // Need to reset list? The onLoad usually appends...
- // If called from parent for refresh, we should probably reset.
- // Let's modify logic slightly or just set pageNum to 1 and empty list
- state.appointList = []
- onLoad()
- }
- })
- </script>
- <style lang="scss" scoped>
- * {
- box-sizing: border-box;
- }
- .panel-wrap {
- height: 100%;
- .data-list {
- .inst-item {
- border-radius: 10px;
- padding: 15px;
- box-shadow: -2px 0px 9px rgba(0, 0, 0, 0.12);
- margin-bottom: 20px;
- background-color: #fff;
- .equ-tit {
- width: 80px;
- min-width: 80px;
- }
- }
- }
- }
- .fontSize14 {
- font-size: 14px;
- }
- .bold {
- font-weight: bold;
- }
- .primary-color {
- color: #1989fa;
- }
- .price {
- color: #ee0a24;
- }
- .flex {
- display: flex;
- }
- .flex-between {
- justify-content: space-between;
- }
- .mb20 {
- margin-bottom: 20px;
- }
- .mb10 {
- margin-bottom: 10px;
- }
- .mr10 {
- margin-right: 10px;
- }
- .mt20 {
- margin-top: 20px;
- }
- .flex-col {
- flex-direction: column;
- }
- .pointer {
- cursor: pointer;
- }
- </style>
|