73 lines
3.2 KiB
TypeScript
73 lines
3.2 KiB
TypeScript
import { ref } from "vue";
|
||
import config from "@/assets/config/host.config";
|
||
|
||
/**
|
||
* 公共办事大厅的"当前站点"(siteCode)——用户面没有站点选择器,来源按优先级:
|
||
* ① URL query(CMS 指南页"我要办理"按钮 / 门户深链:{base}/#/apply?siteCode=&itemCode=)
|
||
* ② 运行时配置 siteCode(env-config / VITE_SITE_CODE:一个部署对应一所学校,最常用)
|
||
* ③ localStorage 上次使用(同一浏览器内的连续办理)
|
||
* 三者皆空 → 页面提示"未配置站点,请从学校门户进入"(不猜也不硬编码)。
|
||
*
|
||
* 注意与后台前端(front/src/utils/site.ts)的区别:那里是"管理端可切换的站点上下文",
|
||
* 这里是"部署/深链决定的固定站点"。
|
||
*/
|
||
const currentSiteCode = ref<string>(localStorage.getItem("svchall.public.site") || "");
|
||
const lastItemCode = ref<string>(localStorage.getItem("svchall.public.item") || "");
|
||
/** CMS 指南页来路(session 级内存,不落 localStorage——回跳是"这一次来的路",不是偏好) */
|
||
const portalFrom = ref<string>("");
|
||
|
||
export function useSite() {
|
||
/** 从 query / 运行时配置 / 本地记忆依次解析站点,命中即记住 */
|
||
function resolveSite(querySiteCode?: unknown): string {
|
||
const fromQuery = typeof querySiteCode === "string" ? querySiteCode.trim() : "";
|
||
const candidates = [fromQuery, String(config.siteCode || ""), currentSiteCode.value];
|
||
const hit = candidates.find(v => v && v.length > 0) || "";
|
||
if (hit && hit !== currentSiteCode.value) {
|
||
currentSiteCode.value = hit;
|
||
}
|
||
if (hit) {
|
||
localStorage.setItem("svchall.public.site", hit);
|
||
}
|
||
return hit;
|
||
}
|
||
|
||
/**
|
||
* 解析并校验 from 参数(CMS 指南页深链带回,T4 回跳闭环):
|
||
* 仅接受 http/https 且 hostname 属于本部署可信域(当前页域名或 baseHost)的 URL,否则忽略——
|
||
* 防 javascript: 伪协议与外域注入。
|
||
*/
|
||
function resolveFrom(queryFrom?: unknown): string {
|
||
const raw = typeof queryFrom === "string" ? queryFrom.trim() : "";
|
||
if (!raw) return "";
|
||
try {
|
||
const u = new URL(raw);
|
||
if (u.protocol !== "http:" && u.protocol !== "https:") return "";
|
||
const mine = location.hostname;
|
||
const base = String(config.baseHost || "");
|
||
const baseHost = base ? new URL(base).hostname : "";
|
||
if (u.hostname !== mine && (!baseHost || u.hostname !== baseHost)) return "";
|
||
portalFrom.value = raw;
|
||
} catch {
|
||
// 非法 URL 当没有
|
||
}
|
||
return portalFrom.value;
|
||
}
|
||
|
||
function setSite(siteCode: string) {
|
||
currentSiteCode.value = siteCode;
|
||
if (siteCode) {
|
||
localStorage.setItem("svchall.public.site", siteCode);
|
||
}
|
||
}
|
||
|
||
/** 记住最近浏览的事项(大厅"继续办理"与返回体验用) */
|
||
function rememberItem(itemCode: string) {
|
||
lastItemCode.value = itemCode;
|
||
if (itemCode) {
|
||
localStorage.setItem("svchall.public.item", itemCode);
|
||
}
|
||
}
|
||
|
||
return { currentSiteCode, lastItemCode, portalFrom, resolveSite, resolveFrom, setSite, rememberItem };
|
||
}
|