diff --git a/src/api/portal/index.js b/src/api/portal/index.js
new file mode 100644
index 0000000..62a544b
--- /dev/null
+++ b/src/api/portal/index.js
@@ -0,0 +1,86 @@
+// 汇聚门户(跨站点汇总)接口。
+// 这些接口由中心端后端提供,返回"所有站"的汇总数据;
+// 与单站业务接口不同,它们不依赖当前登录用户所属站。
+// 后端未就绪时页面以空态展示,不影响其它功能。
+import request from "@/utils/request";
+
+// 场站列表
+// 返回 data: [{ id, stationCode, stationName, baseUrl, portalUrl, enabled }]
+export function getStationList(query) {
+ return request({
+ url: "/agg/station/all",
+ method: "get",
+ params: query,
+ noAlert: true
+ });
+}
+
+// 本轮巡检任务统计(表计/外观/红外)
+// 返回 data: [{ algCategory, inspectedTaskCount, completedTaskCount, defectCount, ... }]
+export function getInspectionOverview(query) {
+ return request({
+ url: "/agg/statistic/inspection",
+ method: "get",
+ params: query,
+ noAlert: true
+ });
+}
+
+// 缺陷发现趋势(最近 12 个月或 4 个季度)
+// 返回 data: [{ date, minorCount, generalCount, seriousCount, urgentCount, ... }]
+export function getDefectTrend(query) {
+ return request({
+ url: "/agg/statistic/defect",
+ method: "get",
+ params: query,
+ noAlert: true
+ });
+}
+
+// 通道设备来源统计
+// 返回 data: { totalCount, deviceSourceCounts: [{ deviceSource, count }] }
+export function getChannelStats(query) {
+ return request({
+ url: "/agg/statistic/channel",
+ method: "get",
+ params: query,
+ noAlert: true
+ });
+}
+
+// 通道树
+// 返回 data: 区域、巡检设备、通道三级树
+export function getChannelTree(query) {
+ return request({
+ url: "/agg/tree/channel",
+ method: "get",
+ params: query,
+ noAlert: true
+ });
+}
+
+// 汇聚侧实时视频启动
+// 返回 data: { stationCode, cameraCode, streamId, hls, flv, status }
+export function startRealtimeVideo(query) {
+ const { stationCode, ...data } = query || {};
+ return request({
+ url: "/agg/video/realtime/start",
+ method: "post",
+ params: { stationCode },
+ data,
+ noAlert: true
+ });
+}
+
+// 汇聚侧实时视频停止
+// 入参按后端要求传 stationCode + cameraCode
+export function stopRealtimeVideo(query) {
+ const { stationCode, ...data } = query || {};
+ return request({
+ url: "/agg/video/realtime/stop",
+ method: "post",
+ params: { stationCode },
+ data,
+ noAlert: true
+ });
+}
diff --git a/src/assets/portal/icon-donghuan.png b/src/assets/portal/icon-donghuan.png
new file mode 100644
index 0000000..c19a33e
Binary files /dev/null and b/src/assets/portal/icon-donghuan.png differ
diff --git a/src/assets/portal/icon-enter.png b/src/assets/portal/icon-enter.png
new file mode 100644
index 0000000..0b30b58
Binary files /dev/null and b/src/assets/portal/icon-enter.png differ
diff --git a/src/assets/portal/icon-fire.png b/src/assets/portal/icon-fire.png
new file mode 100644
index 0000000..1db532a
Binary files /dev/null and b/src/assets/portal/icon-fire.png differ
diff --git a/src/assets/portal/icon-security.png b/src/assets/portal/icon-security.png
new file mode 100644
index 0000000..8933736
Binary files /dev/null and b/src/assets/portal/icon-security.png differ
diff --git a/src/assets/portal/icon-total.png b/src/assets/portal/icon-total.png
new file mode 100644
index 0000000..d40ba66
Binary files /dev/null and b/src/assets/portal/icon-total.png differ
diff --git a/src/assets/portal/icon-triangle.png b/src/assets/portal/icon-triangle.png
new file mode 100644
index 0000000..eb0e2a8
Binary files /dev/null and b/src/assets/portal/icon-triangle.png differ
diff --git a/src/assets/portal/panel-title.png b/src/assets/portal/panel-title.png
new file mode 100644
index 0000000..55f7a28
Binary files /dev/null and b/src/assets/portal/panel-title.png differ
diff --git a/src/assets/portal/tree-toggle.png b/src/assets/portal/tree-toggle.png
new file mode 100644
index 0000000..6dfd55c
Binary files /dev/null and b/src/assets/portal/tree-toggle.png differ
diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue
index 67cbcec..97dd201 100644
--- a/src/layout/components/Navbar.vue
+++ b/src/layout/components/Navbar.vue
@@ -8,6 +8,12 @@