import { useState } from 'react'; import { schemaSql } from '../../core/changeSql'; import { columnTypeLabels, zhCN } from '../../i18n/zh-CN'; import { useChangeStore } from '../../store/changeStore'; import type { ColumnMeta, SchemaChange, TableMeta } from '../../types'; import { Modal } from '../common/Modal'; import styles from '../grid/grid.module.css'; // 建表、删表与索引对话框:结构变更一律暂存,提交时才下发。 export type SchemaAction = { kind: 'create' } | { kind: 'drop' | 'indexes'; table: TableMeta }; const identifier = /^[A-Za-z_][A-Za-z0-9_]*$/; // 列类型的中文名,未知类型原样显示。 function typeLabel(type: string): string { return columnTypeLabels[type] ?? type; } export function SchemaDialog({ action, onClose, onChanged }: { action: SchemaAction; onClose: () => void; onChanged: (message: string) => void; }) { const [name, setName] = useState(''); const [columns, setColumns] = useState>>([{ name: 'id', type: 'int' }, { name: '', type: 'str' }]); const [error, setError] = useState(''); const stageSchema = useChangeStore((state) => state.stageSchema); const schemas = useChangeStore((state) => state.changes.schemas); const target = action.kind === 'create' ? undefined : action.table; const stagedIndex = new Map(); for (const change of schemas.values()) { if (change.table !== target?.name) continue; if (change.op === 'createIndex') stagedIndex.set(change.column, true); else if (change.op === 'dropIndex') stagedIndex.set(change.column, false); } const stage = (change: SchemaChange) => { stageSchema(change); onChanged(zhCN.stagedMessage(schemaSql(change))); }; const create = () => { if (!identifier.test(name) || columns.some((column) => !identifier.test(column.name))) return setError(zhCN.invalidIdentifier); if (new Set(columns.map((column) => column.name)).size !== columns.length) return setError(zhCN.duplicateColumns); stage({ op: 'createTable', table: name, columns }); onClose(); }; const drop = () => { if (!target) return; stage({ op: 'dropTable', table: target.name }); onClose(); }; const changeIndex = (column: string, indexed: boolean) => { if (!target) return; stage(indexed ? { op: 'dropIndex', table: target.name, column } : { op: 'createIndex', table: target.name, column }); }; const title = action.kind === 'create' ? zhCN.newTableTitle : `${action.kind === 'drop' ? zhCN.dropTableTitle : zhCN.indexManagerTitle} · ${target?.name}`; return {action.kind === 'create' && }{action.kind === 'drop' && }}> {action.kind === 'create' ?

{zhCN.createTableHint}

{columns.map((column, index) =>
setColumns(columns.map((item, i) => i === index ? { ...item, name: event.target.value } : item))} />
)}
: action.kind === 'drop' ? <>

{zhCN.dropTableHint(target?.name ?? '', target?.rowCount ?? 0)}

: <>

{zhCN.indexHint}

    {target?.columns.map((column) => { const indexed = stagedIndex.get(column.name) ?? Boolean(column.indexed); return
  • {column.name} {typeLabel(column.type)}{column.primaryKey || column.name === 'id' ? zhCN.builtinIndex : indexed ? zhCN.uniqueIndex : zhCN.noIndex}
  • ; })}
} {error &&

{error}

}
; }