From 37eb51513fdf99f94f075e25f400edd726698983 Mon Sep 17 00:00:00 2001 From: liuwenxin <1009266660@qq.com> Date: Fri, 30 Oct 2026 09:56:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E5=89=8D=E7=AB=AF):=20=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E9=9D=9E=E5=AE=89=E5=85=A8=E4=B8=8A=E4=B8=8B=E6=96=87=E7=9A=84?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E8=AF=B7=E6=B1=82=E9=94=AE=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crypto.randomUUID 仅在 HTTPS 或 localhost 下存在,客户内网 以 http://<内网IP> 访问时该 API 为 undefined,而新建任务 对话框在页面挂载即调用,会直接 TypeError 导致整页白屏。 新增 newRequestKey 工具:优先 randomUUID,不可用时降级为 getRandomValues 拼 v4 格式(非安全上下文仍可用)。 Co-Authored-By: Claude Code --- frontend/src/utils/uuid.ts | 11 +++++++++++ frontend/src/views/system/tplus/CreateTaskDialog.vue | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 frontend/src/utils/uuid.ts diff --git a/frontend/src/utils/uuid.ts b/frontend/src/utils/uuid.ts new file mode 100644 index 0000000..3a66ea5 --- /dev/null +++ b/frontend/src/utils/uuid.ts @@ -0,0 +1,11 @@ +// crypto.randomUUID 仅在安全上下文(HTTPS 或 localhost)存在;客户内网常以 +// http://<内网IP> 访问,此时该 API 为 undefined。降级用 getRandomValues 拼 +// v4 格式(getRandomValues 在非安全上下文仍然可用)。 +export function newRequestKey(): string { + if (typeof crypto.randomUUID === 'function') return crypto.randomUUID() + const bytes = crypto.getRandomValues(new Uint8Array(16)) + bytes[6] = (bytes[6] & 0x0f) | 0x40 // version 4 + bytes[8] = (bytes[8] & 0x3f) | 0x80 // variant 10x + const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')) + return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${hex.slice(10, 16).join('')}` +} diff --git a/frontend/src/views/system/tplus/CreateTaskDialog.vue b/frontend/src/views/system/tplus/CreateTaskDialog.vue index 49d35dc..0c4c1be 100644 --- a/frontend/src/views/system/tplus/CreateTaskDialog.vue +++ b/frontend/src/views/system/tplus/CreateTaskDialog.vue @@ -3,6 +3,7 @@ import { ref, watch } from 'vue' import { ElMessage } from 'element-plus' import * as api from '@/api/tplus' import { handledError } from '@/utils/error' +import { newRequestKey } from '@/utils/uuid' import { entities } from './labels' const visible = defineModel({ required: true }) @@ -11,9 +12,9 @@ const emit = defineEmits<{ created: [batch: api.TPlusDetail] }>() const taskType = ref('READ') const selected = ref(['personnel']) const pending = ref(false) -let requestKey = crypto.randomUUID() +let requestKey = newRequestKey() // 请求失败后保留键,只有意图改变或成功后才换键。 -watch([taskType, selected], () => { requestKey = crypto.randomUUID() }, { deep: true, flush: 'sync' }) +watch([taskType, selected], () => { requestKey = newRequestKey() }, { deep: true, flush: 'sync' }) async function submit(): Promise { if (pending.value || !props.configured) return @@ -21,7 +22,7 @@ async function submit(): Promise { try { const batch = await api.createTask({ task_type: taskType.value, entity_types: taskType.value === 'AUDIT' ? [] : [...selected.value], request_key: requestKey }) - requestKey = crypto.randomUUID() + requestKey = newRequestKey() visible.value = false ElMessage.success('任务已排队,处理完成后可刷新查看') emit('created', batch)