340 lines
8.7 KiB
Vue
340 lines
8.7 KiB
Vue
<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="switchTask(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 class="fs18">{{ task.taskNo }}</view>
|
||
<view style="margin-top: 10px">{{ task.taskName }}</view>
|
||
<view class="x-f" style="margin-top: 10px">
|
||
<u-icon 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>
|
||
<u-col span="3" style="text-align: center">
|
||
<u-row>
|
||
<u-col span="6" style="text-align: center">
|
||
<u-checkbox
|
||
v-model="sample.checked"
|
||
v-if="sample.sampleProcessNo === currentNode"
|
||
@change="selectSample(sample)"
|
||
></u-checkbox>
|
||
</u-col>
|
||
<u-col span="6" style="text-align: center">
|
||
<text>【{{ sample.sort }}】</text>
|
||
</u-col>
|
||
</u-row>
|
||
</u-col>
|
||
<u-col span="9" class="sample_desc">
|
||
<view>
|
||
<view
|
||
><text style="padding-left: 10px">{{ sample.sampleCode }}</text></view
|
||
>
|
||
<view>
|
||
<text style="padding-left: 10px">
|
||
{{ getDataSourceTypeShow(sample.dataSourceType) }}{{ sample.sampleName }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
<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="8"></u-col>
|
||
<u-col span="4">
|
||
<u-button class="btn-operation" :disabled="taskList.length <= 0" type="success" @click="confirmReceipt">
|
||
确认收样
|
||
</u-button>
|
||
</u-col>
|
||
</u-row>
|
||
</view>
|
||
</view>
|
||
</u-col>
|
||
</u-row>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, onMounted } from 'vue'
|
||
import nx from '@/nx'
|
||
import { onLoad, onBackPress } from '@dcloudio/uni-app'
|
||
|
||
// 响应式数据
|
||
const currentNode = ref('F30')
|
||
const scrollTop = ref(0)
|
||
const current = ref(0)
|
||
const taskList = ref([])
|
||
const sampleList = ref([])
|
||
const dicSampleProcessCodeList = ref([])
|
||
|
||
// 计算属性
|
||
const userInfo = computed(() => nx.$store('user').userInfo)
|
||
|
||
// 方法
|
||
const customBack = () => {
|
||
uni.reLaunch({ url: '/pages/analysis/index/index' })
|
||
}
|
||
|
||
const selectSample = sample => {
|
||
sample.checked = !sample.checked
|
||
}
|
||
|
||
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 confirmReceipt = () => {
|
||
const errNodeList = sampleList.value.filter(item => item.sampleProcessNo !== currentNode.value)
|
||
if (errNodeList.length > 0) {
|
||
uni.showToast({
|
||
title: '存在异常节点,联系管理员处理!',
|
||
icon: 'none',
|
||
duration: 3000
|
||
})
|
||
return
|
||
}
|
||
|
||
const checkedSampleList = sampleList.value.filter(item => item.checked)
|
||
if (checkedSampleList.length !== sampleList.value.length) {
|
||
uni.showToast({ title: '样品未全部勾选,请检查!', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确认收样?',
|
||
cancelColor: '#0055A2',
|
||
confirmColor: '#0055A2',
|
||
success: res => {
|
||
if (res.cancel) return
|
||
|
||
const sampleIdList = checkedSampleList.map(item => item.busSubCsampleId)
|
||
const data = {
|
||
busAssayTaskId: taskList.value[current.value]?.id,
|
||
sampleSourceType: 2,
|
||
sampleProcessNo: currentNode.value,
|
||
isGenSampleHandover: false,
|
||
sampleIdList
|
||
}
|
||
|
||
nx.$api.assayTask
|
||
.execReceiveSample(data)
|
||
.then(() => {
|
||
getAssayTask()
|
||
})
|
||
.catch(err => {
|
||
console.error('收样失败:', err)
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
const switchTask = index => {
|
||
if (index === current.value) return
|
||
current.value = index
|
||
|
||
const task = taskList.value[index]
|
||
if (!task) return
|
||
|
||
getAssayTaskDetail(task.taskNo)
|
||
}
|
||
|
||
const getAssayTask = () => {
|
||
const param = {
|
||
finishStatus: 'waiting_receive',
|
||
assayOper: userInfo.value.nickname
|
||
}
|
||
|
||
nx.$api.auncel
|
||
.getAssayTaskList(param)
|
||
.then(res => {
|
||
taskList.value = res || []
|
||
if (taskList.value.length > 0) {
|
||
current.value = 0
|
||
getAssayTaskDetail(taskList.value[0].taskNo)
|
||
} else {
|
||
sampleList.value = []
|
||
}
|
||
})
|
||
.catch(err => {
|
||
console.error('获取任务列表失败:', err)
|
||
sampleList.value = []
|
||
})
|
||
}
|
||
|
||
const getAssayTaskDetail = taskNo => {
|
||
const param = {
|
||
taskNo,
|
||
waiting_receive: '1'
|
||
}
|
||
|
||
nx.$api.assayTask
|
||
.getAssayTaskDetailListByTaskNo(param)
|
||
.then(res => {
|
||
sampleList.value = (res.result || []).map(item => ({ ...item, checked: false }))
|
||
})
|
||
.catch(err => {
|
||
console.error('获取任务详情失败:', err)
|
||
sampleList.value = []
|
||
})
|
||
}
|
||
|
||
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 ''
|
||
}
|
||
|
||
// 生命周期
|
||
onLoad(() => {
|
||
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-bottom: 2px dotted;
|
||
}
|
||
|
||
.u-tab-item-active {
|
||
position: relative;
|
||
color: #0055a2;
|
||
font-weight: 600;
|
||
background: #fff;
|
||
}
|
||
|
||
.content-main-right {
|
||
height: calc(100vh - 205px);
|
||
}
|
||
|
||
.content-main-right-operation {
|
||
height: 80px;
|
||
padding-top: 15px;
|
||
padding-right: 15px;
|
||
}
|
||
|
||
.btn-operation {
|
||
height: 50px;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.sample_desc {
|
||
width: 100%;
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
justify-content: space-between !important;
|
||
padding-right: 15px !important;
|
||
}
|
||
|
||
.sample_desc_warn {
|
||
color: red;
|
||
}
|
||
</style>
|