素材云添加视频图片占位符,对接授权应用接口
This commit is contained in:
@@ -259,6 +259,15 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fadeInUp {
|
||||
animation: fadeInUp 0.45s ease-out both;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ const AuthorizationPage: React.FC = () => {
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '授权账户ID',
|
||||
title: '授权绑定账户ID',
|
||||
dataIndex: 'accountId',
|
||||
key: 'accountId',
|
||||
},
|
||||
@@ -210,7 +210,7 @@ const AuthorizationPage: React.FC = () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '授权账户用户ID',
|
||||
title: '授权登录账户用户ID',
|
||||
dataIndex: 'accountUserid',
|
||||
key: 'accountUserid',
|
||||
render: (text: string) => <span style={{ color: text ? '#1e293b' : '#94a3b8' }}>{text || '-'}</span>,
|
||||
@@ -293,8 +293,16 @@ const AuthorizationPage: React.FC = () => {
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, marginBottom: 16 }}>
|
||||
<div style={{ display: 'flex', gap: 12 }}>
|
||||
<Input
|
||||
placeholder="授权绑定账户ID"
|
||||
value={searchParams.account_id}
|
||||
onChange={(e) => setSearchParams(prev => ({ ...prev, account_id: e.target.value }))}
|
||||
style={{ width: 180 }}
|
||||
allowClear
|
||||
onPressEnter={() => { setCurrentPage(1); loadOAuthList(1, pageSize); }}
|
||||
/>
|
||||
<Input
|
||||
placeholder="账号用户ID"
|
||||
placeholder="授权登录账户用户ID"
|
||||
value={searchParams.account_userid}
|
||||
onChange={(e) => setSearchParams(prev => ({ ...prev, account_userid: e.target.value }))}
|
||||
style={{ width: 180 }}
|
||||
@@ -309,14 +317,6 @@ const AuthorizationPage: React.FC = () => {
|
||||
allowClear
|
||||
options={openTypeOptions}
|
||||
/>
|
||||
<Input
|
||||
placeholder="账号ID"
|
||||
value={searchParams.account_id}
|
||||
onChange={(e) => setSearchParams(prev => ({ ...prev, account_id: e.target.value }))}
|
||||
style={{ width: 180 }}
|
||||
allowClear
|
||||
onPressEnter={() => { setCurrentPage(1); loadOAuthList(1, pageSize); }}
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
size="medium"
|
||||
|
||||
@@ -77,6 +77,7 @@ const GeneratedRecord: React.FC = () => {
|
||||
const [selectedOauthItems, setSelectedOauthItems] = useState<({ value: string; label: string } | undefined)[]>([undefined]);
|
||||
const [materialFileNames, setMaterialFileNames] = useState<Map<string, string>>(new Map());
|
||||
const [unifiedFileName, setUnifiedFileName] = useState('');
|
||||
const [mediaLoadStatus, setMediaLoadStatus] = useState<Map<string, 'loading' | 'loaded' | 'error'>>(new Map());
|
||||
const updateFilenameDebounceRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());
|
||||
|
||||
useEffect(() => {
|
||||
@@ -1247,15 +1248,63 @@ const GeneratedRecord: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
{showImage ? (
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt="预览"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
}}
|
||||
/>
|
||||
<div style={{ width: '100%', height: '100%', position: 'relative' }}>
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt="预览"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
opacity: mediaLoadStatus.get(getItemResourceId(item)) === 'loaded' ? 1 : 0,
|
||||
transition: 'opacity 0.3s',
|
||||
}}
|
||||
onLoad={() => {
|
||||
setMediaLoadStatus(prev => {
|
||||
const newMap = new Map(prev);
|
||||
newMap.set(getItemResourceId(item), 'loaded');
|
||||
return newMap;
|
||||
});
|
||||
}}
|
||||
onError={() => {
|
||||
setMediaLoadStatus(prev => {
|
||||
const newMap = new Map(prev);
|
||||
newMap.set(getItemResourceId(item), 'error');
|
||||
return newMap;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
{mediaLoadStatus.get(getItemResourceId(item)) !== 'loaded' && (
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
background: 'linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%)',
|
||||
}}>
|
||||
<div style={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 8,
|
||||
backgroundColor: '#cbd5e1',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
animation: mediaLoadStatus.get(getItemResourceId(item)) === 'loading' ? 'pulse 1.5s infinite' : 'none',
|
||||
}}>
|
||||
{item.mediaType === 'video' ? (
|
||||
<VideoCameraOutlined style={{ color: '#64748b', fontSize: 16 }} />
|
||||
) : (
|
||||
<PictureOutlined style={{ color: '#64748b', fontSize: 16 }} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div style={{
|
||||
width: '100%',
|
||||
@@ -1377,6 +1426,7 @@ const GeneratedRecord: React.FC = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
{isSelectionMode && isSelectedItem && (
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
|
||||
Reference in New Issue
Block a user