Files
pqs-9100_client/frontend/src/views/plan/planList/index.vue
caozehui 312490ce59 微调
2025-03-24 19:56:11 +08:00

456 lines
16 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>
<div class='table-box' ref='popupBaseView'>
<ProTable
ref='proTable'
:columns='columns'
:request-api='getTableList'
>
<!-- 表格 header 按钮 -->
<template #tableHeader='scope'>
<el-button type='primary' v-auth.plan="'import'" :icon='Download' @click='importClick'>导入</el-button>
<el-button type='primary' v-auth.plan="'export'" :icon='Upload' @click='exportClick'>导出</el-button>
<el-button type='primary' v-auth.plan="'combine'" :icon='ScaleToOriginal' :disabled='!(scope.selectedList.length > 1)' @click='combineClick'>
合并
</el-button>
<el-button type='primary' v-auth.plan="'add'" :icon='CirclePlus' @click="openDialog('add')">新增</el-button>
<el-button type='primary' v-auth.plan="'analysis'" :icon='List' :disabled='!scope.isSelected' @click='statisticalAnalysisMore(scope.selectedListIds,scope.selectedList)'>统计分析</el-button>
<el-button type='danger' v-auth.plan="'delete'" :icon='Delete' plain :disabled='!scope.isSelected' @click='batchDelete(scope.selectedListIds)'>
删除
</el-button>
</template>
<!-- 表格操作 -->
<template #operation='scope'>
<el-button type='primary' v-auth.plan="'edit'" link :icon='EditPen' @click="openDialog('edit',scope.row)">编辑</el-button>
<el-button type='primary' v-auth.plan="'delete'" link :icon='Delete' @click='handleDelete(scope.row)'>删除</el-button>
<!-- <el-button type='primary' link :icon='List' @click='showDeviceOpen(scope.row)'>设备绑定</el-button> -->
<el-button type='primary' v-auth.plan="'analysis'" link :icon='List' v-if="scope.row.testState == '2'" @click='statisticalAnalysis(scope.row)'>统计分析</el-button>
</template>
</ProTable>
</div>
<!-- 向计划导入/导出设备对话框 -->
<PlanPopup :refresh-table='proTable?.getTableList' ref='planPopup'/>
<!-- 查看误差体系详细信息 -->
<ErrorStandardPopup :refresh-table='proTable?.getTableList' ref="errorStandardPopup"/>
<!-- 查看检测源 -->
<TestSourcePopup :refresh-table='proTable?.getTableList' ref="testSourcePopup"/>
<!-- 查看设备绑定
<DevTransfer :refresh-table='proTable?.getTableList' ref='devTransferPopup'/> -->
<ImportExcel ref='planImportExcel' />
</template>
<script setup lang='tsx' name='useProTable'>
import ProTable from '@/components/ProTable/index.vue'
import type { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
import { ScaleToOriginal, CirclePlus, Delete, EditPen, View, Upload, Download, List, Tools } from '@element-plus/icons-vue'
import {getPlanList,deletePlan,exportCNPlan,downloadCNPlanTemplate,importCNPlan } from '@/api/plan/plan.ts'
import { computed, onMounted, reactive, ref } from 'vue'
import type { Plan } from '@/api/plan/interface'
import PlanPopup from '@/views/plan/planList/components/planPopup.vue' // 导入子组件
import DeviceOpen from '@/views/plan/planList/components/devPopup.vue'
import SourceOpen from '@/views/plan/planList/components/sourcePopup.vue'
import DevTransfer from './components/devTransfer.vue'
import { useViewSize } from '@/hooks/useViewSize'
import { useRouter } from 'vue-router'
import { useDictStore } from '@/stores/modules/dict'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { Action } from 'element-plus'
import type { ErrorSystem } from '@/api/error/interface'
import ErrorStandardPopup from '@/views/machine/errorSystem/components/errorStandardPopup.vue' // 导入子组件
import TestSourcePopup from '@/views/machine/testSource/components/testSourcePopup.vue' // 导入子组件
import { type TestSource } from '@/api/device/interface/testSource'
import { useModeStore } from '@/stores/modules/mode'; // 引入模式 store
import { useHandleData } from '@/hooks/useHandleData'
import { dictTestState,dictReportState,dictResult } from '@/api/plan/planData.ts'
import {getTestSourceById} from '@/api/device/testSource/index'
import ImportExcel from '@/components/ImportExcel/index.vue'
import {useDownload} from "@/hooks/useDownload";
import {getTestConfig } from '@/api/system/base/index'
import {type Base } from '@/api/system/base/interface'
import { getBoundPqDevList ,staticsAnalyse} from '@/api/plan/plan.ts'
// defineOptions({
// name: 'planList'
// })
const dictStore = useDictStore()
const openDeviceView = ref()
const openSourceView = ref()
const devTransferVisible = ref(false)
const sourceTransferVisible = ref(false)
// ProTable 实例
const proTable = ref<ProTableInstance>()
const errorStandardPopup = ref()
const testSourcePopup = ref()
const planPopup = ref()
const devTransferPopup = ref()
const modeStore = useModeStore();
const planImportExcel = ref<InstanceType<typeof ImportExcel> | null>(null)
const planList = ref<Plan.ResPlan[]>([]);
const getTableList = async(params: any) => {
let newParams = JSON.parse(JSON.stringify(params))
const patternId = dictStore.getDictData('Pattern').find(item=>item.name=== modeStore.currentMode)?.id//获取数据字典中对应的id
newParams.pattern = patternId
try {
const result = await getPlanList(newParams);
planList.value = result.data as Plan.ResPlan[];
return result;
} catch (error) {
return { data: [] }; // 返回空数据或处理错误
}
}
const dataSourceType = computed(() => {
switch (modeStore.currentMode) {
case '模拟式':
return 'Datasource_Simulate'
case '数字式':
return 'Datasource_Digital'
default:
return 'Datasource_Contrast'
}
})
// 表格配置项
const columns = reactive<ColumnProps<Plan.ReqPlan>[]>([
{ type: 'selection', fixed: 'left', width: 70 },
{ type: 'index', fixed: 'left', width: 70, label: '序号' },
{
prop: 'name',
label: '名称',
width: 220,
search: { el: 'input' },
},
{
prop: 'testState',
label: '检测状态',
width: 120,
enum:dictTestState,
search: { el:'select',props: { filterable: true }},
fieldNames: { label: 'label', value: 'id' },
render: scope => {
return (
scope.row.testState === 0 ? '未检' : scope.row.testState === 1 ? '检测中' : '检测完成'
)
},
},
{
prop: 'reportState',
label: '检测报告状态',
width: 120,
enum:dictReportState,
search: { el: 'select', props: { filterable: true } },
fieldNames: { label: 'label', value: 'id' },
render: scope => {
return (
scope.row.reportState === 0 ? '未生成' : scope.row.reportState === 1 ? '部分生成' : '全部生成'
)
},
},
{
prop: 'result',
label: '检测结果',
width: 120,
enum:dictResult,
search: { el: 'select', props: { filterable: true } },
fieldNames: { label: 'label', value: 'id' },
render: scope => {
console.log('检测结果',scope.row.result)
return (
scope.row.result === 0 ? '不符合' : scope.row.result === 1 ? '符合' : '/'
)
},
},
{
prop: 'createTime',
label: '创建时间',
width: 200,
render: scope => {
if (scope.row.createTime) {
const date = new Date(scope.row.createTime);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
return '';
}
},
{
prop: 'sourceName',
label: '检测源',
minWidth: 400,
render: scope => {
const sourceNames = Array.isArray(scope.row.sourceName) ? scope.row.sourceName : [];
const sourceIds = Array.isArray(scope.row.sourceIds) ? scope.row.sourceIds : [];
const firstSourceName = sourceNames[0];
const firstSourceId = sourceIds[0];
const remainingSourceNames = sourceNames.slice(1);
const remainingSourceIds = sourceIds.slice(1);
return (
<div class='flx-flex-start'>
{firstSourceName && (
<el-link type='primary' link onClick={() => showTestSource(firstSourceId)}>
{firstSourceName}
</el-link>
)}
<moreButtons isShow={isVisible(scope.row)}
sourceNames={remainingSourceNames}//长度>1传给更多子组件从第二位开始的名字
sourceIds={remainingSourceIds} //长度>1时传给更多子组件从第二位开始的id
onSource-clicked={showTestSource}
/>
</div>
)
},
},
{
prop: 'scriptId',
label: '检测脚本',
width: 360,
render: scope => {
return (
<span>{scope.row.scriptName}</span>
)
},
},
{
prop: 'errorSysId',
label: '误差体系',
width: 200,
render: scope => {
return (
<el-link type='primary' link onClick={() => showData(scope.row)}>
{scope.row.errorSysName}
</el-link>
)
},
},
{
prop: 'datasourceIds',
label: '数据源',
enum: dictStore.getDictData(dataSourceType.value),
fieldNames: { label: 'name', value: 'value' },
minWidth: 250,
render: (scope) => {
const codes = scope.row.datasourceIds // 获取当前行的 datasourceIds 字段
if (!codes) {
return '/'
}
// 确保 codes 是一个字符串
const codeString = Array.isArray(codes) ? codes.join(',') : codes
const codeArray = codeString.split(',')
if (codeArray.length > 1) {
// 查找与每个 code 值匹配的 name然后拼接成逗号分割的字符串
const names = codeArray.map(code => {
const dictItem = dictStore.getDictData(dataSourceType.value).find(item => item.value === code)
return dictItem ? dictItem.name : '/' // 如果找到匹配的项,返回对应的 name
})
return names.join(', ') // 用逗号连接所有的 name
}
// 查找单个 code 对应的 name
const dictItem = dictStore.getDictData(dataSourceType.value).find(item => item.value === codeArray[0])
return dictItem ? dictItem.name : '/' // 如果找到匹配的项,返回对应的 name
},
},
{ prop: 'operation', label: '操作', fixed: 'right', width: 300 },
])
function isVisible(row: Plan.ReqPlan) {
if(!row.hasOwnProperty('sourceName') || !Array.isArray(row.sourceName)){
return false
}
else if(row.sourceName.length <= 1){
return false
}
else{
return true
}
}
function showData(row: any) {
let split = row.errorSysName.split('-')
errorStandardPopup.value?.open(row.errorSysName, {id:row.errorSysId,devLevel:split[split.length-1]})
}
async function showTestSource(row:string) {
const patternId = dictStore.getDictData('Pattern').find(item=>item.name=== modeStore.currentMode)?.id ?? ''//获取数据字典中对应的id
const params: TestSource.ResTestSource = {
id: row, // 根据实际情况设
pattern: patternId,
type: '',
devType: '',
state: 0
};
const result = await getTestSourceById(params);
testSourcePopup.value?.open('view', result.data, modeStore.currentMode);
}
function showTestScript(row: string) {
}
function handleFiles(event: Event) {
const target = event.target as HTMLInputElement
const files = target.files
if (files && files.length > 0) {
// 处理文件
// console.log(files)
ElMessageBox.confirm(
'导入的数据与当前数据有冲突,请选择以哪个数据为主进行覆盖',
'数据冲突',
{
distinguishCancelAndClose: true,
confirmButtonText: '以导入数据为主覆盖',
cancelButtonText: '以当前数据为主覆盖',
type: 'warning',
},
)
.then(() => {
ElMessage({
type: 'info',
message: '以导入数据为主完成数据覆盖',
})
})
.catch((action: Action) => {
ElMessage({
type: 'info',
message:
action === 'cancel'
? '以当前数据为主完成数据覆盖'
: '取消本次导入操作',
})
})
}
}
// 点击导入按钮
const importClick = () => {
const params = {
title: '检测计划',
showCover: false,
patternId: dictStore.getDictData('Pattern').find(item=>item.name=== modeStore.currentMode)?.id ?? '',
tempApi: downloadCNPlanTemplate,
importApi: importCNPlan,
getTableList: proTable.value?.getTableList,
}
planImportExcel.value?.acceptParams(params)
}
// 点击导出按钮
const exportClick = () => {
ElMessageBox.confirm('确认导出检测计划?', '温馨提示', { type: 'warning' }).then(() =>{
const patternId = dictStore.getDictData('Pattern').find(item=>item.name=== modeStore.currentMode)?.id//获取数据字典中对应的id
useDownload(exportCNPlan,'检测计划导出数据', {...proTable.value?.searchParam,pattern:patternId}, false,'.xlsx')
})
}
// 点击合并按钮
const combineClick = () => {
ElMessageBox.prompt(
'请输入合并后的计划名称',
'检测计划合并',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
},
)
.then(({ value }) => {
// console.log(`合并后的计划名为:`, value)
proTable.value?.clearSelection()
proTable.value?.getTableList()
})
}
// 打开 drawer(新增、编辑)
const openDialog = (titleType: string, row: Partial<Plan.ReqPlan> = {}) => {
planPopup.value?.open(titleType, row,modeStore.currentMode)
}
// 批量删除设备
const batchDelete = async (id: string[]) => {
await useHandleData(deletePlan, id, '删除所选检测计划')
proTable.value?.clearSelection()
proTable.value?.getTableList()
}
// 删除检测计划
const handleDelete = async (params: Plan.ReqPlanParams) => {
await useHandleData(deletePlan, [params.id], `删除【${params.name}】检测计划`)
proTable.value?.getTableList()
}
const showDeviceOpen = (row: Partial<Plan.ReqPlan> = {}) => {
devTransferPopup.value.open(row)
}
const myDict = new Map<string, any[]>();
const statisticalAnalysisMore = async (ids: string[], rows: Plan.ReqPlan[]) => {
const hasInvalidState = rows.some(row => row.testState != 2);
if (hasInvalidState) {
ElMessage({
type: 'error',
message: '存在检测状态不为检测完成的计划,无法进行统计分析。',
});
proTable.value?.clearSelection()
return;
}
useDownload(staticsAnalyse,'分析结果', ids, false,'.xlsx')
}
const statisticalAnalysis = async (row: Partial<Plan.ReqPlan> = {}) => {
useDownload(staticsAnalyse,'分析结果', [row.id], false,'.xlsx')
// const response = await getTestConfig() as unknown as Base.ResTestConfig
// const maxTime= response.data.maxTime//检测最大次数
// const dev = await getBoundPqDevList({ 'planId': row.id })
// for (let i = 0; i <= maxTime; i++) {
// dev.data.forEach((item: any) => {
// if(item.reCheckNum === i){
// // 向已有的数组中添加元素
// if (myDict.has(i.toString())) {
// myDict.get(i.toString())?.push(item.name);
// }else{
// myDict.set(i.toString(), [item.name]);
// }
// }
// })
// }
// for (let i = 0; i <= maxTime; i++) {
// if (myDict.has(i.toString())) {
// const array = myDict.get(i.toString());
// if (array) {
// for (const value of array) {
// console.log(i + '---'+value);
// }
// }
// }
// }
}
</script>
<style scoped>
</style>