{"record":{"id":"e7e9a7e369dff069","repo":"jeecgboot/JeecgBoot","slug":"token-e7e9a7","errorCode":null,"errorMessage":"token不存在~","messagePattern":"token不存在~","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"jeecgboot-vue3/src/views/super/online/cgform/auto/default/OnlineFormUrlAdd.vue","lineNumber":45,"sourceCode":"  // OnlineForm 这个必须引用，setup模式必须在template里面使用。否则url进入会报错\n  import OnlineForm from '../comp/OnlineForm.vue';\n  import { useMessage } from '/@/hooks/web/useMessage';\n  import OnlineAutoModal from './OnlineAutoModal.vue';\n  import { useOnlineTableContext } from '../../hooks/auto/useOnlineTableContext';\n  import { useListButton } from '../../hooks/auto/useListButton';\n  import { useEnhance } from '../../hooks/auto/useEnhance';\n  import { useRouter } from 'vue-router';\n  import { useFormUrl } from '../../hooks/auto/useFormUrl';\n  const { ID, onlineTableContext, onlineExtConfigJson, handleFormConfig } = useOnlineTableContext();\n  const { createMessage: $message } = useMessage();\n  const wrapRef = ref(null);\n  const contentHeight = ref(400);\n  const loading = ref(true);\n  const router = useRouter();\n\n  const { token } = useFormUrl();\n  if (!unref(token)) {\n    throw new Error('token不存在~');\n  }\n  if (!ID.value) {\n    $message.warning('地址错误, 配置ID不存在!');\n    throw new Error('地址错误, 配置ID不存在!');\n  }\n  // 处理增强\n  let { initCgEnhanceJs } = useEnhance(onlineTableContext);\n  watch(\n    () => wrapRef.value,\n    (elem: HTMLElement) => {\n      // 获取页面实际高度\n      contentHeight.value = elem.offsetHeight - 60;\n    }\n  );\n  // 处理列表button\n  const { registerModal, handleAdd } = useListButton(onlineTableContext, onlineExtConfigJson);\n  const getContainer = (node) => {\n    return document.querySelector(`.online-add-${ID.value}`);","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecgboot-vue3/src/views/super/online/cgform/auto/default/OnlineFormUrlAdd.vue#L27-L63","documentation":"Setup guard in the URL-style online Add form. `useFormUrl()` resolves the token from `route.query.token`, falling back to `userStore.getToken`; if neither is present it schedules an async demo-token fetch + page reload. The synchronous `if (!unref(token))` throw fires immediately when token is still falsy, halting render because every online form API call needs a bearer token.","triggerScenarios":"Opening the form URL without a `?token=` query param while NOT logged in (so `userStore.getToken` is also empty). The companion async token fetch hasn't run yet, so the synchronous guard throws first.","commonSituations":"Sharing the form link externally without appending `?token=...`; session expired and token cleared; opening in an incognito/private window; an SSO/login redirect loop left the user store empty.","solutions":["Log in to the platform first, then reopen the form so `userStore.getToken` populates `token`.","Append a valid `?token=<jwt>` to the URL for external/embedded use.","Ensure the SSO/login flow completes and sets the token before the form route mounts.","For external embedding, generate a long-lived form token server-side and pass it in the URL."],"exampleFix":"// before\nconst { token } = useFormUrl();\nif (!unref(token)) { throw new Error('token不存在~'); }\n\n// after — redirect to login (or back with the return url) instead of a hard throw\nconst { token } = useFormUrl();\nif (!unref(token)) {\n  router.replace({ path: '/user/login', query: { redirect: route.fullPath } });\n  return;\n}","handlingStrategy":"validation","validationCode":"// confirm token presence before relying on it\nconst { token } = useFormUrl();\nif (!unref(token)) {\n  router.replace({ path: '/user/login', query: { redirect: route.fullPath } });\n  return;\n}","typeGuard":"const hasToken = (t: unknown): t is string => typeof t === 'string' && t.length > 0;","tryCatchPattern":null,"preventionTips":["Always include `?token=` when sharing form URLs externally.","Ensure login/SSO completes and sets userStore.getToken before form routes mount.","Add a router guard that requires token for url-form routes.","Avoid relying on the async demo-token fetch path in production."],"tags":["vue3","online-cgform","auth","token","setup-guard","url-form","typescript"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}