feat(W4): 站点path全链路-portalUrlOf/previewPortalUrl纯函数,站点列/向导地址预览/预览frame sitePath,store携带path,mock嵌套路由,T-W4-16..18 绿51/51

This commit is contained in:
chenxing
2026-09-08 15:14:10 +08:00
parent 7b99ec398d
commit dedd4a6a3a
16 changed files with 297 additions and 37 deletions
+6
View File
@@ -8,6 +8,8 @@
export interface MockSite {
id: number;
code: string;
/** 门户路径(W4:顶层=code;子站=父path/code) */
path: string;
/** 上级站点ID(0=顶层校站点;院系子站挂主站 id) */
parentSiteId: number;
schId: number;
@@ -141,6 +143,7 @@ export function seedDb(): MockDb {
{
id: 1,
code: "demo",
path: "demo",
parentSiteId: 0,
schId: 1001,
schName: "云海大学",
@@ -162,6 +165,7 @@ export function seedDb(): MockDb {
{
id: 2,
code: "fsz",
path: "fsz",
parentSiteId: 0,
schId: 1002,
schName: "云海大学附属中学",
@@ -174,6 +178,7 @@ export function seedDb(): MockDb {
{
id: 3,
code: "jdx",
path: "demo/jdx",
parentSiteId: 1,
schId: 1001,
schName: "云海大学",
@@ -189,6 +194,7 @@ export function seedDb(): MockDb {
{
id: 4,
code: "xxgc",
path: "demo/xxgc",
parentSiteId: 1,
schId: 1001,
schName: "云海大学",
+8 -4
View File
@@ -251,15 +251,19 @@ function extractFile(body: Buffer): { name: string; mime: string; buffer: Buffer
/* ===== 简版门户预览页 ===== */
function siteByPath(sitePath: string): MockSite | undefined {
return db.sites.find(s => s.path === sitePath || (s.parentSiteId === 0 && s.code === sitePath));
}
function siteByCode(code: string): MockSite | undefined {
return db.sites.find(s => s.code === code);
}
function portalPage(req: IncomingMessage, res: ServerResponse) {
const path = new URL(req.url!, "http://mock.local").pathname;
// /portal/{code} 或 /portal/{code}/...(含 /a/{id})
// W4:/portal/{path}/ 或 /portal/{path}/...(path 支持嵌套两段;含 /a/{id})
const m = path.replace(/^\/portal\//, "").split("/");
const site = siteByCode(m[0]);
const site = siteByPath(m[0]);
const nav = ["学校概况", "新闻中心", "教学科研", "招生网", "联系我们"]
.map(n => `<a href="javascript:void(0)">${n}</a>`)
.join("");
@@ -274,7 +278,7 @@ function portalPage(req: IncomingMessage, res: ServerResponse) {
const colleges = db.sites.filter(s => s.parentSiteId === anchorId && s.status === 1);
const collegesHtml = colleges.length
? `<div class="colleges"><span class="colleges-toggle">专业院系 ▾</span><ul class="colleges-menu">
${colleges.map(c => `<li${c.code === site.code ? ' class="on"' : ""}><a href="/portal/${c.code}/">${c.name}</a></li>`).join("")}
${colleges.map(c => `<li${c.path === site.path ? ' class="on"' : ""}><a href="/portal/${c.path}/">${c.name}</a></li>`).join("")}
</ul></div>`
: "";
const articleMatch = path.match(/\/a\/(\d+)/);
@@ -333,7 +337,7 @@ function portalPage(req: IncomingMessage, res: ServerResponse) {
function sendThemePreview(req: IncomingMessage, res: ServerResponse) {
const u = new URL(req.url!, "http://mock.local");
const site = siteByCode(u.searchParams.get("siteCode") || "");
const site = siteByPath(u.searchParams.get("sitePath") || "");
const themeName = u.searchParams.get("theme") || "default";
const theme = themeByName(themeName);
const params: Record<string, string> = {};