6f0357e41c
新增 src/config/app.ts(APP_BASE_PATH/ensureAppBasePath/joinAdminPath), vite.config base、router createWebHistory、AdminLayout logo 路径统一消费常量, 禁止散落字面量;8 用例覆盖归一化/幂等/空段/单段/非法输入与字面量单源。
39 lines
1.7 KiB
TypeScript
39 lines
1.7 KiB
TypeScript
/**
|
|
* /admin-vue/ 基准路径与 History 路由约定(任务 2 冻结的单一事实源)。
|
|
* Vite base、Vue Router history base、Nginx location 三者必须共用此常量。
|
|
*/
|
|
export const APP_BASE_PATH = '/admin-vue/'
|
|
|
|
/** 前端路由一律使用 History 模式,不引入 hash(旧 #tab 兼容不在目标契约内)。 */
|
|
export const APP_HISTORY_MODE = 'history' as const
|
|
|
|
function invalidBaseMessage(value: unknown): string {
|
|
return `管理后台 base 路径非法: ${JSON.stringify(value)},必须以 / 开头且形如 /xxx/,不允许空值或 ..`
|
|
}
|
|
|
|
/** 校验并归一化 base 路径:保证以 / 开头、无 ..、无内部连续斜杠、以单个 / 结尾。 */
|
|
export function ensureAppBasePath(value: string): string {
|
|
if (typeof value !== 'string' || value.length === 0) throw new Error(invalidBaseMessage(value))
|
|
if (!value.startsWith('/')) throw new Error(invalidBaseMessage(value))
|
|
if (value.includes('//')) throw new Error(invalidBaseMessage(value))
|
|
if (value.includes('..')) throw new Error(invalidBaseMessage(value))
|
|
return value.endsWith('/') ? value : `${value}/`
|
|
}
|
|
|
|
/** 把后台页面相对路径段拼成绝对 URL(不含 base 前缀的历史兼容子路径段由路由负责)。 */
|
|
export function joinAdminPath(...segments: string[]): string {
|
|
const parts: string[] = []
|
|
for (const segment of segments) {
|
|
for (const raw of segment.split('/')) {
|
|
const part = raw.trim()
|
|
if (!part || part === '.') continue
|
|
if (part === '..') {
|
|
throw new Error(`admin 路由段不允许出现 ..(越权跳转): ${segments.join('/')}`)
|
|
}
|
|
parts.push(part)
|
|
}
|
|
}
|
|
if (parts.length === 0) return APP_BASE_PATH
|
|
return `${APP_BASE_PATH}${parts.join('/')}`
|
|
}
|