{"record":{"id":"2bc7f67dd81b915f","repo":"jeecgboot/JeecgBoot","slug":"token-2bc7f6","errorCode":null,"errorMessage":"token不存在~","messagePattern":"token不存在~","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"jeecgboot-vue3/src/views/super/online/cgform/auto/default/OnlineFormUrlEdit.vue","lineNumber":46,"sourceCode":"  import OnlineForm from '../comp/OnlineForm.vue';\n  import { useMessage } from '/@/hooks/web/useMessage';\n  import { useRoute, useRouter } from 'vue-router';\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 { useFormUrl } from '../../hooks/auto/useFormUrl';\n  const { ID, onlineTableContext, onlineExtConfigJson, handleFormConfig } = useOnlineTableContext();\n  const { createMessage: $message } = useMessage();\n  const route = useRoute();\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 || !route.params.dataId) {\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, handleEdit } = useListButton(onlineTableContext, onlineExtConfigJson);\n  const getContainer = (node) => {\n    return document.querySelector(`.online-edit-${ID.value}`);","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecgboot-vue3/src/views/super/online/cgform/auto/default/OnlineFormUrlEdit.vue#L28-L64","documentation":"Setup guard in the URL-style online Edit form — identical contract to the Add/Detail token guard. Throws if `token` is falsy after `useFormUrl()` resolves, halting render because edit save calls need a bearer token.","triggerScenarios":"Opening the edit URL without `?token=` while not logged in (empty `userStore.getToken`); the async token fetch hasn't completed so the synchronous guard throws.","commonSituations":"Shared edit link without a token; session expired; incognito window; SSO redirect loop left the user store empty.","solutions":["Log in to the platform first, then reopen the edit form.","Append a valid `?token=<jwt>` to the edit URL for external use.","Ensure the login/SSO flow sets the token before the edit route mounts.","For embedding, mint 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 preserving the return path\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":["Include `?token=` on externally shared edit links.","Ensure login/SSO sets userStore.getToken before edit routes mount.","Guard url-edit routes for token presence.","Avoid the demo-token fetch path in production."],"tags":["vue3","online-cgform","auth","token","setup-guard","url-form","edit","typescript"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}