build / build (push) Successful in 2m12s
- 从 Notice/front 复制 flow-approval 六件并本地修复(漂移登记组件 README,Notice 不回改):
· P0-04:四个写调用点(List 通过/驳回 + Card 通过/驳回)全部实际携带本行 bizId,
选中 bizId 随弹窗生命周期锁定/清理
· P0-05:删 useElementHeight/yh-* 平台布局依赖,本地 fa-* 样式(theme-base.css --sh-* 令牌)
· P0-06:types.ts 本地契约——增 my(行=ApplyVo 子集/FlowPage 完整元数据/状态 0=待提交
禁止当全部,全部用 -1 哨兵)、删 instances(不代理全校视角)、approve/reject 增 bizId 参
· P1-05:卡片轨迹不自取(详情页把 /progress 转换 TraceVo 经 props 传入);节点摘要取
active steps 节点名;MULTI_TASK 逐条列出本人待办各带动作,不默认 tasks[0];
未进流程(flowInstanceId 空)详情页不渲染卡片(显式决策)
· P1-09:FlowTaskEmbed 消息四条件(打开中+严格 origin+本 iframe+taskId/bizId 上下文一致),
换址重置高度;宿主换址请求带代际号,关闭/换件废弃在途响应并清上下文;
open-biz 只用与当前办件一致的 bizId 构造 /apply-detail?id=,不透传任意 URL
- ApprovalApi 类挂 svc.ts(todo/my/byBiz/approve/reject/recordUrl/taskPageUrl,写面
taskId/applyId 查询参数+opinion/edgeName JSON body 两形态区分)+ approvalAdapter.ts 唯一映射
- /todo 路由 + 顶部导航第三链接「我的审批」+ MyApprovals.vue(双页签+记录抽屉+完整办理)
- ApplyDetail 挂审批卡片(审批操作区)+ TraceVo 转换器
- 小屏基础响应式(drawer/modal 宽度自适应、列表横向滚动;1200px 全量适配不在本批)
- 门禁:vue-tsc(ts4.9 外挂兼容组合)错误数 HEAD=工作区=18 零新增(仓内 vue-tsc1.8+ts5.9
崩溃系历史遗留);vite build 绿(MyApprovals/approvalAdapter chunk 产出);
preview 冒烟:/todo 渲染完整(导航/页签/表格空态/API 失败优雅降级)、详情页无崩溃(Stage S4/P3.3)
96 lines
4.3 KiB
Vue
96 lines
4.3 KiB
Vue
<script setup lang="ts">
|
||
/**
|
||
* 公共办事大厅外壳(学生/教师/访客入口):
|
||
* 顶栏(站点名 + 在线办理/我的办件导航 + 当前用户)+ 内容区。
|
||
* 与后台前端(front/)刻意不同:不渲染平台模块菜单(app_module 是管理端契约),
|
||
* 只做两个入口——办事大厅、我的办件(详情/办理页从列表进入)。
|
||
*
|
||
* 皮肤三层优先级(T3 弱联动,2026-10-03):
|
||
* CMS 站点推荐(/api/hall/site 的 theme/themeParams,经 utils/cmsTheme 映射;
|
||
* stale-while-revalidate——localStorage 缓存先画、后台刷新,失败静默)
|
||
* > env-config 部署级皮肤 > default。
|
||
* 推荐值、不保证生效:任一层缺失/非法都回落下一层(utils/theme.ts)。
|
||
*/
|
||
import { onMounted, ref } from "vue";
|
||
import { baseApi } from "@/api/module/base";
|
||
import config from "@/assets/config/host.config";
|
||
import { applyTheme, resolveTheme, type ThemeManifest } from "@/utils/theme";
|
||
import { toHallSkin } from "@/utils/cmsTheme";
|
||
import { useSite } from "@/utils/site";
|
||
import { hallApi } from "@/api/module/svc";
|
||
|
||
const userName = ref("");
|
||
const theme = ref<ThemeManifest>(resolveTheme(null));
|
||
// CMS 指南页来路(T4 回跳闭环):仅 /#/apply 深链带合法 from 参数时非空
|
||
const { portalFrom, currentSiteCode } = useSite();
|
||
|
||
onMounted(async () => {
|
||
// ① 基线:env-config 部署级皮肤(现状语义不变,先应用保证首屏观感)
|
||
theme.value = applyTheme(config.theme, config.themeParams);
|
||
// ② 站点推荐:CMS 站点主题(弱联动)——缓存先画,后台刷新
|
||
applySiteThemeRecommend();
|
||
// 用户信息失败不影响办理页面使用
|
||
try {
|
||
const user: any = await baseApi.getUserInfo().send();
|
||
userName.value = user?.name || "";
|
||
} catch (e: any) {
|
||
// CAS 未登录时平台层会跳转登录页(error.message === "redirect"),此处不打扰用户
|
||
if (e?.message !== "redirect") {
|
||
console.warn("[public-hall] 获取用户信息失败", e);
|
||
}
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 站点主题推荐应用(stale-while-revalidate):
|
||
* 未登录时该请求会 302 跳 CAS(与 items 同行为,页面本来就要登录);
|
||
* 任何失败静默保留现皮肤——推荐、不保证生效,绝不阻塞首屏。
|
||
*/
|
||
async function applySiteThemeRecommend() {
|
||
const code = currentSiteCode.value; // useSite() 模块级 ref,当前视图 onMounted 已 resolve
|
||
if (!code) return;
|
||
const cacheKey = `svchall.public.siteTheme.${code}`;
|
||
// ① stale:同步读缓存立即应用(二次访问无闪色)
|
||
try {
|
||
const cached = JSON.parse(localStorage.getItem(cacheKey) || "null");
|
||
const stale = toHallSkin(cached);
|
||
if (stale) theme.value = applyTheme(stale.name, stale.params);
|
||
} catch {
|
||
// 坏缓存当没有
|
||
}
|
||
// ② revalidate:后台刷新(失败静默保留现皮肤——推荐、不保证生效)
|
||
try {
|
||
const info: any = await hallApi.site(code).send();
|
||
const pick = toHallSkin({ theme: info?.theme, themeParams: info?.themeParams });
|
||
localStorage.setItem(cacheKey, JSON.stringify({
|
||
theme: info?.theme || null, themeParams: info?.themeParams || null,
|
||
}));
|
||
if (pick) theme.value = applyTheme(pick.name, pick.params);
|
||
} catch (e) {
|
||
console.warn("[public-hall] 站点主题获取失败,沿用当前皮肤", e);
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="sh-shell">
|
||
<header class="sh-header">
|
||
<div class="sh-brand">
|
||
办事大厅
|
||
<small>在线办理 · {{ theme.title }}</small>
|
||
</div>
|
||
<nav class="sh-nav">
|
||
<router-link to="/hall">办事大厅</router-link>
|
||
<router-link to="/my">我的办件</router-link>
|
||
<router-link to="/todo">我的审批</router-link>
|
||
<a v-if="portalFrom" :href="portalFrom" class="sh-back-portal">返回门户</a>
|
||
</nav>
|
||
<span class="sh-user" v-if="userName">{{ userName }}</span>
|
||
</header>
|
||
<main class="sh-main">
|
||
<router-view :key="$route.fullPath" />
|
||
</main>
|
||
<footer class="sh-footer">云海平台 · 办事大厅(在线申请入口)</footer>
|
||
</div>
|
||
</template>
|