一、场景背景
当业务侧需要快速回答“某个轻应用里有哪些页面”“某个桌面应用下挂了哪些页面”时,逐个进入资源树排查成本较高。更高效的方式,是基于元数据搭一张应用页面映射总表,把移动应用和桌面应用统一收敛到一张明细表里查看。
这篇文章基于真实 UAT 环境的落地过程,整理一套可直接复用的做法,最终展示字段包括:应用类型、应用名称、应用 ID、页面名称、页面 ID。
二、最终效果
最终页面地址:应用页面映射总表_20260415

三、整体实现思路
这次实践本质上是一个元数据报表场景,整体链路可以拆成三步:
- 从元数据中拿到移动轻应用、桌面应用和页面信息。
- 在 ETL 中把移动应用和桌面应用各自包含的页面拆平,并补齐页面名称。
- 基于输出宽表搭一个明细表卡片,统一展示移动应用和桌面应用的页面映射关系。
这次实践里最关键的经验点,是不要直接依赖长期未刷新的快照元数据集。更稳妥的方式,是先基于元数据库构建 latest 数据集,再让 ETL 消费 latest 数据集。
四、数据准备
这次最终使用了三类输入:
- 移动应用最新元数据
- 桌面应用最新元数据
- 页面信息表
其中前两类 latest 数据集建议直接基于元数据库账号构建,按 dom_id + app_id 保留每个应用的最新版本记录,这样能避免历史版本脏数据干扰。

这次实践里,两个 latest 数据集分别是 codex_meta_custom_app_latest_20260415111639(tf068a002446b43f2b5cab07)和 codex_meta_web_portal_latest_20260415111639(c0450df6dd5854b218b10b13)。如果希望完整复用这条链路,建议直接按下面的 SQL 新建这两个 latest 数据集。
4.1 移动应用 latest 数据集创建 SQL
SELECT t.id, t.dom_id, t.u_id, t.app_id, t.name AS app_name, t.layout, t.page_list, t.parent_dir_id, t.ctime, t.utime, t.is_del
FROM custom_app t
LEFT JOIN custom_app t2
ON t.dom_id = t2.dom_id
AND t.app_id = t2.app_id
AND (
COALESCE(t2.utime, '1970-01-01') > COALESCE(t.utime, '1970-01-01')
OR (COALESCE(t2.utime, '1970-01-01') = COALESCE(t.utime, '1970-01-01') AND COALESCE(t2.ctime, '1970-01-01') > COALESCE(t.ctime, '1970-01-01'))
OR (COALESCE(t2.utime, '1970-01-01') = COALESCE(t.utime, '1970-01-01') AND COALESCE(t2.ctime, '1970-01-01') = COALESCE(t.ctime, '1970-01-01') AND t2.id > t.id)
)
WHERE t2.id IS NULL
4.2 桌面应用 latest 数据集创建 SQL
SELECT t.id, t.app_id, t.dom_id, t.app_type, t.name, t.structure, t.parent_dir_id, t.ctime, t.utime, t.is_del, t.is_release
FROM web_portal t
LEFT JOIN web_portal t2
ON t.dom_id = t2.dom_id
AND t.app_id = t2.app_id
AND (
COALESCE(t2.utime, '1970-01-01') > COALESCE(t.utime, '1970-01-01')
OR (COALESCE(t2.utime, '1970-01-01') = COALESCE(t.utime, '1970-01-01') AND COALESCE(t2.ctime, '1970-01-01') > COALESCE(t.ctime, '1970-01-01'))
OR (COALESCE(t2.utime, '1970-01-01') = COALESCE(t.utime, '1970-01-01') AND COALESCE(t2.ctime, '1970-01-01') = COALESCE(t.ctime, '1970-01-01') AND t2.id > t.id)
)
WHERE t2.id IS NULL
五、ETL 处理逻辑
ETL 处理时,移动应用和桌面应用分别走两条映射链路:
- 移动轻应用直接使用
page_list 字段,通过 split + explode 拆平页面 ID。
- 桌面应用不再依赖旧的
page_list 快照字段,而是直接从 structure 中提取 pgId,并只保留 app_type = 1 的页面应用。
- 最后将拆出的
page_id 与页面信息表关联,补齐 page_name。


六、仪表板搭建
页面层实现非常直接,基于输出宽表搭一张明细表即可,建议字段顺序如下:
- 应用类型
- 应用名称
- 应用 ID
- 页面名称
- 页面 ID
为了便于排查和检索,建议按“应用类型 -> 应用名称 -> 页面名称 -> 页面 ID”的顺序排序,这样可以保证移动应用和桌面应用各自成组展示,也更方便快速定位某个应用下的全部页面。
七、实践中的关键坑位
这次实践里最值得记录的一点,是元数据来源要统一且足够新。
如果直接拿长期未刷新的快照数据集来做:
- 会漏掉后续新增的应用
- 会保留过期的应用版本
- 页面关系可能出现滞后
所以更推荐的方案是:
- 先从元数据库构建 latest 数据集
- 再用 ETL 做页面拆分和名称补齐
- 最后将结果挂到仪表板中展示
八、附件下载
如果你希望直接复用这次实践中的 ETL 结构,可以下载附件:
应用页面映射 ETL 附件(zip)
九、小结
对于“轻应用 / 桌面应用里有哪些页面”这类元数据排查需求,最适合的方式不是人工逐个核对,而是直接做一张统一的映射总表。
通过这次实践,可以把排查过程沉淀为一套稳定链路:latest 元数据数据集、页面映射 ETL、仪表板总表展示。后续如果还需要继续扩展,也可以在这张表的基础上再补应用目录、创建人、更新时间、页面类型、是否草稿等字段,进一步升级成完整的应用与页面元数据盘点表。 |