372 lines
11 KiB
Vue
372 lines
11 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="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 class="fs18">{{ task.taskNo }}</view>
|
|
<view style="margin-top: 10px">{{ task.taskName }}</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 v-if="currentTask.reviewCount === sample.reviewCount" 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 &&
|
|
sample.rollbackStatus !== 'running' &&
|
|
sample.rollbackStatus !== 'finished'
|
|
"
|
|
@change="() => selectSample(sample)"
|
|
></u-checkbox>
|
|
</u-col>
|
|
<u-col span="6" style="text-align: center">
|
|
<view
|
|
><text>【{{ sample.sort }}】</text></view
|
|
>
|
|
</u-col>
|
|
</u-row>
|
|
</u-col>
|
|
<u-col span="9">
|
|
<view 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>
|
|
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'revoke'"> 样品退回被驳回 </view>
|
|
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'running'"> 样品退回审批中 </view>
|
|
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'finished'">
|
|
样品已退回,请联系管理员处理
|
|
</view>
|
|
</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.5"></u-col>
|
|
<u-col span="4">
|
|
<u-button class="btn-operation" type="warning" @click="showRollbackModal">申请退回样品</u-button>
|
|
</u-col>
|
|
<u-col span="4">
|
|
<u-button class="btn-operation" :disabled="taskList.length === 0" type="success" @click="startWork">
|
|
开始分析
|
|
</u-button>
|
|
</u-col>
|
|
</u-row>
|
|
</view>
|
|
</view>
|
|
</u-col>
|
|
</u-row>
|
|
|
|
<!-- 退回样品弹窗 -->
|
|
<up-modal
|
|
:show="showRollbackModalFlag"
|
|
showCancelButton
|
|
@confirm="applyRollbackSample"
|
|
@cancel="showRollbackModalFlag = false"
|
|
title="退回说明"
|
|
width="500px"
|
|
>
|
|
<u--textarea v-model="rollbackContent" placeholder="请输入退回原因或说明"></u--textarea>
|
|
</up-modal>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, onMounted } from 'vue'
|
|
import { onLoad, onBackPress } from '@dcloudio/uni-app'
|
|
import nx from '@/nx'
|
|
import { useScreenOrientation } from '@/nx/hooks/useScreenOrientation'
|
|
|
|
// 响应式数据
|
|
const currentNode = ref('F31')
|
|
const dicSampleProcessCodeList = ref([])
|
|
const showRollbackModalFlag = ref(false)
|
|
const rollbackContent = ref('')
|
|
const scrollTop = ref(0)
|
|
const current = ref(0)
|
|
const currentTask = ref({})
|
|
const currentTaskNo = ref('')
|
|
const currentTaskType = ref('')
|
|
const taskList = ref([])
|
|
const sampleList = 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 showRollbackModal = () => {
|
|
const checkedSampleList = sampleList.value.filter(item => item.checked)
|
|
if (checkedSampleList.length === 0) {
|
|
uni.showToast({ title: '请选择要退回的样品!', icon: 'none' })
|
|
return
|
|
}
|
|
showRollbackModalFlag.value = true
|
|
}
|
|
|
|
const applyRollbackSample = () => {
|
|
const checkedSampleList = sampleList.value.filter(item => item.checked)
|
|
if (!rollbackContent.value.trim()) {
|
|
uni.showToast({ title: '请输入退回说明!', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
showRollbackModalFlag.value = false
|
|
uni.showModal({
|
|
title: '提示',
|
|
content: '发起申请,退回已勾选的样品,是否继续?',
|
|
cancelColor: '#0055A2',
|
|
confirmColor: '#0055A2',
|
|
success: res => {
|
|
if (res.cancel) return
|
|
const detailIdList = checkedSampleList.map(item => item.id)
|
|
const data = {
|
|
remark: rollbackContent.value,
|
|
taskId: currentTask.value.id,
|
|
detailIds: detailIdList.join(',')
|
|
}
|
|
nx.$api.assayTask.createRollbackApply(data).then(() => {
|
|
getAssayTaskDetail(currentTaskNo.value)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
const checkWork = () => {
|
|
let checkedSampleList = sampleList.value.filter(
|
|
item => item.rollbackStatus === 'running' || item.rollbackStatus === 'finished'
|
|
)
|
|
if (checkedSampleList.length > 0) {
|
|
uni.showToast({ title: '存在未处理的退回申请,请处理后再分析!', icon: 'none' })
|
|
return false
|
|
}
|
|
checkedSampleList = sampleList.value.filter(item => item.sampleProcessNo !== currentNode.value)
|
|
if (checkedSampleList.length > 0) {
|
|
uni.showToast({ title: '部分样品状态异常,请联系管理员处理!', icon: 'none', duration: 2300 })
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
const startWork = () => {
|
|
if (!checkWork()) return
|
|
uni.navigateTo({
|
|
url: `/pages/analysis/sample/sample-work-detail?currentTaskNo=${currentTaskNo.value}`
|
|
})
|
|
}
|
|
|
|
const swichTask = async index => {
|
|
if (index === current.value) return
|
|
current.value = index
|
|
rollbackContent.value = ''
|
|
|
|
const task = taskList.value[index]
|
|
currentTask.value = task
|
|
currentTaskNo.value = task.taskNo
|
|
currentTaskType.value = task.taskType
|
|
getAssayTaskDetail(task.taskNo)
|
|
}
|
|
|
|
const getAssayTask = () => {
|
|
rollbackContent.value = ''
|
|
const param = {
|
|
finishStatus: 'waiting',
|
|
assayOper: userInfo.value.nickname
|
|
}
|
|
nx.$api.auncel.getAssayTaskList(param).then(res => {
|
|
if (res) {
|
|
taskList.value = res
|
|
if (taskList.value.length > 0) {
|
|
const first = taskList.value[0]
|
|
currentTask.value = first
|
|
currentTaskNo.value = first.taskNo
|
|
currentTaskType.value = first.taskType
|
|
getAssayTaskDetail(first.taskNo)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
const getAssayTaskDetail = taskNo => {
|
|
sampleList.value = []
|
|
nx.$api.assayTask.getAssayTaskDetailListByTaskNo({ taskNo }).then(res => {
|
|
const list = res.result || []
|
|
list.forEach(item => (item.checked = false))
|
|
sampleList.value = list
|
|
})
|
|
}
|
|
|
|
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(() => {
|
|
const { lockOrientation } = useScreenOrientation()
|
|
lockOrientation('landscape')
|
|
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 {
|
|
height: 50px;
|
|
font-size: 18px;
|
|
width: 95%;
|
|
}
|
|
.sample_desc {
|
|
width: 100%;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
.sample_desc_warn {
|
|
color: red;
|
|
padding-right: 10px;
|
|
}
|
|
</style>
|