diff --git a/Tiku.PlatformAdmin.Web/src/api/http.ts b/Tiku.PlatformAdmin.Web/src/api/http.ts index 93c572e..983b811 100644 --- a/Tiku.PlatformAdmin.Web/src/api/http.ts +++ b/Tiku.PlatformAdmin.Web/src/api/http.ts @@ -64,7 +64,11 @@ export async function apiRequest( signal?: AbortSignal, ): Promise { const pathValues = (input.path || {}) as Record; - let route = operation.path.replace(/\{([^}]+)\}/g, (_, name: string) => encodeURIComponent(String(pathValues[name] ?? ''))); + let route = operation.path.replace(/\{([^}]+)\}/g, (_, name: string) => { + const value = pathValues[name]; + if (value === undefined || value === null) throw new Error(`缺少必填路径参数:${name}`); + return encodeURIComponent(String(value)); + }); const url = new URL(route, window.location.origin); appendQuery(url, ((input.query || {}) as Record)); route = `${url.pathname}${url.search}`; diff --git a/Tiku.PlatformAdmin.Web/src/api/token-store.ts b/Tiku.PlatformAdmin.Web/src/api/token-store.ts index 4d85e9c..0991bb8 100644 --- a/Tiku.PlatformAdmin.Web/src/api/token-store.ts +++ b/Tiku.PlatformAdmin.Web/src/api/token-store.ts @@ -21,8 +21,11 @@ export const tokenStore = { get: () => currentTokens, set(tokens: TokenPair | null) { currentTokens = tokens; - if (tokens) localStorage.setItem(storageKey, JSON.stringify(tokens)); - else localStorage.removeItem(storageKey); + if (tokens) { + try { localStorage.setItem(storageKey, JSON.stringify(tokens)); } catch { /* quota exceeded — in-memory copy still valid */ } + } else { + localStorage.removeItem(storageKey); + } window.dispatchEvent(new CustomEvent('platform-auth-change')); }, }; diff --git a/Tiku.PlatformAdmin.Web/src/components/BusinessTable.tsx b/Tiku.PlatformAdmin.Web/src/components/BusinessTable.tsx index 3660823..a4b1af6 100644 --- a/Tiku.PlatformAdmin.Web/src/components/BusinessTable.tsx +++ b/Tiku.PlatformAdmin.Web/src/components/BusinessTable.tsx @@ -34,7 +34,7 @@ export function BusinessTable({ payload, loading, onSelect }: { payload: unknown String(row.id || row.tenantId || row.code || index)} + rowKey={(row, index) => String(row.id ?? row.tenantId ?? row.code ?? index)} rowSelection={{ type: 'radio', onChange: (_, selected) => onSelect(selected[0] || null) }} scroll={{ x: 'max-content' }} pagination={{ pageSize: 20, showSizeChanger: true, showTotal: (total) => `共 ${total} 条` }} diff --git a/Tiku.PlatformAdmin.Web/src/components/ResponseView.tsx b/Tiku.PlatformAdmin.Web/src/components/ResponseView.tsx index e45baed..42a778b 100644 --- a/Tiku.PlatformAdmin.Web/src/components/ResponseView.tsx +++ b/Tiku.PlatformAdmin.Web/src/components/ResponseView.tsx @@ -27,7 +27,7 @@ export function ResponseView({ payload }: { payload: unknown }) { return (
String(row.id || row.code || row.userId || index)} + rowKey={(row, index) => String(row.id ?? row.code ?? row.userId ?? index)} dataSource={rows} scroll={{ x: 'max-content' }} pagination={{ pageSize: 20, showSizeChanger: true }} diff --git a/Tiku.PlatformAdmin.Web/src/pages/QuestionBankPage.tsx b/Tiku.PlatformAdmin.Web/src/pages/QuestionBankPage.tsx index dab191a..54b300f 100644 --- a/Tiku.PlatformAdmin.Web/src/pages/QuestionBankPage.tsx +++ b/Tiku.PlatformAdmin.Web/src/pages/QuestionBankPage.tsx @@ -75,18 +75,21 @@ function toTree(nodes: BankNode[]): DataNode[] { const key = node.parentId || null; children.set(key, [...(children.get(key) || []), node]); } - const build = (parentId: string | null): DataNode[] => (children.get(parentId) || []) - .sort((a, b) => Number(a.sortOrder) - Number(b.sortOrder)) - .map((node) => ({ - key: node.id, - title: {node.name}, - children: build(node.id), - })); + const build = (parentId: string | null, depth = 0): DataNode[] => { + if (depth > 50) return []; + return (children.get(parentId) || []) + .sort((a, b) => Number(a.sortOrder) - Number(b.sortOrder)) + .map((node) => ({ + key: node.id, + title: {node.name}, + children: build(node.id, depth + 1), + })); + }; return build(null); } -function parseJson(value: string | undefined, fallback: unknown) { - if (!value?.trim()) return fallback; +function parseJson(value: unknown, fallback: unknown) { + if (typeof value !== 'string' || !value.trim()) return fallback; return JSON.parse(value); } @@ -197,6 +200,7 @@ export function QuestionBankPage() { const saveBatchNodes = async () => { const values = await batchForm.validateFields(); const names = String(values.names).split(/\n|,/).map((item) => item.trim()).filter(Boolean); + if (!names.length) return message.error('请输入至少一个节点名称'); if (names.length > 100) return message.error('一次最多创建 100 个节点'); await platformRequest('POST', '/api/platform-admin/question-banks/nodes/batch', { body: { questionBankId: bankId, parentId: values.parentId || null, nodeType: values.nodeType, names } }); message.success(`已创建 ${names.length} 个节点`); setBatchNodeOpen(false); batchForm.resetFields(); await loadNodes();