import { useState } from 'react'
import { useNavigate, useParams } from 'react-router'
import { useDataProvider, useList, useOne } from '@refinedev/core'
import {
Alert, Button, Card, CardContent, Checkbox, ConfirmDialog, DetailList, Field, Input, Modal,
PageHeader, PageState, StatusPill, conflictMessage,
} from './lib/ui.jsx'
import { useTitle } from './lib/hooks.js'
export function DraftPage() {
const { id } = useParams()
const navigate = useNavigate()
const dataProvider = useDataProvider()('default')
const [reviewed, setReviewed] = useState(false)
const [confirmOpen, setConfirmOpen] = useState(false)
const [busy, setBusy] = useState(false)
const [notice, setNotice] = useState(null)
const { result, error, isPending, query } = useOne({ resource: 'drafts', id, queryOptions: { retry: false } })
const draft = result
const { result: bindingResult, query: browsersQuery } = useList({ resource: 'browsers', queryOptions: { retry: false } })
const browsers = bindingResult.data ?? []
const browsersError = browsersQuery.error
const refetchBrowsers = browsersQuery.refetch
useTitle('CreatorHub · 草稿核对')
if (isPending) return
if (error || !draft) return {error?.message || '草稿不存在'}
const versions = draft.versions || []
const confirmations = draft.confirmations || []
const tasks = draft.tasks || []
const latestVersion = versions[0]?.version || draft.version
const isLatest = draft.version === latestVersion
const confirmation = confirmations.find(item => item.account_version === draft.account.version && item.draft_version === draft.version)
const binding = browsersError ? undefined : browsers.find(item => item.account_id === draft.account_id)
const readiness = draftReadiness(draft, binding, !!browsersError)
const canConfirm = isLatest && !!binding && !browsersError
const canEnqueue = !!confirmation && isLatest && readiness.ready
async function confirmSnapshot() {
setBusy(true)
setNotice(null)
try {
await dataProvider.confirmDraft(draft.id, draft.account.version, draft.version)
await query.refetch()
setConfirmOpen(false)
setNotice({ variant: 'success', text: '确认快照已保存,可回溯账号、草稿与当前固定资源版本。' })
} catch (reason) {
setConfirmOpen(false)
setNotice({ variant: 'destructive', text: conflictMessage(reason) })
await Promise.all([query.refetch(), refetchBrowsers()])
} finally {
setBusy(false)
}
}
async function enqueue() {
if (!confirmation) return
setBusy(true)
setNotice(null)
try {
const task = await dataProvider.enqueueConfirmation(confirmation.id)
await query.refetch()
setNotice({ variant: 'success', text: `任务已排队:${task.id}。重复提交会返回同一任务。` })
} catch (reason) {
setNotice({ variant: 'destructive', text: conflictMessage(reason) })
await Promise.all([query.refetch(), refetchBrowsers()])
} finally {
setBusy(false)
}
}
return (
{draft.account.platform_account_key} · 草稿版本 {draft.version}}>
{notice ?
{notice.text} : null}
{browsersError ?
环境不可用:当前运行环境与网络出口状态未知,不能确认或排队。 : null}
{!isLatest ? (
当前只读快照已不是最新草稿版本,请刷新到版本 {latestVersion} 后重新核对。
) : null}
只读内容快照
{draft.content}
版本与当前资源
版本链
{versions.map(item => item.id === draft.id ? (
版本 {item.version}(当前快照)
) : (
))}
显式核对与入队
我已核对当前账号、草稿内容、运行环境和网络出口
{confirmation ? null : 保存有效确认后才可加入队列。
}
{confirmation ? (
确认快照 v{confirmation.version}
账号版本 {confirmation.account_version} · 草稿版本 {confirmation.draft_version}
环境:{confirmation.browser_env_alias || '未记录'} · 出口:{confirmation.network_exit_id || '未记录'} · 绑定版本:{confirmation.binding_version || '未记录'}
) : null}
关联任务
{tasks.length === 0 ? 尚未入队。
: (
{tasks.map(task => (
{task.id}
任务状态:{task.state}
))}
)}
setConfirmOpen(false)} title="确认草稿版本" size="sm" labelledBy="confirm-draft-title"
footer={<>
>}>
将保存账号版本 {draft.account.version}、草稿版本 {draft.version}、运行环境 {binding?.alias} 与网络出口 {binding?.network_exit_id || '当前机器直连'} 的只读确认快照。版本变化后必须重新确认。
)
}
// 与账号 readiness 同构的草稿侧判定:只依赖绑定健康与调度状态。
function draftReadiness(draft, binding, bindingsError = false) {
if (draft.account.authorization_status !== 'authorized') return { label: '授权已撤销', ready: false }
if (bindingsError) return { label: '环境状态未知', ready: false }
if (!binding) return { label: '未绑定运行环境', ready: false }
if (binding.network_exit_id && binding.network_exit_health !== 'healthy') return { label: '固定出口不健康', ready: false }
const schedule = binding.schedule_block_reason || ''
return { label: schedule ? `不可调度:${schedule}` : '可调度', ready: !schedule }
}