gbmake-payload/src/components/sync/taobao/TaobaoProductSync.tsx

122 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import { useState } from 'react'
import { useDocumentInfo } from '@payloadcms/ui'
/**
* 产品编辑页 — 淘宝信息同步按钮(仅填充空字段 / 强制覆盖)
* API: POST /api/admin/taobao/sync-product
*
* 使用 useDocumentInfo只能在 Product / PreorderProduct 编辑页使用。
*/
export function TaobaoProductSync() {
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 isValid = collectionSlug === 'products' || collectionSlug === 'preorder-products'
if (!isValid) return null
const busy = loadingNormal || loadingForce
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)
}
}
return (
<div>
<div
style={{
fontSize: '0.8rem',
fontWeight: 600,
color: 'var(--theme-elevation-600)',
marginBottom: '0.5rem',
}}
>
</div>
<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
<button
type="button"
disabled={busy}
onClick={() => run(false)}
style={btnStyle(busy, '#3b82f6')}
>
{loadingNormal ? '解析中…' : '🔄 更新淘宝信息'}
</button>
<button
type="button"
disabled={busy}
onClick={() => run(true)}
style={btnStyle(busy, '#f97316')}
>
{loadingForce ? '解析中…' : '⚡ 强制更新淘宝信息'}
</button>
</div>
<div
style={{
marginTop: '0.5rem',
fontSize: '0.73rem',
color: 'var(--theme-elevation-450)',
lineHeight: 1.5,
}}
>
<strong>🔄 </strong>&emsp;
<strong> </strong>
</div>
{message && <StatusMsg text={message} />}
</div>
)
}
const btnStyle = (busy: boolean, color: string): React.CSSProperties => ({
padding: '0.4rem 0.9rem',
background: busy ? '#9ca3af' : color,
color: '#fff',
border: 'none',
borderRadius: '4px',
cursor: busy ? 'not-allowed' : 'pointer',
fontSize: '0.8rem',
fontWeight: 500,
whiteSpace: 'nowrap',
})
function StatusMsg({ text }: { text: string }) {
const isError = text.startsWith('❌')
return (
<div
style={{
marginTop: '0.5rem',
padding: '0.4rem 0.75rem',
borderRadius: '4px',
fontSize: '0.8rem',
background: isError ? 'var(--theme-error-50)' : 'var(--theme-success-50)',
color: isError ? 'var(--theme-error-750)' : 'var(--theme-success-750)',
}}
>
{text}
</div>
)
}