117 lines
4.2 KiB
TypeScript
117 lines
4.2 KiB
TypeScript
'use client'
|
||
import { useState } from 'react'
|
||
import { Button } from '@payloadcms/ui'
|
||
|
||
/**
|
||
* 数据重置按钮(全量 / 仅 Medusa)
|
||
* API: POST /api/admin/reset-data
|
||
*/
|
||
export function ResetData() {
|
||
const [loading, setLoading] = useState<'full' | 'medusa-only' | null>(null)
|
||
const [message, setMessage] = useState('')
|
||
const [details, setDetails] = useState<any>(null)
|
||
|
||
const handle = async (mode: 'full' | 'medusa-only') => {
|
||
const confirmMsg =
|
||
mode === 'medusa-only'
|
||
? '⚠️ 重置 Medusa 数据\n\n此操作将:\n1. 清理所有 Medusa 数据\n2. 重新导入 Medusa seed 数据\n\nPayload CMS 数据不受影响。\n\n⚠️ 此操作不可撤销!确认继续吗?'
|
||
: '⚠️ 危险操作:重置所有数据\n\n此操作将:\n1. 清理所有 Payload CMS 数据(保留用户)\n2. 清理所有 Medusa 数据\n3. 重新导入 Medusa seed 数据\n\n⚠️ 此操作不可撤销!确认要继续吗?'
|
||
if (!confirm(confirmMsg)) return
|
||
|
||
setLoading(mode)
|
||
setMessage('🔄 开始数据重置流程...')
|
||
setDetails(null)
|
||
|
||
try {
|
||
const res = await fetch('/api/admin/reset-data', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ mode }),
|
||
})
|
||
const result = await res.json()
|
||
if (!result.success) {
|
||
const stepError = result.steps?.find((s: any) => !s.success && !s.skipped && s.error)?.error
|
||
throw new Error(result.error || stepError || 'Reset failed')
|
||
}
|
||
setDetails(result)
|
||
setMessage(
|
||
mode === 'medusa-only'
|
||
? '✅ Medusa 数据重置完成!\n\n下一步:\n1. 同步 Medusa 商品到 Payload CMS'
|
||
: '✅ 数据重置完成!\n\n下一步:\n1. 同步 Medusa 商品到 Payload CMS\n2. 设置 ProductRecommendations\n3. 配置 PreorderProducts 的预购设置',
|
||
)
|
||
} catch (err) {
|
||
setMessage('❌ 重置失败: ' + (err instanceof Error ? err.message : 'Unknown error'))
|
||
} finally {
|
||
setLoading(null)
|
||
}
|
||
}
|
||
|
||
const busy = loading !== null
|
||
|
||
return (
|
||
<div>
|
||
<div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
|
||
<Button onClick={() => handle('full')} buttonStyle="error" disabled={busy} size="small">
|
||
{loading === 'full' ? '🔄 重置中...' : '🗑️ 重置所有数据'}
|
||
</Button>
|
||
<Button
|
||
onClick={() => handle('medusa-only')}
|
||
buttonStyle="secondary"
|
||
disabled={busy}
|
||
size="small"
|
||
>
|
||
{loading === 'medusa-only' ? '🔄 重置中...' : '🔄 仅重置 Medusa'}
|
||
</Button>
|
||
</div>
|
||
|
||
{message && (
|
||
<div
|
||
style={{
|
||
marginTop: '0.75rem',
|
||
padding: '0.75rem',
|
||
borderRadius: '4px',
|
||
whiteSpace: 'pre-wrap',
|
||
fontSize: '0.85rem',
|
||
backgroundColor: message.includes('✅')
|
||
? '#d4edda'
|
||
: message.includes('❌')
|
||
? '#f8d7da'
|
||
: '#d1ecf1',
|
||
border: `1px solid ${message.includes('✅') ? '#c3e6cb' : message.includes('❌') ? '#f5c6cb' : '#bee5eb'}`,
|
||
}}
|
||
>
|
||
{message}
|
||
</div>
|
||
)}
|
||
|
||
{details?.steps && (
|
||
<div
|
||
style={{
|
||
marginTop: '0.75rem',
|
||
padding: '0.75rem',
|
||
background: '#f8f9fa',
|
||
border: '1px solid #dee2e6',
|
||
borderRadius: '4px',
|
||
fontSize: '0.82rem',
|
||
}}
|
||
>
|
||
<h4 style={{ margin: '0 0 0.5rem' }}>详细信息:</h4>
|
||
{details.steps.map((step: any, i: number) => (
|
||
<div key={i} style={{ marginBottom: '0.4rem' }}>
|
||
<strong>
|
||
[{step.step}/3] {step.name}:{' '}
|
||
</strong>
|
||
<span style={{ color: step.skipped ? '#888' : step.success ? 'green' : 'red' }}>
|
||
{step.skipped ? '⏭️ 跳过' : step.success ? '✅ 成功' : '❌ 失败'}
|
||
</span>
|
||
{step.deleted !== undefined && (
|
||
<span style={{ marginLeft: '0.4rem' }}>(删除 {step.deleted} 条记录)</span>
|
||
)}
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|