136 lines
4.2 KiB
TypeScript
136 lines
4.2 KiB
TypeScript
'use client'
|
||
|
||
import React, { useState, useEffect } from 'react'
|
||
import { useDocumentInfo } from '@payloadcms/ui'
|
||
|
||
/**
|
||
* 产品编辑页 — 淘宝信息同步按钮
|
||
*
|
||
* 放置在淘宝链接 Tab 顶部(UI 字段),显示两个操作按钮:
|
||
* 🔄 更新淘宝信息 → 仅填充空字段 (force=false)
|
||
* ⚡ 强制更新淘宝信息 → 覆盖所有字段 (force=true)
|
||
*
|
||
* 依赖 API:POST /api/admin/taobao/sync-product
|
||
*/
|
||
export const TaobaoSyncButtons: React.FC = () => {
|
||
const { id, collectionSlug } = useDocumentInfo()
|
||
|
||
const [loadingNormal, setLoadingNormal] = useState(false)
|
||
const [loadingForce, setLoadingForce] = useState(false)
|
||
const [message, setMessage] = useState<string | null>(null)
|
||
|
||
if (!id) return null // 新建文档时不显示
|
||
|
||
const isValidCollection =
|
||
collectionSlug === 'products' || collectionSlug === 'preorder-products'
|
||
if (!isValidCollection) return null
|
||
|
||
const run = async (force: boolean) => {
|
||
const setLoading = force ? setLoadingForce : setLoadingNormal
|
||
setLoading(true)
|
||
setMessage(null)
|
||
|
||
try {
|
||
const res = await fetch('/api/admin/taobao/sync-product', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ productId: id, collection: collectionSlug, force }),
|
||
})
|
||
const data = await res.json()
|
||
|
||
if (!data.success) throw new Error(data.error || '请求失败')
|
||
setMessage(`✅ ${data.message || '完成'}`)
|
||
|
||
// 刷新页面以显示更新后的字段值
|
||
setTimeout(() => window.location.reload(), 1200)
|
||
} catch (err: any) {
|
||
setMessage(`❌ ${err?.message ?? '未知错误'}`)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
const busy = loadingNormal || loadingForce
|
||
|
||
return (
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: '0.5rem',
|
||
padding: '0.75rem 1rem',
|
||
marginBottom: '1rem',
|
||
background: 'var(--theme-elevation-50)',
|
||
borderRadius: '6px',
|
||
border: '1px solid var(--theme-elevation-150)',
|
||
}}
|
||
>
|
||
<div style={{ fontSize: '0.8rem', fontWeight: 600, color: 'var(--theme-elevation-600)' }}>
|
||
淘宝自动解析
|
||
</div>
|
||
|
||
<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
|
||
{/* 更新(非强制) */}
|
||
<button
|
||
type="button"
|
||
disabled={busy}
|
||
onClick={() => run(false)}
|
||
style={{
|
||
padding: '0.4rem 0.9rem',
|
||
background: busy ? '#9ca3af' : '#3b82f6',
|
||
color: '#fff',
|
||
border: 'none',
|
||
borderRadius: '4px',
|
||
cursor: busy ? 'not-allowed' : 'pointer',
|
||
fontSize: '0.8rem',
|
||
fontWeight: 500,
|
||
whiteSpace: 'nowrap',
|
||
}}
|
||
>
|
||
{loadingNormal ? '解析中…' : '🔄 更新淘宝信息'}
|
||
</button>
|
||
|
||
{/* 强制全量更新 */}
|
||
<button
|
||
type="button"
|
||
disabled={busy}
|
||
onClick={() => run(true)}
|
||
style={{
|
||
padding: '0.4rem 0.9rem',
|
||
background: busy ? '#9ca3af' : '#f97316',
|
||
color: '#fff',
|
||
border: 'none',
|
||
borderRadius: '4px',
|
||
cursor: busy ? 'not-allowed' : 'pointer',
|
||
fontSize: '0.8rem',
|
||
fontWeight: 500,
|
||
whiteSpace: 'nowrap',
|
||
}}
|
||
>
|
||
{loadingForce ? '解析中…' : '⚡ 强制更新淘宝信息'}
|
||
</button>
|
||
</div>
|
||
|
||
{/* 说明文字 */}
|
||
<div style={{ fontSize: '0.73rem', color: 'var(--theme-elevation-450)', lineHeight: 1.5 }}>
|
||
<strong>🔄 更新</strong>:仅填充空白字段(标题、封面、价格) 
|
||
<strong>⚡ 强制更新</strong>:覆盖已有字段
|
||
</div>
|
||
|
||
{message && (
|
||
<div
|
||
style={{
|
||
padding: '0.4rem 0.75rem',
|
||
borderRadius: '4px',
|
||
background: message.startsWith('✅') ? 'var(--theme-success-50)' : 'var(--theme-error-50)',
|
||
color: message.startsWith('✅') ? 'var(--theme-success-750)' : 'var(--theme-error-750)',
|
||
fontSize: '0.8rem',
|
||
}}
|
||
>
|
||
{message}
|
||
</div>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|