From 333a93571452073a9e628c6256044d345099aa50 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期四, 02 四月 2026 08:19:55 +0800
Subject: [PATCH] #
---
rsf-design/src/views/basic-info/task-path-template/modules/task-path-template-flow-drawer.vue | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 366 insertions(+), 38 deletions(-)
diff --git a/rsf-design/src/views/basic-info/task-path-template/modules/task-path-template-flow-drawer.vue b/rsf-design/src/views/basic-info/task-path-template/modules/task-path-template-flow-drawer.vue
index c0f68ba..a4f8fbe 100644
--- a/rsf-design/src/views/basic-info/task-path-template/modules/task-path-template-flow-drawer.vue
+++ b/rsf-design/src/views/basic-info/task-path-template/modules/task-path-template-flow-drawer.vue
@@ -2,60 +2,203 @@
<ElDrawer
:model-value="visible"
title="娴佺▼鍥炬煡鐪�"
- size="900px"
+ size="92%"
destroy-on-close
@update:model-value="handleVisibleChange"
>
- <ElScrollbar class="h-[calc(100vh-180px)] pr-1">
- <div v-if="loading" class="py-6">
- <ElSkeleton :rows="10" animated />
- </div>
- <div v-else class="space-y-4">
- <ElCard shadow="never" class="art-table-card">
+ <div class="flex h-[calc(100vh-160px)] flex-col gap-4">
+ <ElCard shadow="never" class="shrink-0">
+ <div class="flex items-start justify-between gap-4">
+ <div class="min-w-0">
+ <div class="text-base font-semibold text-[var(--art-text-primary)]">
+ {{ detail.templateName || detail.templateCode || '--' }}
+ </div>
+ <div class="mt-1 text-sm text-[var(--art-text-secondary)]">
+ 妯℃澘缂栫爜 {{ detail.templateCode || '--' }}锛岃捣鐐� {{ detail.sourceType || '--' }}锛岀粓鐐�
+ {{ detail.targetType || '--' }}
+ </div>
+ </div>
+ <ElSpace wrap>
+ <ElTag :type="detail.statusType || 'info'" effect="light">
+ {{ detail.statusText || '--' }}
+ </ElTag>
+ <ElTag :type="detail.isCurrentType || 'info'" effect="light">
+ {{ detail.isCurrentText || '--' }}
+ </ElTag>
+ </ElSpace>
+ </div>
+ </ElCard>
+
+ <div class="grid min-h-0 flex-1 gap-4 xl:grid-cols-3">
+ <ElCard shadow="never" class="min-h-0">
<template #header>
<div class="flex items-center justify-between gap-3">
- <div>
- <h3 class="m-0 text-base font-semibold">妯℃澘娴佺▼蹇収</h3>
- <p class="m-0 text-sm text-[var(--art-text-secondary)]">
- 杩欓噷灞曠ず鐨勬槸鍚庣妯℃澘瀛楁缁勫悎鍑虹殑鐪熷疄娴佺▼淇℃伅锛屼笉鍋氶澶栧亣鏁版嵁鎺ㄦ紨銆�
- </p>
- </div>
- <ElTag :type="detail.statusType || 'info'" effect="light">
- {{ detail.statusText || '--' }}
- </ElTag>
+ <span class="font-medium">妯℃澘鑺傜偣</span>
+ <span class="text-xs text-[var(--art-text-secondary)]">
+ {{ nodeLoading ? '鍔犺浇涓�' : `绗� ${nodePagination.current} 椤� / 鍏� ${nodePagination.total} 鏉 }}
+ </span>
</div>
</template>
- <div class="grid gap-3 md:grid-cols-4">
- <div
- v-for="item in flowSnapshot"
- :key="item.key"
- class="rounded-lg border border-[var(--art-border-color)] bg-[var(--art-main-bg-color)] p-4"
- >
- <div class="text-sm text-[var(--art-text-secondary)]">{{ item.title }}</div>
- <div class="mt-2 text-base font-semibold text-[var(--art-text-primary)]">
- {{ item.value }}
+ <div class="flex h-[calc(100vh-300px)] flex-col">
+ <ElSkeleton v-if="loading || nodeLoading" :rows="8" animated />
+ <ElEmpty
+ v-else-if="nodeRows.length === 0"
+ description="鏆傛棤鑺傜偣鏁版嵁"
+ :image-size="100"
+ />
+ <template v-else>
+ <ElTable
+ :data="nodeRows"
+ border
+ highlight-current-row
+ height="100%"
+ :current-row-key="selectedNodeId"
+ row-key="id"
+ @current-change="handleNodeClick"
+ >
+ <ElTableColumn prop="nodeOrder" label="椤哄簭" width="72" align="center" />
+ <ElTableColumn prop="nodeCode" label="鑺傜偣缂栫爜" min-width="140" show-overflow-tooltip />
+ <ElTableColumn prop="nodeName" label="鑺傜偣鍚嶇О" min-width="160" show-overflow-tooltip />
+ <ElTableColumn prop="systemCode" label="绯荤粺缂栫爜" min-width="140" show-overflow-tooltip />
+ </ElTable>
+ <div class="mt-3 flex justify-end">
+ <ElPagination
+ small
+ background
+ layout="prev, pager, next"
+ :current-page="nodePagination.current"
+ :page-size="nodePagination.pageSize"
+ :total="nodePagination.total"
+ @current-change="handleNodePageChange"
+ />
</div>
- </div>
+ </template>
</div>
</ElCard>
- <ElDescriptions title="娴佺▼渚濇嵁" :column="2" border>
- <ElDescriptionsItem label="妯℃澘缂栫爜">{{ detail.templateCode || '--' }}</ElDescriptionsItem>
- <ElDescriptionsItem label="妯℃澘鍚嶇О">{{ detail.templateName || '--' }}</ElDescriptionsItem>
- <ElDescriptionsItem label="璧风偣绫诲瀷">{{ detail.sourceType || '--' }}</ElDescriptionsItem>
- <ElDescriptionsItem label="缁堢偣绫诲瀷">{{ detail.targetType || '--' }}</ElDescriptionsItem>
- <ElDescriptionsItem label="姝ュ簭闀垮害">{{ detail.stepSize ?? '--' }}</ElDescriptionsItem>
- <ElDescriptionsItem label="浼樺厛绾�">{{ detail.priority ?? '--' }}</ElDescriptionsItem>
- </ElDescriptions>
+ <ElCard shadow="never" class="min-h-0">
+ <template #header>
+ <div class="flex items-center justify-between gap-3">
+ <span class="font-medium">瀛愮郴缁熸祦绋�</span>
+ <span class="text-xs text-[var(--art-text-secondary)]">
+ {{
+ flowLoading
+ ? '鍔犺浇涓�'
+ : selectedNodeId
+ ? `绗� ${flowPagination.current} 椤� / 鍏� ${flowPagination.total} 鏉
+ : '寰呴�夋嫨鑺傜偣'
+ }}
+ </span>
+ </div>
+ </template>
+
+ <div class="flex h-[calc(100vh-300px)] flex-col">
+ <div
+ v-if="!selectedNodeId"
+ class="flex h-full items-center justify-center text-sm text-[var(--art-text-secondary)]"
+ >
+ 璇峰厛閫夋嫨宸︿晶妯℃澘鑺傜偣
+ </div>
+ <ElSkeleton v-else-if="flowLoading" :rows="8" animated />
+ <ElEmpty
+ v-else-if="flowRows.length === 0"
+ description="鏆傛棤娴佺▼鏁版嵁"
+ :image-size="100"
+ />
+ <template v-else>
+ <ElTable
+ :data="flowRows"
+ border
+ highlight-current-row
+ height="100%"
+ :current-row-key="selectedFlowId"
+ row-key="id"
+ @current-change="handleFlowClick"
+ >
+ <ElTableColumn prop="flowCode" label="娴佺▼缂栫爜" min-width="160" show-overflow-tooltip />
+ <ElTableColumn prop="flowName" label="娴佺▼鍚嶇О" min-width="180" show-overflow-tooltip />
+ <ElTableColumn prop="systemCode" label="绯荤粺缂栫爜" min-width="140" show-overflow-tooltip />
+ </ElTable>
+ <div class="mt-3 flex justify-end">
+ <ElPagination
+ small
+ background
+ layout="prev, pager, next"
+ :current-page="flowPagination.current"
+ :page-size="flowPagination.pageSize"
+ :total="flowPagination.total"
+ @current-change="handleFlowPageChange"
+ />
+ </div>
+ </template>
+ </div>
+ </ElCard>
+
+ <ElCard shadow="never" class="min-h-0">
+ <template #header>
+ <div class="flex items-center justify-between gap-3">
+ <span class="font-medium">娴佺▼姝ラ</span>
+ <span class="text-xs text-[var(--art-text-secondary)]">
+ {{
+ stepLoading
+ ? '鍔犺浇涓�'
+ : selectedFlowId
+ ? `绗� ${stepPagination.current} 椤� / 鍏� ${stepPagination.total} 鏉
+ : '寰呴�夋嫨娴佺▼'
+ }}
+ </span>
+ </div>
+ </template>
+
+ <div class="flex h-[calc(100vh-300px)] flex-col">
+ <div
+ v-if="!selectedFlowId"
+ class="flex h-full items-center justify-center text-sm text-[var(--art-text-secondary)]"
+ >
+ 璇峰厛閫夋嫨涓棿瀛愮郴缁熸祦绋�
+ </div>
+ <ElSkeleton v-else-if="stepLoading" :rows="8" animated />
+ <ElEmpty
+ v-else-if="stepRows.length === 0"
+ description="鏆傛棤姝ラ鏁版嵁"
+ :image-size="100"
+ />
+ <template v-else>
+ <ElTable :data="stepRows" border height="100%" row-key="id">
+ <ElTableColumn prop="stepOrder" label="椤哄簭" width="72" align="center" />
+ <ElTableColumn prop="stepCode" label="姝ラ缂栫爜" min-width="140" show-overflow-tooltip />
+ <ElTableColumn prop="stepName" label="姝ラ鍚嶇О" min-width="180" show-overflow-tooltip />
+ <ElTableColumn prop="stepType" label="姝ラ绫诲瀷" min-width="140" show-overflow-tooltip />
+ </ElTable>
+ <div class="mt-3 flex justify-end">
+ <ElPagination
+ small
+ background
+ layout="prev, pager, next"
+ :current-page="stepPagination.current"
+ :page-size="stepPagination.pageSize"
+ :total="stepPagination.total"
+ @current-change="handleStepPageChange"
+ />
+ </div>
+ </template>
+ </div>
+ </ElCard>
</div>
- </ElScrollbar>
+ </div>
</ElDrawer>
</template>
<script setup>
- import { computed } from 'vue'
- import { buildTaskPathTemplateFlowSnapshot } from '../taskPathTemplatePage.helpers'
+ import { computed, ref, watch } from 'vue'
+ import { ElMessage } from 'element-plus'
+ import { guardRequestWithMessage } from '@/utils/sys/requestGuard'
+ import {
+ fetchTaskPathTemplateNodePage
+ } from '@/api/task-path-template-node'
+ import { fetchSubsystemFlowTemplatePage } from '@/api/subsystem-flow-template'
+ import { fetchFlowStepTemplatePage } from '@/api/flow-step-template'
const props = defineProps({
visible: { type: Boolean, default: false },
@@ -70,9 +213,194 @@
set: (value) => emit('update:visible', value)
})
- const flowSnapshot = computed(() => buildTaskPathTemplateFlowSnapshot(props.detail))
+ const nodeLoading = ref(false)
+ const flowLoading = ref(false)
+ const stepLoading = ref(false)
+ const nodeRows = ref([])
+ const flowRows = ref([])
+ const stepRows = ref([])
+ const selectedNodeId = ref(null)
+ const selectedFlowId = ref(null)
+ const DEFAULT_PAGE_SIZE = 20
+ const nodePagination = ref({ current: 1, pageSize: DEFAULT_PAGE_SIZE, total: 0 })
+ const flowPagination = ref({ current: 1, pageSize: DEFAULT_PAGE_SIZE, total: 0 })
+ const stepPagination = ref({ current: 1, pageSize: DEFAULT_PAGE_SIZE, total: 0 })
+
+ function normalizeRecords(response) {
+ return Array.isArray(response?.records) ? response.records : []
+ }
+
+ function normalizeTotal(response) {
+ const total = Number(response?.total)
+ return Number.isNaN(total) ? 0 : total
+ }
+
+ function resetFlowState() {
+ nodeRows.value = []
+ flowRows.value = []
+ stepRows.value = []
+ selectedNodeId.value = null
+ selectedFlowId.value = null
+ nodePagination.value.current = 1
+ nodePagination.value.total = 0
+ flowPagination.value.current = 1
+ flowPagination.value.total = 0
+ stepPagination.value.current = 1
+ stepPagination.value.total = 0
+ }
+
+ async function loadStepRows(flowId, current = stepPagination.value.current) {
+ if (!flowId) {
+ stepRows.value = []
+ selectedFlowId.value = null
+ stepPagination.value.total = 0
+ return
+ }
+
+ stepLoading.value = true
+ try {
+ const response = await guardRequestWithMessage(
+ fetchFlowStepTemplatePage({
+ current,
+ pageSize: stepPagination.value.pageSize,
+ flowId
+ }),
+ { records: [] },
+ { timeoutMessage: '娴佺▼姝ラ鍔犺浇瓒呮椂锛屽凡鍋滄绛夊緟' }
+ )
+ stepRows.value = normalizeRecords(response)
+ stepPagination.value.current = current
+ stepPagination.value.total = normalizeTotal(response)
+ } catch (error) {
+ stepRows.value = []
+ stepPagination.value.total = 0
+ ElMessage.error(error?.message || '娴佺▼姝ラ鍔犺浇澶辫触')
+ } finally {
+ stepLoading.value = false
+ }
+ }
+
+ async function loadFlowRows(node, current = flowPagination.value.current) {
+ if (!node?.nodeCode) {
+ flowRows.value = []
+ stepRows.value = []
+ selectedFlowId.value = null
+ flowPagination.value.total = 0
+ stepPagination.value.total = 0
+ return
+ }
+
+ flowLoading.value = true
+ try {
+ const response = await guardRequestWithMessage(
+ fetchSubsystemFlowTemplatePage({
+ current,
+ pageSize: flowPagination.value.pageSize,
+ flowCode: node.nodeCode
+ }),
+ { records: [] },
+ { timeoutMessage: '瀛愮郴缁熸祦绋嬪姞杞借秴鏃讹紝宸插仠姝㈢瓑寰�' }
+ )
+ flowRows.value = normalizeRecords(response)
+ flowPagination.value.current = current
+ flowPagination.value.total = normalizeTotal(response)
+ selectedFlowId.value = null
+ stepRows.value = []
+ stepPagination.value.current = 1
+ stepPagination.value.total = 0
+ } catch (error) {
+ flowRows.value = []
+ stepRows.value = []
+ selectedFlowId.value = null
+ flowPagination.value.total = 0
+ stepPagination.value.total = 0
+ ElMessage.error(error?.message || '瀛愮郴缁熸祦绋嬪姞杞藉け璐�')
+ } finally {
+ flowLoading.value = false
+ }
+ }
+
+ async function loadNodeRows(templateId, current = nodePagination.value.current) {
+ if (!templateId) {
+ resetFlowState()
+ return
+ }
+
+ nodeLoading.value = true
+ try {
+ const response = await guardRequestWithMessage(
+ fetchTaskPathTemplateNodePage({
+ current,
+ pageSize: nodePagination.value.pageSize,
+ templateId
+ }),
+ { records: [] },
+ { timeoutMessage: '妯℃澘鑺傜偣鍔犺浇瓒呮椂锛屽凡鍋滄绛夊緟' }
+ )
+ nodeRows.value = normalizeRecords(response)
+ nodePagination.value.current = current
+ nodePagination.value.total = normalizeTotal(response)
+ selectedNodeId.value = null
+ flowRows.value = []
+ stepRows.value = []
+ flowPagination.value.current = 1
+ flowPagination.value.total = 0
+ stepPagination.value.current = 1
+ stepPagination.value.total = 0
+ } catch (error) {
+ resetFlowState()
+ ElMessage.error(error?.message || '妯℃澘鑺傜偣鍔犺浇澶辫触')
+ } finally {
+ nodeLoading.value = false
+ }
+ }
+
+ function handleNodeClick(node) {
+ if (!node || selectedNodeId.value === node.id) return
+ selectedNodeId.value = node.id
+ selectedFlowId.value = null
+ stepRows.value = []
+ flowPagination.value.current = 1
+ stepPagination.value.current = 1
+ loadFlowRows(node)
+ }
+
+ function handleFlowClick(flow) {
+ if (!flow || selectedFlowId.value === flow.id) return
+ selectedFlowId.value = flow.id
+ stepPagination.value.current = 1
+ loadStepRows(flow.id)
+ }
+
+ function handleNodePageChange(current) {
+ loadNodeRows(props.detail?.id, current)
+ }
+
+ function handleFlowPageChange(current) {
+ const node = nodeRows.value.find((item) => item.id === selectedNodeId.value)
+ if (!node) return
+ loadFlowRows(node, current)
+ }
+
+ function handleStepPageChange(current) {
+ if (!selectedFlowId.value) return
+ loadStepRows(selectedFlowId.value, current)
+ }
function handleVisibleChange(value) {
visible.value = value
}
+
+ watch(
+ () => [props.visible, props.detail?.id],
+ ([isVisible, detailId]) => {
+ if (isVisible && detailId) {
+ loadNodeRows(detailId)
+ }
+ if (!isVisible) {
+ resetFlowState()
+ }
+ },
+ { immediate: true }
+ )
</script>
--
Gitblit v1.9.1