- 优化测量点对话框路径解析格式化 - 添加稳态校验重启API端点验证功能 - 更新创建参数类型定义支持可选lineId和lineIds数组 - 修复任务表格组件模板缩进格式问题 - 扩展任务表格列配置验证数组格式 - 添加任务表格仅对失败行显示重启操作功能 - 集成共享台账树组件发送选中叶节点监测点功能 - 添加多监测点创建参数构建支持 - 实现指标选择为空时全指标校验功能 - 添加预期项目数量计算功能 - 优化创建对话框指标选择标签防止输入框重置 - 添加任务表格树形选择滚动下拉菜单样式 - 实现页面创建流程调用创建API并轮询任务状态 - 添加创建结果面板加载状态和进度显示 - 实现页面重启流程确认调用重启API功能 - 优化汇总表格异常字段持久化支持 - 添加汇总表格监测点名称显示功能 - 优化详情面板按需加载项目详情 - 更新接口类型支持分页字段定义 - 优化ICD路径检查对话框标准映射参数传递 - 添加ICD记录导出SQL和JSON功能 - 扩展ICD路径API端点和类型定义 - 添加ICD路径参考选项和映射详情功能 - 重构ICD表格列显示移除激活和创建时间列 - 添加ICD映射详情对话框三个标签页功能 - 优化ICD映射详情JSON树形视图显示 - 更新ICD类型选项覆盖手动和上游标准状态
349 lines
11 KiB
Vue
349 lines
11 KiB
Vue
<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>
|