fix(diagram): 嵌入页补滚动容器(裸渲染页被全局 body overflow:hidden 裁剪无滚动条)+ 流程图 PNG 按逻辑尺寸显示(SCALE=2 图按自然尺寸渲染整体放大一倍,四处 PNG 消费点统一走 fitDiagram)
build / build (push) Successful in 3m46s
build / build (push) Successful in 3m46s
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 流程示意图 PNG 显示口径(2026-10-10 用户反馈:嵌入页图过大):服务端 DiagramImageService
|
||||
* 按 SCALE=2 出图(视网膜清晰度),页面若按自然尺寸渲染等于整体放大一倍。
|
||||
* 须按逻辑尺寸(自然宽一半)显示;>3 分支等超宽长图再收缩到容器宽。
|
||||
* 用法:<img ref="diagramEl" :src="..." @load="onDiagramLoad">,onMounted 里对 complete 的图补调一次。
|
||||
*/
|
||||
export function fitDiagram(el: HTMLImageElement | null | undefined): void {
|
||||
if (!el || !el.naturalWidth) return;
|
||||
const want = el.naturalWidth / 2;
|
||||
const cap = (el.parentElement?.clientWidth || 0) - 8; // Card body 左右衬
|
||||
el.style.width = Math.round(Math.min(want, cap > 120 ? cap : want)) + "px";
|
||||
}
|
||||
@@ -3,11 +3,12 @@
|
||||
// 展示"进度 + 流程示意图",零样式复制、单点维护。全程零 CAS 交互——数据走 /open/flow/embed/data
|
||||
// 免签端点(只认 token),示意图 token 两用(/open/flow/diagram/img 同一 token 出图)。
|
||||
// 本页只读(方案 §9):不做任何审批动作;办理入口仍是待办站内信 → /task/:taskId 既有链路。
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { ref, computed, onMounted, nextTick } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { Tag } from "view-ui-plus";
|
||||
import { INSTANCE_STATUS, INSTANCE_STATUS_COLOR, TASK_STATUS } from "@/api/module/flow";
|
||||
import TraceTimeline from "@/views/flow/components/TraceTimeline.vue";
|
||||
import { fitDiagram } from "@/utils/diagramImg";
|
||||
import config from "@/assets/config/host.config";
|
||||
|
||||
const route = useRoute();
|
||||
@@ -29,6 +30,10 @@ const token = computed(() => String(route.query.token || ""));
|
||||
const diagramSrc = computed(
|
||||
() => `${config.serviceHost}/open/flow/diagram/img?token=${token.value}`,
|
||||
);
|
||||
const diagramEl = ref<HTMLImageElement | null>(null);
|
||||
function onDiagramLoad() {
|
||||
fitDiagram(diagramEl.value);
|
||||
}
|
||||
|
||||
const snapshotRows = computed(() => {
|
||||
const raw = detail.value?.bizSnapshot;
|
||||
@@ -186,6 +191,11 @@ onMounted(async () => {
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
// 缓存命中的图可能在监听器挂上之前就 complete,补一次适配
|
||||
await nextTick();
|
||||
if (diagramEl.value?.complete) {
|
||||
fitDiagram(diagramEl.value);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -217,7 +227,7 @@ onMounted(async () => {
|
||||
|
||||
<Card class="block" :bordered="false" dis-hover>
|
||||
<template #title>流程示意图</template>
|
||||
<img class="diagram-img" :src="diagramSrc" alt="流程示意图" />
|
||||
<img class="diagram-img" ref="diagramEl" :src="diagramSrc" alt="流程示意图" @load="onDiagramLoad" />
|
||||
</Card>
|
||||
|
||||
<Card class="block" :bordered="false" dis-hover>
|
||||
@@ -255,7 +265,9 @@ onMounted(async () => {
|
||||
|
||||
<style scoped>
|
||||
/* 根类不用 .page:UnoCSS 原子类同名会以更高优先级盖掉 scoped 的 padding(裸渲染无 layout 壳时暴露) */
|
||||
.embed-page { padding: 12px 16px; }
|
||||
/* 嵌入页自身即滚动容器:全局 html/body overflow:hidden(App.vue 壳用),裸渲染页无 layout 滚动壳,
|
||||
不在此定高滚动的话内容超一屏被裁且无滚动条(2026-10-10 用户反馈) */
|
||||
.embed-page { height: 100vh; overflow-y: auto; padding: 12px 16px; box-sizing: border-box; }
|
||||
.head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
|
||||
.title { font-size: 16px; font-weight: 600; }
|
||||
.block { margin-bottom: 12px; }
|
||||
@@ -264,7 +276,7 @@ onMounted(async () => {
|
||||
.v { white-space: pre-wrap; word-break: break-all; }
|
||||
.muted { color: #999; }
|
||||
.expired { padding: 48px 16px; text-align: center; }
|
||||
.diagram-img { max-width: 100%; }
|
||||
.diagram-img { max-width: 100%; height: auto; display: block; margin: 0 auto; }
|
||||
.trace-mode { float: right; font-weight: normal; margin-right: 16px; }
|
||||
/* 类名带 record- 前缀:防 UnoCSS 原子类撞名(嵌入页裸渲染无 layout 壳,撞名实测会盖样式) */
|
||||
.record-tip {
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
// 办件详情:状态 + 业务摘要 + 流程轨迹时间线 + 分支会签进度(概览 §9.4 进度图数据源)
|
||||
// 轨迹两档显示(2026-09-18):mode=user(人员,缺省)|dept(科室),写进 query 便于分享/刷新保持,
|
||||
// 并随"流程示意图"跳转带给图示页(两边口径一致)。
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { ref, computed, onMounted, nextTick } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { flowApi, INSTANCE_STATUS } from "@/api/module/flow";
|
||||
import TraceTimeline from "@/views/flow/components/TraceTimeline.vue";
|
||||
import { fitDiagram } from "@/utils/diagramImg";
|
||||
import config from "@/assets/config/host.config";
|
||||
|
||||
const route = useRoute();
|
||||
@@ -72,6 +73,12 @@ const diagramSrc = computed(
|
||||
() => `${config.serviceHost}/api/flow/diagram.png?instanceId=${route.params.instanceId}&mode=${mode.value}`,
|
||||
);
|
||||
|
||||
/** PNG 按 SCALE=2 出图:显示逻辑尺寸(自然宽一半),超宽收缩到容器(src 随口径切换会重新 load) */
|
||||
const diagramEl = ref<HTMLImageElement | null>(null);
|
||||
function onDiagramLoad() {
|
||||
fitDiagram(diagramEl.value);
|
||||
}
|
||||
|
||||
/** 跳流程图时带上当前口径(图示页读 mode,缺省人员) */
|
||||
function toDiagram() {
|
||||
router.push({ path: "/diagram", query: { instanceId: String(route.params.instanceId), mode: mode.value } });
|
||||
@@ -92,6 +99,10 @@ onMounted(async () => {
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
await nextTick();
|
||||
if (diagramEl.value?.complete) {
|
||||
fitDiagram(diagramEl.value);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -139,7 +150,7 @@ onMounted(async () => {
|
||||
流程示意图
|
||||
<a class="diagram-more" @click="toDiagram()">查看大图</a>
|
||||
</template>
|
||||
<img class="diagram-img" :src="diagramSrc" alt="流程示意图" />
|
||||
<img class="diagram-img" ref="diagramEl" :src="diagramSrc" alt="流程示意图" @load="onDiagramLoad" />
|
||||
</Card>
|
||||
|
||||
<Card class="block" :bordered="false" dis-hover>
|
||||
|
||||
Reference in New Issue
Block a user