Register 直播切片 as a video-only material type. Upload and edit flows collect required title, live date (defaults to today), optional host with user link, and live platform presets. Persist the fields on Material and skip SPU formatting for free-text titles.
152 lines
4.1 KiB
TypeScript
152 lines
4.1 KiB
TypeScript
/**
|
||
* 直播切片专用字段:直播日期 / 主播(可关联用户)/ 直播平台
|
||
*/
|
||
|
||
'use client'
|
||
|
||
import { useEffect, useState } from 'react'
|
||
import {
|
||
fieldControlClass,
|
||
fieldHintClass,
|
||
fieldLabelClass,
|
||
} from '@/components/upload/upload-field-styles'
|
||
import {
|
||
getDefaultLiveDate,
|
||
LIVE_CLIP_PLATFORMS,
|
||
} from '@/lib/live-clip'
|
||
|
||
export interface LiveClipFieldsProps {
|
||
liveDate: string
|
||
liveHost: string
|
||
liveHostUserId: string
|
||
livePlatform: string
|
||
onLiveDateChange: (value: string) => void
|
||
onLiveHostChange: (value: string) => void
|
||
onLiveHostUserIdChange: (value: string) => void
|
||
onLivePlatformChange: (value: string) => void
|
||
}
|
||
|
||
interface UserOption {
|
||
id: string
|
||
displayName: string
|
||
username: string
|
||
}
|
||
|
||
export default function LiveClipFields({
|
||
liveDate,
|
||
liveHost,
|
||
liveHostUserId,
|
||
livePlatform,
|
||
onLiveDateChange,
|
||
onLiveHostChange,
|
||
onLiveHostUserIdChange,
|
||
onLivePlatformChange,
|
||
}: LiveClipFieldsProps) {
|
||
const [users, setUsers] = useState<UserOption[]>([])
|
||
const [usersLoaded, setUsersLoaded] = useState(false)
|
||
|
||
useEffect(() => {
|
||
if (!liveDate) {
|
||
onLiveDateChange(getDefaultLiveDate())
|
||
}
|
||
// 仅在日期为空时补默认值,避免依赖回调导致循环
|
||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||
}, [])
|
||
|
||
useEffect(() => {
|
||
let cancelled = false
|
||
fetch('/api/users/list')
|
||
.then((res) => (res.ok ? res.json() : []))
|
||
.then((data: UserOption[]) => {
|
||
if (!cancelled && Array.isArray(data)) {
|
||
setUsers(data)
|
||
setUsersLoaded(true)
|
||
}
|
||
})
|
||
.catch(() => {
|
||
if (!cancelled) setUsersLoaded(true)
|
||
})
|
||
return () => {
|
||
cancelled = true
|
||
}
|
||
}, [])
|
||
|
||
return (
|
||
<>
|
||
<div>
|
||
<label htmlFor="liveDate" className={fieldLabelClass}>
|
||
直播日期
|
||
</label>
|
||
<input
|
||
id="liveDate"
|
||
type="date"
|
||
value={liveDate}
|
||
onChange={(e) => onLiveDateChange(e.target.value)}
|
||
className={fieldControlClass}
|
||
max={getDefaultLiveDate()}
|
||
/>
|
||
<p className={`mt-2 ${fieldHintClass}`}>默认上传当天,可按日历修改</p>
|
||
</div>
|
||
|
||
<div>
|
||
<label htmlFor="liveHost" className={fieldLabelClass}>
|
||
主播 <span className={`ml-1 font-normal ${fieldHintClass}`}>(可选)</span>
|
||
</label>
|
||
<input
|
||
id="liveHost"
|
||
type="text"
|
||
value={liveHost}
|
||
onChange={(e) => onLiveHostChange(e.target.value)}
|
||
className={fieldControlClass}
|
||
maxLength={50}
|
||
placeholder="填写主播昵称"
|
||
/>
|
||
<label htmlFor="liveHostUserId" className={`${fieldLabelClass} mt-4 block`}>
|
||
关联用户 <span className={`ml-1 font-normal ${fieldHintClass}`}>(可选,便于按人筛选)</span>
|
||
</label>
|
||
<select
|
||
id="liveHostUserId"
|
||
value={liveHostUserId}
|
||
onChange={(e) => {
|
||
const userId = e.target.value
|
||
onLiveHostUserIdChange(userId)
|
||
if (userId) {
|
||
const matched = users.find((u) => u.id === userId)
|
||
if (matched && !liveHost.trim()) {
|
||
onLiveHostChange(matched.displayName)
|
||
}
|
||
}
|
||
}}
|
||
className={fieldControlClass}
|
||
>
|
||
<option value="">{usersLoaded ? '不关联用户' : '加载用户…'}</option>
|
||
{users.map((user) => (
|
||
<option key={user.id} value={user.id}>
|
||
{user.displayName}
|
||
</option>
|
||
))}
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label htmlFor="livePlatform" className={fieldLabelClass}>
|
||
直播平台
|
||
</label>
|
||
<select
|
||
id="livePlatform"
|
||
value={livePlatform}
|
||
onChange={(e) => onLivePlatformChange(e.target.value)}
|
||
className={fieldControlClass}
|
||
>
|
||
<option value="">请选择平台</option>
|
||
{LIVE_CLIP_PLATFORMS.map((platform) => (
|
||
<option key={platform} value={platform}>
|
||
{platform}
|
||
</option>
|
||
))}
|
||
</select>
|
||
</div>
|
||
</>
|
||
)
|
||
}
|