| 41 | } |
| 42 | |
| 43 | export function ResolveButtons({ path, actions, showEditLink = true }: ResolveButtonsProps) { |
| 44 | const t = useT(); |
| 45 | const router = useRouter(); |
| 46 | const [busy, setBusy] = useState(false); |
| 47 | const [msg, setMsg] = useState<{ kind: "ok" | "err" | "info"; text: string } | null>(null); |
| 48 | |
| 49 | async function handle(action: ActionDef) { |
| 50 | if (busy) return; |
| 51 | if (action.confirmKey && !confirm(t(action.confirmKey, action.vars))) return; |
| 52 | |
| 53 | let payload: { newClaim?: string; mergedText?: string } | undefined; |
| 54 | if (action.promptKey && action.payloadField) { |
| 55 | const input = window.prompt(t(action.promptKey, action.vars)); |
| 56 | if (input === null || !input.trim()) { |
| 57 | // 用户取消或输入空 — 静默退出 |
| 58 | return; |
| 59 | } |
| 60 | payload = { [action.payloadField]: input }; |
| 61 | } |
| 62 | |
| 63 | setBusy(true); |
| 64 | setMsg({ kind: "info", text: t("common.processing") }); |
| 65 | try { |
| 66 | const res = await fetch("/api/resolve", { |
| 67 | method: "POST", |
| 68 | headers: { "Content-Type": "application/json" }, |
| 69 | body: JSON.stringify({ path, action: action.action, payload }), |
| 70 | }); |
| 71 | const data = await res.json(); |
| 72 | if (res.ok) { |
| 73 | const text = data.commit |
| 74 | ? t("action.commit_msg", { commit: data.commit }) |
| 75 | : t("action.commit_noop"); |
| 76 | setMsg({ kind: "ok", text }); |
| 77 | setTimeout(() => router.refresh(), 600); |
| 78 | } else { |
| 79 | // 已知 error enum 映射成 i18n key——避免中英文 mix |
| 80 | const errorKeyMap: Record<string, TranslationKey> = { |
| 81 | invalid_json: "action.error.invalid_json", |
| 82 | missing_path: "action.error.missing_path", |
| 83 | invalid_action: "action.error.invalid_action", |
| 84 | invalid_path: "action.error.invalid_path", |
| 85 | permission_denied: "action.error.permission_denied", |
| 86 | commit_failed: "action.error.commit_failed", |
| 87 | write_failed: "action.error.write_failed", |
| 88 | read_failed: "action.error.read_failed", |
| 89 | }; |
| 90 | const knownKey = errorKeyMap[data.error]; |
| 91 | const text = knownKey ? t(knownKey) : t("action.error.generic"); |
| 92 | setMsg({ kind: "err", text }); |
| 93 | } |
| 94 | } catch (e) { |
| 95 | setMsg({ kind: "err", text: t("common.network_error", { err: String(e) }) }); |
| 96 | } finally { |
| 97 | setBusy(false); |
| 98 | } |
| 99 | } |
| 100 | |