Files
zgty-mas-m/pages/analysis/sample/sample-report.vue
2025-10-10 18:16:14 +08:00

409 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<navbar-back :autoBack="false" title="数据上报" @leftClick="customBack"></navbar-back>
<u-row class="content-title" gutter="16">
<u-col span="4">
<view class="content-title-name">
<text>任务列表</text>
</view>
<u-gap height="5" bg-color="#0055A2"></u-gap>
</u-col>
<u-col span="8">
<view class="content-title-name">
<text>样品列表</text>
</view>
<u-gap height="5" bg-color="#0055A2"></u-gap>
</u-col>
</u-row>
<u-row class="content-main-height" gutter="16" align="top">
<u-col span="4">
<scroll-view
scroll-y
scroll-with-animation
class="content-main-height content-main-left"
:scroll-top="scrollTop"
>
<view
v-for="(task, index) in taskList"
:key="index"
class="u-tab-item"
:class="current === index ? 'u-tab-item-active' : ''"
@tap.stop="swichTask(index)"
>
<u-row style="width: 100%">
<u-col span="2" style="text-align: center">
<u-icon :color="taskStyle(task)" name="tags-fill" size="34"></u-icon>
</u-col>
<u-col span="10">
<view>
<text style="font-size: 18px">{{ task.taskNo }}</text>
</view>
<view style="margin-top: 10px">
<text>{{ task.taskName }} {{ task.assayOper }}</text>
</view>
<view class="x-f" style="margin-top: 10px">
<u-icon color="" name="clock"></u-icon>
<text style="margin-left: 5px">{{ task.taskOperTime }}</text>
</view>
</u-col>
</u-row>
</view>
</scroll-view>
</u-col>
<u-col span="8">
<view class="content-main-height">
<scroll-view scroll-y scroll-with-animation class="content-main-right">
<block v-for="(sample, index) in sampleList" :key="index">
<view style="padding: 5px; font-size: 16px">
<u-row
@click="showSampleDetail(sample.id, index)"
:class="selectedIndex === index ? 'selected_Sample' : ''"
>
<u-col span="2" style="text-align: center" :style="sampleStyle(sample)">
<view>
<text>{{ sample.sort }}</text>
</view>
</u-col>
<u-col span="5">
<view>
<text style="padding-left: 10px">{{ sample.sampleCode }}</text>
</view>
<view>
<text style="padding-left: 10px"
>{{ getDataSourceTypeShow(sample.dataSourceType) }}{{ sample.sampleName }}</text
>
</view>
</u-col>
<u-col span="5">
<view class="sample_desc_warn" v-if="sample.sampleProcessNo !== currentNode">
当前节点{{ getProcessNameShow(sample.sampleProcessNo) }}
</view>
</u-col>
</u-row>
<u-line style="padding: 5px" color="#bbb" />
</view>
</block>
</scroll-view>
<view class="content-main-right-operation">
<u-row>
<u-col span="3"></u-col>
<u-col span="3">
<u-button class="btn-operation" type="primary" @click="previewPDF" v-if="currentTaskId">
任务单预览
</u-button>
</u-col>
<u-col span="3">
<u-button
class="btn-operation"
v-if="currentTaskId"
type="warning"
:disabled="taskReviewDisabled"
@click="taskReview"
>
撤回任务单
</u-button>
</u-col>
<u-col span="3">
<u-button class="btn-operation" :disabled="dataReportDisabled" type="success" @click="dataReport">
数据上报
</u-button>
</u-col>
</u-row>
</view>
</view>
</u-col>
</u-row>
<!-- 样品详情 -->
<sample-detail-popup
ref="sampleDetailPopup"
v-model:showPopup="showDetailPopup"
:detailPopupParam="detailPopupParam"
></sample-detail-popup>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { onLoad, onBackPress } from '@dcloudio/uni-app'
import SampleDetailPopup from '@/components/sample/sample-detail-popup.vue'
import nx from '@/nx'
// 响应式数据
const scrollTop = ref(0)
const current = ref(0)
const currentTask = ref({})
const currentTaskId = ref('')
const currentTaskNo = ref('')
const conAssayTask = ref('')
const reviewNum = ref(0)
const selectedIndex = ref(-1)
const taskList = ref([])
const sampleList = ref([])
const showDetailPopup = ref(false)
const detailPopupParam = ref({ taskDetailId: '' })
const currentNode = ref('F31')
const dicSampleProcessCodeList = ref([])
// 计算属性
const taskReviewDisabled = computed(() => currentTask.value.finishStatus !== 'finished')
const dataReportDisabled = computed(() => currentTask.value.finishStatus !== 'finished')
const userInfo = computed(() => nx.$store('user').userInfo)
// 方法
const customBack = () => {
uni.reLaunch({ url: '/pages/analysis/index/index' })
}
const taskStyle = task => {
if ((task.weightTaskStatus === 0 || task.weightTaskStatus === 1) && task.reviewCount > 0) return 'red'
if (task.weightTaskStatus === 2 && task.reviewCount > 0) return 'green'
return ''
}
const sampleStyle = sample => {
if ((sample.weightSubmitStatus === 0 || sample.weightSubmitStatus === 1) && sample.reviewCount > 0) {
return 'color: red'
}
if (sample.weightSubmitStatus === 2 && sample.reviewCount > 0) {
return 'color: green'
}
return ''
}
const swichTask = async index => {
if (index === current.value) return
current.value = index
const task = taskList.value[index]
currentTask.value = task
currentTaskNo.value = task.taskNo
currentTaskId.value = task.id
getAssayTaskDetail(task.taskNo)
}
const showSampleDetail = (detailId, index) => {
selectedIndex.value = index
detailPopupParam.value = { taskDetailId: detailId }
showDetailPopup.value = true
}
const getAssayTask = () => {
taskList.value = []
sampleList.value = []
const param = {
finishStatus: 'finished',
wfStatus: '0,revoke',
assayOper: userInfo.value.nickname
}
nx.$api.auncel
.getAssayTaskList(param)
.then(res => {
taskList.value = res
if (taskList.value.length > 0) {
current.value = 0
currentTask.value = taskList.value[0]
currentTaskNo.value = taskList.value[0].taskNo
currentTaskId.value = taskList.value[0].id
getAssayTaskDetail(currentTaskNo.value)
} else {
current.value = 0
currentTask.value = {}
currentTaskNo.value = ''
currentTaskId.value = ''
}
})
.catch(err => {
console.error(err)
})
}
const getAssayTaskDetail = taskNo => {
reviewNum.value = 0
$u.api
.getAssayTaskDetailListByTaskNo({ taskNo })
.then(res => {
sampleList.value = res.result || []
if (res.additionalProperties?.conAssayTask) {
conAssayTask.value = res.additionalProperties.conAssayTask
}
})
.catch(err => {
console.error(err)
})
}
const previewPDF = () => {
const url = `/pages/analysis/sample/pdf-preview?taskId=${currentTaskId.value}&reportKey=${conAssayTask.value.assayTaskTemplateKey}&hideResultFlag=true`
uni.navigateTo({ url })
}
const taskReview = () => {
const errNodeList = sampleList.value.filter(item => item.sampleProcessNo !== currentNode.value)
if (errNodeList.length > 0) {
uni.showToast({ title: '存在异常节点,联系管理员处理!', icon: 'none', duration: 3000 })
return
}
uni.showModal({
title: '提示',
content: '撤回当前任务指派单,是否继续?',
cancelColor: '#0055A2',
confirmColor: '#0055A2',
success: res => {
if (res.confirm) {
nx.$api.assayTask.rollbackAssayTask(currentTaskId.value).then(() => {
currentTaskId.value = ''
currentTask.value = {}
uni.showToast({ title: '撤回成功!' })
uni.navigateTo({ url: '/pages/analysis/sample/sample-work-list' })
})
}
}
})
}
const dataReport = () => {
const errNodeList = sampleList.value.filter(item => item.sampleProcessNo !== currentNode.value)
if (errNodeList.length > 0) {
uni.showToast({ title: '存在异常节点,联系管理员处理!', icon: 'none', duration: 3000 })
return
}
uni.showModal({
title: '提示',
content: '确定上报数据?',
cancelColor: '#0055A2',
confirmColor: '#0055A2',
success: res => {
if (res.confirm) {
nx.$api.assayTask.reportAssayTask(currentTaskId.value).then(res => {
currentTaskId.value = ''
currentTask.value = {}
if (res.additionalProperties?.conAssayTask?.isPrint === 1) {
printTask()
}
getAssayTask()
})
}
}
})
}
const getDicSampleProcessCodeList = () => {
nx.$api.assayTask.queryQmsDicSampleProcessCodeList().then(res => {
dicSampleProcessCodeList.value = res.records
})
}
const getProcessNameShow = val => {
const item = dicSampleProcessCodeList.value.find(i => i.processCode === val)
return item ? item.processName : val
}
const getDataSourceTypeShow = val => {
if (val === 2) return '【筛上】'
if (val === 3) return '【筛下】'
return ''
}
const printTask = () => {
uni.showModal({
title: '提示',
content: '数据上报成功!是否打印“原始记录单”?',
cancelColor: '#0055A2',
confirmColor: '#0055A2',
success: res => {
if (res.confirm) {
nx.$print.getPrintTemplateAndPrint(currentTask.value)
}
}
})
}
// 生命周期
onMounted(() => {
getDicSampleProcessCodeList()
getAssayTask()
})
onBackPress(() => {
customBack()
return true
})
</script>
<style lang="scss" scoped>
/* 样式保持不变 */
.content-title {
height: 50px;
width: 100%;
font-size: 20px;
font-weight: 300;
}
.content-title-name {
padding: 10px;
text-align: center;
}
.content-main-height {
height: calc(100vh - 125px);
}
.content-main-left {
background-color: #f6f6f6;
}
.u-tab-item {
padding: 5px;
height: 100px;
background: #f6f6f6;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: #444;
line-height: 1;
border-width: 2px;
border-bottom: dotted;
}
.u-tab-item-active {
position: relative;
color: #0055a2;
font-weight: 600;
background: #fff;
}
.u-tab-item-active::before {
content: '';
position: absolute;
height: 16px;
left: 0;
top: 20px;
}
.content-main-right {
height: calc(100vh - 205px);
}
.content-main-right-operation {
height: 80px;
padding-top: 15px;
padding-right: 15px;
}
.btn-operation {
width: 95%;
}
.selected_Sample {
background-color: #d7e9fa;
}
.sample_desc_warn {
color: red;
padding-right: 10px;
}
</style>