|
@@ -0,0 +1,131 @@
|
|
|
|
|
+/*const COOKIE_EXPIRES_DAYS = 7;
|
|
|
|
|
+
|
|
|
|
|
+export const getNativeCookie = (name: string): string | null => {
|
|
|
|
|
+ if (typeof document === "undefined") return null;
|
|
|
|
|
+
|
|
|
|
|
+ const cookies = document.cookie.split("; ").map((c) => c.trim());
|
|
|
|
|
+ const found = cookies.find((c) => c.startsWith(name + "="));
|
|
|
|
|
+ return found ? decodeURIComponent(found.split("=")[1]) : null;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+export const getCookie = (name: string): string | null => {
|
|
|
|
|
+ if (typeof document === "undefined") return null;
|
|
|
|
|
+
|
|
|
|
|
+ const match = document.cookie.match(new RegExp("(^| )" + name + "=([^;]+)"));
|
|
|
|
|
+ return match ? decodeURIComponent(match[2]) : null;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+export const setCookie = (
|
|
|
|
|
+ name: string,
|
|
|
|
|
+ value: string | number,
|
|
|
|
|
+ { days = COOKIE_EXPIRES_DAYS, isEncode = false }: { days?: number; isEncode?: boolean } = {}
|
|
|
|
|
+) => {
|
|
|
|
|
+ if (typeof document === "undefined") return;
|
|
|
|
|
+ const d = new Date();
|
|
|
|
|
+ d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
|
|
|
|
|
+ // const expires = new Date(Date.now() + days * 864e5).toUTCString();
|
|
|
|
|
+ const expires = d.toUTCString();
|
|
|
|
|
+ const val = isEncode ? encodeURIComponent(String(value)) : value;
|
|
|
|
|
+ document.cookie = `${name}=${val}; expires=${expires}; path=/`;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+export const deleteCookie = (name: string) => {
|
|
|
|
|
+ if (typeof document === "undefined") return;
|
|
|
|
|
+ document.cookie = `${name}=; Max-Age=0; path=/`;
|
|
|
|
|
+};
|
|
|
|
|
+*/
|
|
|
|
|
+// cookie.ts
|
|
|
|
|
+
|
|
|
|
|
+const DEFAULT_EXPIRES_DAYS = 7;
|
|
|
|
|
+
|
|
|
|
|
+export interface CookieOptions {
|
|
|
|
|
+ /** 过期天数(从当前时间起算),默认 7 天 */
|
|
|
|
|
+ days?: number;
|
|
|
|
|
+ /** 是否需要对值进行编码(encodeURIComponent),默认 false */
|
|
|
|
|
+ encode?: boolean;
|
|
|
|
|
+ /** Cookie 路径,默认 '/' */
|
|
|
|
|
+ path?: string;
|
|
|
|
|
+ /** Cookie 域名 */
|
|
|
|
|
+ domain?: string;
|
|
|
|
|
+ /** 是否仅 HTTPS 传输 */
|
|
|
|
|
+ secure?: boolean;
|
|
|
|
|
+ /** SameSite 属性 */
|
|
|
|
|
+ sameSite?: 'Strict' | 'Lax' | 'None';
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 对正则特殊字符进行转义,避免名称中的特殊字符导致匹配错误
|
|
|
|
|
+function escapeRegExp(string: string): string {
|
|
|
|
|
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取指定名称的 cookie 值
|
|
|
|
|
+ * 解决了值中包含等号的问题,并对名称中的正则特殊字符做了转义
|
|
|
|
|
+ */
|
|
|
|
|
+export function getCookie(name: string): string | null {
|
|
|
|
|
+ if (typeof document === 'undefined') return null;
|
|
|
|
|
+
|
|
|
|
|
+ const escapedName = escapeRegExp(name);
|
|
|
|
|
+ // 在 document.cookie 开头或分号后的空格之后匹配名称,值部分匹配到下一个分号或结束
|
|
|
|
|
+ const regex = new RegExp(`(?:^|;\\s*)${escapedName}=([^;]*)`);
|
|
|
|
|
+ const match = document.cookie.match(regex);
|
|
|
|
|
+
|
|
|
|
|
+ return match ? decodeURIComponent(match[1]) : null;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 设置 cookie
|
|
|
|
|
+ * 默认对值进行编码以保证安全存储,可通过 options.encode = false 关闭
|
|
|
|
|
+ */
|
|
|
|
|
+export function setCookie(
|
|
|
|
|
+ name: string,
|
|
|
|
|
+ value: string | number | boolean,
|
|
|
|
|
+ options: CookieOptions = {}
|
|
|
|
|
+): void {
|
|
|
|
|
+ if (typeof document === 'undefined') return;
|
|
|
|
|
+
|
|
|
|
|
+ const {
|
|
|
|
|
+ days = DEFAULT_EXPIRES_DAYS,
|
|
|
|
|
+ encode = true, // 默认编码,更加安全
|
|
|
|
|
+ path = '/',
|
|
|
|
|
+ domain,
|
|
|
|
|
+ secure,
|
|
|
|
|
+ sameSite,
|
|
|
|
|
+ } = options;
|
|
|
|
|
+
|
|
|
|
|
+ // 处理过期时间
|
|
|
|
|
+ const expires = new Date(Date.now() + days * 864e5).toUTCString();
|
|
|
|
|
+
|
|
|
|
|
+ // 处理值:编码或直接转换
|
|
|
|
|
+ const val = encode
|
|
|
|
|
+ ? encodeURIComponent(String(value))
|
|
|
|
|
+ : String(value);
|
|
|
|
|
+
|
|
|
|
|
+ // 构建 cookie 字符串
|
|
|
|
|
+ let cookie = `${name}=${val}; expires=${expires}; path=${path}`;
|
|
|
|
|
+ if (domain) cookie += `; domain=${domain}`;
|
|
|
|
|
+ if (secure) cookie += '; secure';
|
|
|
|
|
+ if (sameSite) cookie += `; samesite=${sameSite}`;
|
|
|
|
|
+
|
|
|
|
|
+ document.cookie = cookie;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 删除指定名称的 cookie
|
|
|
|
|
+ * 通过设置 Max-Age=0 并匹配 path/domain 等属性来确保删除
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteCookie(
|
|
|
|
|
+ name: string,
|
|
|
|
|
+ options: Pick<CookieOptions, 'path' | 'domain' | 'secure'> = {}
|
|
|
|
|
+): void {
|
|
|
|
|
+ if (typeof document === 'undefined') return;
|
|
|
|
|
+
|
|
|
|
|
+ const { path = '/', domain, secure } = options;
|
|
|
|
|
+
|
|
|
|
|
+ // 若删除时指定了 domain 或 secure,需要与设置时一致才能删除成功
|
|
|
|
|
+ let cookie = `${name}=; Max-Age=0; path=${path}`;
|
|
|
|
|
+ if (domain) cookie += `; domain=${domain}`;
|
|
|
|
|
+ if (secure) cookie += '; secure';
|
|
|
|
|
+
|
|
|
|
|
+ document.cookie = cookie;
|
|
|
|
|
+}
|