86 lines
2.9 KiB
TypeScript
86 lines
2.9 KiB
TypeScript
'use client'
|
||
|
||
import { useField, useFormFields } from '@payloadcms/ui'
|
||
import React, { useState } from 'react'
|
||
|
||
/**
|
||
* 淘宝自动解析按钮
|
||
* 放置在 taobaoLinks 数组项内,读取当前 url 字段,
|
||
* 调用 /api/taobao/parse 获取标题 / 封面 / 价格,
|
||
* 然后自动填入同一数组项的对应字段。
|
||
*
|
||
* 使用方式(TaobaoLinksField.ts 的 UI 字段):
|
||
* { type: 'ui', name: 'fetchButton', admin: { components: { Field: '/components/fields/TaobaoFetchButton#TaobaoFetchButton' } } }
|
||
*/
|
||
export const TaobaoFetchButton: React.FC<{ path?: string }> = ({ path = '' }) => {
|
||
const [loading, setLoading] = useState(false)
|
||
const [message, setMessage] = useState<string | null>(null)
|
||
|
||
// path 例如 "taobaoLinks.0.fetchButton",取前缀 "taobaoLinks.0."
|
||
const prefix = path.replace(/[^.]+$/, '')
|
||
|
||
const { value: url } = useField<string>({ path: `${prefix}url` })
|
||
const { setValue: setTitle } = useField<string>({ path: `${prefix}title` })
|
||
const { setValue: setThumbnail } = useField<string>({ path: `${prefix}thumbnail` })
|
||
const { setValue: setPrice } = useField<number>({ path: `${prefix}price` })
|
||
|
||
const handleFetch = async () => {
|
||
if (!url) {
|
||
setMessage('请先填写淘宝链接')
|
||
return
|
||
}
|
||
setLoading(true)
|
||
setMessage(null)
|
||
try {
|
||
const res = await fetch('/api/taobao/parse', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ url }),
|
||
})
|
||
const data = await res.json()
|
||
if (!data.success) throw new Error(data.error || '解析失败')
|
||
|
||
if (data.title) setTitle(data.title)
|
||
if (data.thumbnail) setThumbnail(data.thumbnail)
|
||
if (data.price != null) setPrice(data.price)
|
||
|
||
const filled = [data.title && '标题', data.thumbnail && '封面', data.price != null && '价格']
|
||
.filter(Boolean)
|
||
.join('、')
|
||
setMessage(filled ? `✅ 已填入:${filled}` : '⚠️ 未能解析到内容')
|
||
} catch (err: any) {
|
||
setMessage(`❌ ${err?.message ?? '请求失败'}`)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div style={{ marginTop: '0.5rem', display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
|
||
<button
|
||
type="button"
|
||
onClick={handleFetch}
|
||
disabled={loading || !url}
|
||
style={{
|
||
padding: '0.4rem 0.9rem',
|
||
background: loading ? '#9ca3af' : '#f97316',
|
||
color: '#fff',
|
||
border: 'none',
|
||
borderRadius: '4px',
|
||
cursor: loading || !url ? 'not-allowed' : 'pointer',
|
||
fontSize: '0.8rem',
|
||
fontWeight: 500,
|
||
whiteSpace: 'nowrap',
|
||
}}
|
||
>
|
||
{loading ? '解析中…' : '🔍 自动解析'}
|
||
</button>
|
||
{message && (
|
||
<span style={{ fontSize: '0.78rem', color: message.startsWith('✅') ? '#16a34a' : '#dc2626' }}>
|
||
{message}
|
||
</span>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|