fix: crypto.randomUUID 在非安全上下文(非HTTPS)下崩溃
新增 src/lib/uuid.js 提供 genUUID(), 优先使用 crypto.randomUUID, 不可用时回退到 getRandomValues 手动拼装 v4 UUID, 最终回退到 Math.random。 原因: crypto.randomUUID() 仅在安全上下文(HTTPS 或 localhost)可用。 当前站点通过 http://f.zikai.wang:8888 访问, 属于非安全上下文, 导致 event-factory.js 的新增日程和 split.js 的拆分事件功能崩溃。 涉及文件: - src/lib/uuid.js (新增): 带 fallback 的 UUID 生成 - src/lib/event-factory.js: crypto.randomUUID -> genUUID - src/lib/split.js: crypto.randomUUID -> genUUID
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
* and cloning so that useCalendar.js stays focused on state management.
|
||||
*/
|
||||
import { todayISO, nowCompactTimestamp } from './date.js'
|
||||
import { genUUID } from './uuid.js'
|
||||
|
||||
/**
|
||||
* Create a new single-occurrence event with sensible defaults.
|
||||
@@ -14,7 +15,7 @@ import { todayISO, nowCompactTimestamp } from './date.js'
|
||||
*/
|
||||
export function createEvent(overrides = {}) {
|
||||
return {
|
||||
uid: crypto.randomUUID(),
|
||||
uid: genUUID(),
|
||||
summary: '新日程',
|
||||
location: '',
|
||||
description: '',
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
import { intervalDays } from './recur.js'
|
||||
import { cloneEvent } from './event-factory.js'
|
||||
import { genUUID } from './uuid.js'
|
||||
import { toDate, toISODate, addDays, daysBetween } from './date.js'
|
||||
|
||||
/** Snap a date forward to the next grid point on or after it. */
|
||||
@@ -42,7 +43,7 @@ export function splitRecurringEvent(ev, splitDate) {
|
||||
partA.exdates = ev.exdates.filter((d) => d < splitDate)
|
||||
|
||||
const partB = cloneEvent(ev)
|
||||
partB.uid = crypto.randomUUID()
|
||||
partB.uid = genUUID()
|
||||
partB.dtstartDate = snapStr
|
||||
partB.exdates = ev.exdates.filter((d) => d >= splitDate)
|
||||
|
||||
|
||||
37
src/lib/uuid.js
Normal file
37
src/lib/uuid.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* UUID 生成工具。
|
||||
*
|
||||
* 优先使用 crypto.randomUUID(), 但该方法仅在安全上下文 (HTTPS 或 localhost)
|
||||
* 中可用。当前站点通过 http://f.zikai.wang:8888 访问, 属于非安全上下文,
|
||||
* crypto.randomUUID 会是 undefined, 因此需要回退方案。
|
||||
*
|
||||
* 回退一: 用 crypto.getRandomValues (不受安全上下文限制) 手动拼装
|
||||
* RFC 4122 version 4 UUID。
|
||||
* 回退二: 若 crypto 对象完全不存在 (如旧版 Node 直接运行 .mjs), 用
|
||||
* Math.random 拼装, 牺牲少量随机性但保证可用。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 生成一个 RFC 4122 version 4 UUID 字符串。
|
||||
* @returns {string} 形如 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
||||
*/
|
||||
export function genUUID() {
|
||||
const c = typeof globalThis !== 'undefined' ? globalThis.crypto : undefined
|
||||
if (c && typeof c.randomUUID === 'function') {
|
||||
return c.randomUUID()
|
||||
}
|
||||
if (c && typeof c.getRandomValues === 'function') {
|
||||
const bytes = new Uint8Array(16)
|
||||
c.getRandomValues(bytes)
|
||||
bytes[6] = (bytes[6] & 0x0f) | 0x40 // version 4
|
||||
bytes[8] = (bytes[8] & 0x3f) | 0x80 // variant
|
||||
const h = [...bytes].map((b) => b.toString(16).padStart(2, '0'))
|
||||
return `${h.slice(0, 4).join('')}-${h.slice(4, 6).join('')}-${h.slice(6, 8).join('')}-${h.slice(8, 10).join('')}-${h.slice(10, 16).join('')}`
|
||||
}
|
||||
// 最终回退: Math.random
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {
|
||||
const r = (Math.random() * 16) | 0
|
||||
const v = ch === 'x' ? r : (r & 0x3) | 0x8
|
||||
return v.toString(16)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user