Files
CN_Tool_client/frontend/src/views/steady/checksquare/components/ChecksquareTaskTable.vue
yexb 92b7d3cd73 refactor(steady): 重构稳态校验功能的合同验证逻辑
- 优化测量点对话框路径解析格式化
- 添加稳态校验重启API端点验证功能
- 更新创建参数类型定义支持可选lineId和lineIds数组
- 修复任务表格组件模板缩进格式问题
- 扩展任务表格列配置验证数组格式
- 添加任务表格仅对失败行显示重启操作功能
- 集成共享台账树组件发送选中叶节点监测点功能
- 添加多监测点创建参数构建支持
- 实现指标选择为空时全指标校验功能
- 添加预期项目数量计算功能
- 优化创建对话框指标选择标签防止输入框重置
- 添加任务表格树形选择滚动下拉菜单样式
- 实现页面创建流程调用创建API并轮询任务状态
- 添加创建结果面板加载状态和进度显示
- 实现页面重启流程确认调用重启API功能
- 优化汇总表格异常字段持久化支持
- 添加汇总表格监测点名称显示功能
- 优化详情面板按需加载项目详情
- 更新接口类型支持分页字段定义
- 优化ICD路径检查对话框标准映射参数传递
- 添加ICD记录导出SQL和JSON功能
- 扩展ICD路径API端点和类型定义
- 添加ICD路径参考选项和映射详情功能
- 重构ICD表格列显示移除激活和创建时间列
- 添加ICD映射详情对话框三个标签页功能
- 优化ICD映射详情JSON树形视图显示
- 更新ICD类型选项覆盖手动和上游标准状态
2026-06-18 16:35:06 +08:00

349 lines
11 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>
<ProTable
ref="proTable"
row-key="taskId"
:columns="columns"
:request-api="getTableList"
:search-col="{ xs: 1, sm: 2, md: 2, lg: 5, xl: 5 }"
>
<template #tableHeader>
<el-button type="primary" :icon="Plus" @click="emit('createTask')">新增</el-button>
</template>
<template #operation="{ row }">
<el-button
v-if="row.taskStatus === 'FAIL'"
type="primary"
link
:icon="RefreshRight"
@click="emit('restart', row)"
>
重启
</el-button>
<el-button type="danger" link :icon="Delete" @click="emit('delete', row)">删除</el-button>
</template>
</ProTable>
</template>
<script setup lang="ts">
import { computed, h, reactive, ref } from 'vue'
import { ElButton, ElDatePicker, ElTag, ElTreeSelect } from 'element-plus'
import { Delete, Plus, RefreshRight } from '@element-plus/icons-vue'
import ProTable from '@/components/ProTable/index.vue'
import type { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
import type { SteadyDataView } from '@/api/steady/steadyDataView/interface'
import {
buildChecksquareTaskQueryParams,
formatChecksquareIntegrity,
formatChecksquareTaskStatus,
resolveChecksquareTaskStatusType,
resolveChecksquareText,
type ChecksquareTaskSearchParams
} from '../utils/checksquareTaskTable'
defineOptions({
name: 'ChecksquareTaskTable'
})
const props = defineProps<{
ledgerTree: SteadyDataView.SteadyLedgerNode[]
indicatorTree: SteadyDataView.SteadyIndicatorNode[]
requestApi: (params: SteadyDataView.SteadyChecksquareTaskQueryParams) => Promise<any>
}>()
const emit = defineEmits<{
createTask: []
detail: [row: SteadyDataView.SteadyChecksquareTask]
restart: [row: SteadyDataView.SteadyChecksquareTask]
delete: [row: SteadyDataView.SteadyChecksquareTask]
viewMeasurementPoint: [row: SteadyDataView.SteadyChecksquareTask]
}>()
const proTable = ref<ProTableInstance>()
interface ChecksquareFilterTreeNode {
label: string
value: string
disabled?: boolean
children?: ChecksquareFilterTreeNode[]
}
const normalizeLineFilterTree = (nodes: SteadyDataView.SteadyLedgerNode[]): ChecksquareFilterTreeNode[] => {
return nodes.map(node => ({
label: node.name,
value: node.id,
disabled: node.level !== 3 || node.selectable === false,
children: node.children?.length ? normalizeLineFilterTree(node.children) : undefined
}))
}
const normalizeIndicatorFilterTree = (
nodes: SteadyDataView.SteadyIndicatorNode[],
parentKey = ''
): ChecksquareFilterTreeNode[] => {
return nodes.map((node, index) => {
const isLeaf = !node.children?.length
const value =
isLeaf && node.indicatorCode
? node.indicatorCode
: node.id || `${parentKey}${node.groupCode || node.name || 'node'}-${index}`
return {
label: node.unit ? `${node.name}${node.unit}` : node.name,
value,
disabled: !isLeaf || !node.indicatorCode,
children: node.children?.length ? normalizeIndicatorFilterTree(node.children, `${value}-`) : undefined
}
})
}
const lineFilterTree = computed(() => normalizeLineFilterTree(props.ledgerTree))
const indicatorFilterTree = computed(() => normalizeIndicatorFilterTree(props.indicatorTree))
const splitTreeSelectValues = (value?: string) => {
return (value || '')
.split(',')
.map(item => item.trim())
.filter(Boolean)
}
const normalizeTreeSelectValues = (value: unknown) => {
const rawValues = Array.isArray(value) ? value : value === undefined || value === null || value === '' ? [] : [value]
return Array.from(
new Set(
rawValues
.filter((item): item is string | number => typeof item === 'string' || typeof item === 'number')
.map(item => String(item).trim())
.filter(Boolean)
)
)
}
const renderTimeRangeSearch = ({ searchParam }: { searchParam: ChecksquareTaskSearchParams }) =>
h(ElDatePicker, {
modelValue: searchParam.taskTimeRange,
type: 'datetimerange',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
clearable: true,
'onUpdate:modelValue': (value: string[] | null) => {
searchParam.taskTimeRange = value || undefined
}
})
const renderLineSearch = ({ searchParam }: { searchParam: ChecksquareTaskSearchParams }) =>
h(ElTreeSelect, {
class: 'checksquare-search-tree-select',
style: { width: '100%' },
modelValue: splitTreeSelectValues(searchParam.lineId),
data: lineFilterTree.value,
nodeKey: 'value',
multiple: true,
showCheckbox: true,
collapseTags: true,
collapseTagsTooltip: true,
maxCollapseTags: 1,
popperClass: 'checksquare-search-tree-popper',
filterable: true,
clearable: true,
defaultExpandAll: true,
checkStrictly: true,
props: { label: 'label', children: 'children', disabled: 'disabled' },
placeholder: '请选择监测点',
'onUpdate:modelValue': (value: unknown) => {
const selectedValues = normalizeTreeSelectValues(value)
searchParam.lineId = selectedValues.length ? selectedValues.join(',') : undefined
}
})
const renderIndicatorSearch = ({ searchParam }: { searchParam: ChecksquareTaskSearchParams }) =>
h(ElTreeSelect, {
class: 'checksquare-search-tree-select',
style: { width: '100%' },
modelValue: splitTreeSelectValues(searchParam.indicatorCode),
data: indicatorFilterTree.value,
nodeKey: 'value',
multiple: true,
showCheckbox: true,
collapseTags: true,
collapseTagsTooltip: true,
maxCollapseTags: 1,
popperClass: 'checksquare-search-tree-popper',
filterable: true,
clearable: true,
defaultExpandAll: true,
checkStrictly: true,
props: { label: 'label', children: 'children', disabled: 'disabled' },
placeholder: '请选择稳态指标',
'onUpdate:modelValue': (value: unknown) => {
const selectedValues = normalizeTreeSelectValues(value)
searchParam.indicatorCode = selectedValues.length ? selectedValues.join(',') : undefined
}
})
const columns = reactive<ColumnProps<SteadyDataView.SteadyChecksquareTask>[]>([
{ type: 'index', fixed: 'left', width: 70, label: '序号' },
{
prop: 'taskNo',
label: '任务编号',
minWidth: 180,
render: ({ row }) => resolveChecksquareText(row.taskNo)
},
{
prop: 'lineId',
label: '监测点ID',
isShow: false,
isSetting: false,
search: {
label: '监测点',
order: 2,
render: renderLineSearch
}
},
{
prop: 'lineName',
label: '监测点名称',
minWidth: 160,
render: ({ row }) =>
h(
ElButton,
{
type: 'primary',
link: true,
onClick: () => emit('viewMeasurementPoint', row)
},
() => resolveChecksquareText(row.lineName || row.lineId)
)
},
{
prop: 'indicatorCode',
label: '稳态指标',
isShow: false,
isSetting: false,
search: {
label: '稳态指标',
order: 3,
render: renderIndicatorSearch
}
},
{
prop: 'timeStart',
label: '开始时间',
minWidth: 170,
render: ({ row }) => resolveChecksquareText(row.timeStart),
search: {
label: '检测时间',
key: 'taskTimeRange',
order: 1,
render: renderTimeRangeSearch
}
},
{
prop: 'timeEnd',
label: '结束时间',
minWidth: 170,
render: ({ row }) => resolveChecksquareText(row.timeEnd)
},
{
prop: 'taskStatus',
label: '任务状态',
minWidth: 110,
render: ({ row }) =>
h(
ElTag,
{ type: resolveChecksquareTaskStatusType(row.taskStatus), effect: 'plain' },
() => formatChecksquareTaskStatus(row.taskStatus)
)
},
{
prop: 'itemCount',
label: '检测项数',
minWidth: 100,
align: 'center',
render: ({ row }) => resolveChecksquareText(row.itemCount)
},
{
prop: 'abnormalItemCount',
label: '异常项数',
minWidth: 100,
align: 'center',
render: ({ row }) =>
h(
ElButton,
{
type: 'primary',
link: true,
onClick: () => emit('detail', row)
},
() => resolveChecksquareText(row.abnormalItemCount)
),
search: {
label: '异常状态',
key: 'hasAbnormal',
order: 4,
el: 'select'
},
enum: [
{ label: '存在异常', value: true },
{ label: '全部', value: false }
],
isFilterEnum: false
},
{
prop: 'minDataIntegrity',
label: '最低完整性',
minWidth: 120,
align: 'center',
render: ({ row }) => formatChecksquareIntegrity(row.minDataIntegrity)
},
{
prop: 'createTime',
label: '创建时间',
minWidth: 170,
render: ({ row }) => resolveChecksquareText(row.createTime)
},
{ prop: 'operation', label: '操作', fixed: 'right', width: 180 }
])
const getTableList = (params: ChecksquareTaskSearchParams) => {
return props.requestApi(buildChecksquareTaskQueryParams(params))
}
const refresh = () => {
proTable.value?.getTableList()
}
defineExpose({
refresh
})
</script>
<style scoped lang="scss">
.checksquare-search-tree-select {
width: 100%;
}
:deep(.checksquare-search-tree-select .el-select__wrapper) {
min-height: 32px;
}
:deep(.checksquare-search-tree-select .el-select__selection) {
min-width: 0;
}
:deep(.checksquare-search-tree-select .el-select__tags-text) {
display: inline-block;
max-width: 120px;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: bottom;
white-space: nowrap;
}
:global(.checksquare-search-tree-popper .el-select-dropdown__wrap) {
max-height: 280px;
}
</style>