Files
pqs-9100_client/frontend/src/views/home/components/table.vue

1078 lines
31 KiB
Vue
Raw Normal View History

2025-08-07 08:47:56 +08:00
<!--
设备管理表格组件 - 支持多种业务模式
主要功能设备检测报告生成设备归档数据操作
支持手动/一键检测批量操作通道配对等高级功能
-->
2024-08-23 13:19:20 +08:00
<template>
2025-01-15 18:01:12 +08:00
<div class='table_info'>
2025-08-07 08:47:56 +08:00
<!-- 主表格组件支持排序选择动态列等功能 -->
2024-08-27 18:37:46 +08:00
<ProTable
2025-08-07 08:47:56 +08:00
ref='proTable'
:columns='columns'
@drag-sort='sortTable'
:default-sort="{ prop: 'check_State', order: 'ascending' }"
:stripe='true'
:pagination='false'
:key='tableKey'
@selection-change='handleSelectionChange'
:request-api='getTableList'
:toolButton='false'
2024-08-27 18:37:46 +08:00
>
2025-08-07 08:47:56 +08:00
<!-- 表格头部操作区域包含查询筛选和功能按钮 -->
2025-01-15 18:01:12 +08:00
<template #tableHeader=''>
<el-form :model='form' :inline='true'>
2025-08-07 08:47:56 +08:00
<!-- 查询筛选区域 -->
2025-01-15 18:01:12 +08:00
<el-form-item label='关键字'>
2025-08-07 08:47:56 +08:00
<el-input v-model='form.search' placeholder='请输入设备名称' clearable style='width: 170px;' show-word-limit
maxlength='32'></el-input>
2024-11-25 21:11:10 +08:00
</el-form-item>
2025-08-07 08:47:56 +08:00
<!-- 检测状态筛选仅在设备检测模式下显示 -->
2025-01-15 18:01:12 +08:00
<el-form-item label='检测状态' v-if='form.activeTabs != 3 && form.activeTabs != 4 && form.activeTabs != 5'>
<el-select v-model='form.checkStatus' clearable>
2024-09-02 16:10:33 +08:00
<el-option
2025-08-07 08:47:56 +08:00
v-for='(item, index) in checkStatus'
:label='item.label'
:value='item.id'
:key='index'
v-show='shouldShowOption(item)'
2024-09-02 16:10:33 +08:00
></el-option>
</el-select>
</el-form-item>
2025-08-07 08:47:56 +08:00
<!-- 检测结果筛选 -->
2025-01-15 18:01:12 +08:00
<el-form-item label='检测结果'>
<el-select v-model='form.checkResult' clearable>
2024-11-29 13:45:48 +08:00
<el-option
2025-08-07 08:47:56 +08:00
v-for='(item, index) in checkResult'
:label='item.label'
:value='item.id'
:key='index'
v-show='shouldShowOption(item)'
2024-11-29 13:45:48 +08:00
></el-option>
</el-select>
</el-form-item>
2025-08-07 08:47:56 +08:00
<!-- 报告状态筛选 -->
2025-01-15 18:01:12 +08:00
<el-form-item label='报告状态'>
<el-select v-model='form.checkReportStatus' clearable>
2024-09-02 16:10:33 +08:00
<el-option
2025-08-07 08:47:56 +08:00
v-for='(item, index) in checkReportStatus'
:label='item.label'
:value='item.id'
:key='index'
v-show='shouldShowOption(item)'
2024-09-02 16:10:33 +08:00
></el-option>
</el-select>
</el-form-item>
2025-08-07 08:47:56 +08:00
<!-- 功能按钮区域 -->
2024-09-02 16:10:33 +08:00
<el-form-item>
2025-08-07 08:47:56 +08:00
<!-- 基本查询操作 -->
<el-button type='primary' icon='Search' @click='handleSearch'
2025-01-15 18:01:12 +08:00
>查询
</el-button
2024-09-02 16:10:33 +08:00
>
2025-08-07 08:47:56 +08:00
<el-button icon='Delete' @click='handleRefresh'
>重置
</el-button
2025-01-15 13:46:11 +08:00
>
2025-08-07 08:47:56 +08:00
<!-- 比对模式下的通道配对功能 -->
<el-button
type='primary'
icon='Clock' @click='handleTest2'>通道配对
</el-button>
<!-- 设备检测模式下的操作按钮 -->
2024-09-02 16:10:33 +08:00
<el-button
2025-08-07 08:47:56 +08:00
type='primary'
icon='Clock'
@click="handleTest('手动检测')"
v-if='form.activeTabs === 0'
2025-01-15 18:01:12 +08:00
>手动检测
</el-button
2024-09-02 16:10:33 +08:00
>
<el-button
2025-08-07 08:47:56 +08:00
type='primary'
icon='ChatLineRound'
@click="handleTest('一键检测')"
v-if='form.activeTabs === 0'
>一键检测
</el-button>
2025-08-07 08:47:56 +08:00
<!-- 报告生成模式下的批量操作 -->
<el-button type='primary' icon='Postcard' @click="handleTest('批量生成')" v-if='form.activeTabs === 3'>
报告生成
</el-button>
<!-- 设备归档模式下的批量操作 -->
<el-button type='primary' icon='Notebook' @click="handleTest('批量归档')" v-if='form.activeTabs === 4'>
归档
</el-button>
2024-09-02 16:10:33 +08:00
</el-form-item>
</el-form>
</template>
2025-08-07 08:47:56 +08:00
<!-- 表格行操作列根据不同模式显示不同的操作按钮 -->
2025-01-15 18:01:12 +08:00
<template #operation='scope'>
2025-08-07 08:47:56 +08:00
<!-- 报告下载仅在报告已生成或已上传时显示 -->
2024-08-27 18:37:46 +08:00
<el-button
2025-08-07 08:47:56 +08:00
type='primary'
link
icon='Download'
@click="openDrawer('报告下载', scope.row)"
v-if='form.activeTabs === 3 && (scope.row.reportState === 1 ||scope.row.reportState === 3)'
2025-01-15 18:01:12 +08:00
>报告下载
</el-button>
2025-08-07 08:47:56 +08:00
<!-- 单个设备报告生成 -->
2025-01-15 18:01:12 +08:00
<el-button
2025-08-07 08:47:56 +08:00
type='primary'
link
icon='Postcard'
@click="openDrawer('报告生成', scope.row)"
v-if='form.activeTabs === 3 '
2025-01-15 18:01:12 +08:00
>报告生成
</el-button>
2025-08-07 08:47:56 +08:00
<!-- 设备归档模式下的单个归档操作 -->
2025-01-13 22:50:55 +08:00
<el-button type='primary'
2025-01-15 18:01:12 +08:00
link
2025-08-07 08:47:56 +08:00
icon='Notebook'
2025-01-15 18:01:12 +08:00
@click="openDrawer('归档', scope.row)"
v-if='form.activeTabs === 4'
>归档
</el-button>
2025-08-07 08:47:56 +08:00
<!-- 数据操作模式下的功能 -->
2024-08-27 18:37:46 +08:00
<el-button
2025-08-07 08:47:56 +08:00
type='primary'
link
icon='PieChart'
@click="openDrawer('检测数据查询', scope.row)"
v-if='form.activeTabs === 5'
2025-01-15 18:01:12 +08:00
>检测数据查询
</el-button>
2025-08-07 08:47:56 +08:00
<!-- 误差体系更换功能 -->
<el-button
2025-08-07 08:47:56 +08:00
type='primary'
link
icon='Switch'
@click="openDrawer('误差体系更换', scope.row)"
v-if='form.activeTabs === 5'
2025-01-15 18:01:12 +08:00
>误差体系更换
</el-button>
</template>
2024-08-27 18:37:46 +08:00
</ProTable>
2025-08-07 08:47:56 +08:00
<!-- ======================== 弹窗组件区域 ======================== -->
<!-- 检测过程显示弹窗 -->
<TestPopup ref='testPopup' @quitClicked='handleQuitClicked'></TestPopup>
2025-08-07 08:47:56 +08:00
<!-- 检测数据查询弹窗 -->
<dataCheckPopup ref='dataCheckPopupRef' />
<!-- 手动检测检测项选择弹窗 -->
<SelectTestItemPopup ref='selectTestItemPopupRef' @openTestDialog='openTestDialog'></SelectTestItemPopup>
<!-- 省平台模式下的温度湿度填写弹窗 -->
<WriteTHPopup ref='writeTHPopupRef' @openTestDialog2='openTestDialog2'></WriteTHPopup>
<!-- 比对模式下的通道配对弹窗 -->
<DeviceConnectionPopup ref='deviceConnectionPopupRef'></DeviceConnectionPopup>
2024-08-23 13:19:20 +08:00
</div>
</template>
2024-08-27 18:37:46 +08:00
2025-01-15 18:01:12 +08:00
<script setup lang='tsx' name='useProTable'>
2025-08-07 08:47:56 +08:00
import { onBeforeMount, onMounted, type PropType, reactive, ref, watch } from 'vue'
import { ElMessage, ElMessageBox, type Action } from 'element-plus'
2025-01-15 18:01:12 +08:00
import TestPopup from './testPopup.vue'
import dataCheckPopup from './dataCheckSingleChannelSingleTestPopup.vue'
2025-08-07 08:47:56 +08:00
import ProTable from '@/components/ProTable/index.vue'
2025-01-15 18:01:12 +08:00
import socketClient from '@/utils/webSocketClient'
2025-08-07 08:47:56 +08:00
import SelectTestItemPopup from '@/views/home/components/selectTestItemPopup.vue'
import WriteTHPopup from '@/views/home/components/writeTHPopup.vue'
import DeviceConnectionPopup from '@/views/home/components/deviceConnectionPopup.vue'
import { type Device } from '@/api/device/interface/device'
import { type ProTableInstance, type ColumnProps } from '@/components/ProTable/interface'
import { type Plan } from '@/api/plan/interface'
import { type StandardDevice } from '@/api/device/interface/standardDevice'
import { generateDevReport, getBoundPqDevList } from '@/api/plan/plan'
import { downloadDevData } from '@/api/plan/plan'
import { getPqDev } from '@/api/device/device'
import { useModeStore, useAppSceneStore } from '@/stores/modules/mode' // 引入模式 store
import { useCheckStore } from '@/stores/modules/check'
import { CheckData } from '@/api/check/interface'
import { useAuthStore } from '@/stores/modules/auth'
import { useDownload } from '@/hooks/useDownload'
import { documentedPqDev } from '@/api/device/report'
import { ResultEnum } from '@/enums/httpEnum'
const checkStore = useCheckStore()
2025-01-15 18:01:12 +08:00
let devNum = 0//当前选取的被检设备数量
let devChannelsNum = 0//当前选择的被检设备通道总数
const tableKey = ref(0)
const tableHeight = ref(0)
2025-01-15 18:01:12 +08:00
const dataCheckPopupRef = ref<InstanceType<typeof dataCheckPopup>>()
const selectTestItemPopupRef = ref<InstanceType<typeof SelectTestItemPopup>>()
const writeTHPopupRef = ref<InstanceType<typeof WriteTHPopup>>()
const deviceConnectionPopupRef = ref<InstanceType<typeof DeviceConnectionPopup>>()
const dialogTitle = ref('手动检测')
2025-01-15 18:01:12 +08:00
const checkStateTable = ref<number[]>([0, 1, 2])
const modeStore = useModeStore()
2025-08-07 08:47:56 +08:00
/**
* 控制下拉框选项的显示逻辑
* 根据当前Tab模式动态控制哪些选项可见
* @param item 下拉框选项对象
* @returns 是否显示该选项
*/
const shouldShowOption = (item: any) => {
// 非设备检测模式weiJianTab !== 0隐藏"归档"和"未检"选项
2025-01-15 18:01:12 +08:00
if (weiJianTab.value !== 0) {
return item.label !== '归档' && item.label !== '未检'
2025-01-06 09:21:24 +08:00
} else {
2025-08-07 08:47:56 +08:00
// 设备检测模式只隐藏"归档"选项
2025-01-15 18:01:12 +08:00
return item.label !== '归档'
2025-01-06 09:21:24 +08:00
}
2025-01-15 18:01:12 +08:00
}
2025-08-07 08:47:56 +08:00
// WebSocket客户端配置用于实时通信
2025-01-16 16:32:06 +08:00
const dataSocket = reactive({
socketServe: socketClient.Instance,
2025-08-07 08:47:56 +08:00
})
2025-01-16 16:32:06 +08:00
2025-01-15 18:01:12 +08:00
tableHeight.value = window.innerHeight - 600
const operationShow = ref(false)
const documentStateShow = ref(false)
const checkStateShow = ref(true)
const factorCheckShow = ref(true)
const selectionShow = ref(true)
2024-12-18 15:49:29 +08:00
const testPopup = ref()
2025-08-07 08:47:56 +08:00
const weiJianTab = ref(0) // 当前Tab索引用于控制选项显示逻辑
2024-12-20 10:21:36 +08:00
const channelsSelection = ref<Device.ResPqDev[]>([])
2024-12-13 16:35:27 +08:00
const props = defineProps({
2025-01-15 18:01:12 +08:00
id: {
type: String,
required: true,
},
2025-01-08 11:40:12 +08:00
plan: {
type: Object,
2025-01-15 18:01:12 +08:00
default: null,
},
2025-07-24 08:29:03 +08:00
planArray: {
2025-08-07 08:47:56 +08:00
type: Array as PropType<Plan.ReqPlan[]>,
default: null,
2025-08-06 15:18:27 +08:00
},
planTable: {
2025-08-07 08:47:56 +08:00
type: Array,
default: () => [],
2025-08-06 15:18:27 +08:00
},
2024-12-13 16:35:27 +08:00
})
2025-05-06 11:00:12 +08:00
const appSceneStore = useAppSceneStore()
2025-08-06 15:18:27 +08:00
2025-08-05 10:37:40 +08:00
2025-01-13 21:06:24 +08:00
const emit = defineEmits<{
(e: 'batchGenerateClicked'): void;
2025-01-15 18:01:12 +08:00
}>()
2025-01-13 19:28:51 +08:00
// 存储设备类型选项
2025-01-15 18:01:12 +08:00
const devTypeOptions = ref<{
id: string;
name: string,
icd: string,
power: string,
devVolt: number,
devCurr: number,
devChns: number,
}[]>([])
2025-01-13 19:28:51 +08:00
2024-09-02 16:10:33 +08:00
//下拉框数据
2024-12-16 16:33:18 +08:00
interface Dict {
id: string;
label: string;
}
2025-01-15 18:01:12 +08:00
2024-09-02 16:10:33 +08:00
//检测状态数据
2024-12-16 16:33:18 +08:00
const checkStatus: Dict[] = [
2024-09-02 16:10:33 +08:00
{
2025-01-15 18:01:12 +08:00
id: '0',
2024-12-16 16:33:18 +08:00
label: '未检',
2024-09-02 16:10:33 +08:00
},
{
2025-01-15 18:01:12 +08:00
id: '1',
2024-12-16 16:33:18 +08:00
label: '检测中',
2024-09-02 16:10:33 +08:00
},
{
2025-01-15 18:01:12 +08:00
id: '2',
2024-12-16 16:33:18 +08:00
label: '检测完成',
2024-09-02 16:10:33 +08:00
},
{
2025-01-15 18:01:12 +08:00
id: '3',
2024-12-16 16:33:18 +08:00
label: '归档',
2024-09-02 16:10:33 +08:00
},
2024-12-16 16:33:18 +08:00
]
2024-09-02 16:10:33 +08:00
//检测报告状态数据
2024-12-16 16:33:18 +08:00
const checkReportStatus: Dict[] = [
2024-12-16 15:25:30 +08:00
{
2025-01-15 18:01:12 +08:00
id: '0',
2024-12-17 13:38:59 +08:00
label: '未生成',
2024-09-02 16:10:33 +08:00
},
{
2025-01-15 18:01:12 +08:00
id: '1',
2024-12-17 13:38:59 +08:00
label: '已生成',
},
{
2025-01-15 18:01:12 +08:00
id: '2',
2024-12-17 13:38:59 +08:00
label: '未检',
2024-09-02 16:10:33 +08:00
},
2024-12-16 16:33:18 +08:00
]
2024-09-02 16:10:33 +08:00
//检测结果数组
2024-12-16 16:33:18 +08:00
const checkResult: Dict[] = [
2024-09-02 16:10:33 +08:00
{
2025-01-15 18:01:12 +08:00
id: '0',
2024-12-16 16:33:18 +08:00
label: '不符合',
2024-09-02 16:10:33 +08:00
},
{
2025-01-15 18:01:12 +08:00
id: '1',
2024-12-16 16:33:18 +08:00
label: '符合',
2024-09-02 16:10:33 +08:00
},
{
2025-01-15 18:01:12 +08:00
id: '2',
2024-12-16 16:33:18 +08:00
label: '未检',
2024-09-02 16:10:33 +08:00
},
2024-12-16 16:33:18 +08:00
]
2024-09-02 16:10:33 +08:00
//查询条件
const form: any = ref({
activeTabs: 0, //功能选择
2024-12-17 11:34:54 +08:00
search: null,//搜索内容
2024-11-29 13:45:48 +08:00
checkStatus: null, //检测状态
checkResult: null, //检测结果
checkReportStatus: null, //检测报告状态
2024-09-02 16:10:33 +08:00
deviceBindStatus: 0, //绑定状态
deviceType: 0, //设备类型
manufacturer: 0, //制造厂商
2025-01-15 18:01:12 +08:00
})
2024-08-27 18:37:46 +08:00
// ProTable 实例
2025-01-15 18:01:12 +08:00
const proTable = ref<ProTableInstance>()
2024-08-23 13:19:20 +08:00
2025-08-07 08:47:56 +08:00
/**
* 获取表格数据的异步函数
* 根据权限控制列显示根据查询条件获取设备列表
*/
const getTableList = async () => {
// 权限控制:没有通道系数权限时隐藏相关列
2025-01-15 18:01:12 +08:00
const authStore = useAuthStore()
const currentPageRoles = authStore.authButtonListGet[authStore.routeName] ?? []
if (!currentPageRoles.includes('channelsTest')) {
factorCheckShow.value = false
}
2025-01-09 13:56:56 +08:00
2025-08-07 08:47:56 +08:00
// 清空当前表格选择
2025-01-15 18:01:12 +08:00
if (proTable.value) {
proTable.value.clearSelection()
}
if (props.id) {
2024-12-17 13:38:59 +08:00
const checkStateList = ref<any>()
2025-01-15 18:01:12 +08:00
if (form.value.checkStatus != null) {
2025-01-13 21:06:24 +08:00
checkStateList.value = [form.value.checkStatus]
2025-01-15 18:01:12 +08:00
} else {
2025-01-13 21:06:24 +08:00
checkStateList.value = checkStateTable.value
}
2025-01-15 18:01:12 +08:00
return getBoundPqDevList({
2025-07-21 13:47:56 +08:00
'planIdList': [props.id],
2025-01-15 18:01:12 +08:00
'checkStateList': checkStateList.value,
'checkResult': form.value.checkResult,
'reportState': form.value.checkReportStatus,
'name': form.value.search,
})
}
}
2024-08-27 18:37:46 +08:00
// 表格配置项
2024-12-13 16:35:27 +08:00
const columns = reactive<ColumnProps<Device.ResPqDev>[]>([
2025-01-15 18:01:12 +08:00
{
type: 'selection', fixed: 'left', width: 70,
isShow: selectionShow,
selectable(row) {
if (weiJianTab.value === 4) {
2025-08-07 08:47:56 +08:00
return row.reportState === 1 || row.reportState === 3
2025-01-15 18:01:12 +08:00
}
return true
2024-08-27 18:37:46 +08:00
},
2025-01-15 18:01:12 +08:00
},
2025-08-07 08:47:56 +08:00
{ type: 'index', fixed: 'left', width: 70, label: '序号' },
2025-01-15 18:01:12 +08:00
{
prop: 'name',
label: '设备名称',
minWidth: 220,
},
{
prop: 'devType',
label: '设备类型',
2025-07-24 08:29:03 +08:00
minWidth: 150,
2025-01-15 18:01:12 +08:00
},
2025-07-24 08:29:03 +08:00
{
prop: 'boundPlanName',
label: '来源计划名称',
minWidth: 200,
2025-08-07 08:47:56 +08:00
isShow: modeStore.currentMode === '比对式',
2025-07-24 08:29:03 +08:00
render(scope) {
return scope.row.boundPlanName ? scope.row.boundPlanName : props.plan.name
2025-08-07 08:47:56 +08:00
},
2025-07-24 08:29:03 +08:00
},
{
prop: 'standardDevs',
label: '标准设备',
minWidth: 200,
2025-08-07 08:47:56 +08:00
isShow: modeStore.currentMode === '比对式',
2025-07-24 08:29:03 +08:00
render(scope) {
const boundPlanName = ref('')
2025-08-07 08:47:56 +08:00
if (scope.row.boundPlanName) {
2025-07-24 08:29:03 +08:00
boundPlanName.value = scope.row.boundPlanName
2025-08-07 08:47:56 +08:00
} else {
2025-07-24 08:29:03 +08:00
boundPlanName.value = props.plan.name
}
const standardDevNames = props.planArray.flatMap(item => {
if (item.children) {
return item.children
.filter(child => child.name === boundPlanName.value)
2025-08-07 08:47:56 +08:00
.flatMap(child =>
child.standardDevs.map(dev => dev.name),
2025-07-24 08:29:03 +08:00
)
}
return []
})
2025-08-07 08:47:56 +08:00
return standardDevNames.length > 0 ? standardDevNames.join(',') : '/'
},
2025-07-24 08:29:03 +08:00
},
2025-01-15 18:01:12 +08:00
{
prop: 'devChns',
label: '通道数',
minWidth: 100,
sortable: true,
},
{
prop: 'recheckNum',
2025-01-15 18:01:12 +08:00
label: '检测次数',
minWidth: 100,
sortable: true,
},
{
prop: 'checkState',
label: '检测状态',
minWidth: 100,
sortable: true,
isShow: checkStateShow,
render: scope => {
return (
2025-08-07 08:47:56 +08:00
scope.row.checkState === 0 ? '未检' : scope.row.checkState === 1 ? '检测中' : '检测完成'
2025-01-15 18:01:12 +08:00
)
2024-08-27 18:37:46 +08:00
},
2025-01-15 18:01:12 +08:00
},
{
prop: 'checkResult',
label: '检测结果',
minWidth: 100,
sortable: true,
render: (scope) => {
if (scope.row.checkResult === 0) {
return <el-tag type='danger'>不符合</el-tag>
} else if (scope.row.checkResult === 1) {
return '符合'
} else if (scope.row.checkResult === 2) {
return '未检'
}
return ''
},
2025-01-15 18:01:12 +08:00
},
{
prop: 'reportState',
label: '报告状态',
minWidth: 100,
sortable: true,
render: scope => {
if (scope.row.reportState === 0) {
return '未生成'
} else if (scope.row.reportState === 1) {
return '已生成'
} else if (scope.row.reportState === 2) {
return '未检'
2025-08-07 08:47:56 +08:00
} else if (scope.row.reportState === 3) {
2025-07-24 16:30:19 +08:00
return '已上传'
2024-12-17 13:38:59 +08:00
}
2025-01-15 18:01:12 +08:00
return ''
},
2025-01-15 18:01:12 +08:00
},
{
prop: 'factorCheckResult',
label: '系数校准结果',
minWidth: 100,
sortable: true,
2025-08-07 08:47:56 +08:00
isShow: factorCheckShow.value && appSceneStore.currentScene === '1',
2025-01-15 18:01:12 +08:00
render: scope => {
if (scope.row.factorCheckResult === 0) {
return '不合格'
} else if (scope.row.factorCheckResult === 1) {
return '合格'
} else {
return '未检'
2025-01-09 13:56:56 +08:00
}
2025-08-07 08:47:56 +08:00
2025-01-09 13:56:56 +08:00
},
2025-01-15 18:01:12 +08:00
},
2025-08-07 08:47:56 +08:00
{ prop: 'operation', label: '操作', fixed: 'right', minWidth: 200, isShow: operationShow },
2025-01-15 18:01:12 +08:00
])
2025-08-07 08:47:56 +08:00
let testType = 'test' // 检测类型:'test'-检测 'reTest'-复检
2024-12-04 21:36:12 +08:00
2025-08-07 08:47:56 +08:00
/**
* 表格行选择变化时的处理函数
* 更新全局统计信息用于后续操作的校验和限制
*/
2024-11-25 21:11:10 +08:00
const handleSelectionChange = (selection: any[]) => {
2024-12-20 10:21:36 +08:00
channelsSelection.value = selection
2025-08-07 08:47:56 +08:00
// 统计选中设备数量
2025-01-15 18:01:12 +08:00
devNum = selection.length
2025-08-07 08:47:56 +08:00
// 统计选中设备的总通道数
2025-01-15 18:01:12 +08:00
devChannelsNum = 0
2024-12-04 21:36:12 +08:00
for (let i = 0; i < selection.length; i++) {
2025-02-11 10:59:41 +08:00
devChannelsNum += selection[i].devChns
2024-12-04 21:36:12 +08:00
}
2025-08-07 08:47:56 +08:00
// 统计已完成检测的设备数量
2024-12-18 15:49:29 +08:00
const result = selection.filter((item) => item.checkResult != 0)
2025-01-15 18:01:12 +08:00
if (result.length > 0) {
testType = 'test'
} else {
testType = 'reTest'
2024-11-29 13:45:48 +08:00
}
2024-12-21 12:41:06 +08:00
let devices: CheckData.Device[] = selection.map((item: any) => {
return {
deviceId: item.id,
deviceName: item.name,
chnNum: item.devChns,
planId: item.planId,
deviceType: item.devType,
devVolt: item.devVolt,
devCurr: item.devCurr,
2025-02-26 13:57:07 +08:00
factorFlag: item.factorFlag,
2025-05-26 14:41:06 +08:00
checkResult: item.checkResult,
}
2025-01-15 18:01:12 +08:00
})
2024-12-26 09:28:19 +08:00
2025-01-15 18:01:12 +08:00
if (selection.length > 0) {
2024-12-26 09:28:19 +08:00
checkStore.clearDevices()
checkStore.addDevices(devices)
2025-01-15 18:01:12 +08:00
} else {
2024-12-26 09:28:19 +08:00
checkStore.clearDevices()
}
2024-11-25 21:11:10 +08:00
}
2024-11-29 13:45:48 +08:00
2024-08-27 18:37:46 +08:00
//查询
const handleSearch = () => {
2025-01-15 18:01:12 +08:00
proTable.value?.getTableList()
}
2024-08-27 18:37:46 +08:00
//重置
const handleRefresh = () => {
2025-01-15 18:01:12 +08:00
form.value.search = null
form.value.checkStatus = null
form.value.checkResult = null
form.value.checkReportStatus = null
proTable.value?.getTableList()
}
2025-08-07 08:47:56 +08:00
// 表格排序
2024-08-27 18:37:46 +08:00
const sortTable = ({
2025-01-15 18:01:12 +08:00
newIndex,
oldIndex,
}: {
2024-08-27 18:37:46 +08:00
newIndex?: number;
oldIndex?: number;
}) => {
2025-08-07 08:47:56 +08:00
console.log(newIndex, oldIndex) // 避免未使用参数警告
2025-01-15 18:01:12 +08:00
ElMessage.success('修改列表排序成功')
}
2024-08-27 18:37:46 +08:00
2025-08-07 08:47:56 +08:00
/**
* 切换顶部功能Tab时的处理函数
* @param val Tab索引0-设备检测 1-手动检测 2-设备复检 3-报告生成 4-设备归档 5-数据查询
* 现在1和2已不做考虑了其他4种tab满足当前的工作需求
*/
const changeActiveTabs = (val: number) => {
2025-01-15 18:01:12 +08:00
form.value.activeTabs = val
tableHeaderInit(val)
2025-01-15 18:01:12 +08:00
}
2025-08-07 08:47:56 +08:00
/**
* 根据当前功能Tab初始化表格配置
* 不同Tab模式下表格会显示不同的列和操作按钮
* @param val Tab索引0-设备检测 1-手动检测 2-设备复检 3-报告生成 4-设备归档 5-数据查询
*/
function tableHeaderInit(val: number) {
2025-08-07 08:47:56 +08:00
// 重置查询条件和选择状态
refreshStatusList()
2025-01-15 18:01:12 +08:00
weiJianTab.value = val
2025-08-07 08:47:56 +08:00
// 根据Tab索引配置不同的表格显示模式
switch (val) {
2025-08-07 08:47:56 +08:00
case 0: // 设备检测模式
case 1: // 手动检测模式
checkStateTable.value = [0, 1, 2] // 显示所有检测状态
2025-01-15 18:01:12 +08:00
tableKey.value++
2025-08-07 08:47:56 +08:00
operationShow.value = false // 隐藏操作列
documentStateShow.value = false // 隐藏文档状态
checkStateShow.value = true // 显示检测状态
selectionShow.value = true // 显示选择框
factorCheckShow.value = true // 显示系数校准
2025-01-15 18:01:12 +08:00
break
2025-08-07 08:47:56 +08:00
case 2: // 设备复检模式
2025-01-15 18:01:12 +08:00
break
2025-08-07 08:47:56 +08:00
case 3: // 报告生成模式
checkStateTable.value = [2, 3] // 只显示检测完成和归档状态
2025-01-15 18:01:12 +08:00
columns[columns.length - 1].minWidth = 180
tableKey.value += 1
2025-08-07 08:47:56 +08:00
operationShow.value = true // 显示操作列
documentStateShow.value = true // 显示文档状态
checkStateShow.value = false // 隐藏检测状态
factorCheckShow.value = false // 隐藏系数校准
selectionShow.value = true // 显示选择框
2025-01-15 18:01:12 +08:00
break
2025-08-07 08:47:56 +08:00
case 4: // 设备归档模式
checkStateTable.value = [2] // 只显示检测完成状态
2025-01-15 18:01:12 +08:00
columns[columns.length - 1].minWidth = 100
tableKey.value += 1
2025-08-07 08:47:56 +08:00
operationShow.value = true // 显示操作列
documentStateShow.value = false // 隐藏文档状态
checkStateShow.value = false // 隐藏检测状态
factorCheckShow.value = false // 隐藏系数校准
selectionShow.value = true // 显示选择框
2025-01-15 18:01:12 +08:00
break
2025-08-07 08:47:56 +08:00
case 5: // 数据查询模式
checkStateTable.value = [2, 3] // 显示检测完成和归档状态
2025-01-15 18:01:12 +08:00
columns[columns.length - 1].minWidth = 290
2025-08-07 08:47:56 +08:00
operationShow.value = true // 显示操作列
documentStateShow.value = true // 显示文档状态
checkStateShow.value = false // 隐藏检测状态
factorCheckShow.value = false // 隐藏系数校准
selectionShow.value = false // 隐藏选择框
columns[0].isShow = false // 隐藏序号列
2025-01-15 18:01:12 +08:00
tableKey.value += 1
break
}
2025-08-07 08:47:56 +08:00
}
2024-11-29 13:45:48 +08:00
2025-08-07 08:47:56 +08:00
/**
* 重置表格状态和查询条件
* 在切换Tab或重置操作时调用清空所有筛选条件和选择状态
*/
2025-01-15 18:01:12 +08:00
function refreshStatusList() {
2025-08-07 08:47:56 +08:00
// 重置设备选择统计信息
2025-01-15 18:01:12 +08:00
devNum = 0
devChannelsNum = 0
2025-08-07 08:47:56 +08:00
// 清空查询表单
form.value.search = null
2025-01-15 18:01:12 +08:00
form.value.checkStatus = null//检测状态默认为未检
form.value.checkReportStatus = null//检测报告状态默认为未生成报告
form.value.checkResult = null//检测结果默认为未出结果
}
2025-01-15 18:01:12 +08:00
2025-08-07 08:47:56 +08:00
/**
* 通道配对功能处理函数比对模式专用
* 校验选中设备的一致性然后打开通道配对弹窗
*/
const handleTest2 = () => {
// 检查是否选择了设备
2025-07-24 08:29:03 +08:00
if (devNum == 0) {
ElMessageBox.confirm(
2025-08-07 08:47:56 +08:00
'请先选择被检设备',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
2025-07-24 08:29:03 +08:00
)
return
}
2025-08-07 08:47:56 +08:00
// 检查选中设备是否属于同一个计划
2025-07-24 08:29:03 +08:00
const planName = channelsSelection.value.map(item => item.boundPlanName)
const isPlanConsistent = new Set(planName).size === 1
if (!isPlanConsistent) {
ElMessageBox.confirm(
2025-08-07 08:47:56 +08:00
'所勾选被检设备所属计划名称不一致,请重新选择',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
2025-07-24 08:29:03 +08:00
)
return
}
2025-08-07 08:47:56 +08:00
// 获取设备所属计划名称
2025-07-24 08:29:03 +08:00
const boundPlanName = ref('')
2025-08-07 08:47:56 +08:00
if (channelsSelection.value[0].boundPlanName) {
boundPlanName.value = channelsSelection.value[0].boundPlanName
} else {
boundPlanName.value = props.plan.name
2025-07-24 08:29:03 +08:00
}
2025-08-07 08:47:56 +08:00
// 查找选中设备所属计划的标准设备列表
const pqStandardDevList = ref<StandardDevice.ResPqStandardDevice[]>([])
2025-07-24 08:29:03 +08:00
pqStandardDevList.value = props.planArray.flatMap(item => {
2025-08-07 08:47:56 +08:00
if (item.children) {
return item.children
.filter(child => child.name === boundPlanName.value)
.flatMap(child =>
child.standardDevs,
)
}
return []
2025-07-24 08:29:03 +08:00
})
2025-08-07 08:47:56 +08:00
// 检查是否有标准设备可用于配对
if (pqStandardDevList.value.length == 0) {
2025-07-24 08:29:03 +08:00
ElMessageBox.confirm(
2025-08-07 08:47:56 +08:00
'所勾选被检设备所属计划无标准设备,请重新选择',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
2025-07-24 08:29:03 +08:00
)
return
}
2025-08-07 08:47:56 +08:00
// 获取选中计划的数据源配置
2025-08-05 10:37:40 +08:00
const dataSources = ref([])
2025-08-06 15:18:27 +08:00
const matchedItem = props.planTable.data.find(item => item.name === props.plan.name)
2025-08-05 10:37:40 +08:00
if (matchedItem) {
dataSources.value = matchedItem.datasourceIds
}
2025-08-07 08:47:56 +08:00
deviceConnectionPopupRef.value?.open(channelsSelection.value, pqStandardDevList.value, dataSources.value)
}
2025-08-07 08:47:56 +08:00
/**
* 检测操作主处理函数
* 根据操作类型手动检测/一键检测/批量生成/批量归档等执行相应逻辑
* @param val 操作类型字符串
*/
2025-01-15 18:01:12 +08:00
const handleTest = async (val: string) => {
2025-08-07 08:47:56 +08:00
// 检查是否选择了设备
2025-01-15 18:01:12 +08:00
if (devNum == 0) {
ElMessageBox.confirm(
2025-08-07 08:47:56 +08:00
'请先选择被检设备',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
2025-01-15 18:01:12 +08:00
)
return
}
2024-12-24 20:22:36 +08:00
2025-08-07 08:47:56 +08:00
// 检查选中设备的额定电压是否一致
2025-01-15 18:01:12 +08:00
const checkDevVolt = channelsSelection.value.map(item => item.devVolt)
const isDevVoltConsistent = new Set(checkDevVolt).size === 1
if (!isDevVoltConsistent) {
ElMessageBox.confirm(
2025-08-07 08:47:56 +08:00
'所勾选设备额定电压不一致,请重新选择',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
2025-01-15 18:01:12 +08:00
)
return
}
2024-12-24 20:22:36 +08:00
2025-08-07 08:47:56 +08:00
// 检查选中设备的额定电流是否一致
2025-01-15 18:01:12 +08:00
const checkDevCurr = channelsSelection.value.map(item => item.devCurr)
const isDevCurrConsistent = new Set(checkDevCurr).size === 1
if (!isDevCurrConsistent) {
ElMessageBox.confirm(
2025-08-07 08:47:56 +08:00
'所勾选设备额定电流不一致,请重新选择',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
2025-01-15 18:01:12 +08:00
)
return
}
2024-12-24 20:22:36 +08:00
2025-08-07 08:47:56 +08:00
// 处理检测相关操作
if (val === '手动检测' || val === '一键检测' || val === '系数校准') {
2025-08-07 08:47:56 +08:00
// 检查选中设备的检测状态是否一致
2025-01-15 18:01:12 +08:00
const checkStates = channelsSelection.value.map(item => item.checkState)
const allCheckStatesEqual = new Set(checkStates).size <= 1
2025-01-09 13:56:56 +08:00
2025-08-07 08:47:56 +08:00
// 如果检测状态不一致,设置为复检模式
2025-01-09 13:56:56 +08:00
if (!allCheckStatesEqual) {
2025-03-03 13:29:48 +08:00
checkStore.setReCheckType(1)
2025-01-09 13:56:56 +08:00
}
2025-08-07 08:47:56 +08:00
// 限制每次检测最多12个通道
if (devChannelsNum > 12) {
2025-01-09 13:56:56 +08:00
ElMessageBox.confirm(
2025-08-07 08:47:56 +08:00
'每次检测最多只能检测12个设备通道请重新选择',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
2025-01-09 13:56:56 +08:00
)
return
}
dialogTitle.value = val
if (val === '手动检测') {
2025-03-18 19:38:27 +08:00
checkStore.setShowDetailType(2)
if (testType === 'reTest') {
ElMessageBox.confirm('请选择复检检测方式', '设备复检',
2025-08-07 08:47:56 +08:00
{
distinguishCancelAndClose: true,
confirmButtonText: '不合格项复检',
cancelButtonText: '全部复检',
type: 'warning',
})
.then(() => {
ElMessage.success('不合格项复检')
checkStore.setReCheckType(0)
// 控制是否显示温度湿度输入框
if (appSceneStore.currentScene === '0') {
writeTHPopupRef.value?.open()
} else {
selectTestItemPopupRef.value?.open([])
}
})
.catch((action: Action) => {
if (action === 'cancel') {
ElMessage.success('全部复检')
checkStore.setReCheckType(1)
if (appSceneStore.currentScene === '0') {
2025-06-04 22:15:37 +08:00
writeTHPopupRef.value?.open()
2025-08-07 08:47:56 +08:00
} else {
2025-08-05 10:37:40 +08:00
selectTestItemPopupRef.value?.open([])
2025-04-08 09:43:12 +08:00
}
2025-08-07 08:47:56 +08:00
}
})
2025-08-07 08:47:56 +08:00
checkStore.setSelectTestItems({ preTest: false, timeTest: false, channelsTest: false, test: true })
2025-01-15 18:01:12 +08:00
} else {
2025-08-05 10:37:40 +08:00
selectTestItemPopupRef.value?.open([])
2025-04-08 09:43:12 +08:00
checkStore.setReCheckType(1)
}
} else {
2025-03-18 19:38:27 +08:00
checkStore.setShowDetailType(2)
2025-02-25 11:00:04 +08:00
checkStore.setCheckType(1)
checkStore.initSelectTestItems()
2025-03-03 11:35:12 +08:00
// 一键检测
if (testType === 'reTest') {
ElMessageBox.confirm('请选择复检检测方式', '设备复检',
2025-08-07 08:47:56 +08:00
{
distinguishCancelAndClose: true,
confirmButtonText: '不合格项复检',
cancelButtonText: '全部复检',
type: 'warning',
})
.then(() => {
ElMessage.success('不合格项复检')
checkStore.setReCheckType(0)
if (appSceneStore.currentScene === '0') {
writeTHPopupRef.value?.open()
} else {
openTestDialog(true)
}
})
.catch((action: Action) => {
if (action === 'cancel') {
ElMessage.success('全部复检')
checkStore.setReCheckType(1)
if (appSceneStore.currentScene === '0') {
writeTHPopupRef.value?.open()
} else {
openTestDialog(true)
2025-05-26 14:41:06 +08:00
}
2025-08-07 08:47:56 +08:00
}
})
checkStore.setSelectTestItems({ preTest: false, timeTest: false, channelsTest: false, test: true })
2025-03-03 11:35:12 +08:00
} else {
2025-07-14 15:02:07 +08:00
checkStore.setReCheckType(1)
2025-06-04 16:38:02 +08:00
openTestDialog(true)
2025-03-03 11:35:12 +08:00
}
}
2024-12-04 21:36:12 +08:00
}
2025-01-15 18:01:12 +08:00
if (val === '批量归档') {
documentedPqDev(checkStore.devices.map(item => {
2025-05-15 16:08:35 +08:00
return item.deviceId
2025-01-15 18:01:12 +08:00
})).then((res) => {
if (res.code === ResultEnum.SUCCESS) {
ElMessage.success('归档成功!')
2025-01-13 22:50:55 +08:00
}
})
2025-01-16 14:24:55 +08:00
emit('batchGenerateClicked') // 触发事件
2024-09-02 16:10:33 +08:00
}
2025-08-07 08:47:56 +08:00
if (val === '批量生成') {
let devIdList = checkStore.devices.map(item => {
2025-05-15 16:08:35 +08:00
return item.deviceId
})
await generateDevReport({
'planId': checkStore.plan.id,
2025-08-07 08:47:56 +08:00
'devIdList': devIdList,
'scriptId': checkStore.plan.scriptId,
'planCode': checkStore.plan.code + '',
'pageNum': 1,
'pageSize': 999,
2025-05-15 16:08:35 +08:00
})
2025-08-07 08:47:56 +08:00
ElMessage.success({ message: `报告生成成功!` })
2025-05-15 16:08:35 +08:00
}
}
2024-12-18 15:49:29 +08:00
2025-08-07 08:47:56 +08:00
const openTestDialog = (testData: any) => {
2025-05-26 14:41:06 +08:00
if (appSceneStore.currentScene === '0') {
2025-08-07 08:47:56 +08:00
if (testData) {
2025-06-04 16:38:02 +08:00
writeTHPopupRef.value?.open()
2025-08-07 08:47:56 +08:00
} else {
2025-06-04 16:38:02 +08:00
testPopup.value?.open(dialogTitle.value)
2025-08-07 08:47:56 +08:00
}
2025-05-26 14:41:06 +08:00
} else {
testPopup.value?.open(dialogTitle.value)
}
}
const openTestDialog2 = () => {
2025-08-07 08:47:56 +08:00
testPopup.value?.open(dialogTitle.value)
2025-01-15 18:01:12 +08:00
}
// 打开 drawer(新增、查看、编辑)
2025-08-07 08:47:56 +08:00
/**
* 打开操作弹窗或执行单行操作
* 根据操作类型处理报告生成下载归档数据查询等功能
* @param title 操作类型
* @param row 当前行数据
*/
2025-01-13 21:38:52 +08:00
const openDrawer = async (title: string, row: any) => {
2025-08-07 08:47:56 +08:00
// 单个设备报告生成
2025-01-15 18:01:12 +08:00
if (title === '报告生成') {
2025-08-07 08:47:56 +08:00
await generateDevReport({
'planId': checkStore.plan.id,
'devIdList': [row.id],
'scriptId': checkStore.plan.scriptId,
'planCode': checkStore.plan.code + '',
'pageNum': 1,
'pageSize': 999,
})
2025-01-15 18:01:12 +08:00
emit('batchGenerateClicked') // 触发事件
2025-08-07 08:47:56 +08:00
ElMessage.success({ message: `报告生成成功!` })
2025-01-15 18:01:12 +08:00
}
if (title === '报告下载') {
await useDownload(downloadDevData, row.createId, {
planId: checkStore.plan.id,
2025-01-15 18:01:12 +08:00
devId: row.id,
}, false, '.docx')
emit('batchGenerateClicked') // 触发事件
}
if (title === '检测数据查询') {
2025-03-06 15:50:45 +08:00
checkStore.setShowDetailType(0)
2025-01-15 18:01:12 +08:00
dataCheckPopupRef.value?.open(row.id, '-1', null)
}
if (title === '误差体系更换') {
2025-03-06 15:50:45 +08:00
checkStore.setShowDetailType(1)
dataCheckPopupRef.value?.open(row.id, '-1', null)
2025-01-15 18:01:12 +08:00
}
2025-01-15 18:01:12 +08:00
if (title === '归档') {
await documentedPqDev([row.id]).then((res) => {
if (res.code === ResultEnum.SUCCESS) {
ElMessage.success('归档成功!')
}
})
emit('batchGenerateClicked') // 触发事件
}
}
2025-01-13 09:59:05 +08:00
2024-12-13 16:35:27 +08:00
// 监听 props.id 的变化
watch(
2025-08-07 08:47:56 +08:00
() => props.id,
() => {
handleRefresh()
},
{ immediate: true },
2025-01-15 18:01:12 +08:00
)
2024-12-13 16:35:27 +08:00
2025-01-13 19:28:51 +08:00
onBeforeMount(async () => {
const response = await getPqDev()
2025-01-15 18:01:12 +08:00
devTypeOptions.value = response.data.map(item => ({
id: item.id,
name: item.name,
icd: item.icd,
power: item.power,
devVolt: item.devVolt,
devCurr: item.devCurr,
devChns: item.devChns,
}))
2025-01-13 19:28:51 +08:00
})
2025-01-13 21:06:24 +08:00
2025-08-05 10:37:40 +08:00
onMounted(async () => {
2025-08-07 08:47:56 +08:00
// 初始化表格配置,使用默认的设备检测模式(activeTabs = 0)
tableHeaderInit(form.value.activeTabs)
2025-08-05 10:37:40 +08:00
})
2025-01-13 21:06:24 +08:00
const handleQuitClicked = () => {
2025-03-14 12:27:04 +08:00
dataSocket.socketServe.closeWs()
2025-01-15 18:01:12 +08:00
emit('batchGenerateClicked') // 触发事件
}
2025-01-13 21:06:24 +08:00
2025-01-17 09:25:52 +08:00
2025-01-17 09:59:23 +08:00
const handleSubmitClicked = async (resolve: (value: boolean) => void) => {
if (!dataSocket.socketServe.connected) {
2025-08-07 08:47:56 +08:00
ElMessage.error('webSocket连接中断请退出重新进行系数校准')
resolve(false)
2025-01-17 09:59:23 +08:00
} else {
2025-08-07 08:47:56 +08:00
resolve(true)
2025-01-17 09:25:52 +08:00
}
2025-08-07 08:47:56 +08:00
}
2025-01-17 09:25:52 +08:00
2025-08-07 08:47:56 +08:00
defineExpose({ changeActiveTabs })
2024-08-23 13:19:20 +08:00
</script>
2025-01-15 18:01:12 +08:00
<style lang='scss' scoped>
2024-09-02 16:10:33 +08:00
/* 当屏幕宽度小于或等于1300像素时 */
@media screen and (max-width: 1300px) {
.el-select {
width: 130px !important;
}
2024-08-23 13:19:20 +08:00
}
2025-01-15 18:01:12 +08:00
2024-09-02 16:10:33 +08:00
@media screen and (min-width: 1300px) {
.el-select {
width: 150px !important;
}
2024-08-27 18:37:46 +08:00
}
.el-form {
width: 100%;
display: flex;
flex-wrap: wrap;
2025-01-15 18:01:12 +08:00
2024-08-27 18:37:46 +08:00
.el-form-item {
display: flex;
align-items: center;
justify-content: space-between;
2025-01-15 18:01:12 +08:00
2024-08-27 18:37:46 +08:00
.el-button {
margin: 0 !important;
margin-right: 10px !important;
}
}
}
2025-01-15 18:01:12 +08:00
:deep(.card) {
2025-01-06 14:02:22 +08:00
border: 0 !important;
}
2024-08-23 13:19:20 +08:00
</style>