chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
/**
* URL 解析工具(兼容 H5 & 微信小程序)
*/
export interface ParseUrlResult {
path: string;
query: Record<string, string>;
}
/**
* 从 url 中解析 path 和指定 query 参数
* @param input url 字符串(完整 url / 相对路径 / query
* @param pickKeys 需要提取的 query key不传则全部返回
*/
export function parseUrlInfo(
input: string,
pickKeys?: string[],
): ParseUrlResult {
if (!input) {
return { path: "", query: {} };
}
// 统一 decode避免多次 decode
let decoded = input;
try {
decoded = decodeURIComponent(input);
} catch {
decoded = input;
}
let path = "";
let queryStr = "";
// 1⃣ 完整 URLhttps://xxx.com/xx?a=1
if (/^https?:\/\//i.test(decoded)) {
const [p, q = ""] = decoded.split("?");
path = p.replace(/^https?:\/\/[^/]+/, "");
queryStr = q;
}
// 2⃣ 相对路径(/xx/yy?a=1
else if (decoded.includes("?")) {
const [p, q] = decoded.split("?");
path = p;
queryStr = q;
}
// 3⃣ 仅 path
else if (decoded.startsWith("/")) {
path = decoded;
}
// 4⃣ 仅 querya=1&b=2
else {
queryStr = decoded;
}
// 解析 query
const query: Record<string, string> = {};
if (queryStr) {
queryStr.split("&").forEach((item) => {
if (!item) return;
const [k, v = ""] = item.split("=");
if (!k) return;
// 二次保护 decode
try {
query[k] = decodeURIComponent(v);
} catch {
query[k] = v;
}
});
}
// 只取指定 key
if (pickKeys?.length) {
const picked: Record<string, string> = {};
pickKeys.forEach((k) => {
if (query[k] !== undefined) {
picked[k] = query[k];
}
});
return { path, query: picked };
}
return { path, query };
}
/**
* 从 URL 或字符串中获取文件名
* @param input URL 或 文件名
* @returns 文件名
*/
export function getFileName(input: string): string {
if (!input) return '';
// 去掉 query 参数
const withoutQuery = input.split('?')[0];
// 取最后一个 /
const lastSlashIndex = withoutQuery.lastIndexOf('/');
const fileName =
lastSlashIndex !== -1
? withoutQuery.slice(lastSlashIndex + 1)
: withoutQuery;
// 解码(防止中文被 encode
try {
return decodeURIComponent(fileName);
} catch {
return fileName;
}
}