416 lines
12 KiB
Vue
416 lines
12 KiB
Vue
<template>
|
||
<view>
|
||
<up-sticky>
|
||
<navbar-back title="使用">
|
||
<up-button
|
||
v-if="detailInfo.id"
|
||
type="primary"
|
||
:plain="true"
|
||
icon="list"
|
||
size="small"
|
||
text="设备使用记录"
|
||
@click="handleUseRecord"
|
||
></up-button>
|
||
</navbar-back>
|
||
</up-sticky>
|
||
<view class="container">
|
||
<n-scanTemp
|
||
v-if="!detailInfo.id"
|
||
title="请扫描设备条码进行设备使用"
|
||
@deviceId="id => handleTestAction(id)"
|
||
@scanResult="result => handleScanResult(result)"
|
||
/>
|
||
<view v-else class="content">
|
||
<view>
|
||
<uni-section titleFontSize="20px" type="line" title="设备信息"> </uni-section>
|
||
<up-row class="flex-wrap p10" style="background-color: #f5f7fa">
|
||
<up-col class="mb10" :span="gridCol" v-for="(item, index) in detailSchema">
|
||
<view style="color: #666"
|
||
><span style="color: #333">{{ item.label }}:</span>{{ detailInfo[item.value] }}</view
|
||
>
|
||
</up-col>
|
||
</up-row>
|
||
</view>
|
||
<view>
|
||
<up-row justify="space-around">
|
||
<up-col span="3.5">
|
||
<view class="p5">使用前状态:</view>
|
||
<uni-data-select :disabled="useIng" v-model="formData.stateBefore" :localdata="ditData"></uni-data-select>
|
||
</up-col>
|
||
<up-col span="3.5">
|
||
<view class="p5">使用中状态:</view>
|
||
<uni-data-select :disabled="!useIng" v-model="formData.stateRun" :localdata="ditData"></uni-data-select>
|
||
</up-col>
|
||
<up-col span="3.5">
|
||
<view class="p5">使用后状态:</view>
|
||
<uni-data-select :disabled="!useIng" v-model="formData.stateAfter" :localdata="ditData"></uni-data-select>
|
||
</up-col>
|
||
</up-row>
|
||
<up-row justify="space-around">
|
||
<up-col span="3.5">
|
||
<view class="p5">{{ isHighTemperature ? '使用' : '' }}温度(℃):</view>
|
||
<up-input v-model="formData.temperature"></up-input>
|
||
</up-col>
|
||
<up-col v-if="!isHighTemperature" span="3.5">
|
||
<view class="p5">湿度(%HR):</view>
|
||
<up-input v-model="formData.humidity"></up-input>
|
||
</up-col>
|
||
<up-col span="3.5">
|
||
<view class="p5">检测项目:</view>
|
||
<up-input v-model="formData.useItem"></up-input>
|
||
</up-col>
|
||
</up-row>
|
||
<up-row justify="space-around">
|
||
<up-col span="11.5">
|
||
<view class="p5">备注:</view>
|
||
<up-input v-model="formData.remark" placeholder="请输入内容"></up-input>
|
||
</up-col>
|
||
</up-row>
|
||
</view>
|
||
<view class="x-f mt8">
|
||
<up-button
|
||
size="small"
|
||
type="primary"
|
||
style="width: 100px"
|
||
text="选择样品"
|
||
@click="handleSelect('sample')"
|
||
></up-button>
|
||
<up-button
|
||
size="small"
|
||
style="width: 100px"
|
||
type="primary"
|
||
text="选择标准物质"
|
||
@click="handleSelect('standard')"
|
||
></up-button>
|
||
</view>
|
||
<u-table2 class="mt8" height="240px" :data="tableData" :columns="columns" stripe border>
|
||
<template #cell="{ row, column }">
|
||
<up-button
|
||
v-if="column.key === 'action'"
|
||
size="mini"
|
||
plain
|
||
style="width: 50%"
|
||
type="error"
|
||
text="移除"
|
||
@click="handleDelete(row)"
|
||
></up-button>
|
||
</template>
|
||
</u-table2>
|
||
<up-button
|
||
style="width: 90%"
|
||
class="mt20"
|
||
loadingText="提交中..."
|
||
type="primary"
|
||
:text="useIng ? '结束使用' : '开始使用'"
|
||
@click="handleValidate"
|
||
></up-button>
|
||
</view>
|
||
</view>
|
||
<up-modal
|
||
:show="modalShow"
|
||
title="提示"
|
||
content="确定提交吗?"
|
||
ref="uModal"
|
||
:asyncClose="true"
|
||
showCancelButton
|
||
@confirm="submitConfirm"
|
||
@cancel="modalShow = false"
|
||
></up-modal>
|
||
<up-loading-page :loading="pageLoading"></up-loading-page>
|
||
|
||
<SampleSelectPopup ref="sampleSelectPopupRef" @confirm="list => handleSampleSelect(list, 'sample')" />
|
||
<StandardSelectPopup ref="standardSelectPopupRef" @confirm="list => handleSampleSelect(list, 'standard')" />
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, onMounted, onUnmounted, watch, toRefs, computed } from 'vue'
|
||
import { onShow, onLoad } from '@dcloudio/uni-app'
|
||
import { getDeviceBusInfoById } from '@/nx/api/deviceInfo'
|
||
import { getUseRecordById, addUseRecord, editUseRecord, getDetailList } from './useRecord.api'
|
||
import dailyCheckApi from '@/nx/api/dailyCheck'
|
||
import { useScreenOrientation } from '@/nx/hooks/useScreenOrientation'
|
||
import { useGridCol } from '@/nx/hooks/useGridCol'
|
||
import SampleSelectPopup from './SampleSelectPopup.vue'
|
||
import StandardSelectPopup from './StandardSelectPopup.vue'
|
||
import nx from '@/nx'
|
||
|
||
const { gridCol } = useGridCol([700], [6, 4])
|
||
const { lockOrientation } = useScreenOrientation()
|
||
const ditData = ref([
|
||
{ value: '正常', text: '正常' },
|
||
{ value: '异常', text: '异常' }
|
||
])
|
||
const detailSchema = [
|
||
{ label: '设备名称', value: 'deviceName' },
|
||
{ label: '设备型号', value: 'modelNo' },
|
||
{ label: '设备编码', value: 'deviceCode' },
|
||
{ label: '使用班组', value: 'deptName' }
|
||
]
|
||
const columns = ref([
|
||
{ title: '任务单号', key: 'taskNo', align: 'center' },
|
||
{ title: '样品名称', key: 'sampleName', align: 'center' },
|
||
{ title: '样品编号', key: 'sampleCode', align: 'center' },
|
||
{ title: '操作', key: 'action', width: '100px', align: 'center' }
|
||
])
|
||
const tableData = ref([])
|
||
|
||
const sampleSelectPopupRef = ref()
|
||
const standardSelectPopupRef = ref()
|
||
function handleSelect(type) {
|
||
if (type === 'sample') {
|
||
sampleSelectPopupRef.value.show()
|
||
} else {
|
||
standardSelectPopupRef.value.show()
|
||
}
|
||
}
|
||
function handleSampleSelect(dataList, type) {
|
||
const transformData = newData => {
|
||
if (type === 'sample') {
|
||
return {
|
||
detailType: 'sample',
|
||
sampleCode: newData.sampleCode,
|
||
sampleName: newData.sampleName,
|
||
taskNo: newData.taskNo,
|
||
taskId: newData.businessAssayTaskId
|
||
}
|
||
} else {
|
||
return {
|
||
detailType: 'standard',
|
||
sampleCode: newData.code,
|
||
sampleName: newData.name,
|
||
taskId: newData.id
|
||
}
|
||
}
|
||
}
|
||
for (const newData of dataList) {
|
||
const taskIdKey = type === 'sample' ? 'businessAssayTaskId' : 'id'
|
||
const index = tableData.value.findIndex(item => item.taskId === newData[taskIdKey])
|
||
const transformedItem = transformData(newData)
|
||
|
||
if (index > -1) {
|
||
// 找到匹配的项,直接替换
|
||
tableData.value[index] = transformedItem
|
||
} else {
|
||
// 没有找到匹配的项,添加到末尾
|
||
tableData.value.push(transformedItem)
|
||
}
|
||
}
|
||
}
|
||
|
||
function handleDelete(row) {
|
||
tableData.value = tableData.value.filter(item => item.id !== row.id)
|
||
}
|
||
const pageLoading = ref(false)
|
||
const userId = nx.$store('user').userInfo['id']
|
||
const userName = nx.$store('user').userInfo['realname']
|
||
let detailInfo = ref({})
|
||
|
||
function handleScanResult(result) {
|
||
const codeObj = JSON.parse(result)
|
||
if (!pageLoading.value) {
|
||
getLastDailyCheckOfToday(codeObj.id)
|
||
}
|
||
}
|
||
// 检查该设备在使用前是否已经点检过
|
||
async function getLastDailyCheckOfToday(id) {
|
||
pageLoading.value = true
|
||
try {
|
||
// dailyCheckApi.getLastDailyCheckOfToday({ deviceId: id }).then(async res => {
|
||
// if (!res || res.submitFlag == '0') {
|
||
// setTimeout(() => {
|
||
// uni.showToast({
|
||
// title: '设备使用前请先进行设备点检',
|
||
// icon: 'none'
|
||
// })
|
||
// }, 100)
|
||
// pageLoading.value = false
|
||
// nx.$router.go('/pages/device/deviceBusDailyCheck/index', { deviceId: id })
|
||
// } else {
|
||
// getDeviceInfo(id)
|
||
// await getUseIngRecord(id)
|
||
// pageLoading.value = false
|
||
// }
|
||
// })
|
||
getDeviceInfo(id)
|
||
await getUseIngRecord(id)
|
||
pageLoading.value = false
|
||
} catch (error) {
|
||
pageLoading.value = false
|
||
}
|
||
}
|
||
function handleTestAction(id) {
|
||
getLastDailyCheckOfToday(id)
|
||
}
|
||
// 是否是高温设备
|
||
const isHighTemperature = computed(() => {
|
||
if (detailInfo.value.customConfigJson && detailInfo.value.customConfigJson.highTemperature) {
|
||
return true
|
||
} else {
|
||
return false
|
||
}
|
||
})
|
||
// 获取设备详情
|
||
async function getDeviceInfo(id) {
|
||
const res = await getDeviceBusInfoById(id).finally(() => {})
|
||
detailInfo.value = res
|
||
lockOrientation('landscape')
|
||
}
|
||
|
||
const useIng = ref(false)
|
||
// 获取使用记录判断是否在使用中
|
||
async function getUseIngRecord(id) {
|
||
const res = await getUseRecordById(id)
|
||
if (res) {
|
||
useIng.value = true
|
||
formData.value = res
|
||
formData.value.userIdEnd = userId
|
||
formData.value.userNameEnd = userName
|
||
getUseRecordDetailList(res.id)
|
||
|
||
// checkUseStatusIsMySelf(res)
|
||
} else {
|
||
useIng.value = false
|
||
}
|
||
}
|
||
async function getUseRecordDetailList(id) {
|
||
const res = await getDetailList({ parentId: id })
|
||
tableData.value = res
|
||
}
|
||
// 定义一个变量,用于标记当前是否有 modal 正在显示
|
||
let isModalShowing = false
|
||
// 如果设备在使用中,检查设备使用记录是否是所登录用户的
|
||
function checkUseStatusIsMySelf(useInfo) {
|
||
if (isModalShowing) {
|
||
return
|
||
}
|
||
if (useInfo.userId != userId) {
|
||
isModalShowing = true
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '该设备正在使用中,是否结束使用',
|
||
success: function (res) {
|
||
if (res.confirm) {
|
||
submitConfirm()
|
||
isModalShowing = false
|
||
} else if (res.cancel) {
|
||
console.log('用户点击取消')
|
||
isModalShowing = false
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
let formData = ref({
|
||
stateBefore: '正常'
|
||
})
|
||
|
||
const modalShow = ref(false)
|
||
function handleValidate() {
|
||
if (!useIng.value && !formData.value.stateBefore) {
|
||
return uni.showToast({
|
||
title: '请选择使用前状态',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
if (useIng.value) {
|
||
if (!formData.value.stateRun) {
|
||
return uni.showToast({
|
||
title: '请选择使用中状态',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
if (!formData.value.stateAfter) {
|
||
return uni.showToast({
|
||
title: '请选择使用后状态',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
if (!formData.value.useItem) {
|
||
return uni.showToast({
|
||
title: '请输入检测项目',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
if (tableData.value.length === 0) {
|
||
return uni.showToast({
|
||
title: '请选择样品和标准物质',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
modalShow.value = true
|
||
}
|
||
const submitLoading = ref(false)
|
||
async function submitConfirm() {
|
||
if (submitLoading.value) return
|
||
submitLoading.value = true
|
||
let submitParams = {
|
||
...formData.value,
|
||
deviceId: detailInfo.value.id,
|
||
temperature: formData.value.temperature || '/',
|
||
humidity: formData.value.humidity || '/',
|
||
detailList: tableData.value
|
||
}
|
||
// 如果在使用中加入使用结束参数
|
||
let currentTime = nx.$dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||
let submitApi = useIng.value ? editUseRecord : addUseRecord
|
||
if (useIng.value) {
|
||
submitParams.useTimeEnd = currentTime
|
||
} else {
|
||
submitParams.useTimeStart = currentTime
|
||
}
|
||
await submitApi(submitParams)
|
||
.then(() => {
|
||
submitLoading.value = false
|
||
modalShow.value = false
|
||
reset()
|
||
})
|
||
.catch(() => {
|
||
modalShow.value = false
|
||
submitLoading.value = false
|
||
})
|
||
}
|
||
function reset() {
|
||
formData.value = {}
|
||
detailInfo.value = {}
|
||
tableData.value = []
|
||
}
|
||
function handleUseRecord() {
|
||
nx.$store('biz').deviceInfo = detailInfo.value
|
||
nx.$router.go('/pages/device/deviceBusUseRecord/list')
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.u-sticky {
|
||
top: 0 !important;
|
||
}
|
||
.container {
|
||
.content {
|
||
background-color: #fff;
|
||
height: 100%;
|
||
padding: 16px;
|
||
padding-top: 0px;
|
||
padding-bottom: 0px;
|
||
font-size: 16px;
|
||
.title {
|
||
font-size: 22px;
|
||
font-weight: bold;
|
||
}
|
||
.check-header {
|
||
.u-sticky {
|
||
top: 70px !important;
|
||
}
|
||
}
|
||
.fill-content {
|
||
border-radius: 3px;
|
||
box-shadow: 2px 2px 8px 2px rgba(0, 0, 0, 0.2);
|
||
background-color: #fdf6ec;
|
||
padding: 10px;
|
||
}
|
||
}
|
||
}
|
||
</style>
|