解决dist冲突
This commit is contained in:
@@ -338,7 +338,7 @@ const AdminPlatform: React.FC = () => {
|
|||||||
const res = await uploadImage(uploadFile);
|
const res = await uploadImage(uploadFile);
|
||||||
console.log(res);
|
console.log(res);
|
||||||
createForm.setFieldsValue({ thumb: res.url });
|
createForm.setFieldsValue({ thumb: res.url });
|
||||||
onSuccess?.(res);
|
onSuccess?.({ url: res.url });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
onError?.(normalizeUploadError(e));
|
onError?.(normalizeUploadError(e));
|
||||||
}
|
}
|
||||||
@@ -440,7 +440,7 @@ const AdminPlatform: React.FC = () => {
|
|||||||
const uploadFile = assertUploadFile(file);
|
const uploadFile = assertUploadFile(file);
|
||||||
const res = await uploadImage(uploadFile);
|
const res = await uploadImage(uploadFile);
|
||||||
updateForm.setFieldsValue({ thumb: res.url });
|
updateForm.setFieldsValue({ thumb: res.url });
|
||||||
onSuccess?.(res);
|
onSuccess?.({ url: res.url });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
onError?.(normalizeUploadError(e));
|
onError?.(normalizeUploadError(e));
|
||||||
}
|
}
|
||||||
|
|||||||
+442
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/assets/index-C1Aswo8N.js"></script>
|
<script type="module" crossorigin src="/assets/index-D9QoFfGP.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-eLRg4pQk.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-eLRg4pQk.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Popover, Tag, List, Descriptions, Typography } from 'antd';
|
||||||
|
|
||||||
|
interface PreResultData {
|
||||||
|
video_id: string; //视频id
|
||||||
|
advertiser_id: number; //广告主id
|
||||||
|
material_id: string; //素材id
|
||||||
|
is_ad_high_quality_material: string; //是否优质素材
|
||||||
|
is_ecp_high_quality_material: string; //是否千川优质素材
|
||||||
|
is_inefficient_material: string; //是否低效素材
|
||||||
|
is_first_publish_material: string; //是否首发素材
|
||||||
|
not_ad_high_quality_reason: string[] | null; //AD非优质原因
|
||||||
|
not_ecp_high_quality_reason: string[] | null; //千川非优质原因
|
||||||
|
is_local_high_quality_material: string; //是否本地推优质素材
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PreResultDisplayProps {
|
||||||
|
preResult: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qualityConfig: Record<string, { color: string; label: string }> = {
|
||||||
|
YES: { color: 'green', label: '是' },
|
||||||
|
NO: { color: 'red', label: '否' },
|
||||||
|
UNKNOWN: { color: 'default', label: '未知' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const PreResultDisplay: React.FC<PreResultDisplayProps> = ({ preResult }) => {
|
||||||
|
const [parsedData, setParsedData] = useState<PreResultData | null>(null);
|
||||||
|
const [hasError, setHasError] = useState(false);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!preResult) {
|
||||||
|
setParsedData(null);
|
||||||
|
setHasError(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(preResult);
|
||||||
|
setParsedData(data);
|
||||||
|
setHasError(false);
|
||||||
|
} catch {
|
||||||
|
setParsedData(null);
|
||||||
|
setHasError(true);
|
||||||
|
}
|
||||||
|
}, [preResult]);
|
||||||
|
|
||||||
|
if (!preResult || hasError || !parsedData) {
|
||||||
|
return <span style={{ color: '#64748b' }}>-</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allQualityFields = [
|
||||||
|
parsedData.is_ad_high_quality_material,
|
||||||
|
parsedData.is_ecp_high_quality_material,
|
||||||
|
parsedData.is_local_high_quality_material,
|
||||||
|
];
|
||||||
|
|
||||||
|
const hasNoQuality = allQualityFields.some((val) => val === 'NO');
|
||||||
|
const allYes = allQualityFields.every((val) => val === 'YES');
|
||||||
|
|
||||||
|
let statusTag;
|
||||||
|
if (hasNoQuality) {
|
||||||
|
statusTag = <Tag color="red">非优质</Tag>;
|
||||||
|
} else if (allYes) {
|
||||||
|
statusTag = <Tag color="green">优质</Tag>;
|
||||||
|
} else {
|
||||||
|
statusTag = <Tag color="default">待评估</Tag>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = (
|
||||||
|
<div style={{ maxWidth: 500 }}>
|
||||||
|
<Typography.Text strong style={{ fontSize: 14, display: 'block', marginBottom: 12 }}>前测结果详情</Typography.Text>
|
||||||
|
|
||||||
|
<Descriptions column={1} size="small" style={{ marginBottom: 12 }}>
|
||||||
|
<Descriptions.Item label="视频ID">{parsedData.video_id}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="广告主ID">{parsedData.advertiser_id}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="素材ID">{parsedData.material_id}</Descriptions.Item>
|
||||||
|
</Descriptions>
|
||||||
|
|
||||||
|
<Typography.Text strong style={{ fontSize: 12, color: '#64748b', display: 'block', marginBottom: 8 }}>质量评估</Typography.Text>
|
||||||
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 12 }}>
|
||||||
|
<Tag color={qualityConfig[parsedData.is_ad_high_quality_material]?.color}>
|
||||||
|
AD优质素材: {qualityConfig[parsedData.is_ad_high_quality_material]?.label}
|
||||||
|
</Tag>
|
||||||
|
<Tag color={qualityConfig[parsedData.is_ecp_high_quality_material]?.color}>
|
||||||
|
千川优质素材: {qualityConfig[parsedData.is_ecp_high_quality_material]?.label}
|
||||||
|
</Tag>
|
||||||
|
<Tag color={qualityConfig[parsedData.is_local_high_quality_material]?.color}>
|
||||||
|
本地推优质素材: {qualityConfig[parsedData.is_local_high_quality_material]?.label}
|
||||||
|
</Tag>
|
||||||
|
<Tag color={qualityConfig[parsedData.is_inefficient_material]?.color}>
|
||||||
|
低效素材: {qualityConfig[parsedData.is_inefficient_material]?.label}
|
||||||
|
</Tag>
|
||||||
|
<Tag color={qualityConfig[parsedData.is_first_publish_material]?.color}>
|
||||||
|
首发素材: {qualityConfig[parsedData.is_first_publish_material]?.label}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{parsedData.not_ad_high_quality_reason && parsedData.not_ad_high_quality_reason.length > 0 && (
|
||||||
|
<div style={{ marginBottom: 12 }}>
|
||||||
|
<Typography.Text strong style={{ fontSize: 12, color: '#ef4444', display: 'block', marginBottom: 8 }}>
|
||||||
|
AD非优质原因
|
||||||
|
</Typography.Text>
|
||||||
|
<List
|
||||||
|
dataSource={parsedData.not_ad_high_quality_reason}
|
||||||
|
renderItem={(item, index) => (
|
||||||
|
<List.Item key={index} style={{ padding: '4px 0', fontSize: 12, color: '#64748b' }}>
|
||||||
|
{index + 1}. {item}
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{parsedData.not_ecp_high_quality_reason && parsedData.not_ecp_high_quality_reason.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<Typography.Text strong style={{ fontSize: 12, color: '#ef4444', display: 'block', marginBottom: 8 }}>
|
||||||
|
千川非优质原因
|
||||||
|
</Typography.Text>
|
||||||
|
<List
|
||||||
|
dataSource={parsedData.not_ecp_high_quality_reason}
|
||||||
|
renderItem={(item, index) => (
|
||||||
|
<List.Item key={index} style={{ padding: '4px 0', fontSize: 12, color: '#64748b' }}>
|
||||||
|
{index + 1}. {item}
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover content={content} title={null} trigger="hover">
|
||||||
|
{statusTag}
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PreResultDisplay;
|
||||||
@@ -1433,7 +1433,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
<Input
|
<Input
|
||||||
value={materialFileNames.get(itemId) || item?.fileName || ''}
|
value={materialFileNames.has(itemId) ? materialFileNames.get(itemId)! : item?.fileName || ''}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const newName = e.target.value;
|
const newName = e.target.value;
|
||||||
const newNames = new Map(materialFileNames);
|
const newNames = new Map(materialFileNames);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Button, Table, Tag, Input, Pagination, Typography, Select, App } from '
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { FolderOpenOutlined, EyeOutlined } from '@ant-design/icons';
|
import { FolderOpenOutlined, EyeOutlined } from '@ant-design/icons';
|
||||||
import { getResourcesMaterialList } from '../api';
|
import { getResourcesMaterialList } from '../api';
|
||||||
|
import PreResultDisplay from '../components/PreResultDisplay';
|
||||||
|
|
||||||
// 格式化时间 2026-06-12T03:47:28.542988Z -> 2026-06-12 03:47:28
|
// 格式化时间 2026-06-12T03:47:28.542988Z -> 2026-06-12 03:47:28
|
||||||
const formatDateTime = (dateStr: string) => {
|
const formatDateTime = (dateStr: string) => {
|
||||||
@@ -243,7 +244,7 @@ const MaterialListPage: React.FC = () => {
|
|||||||
dataIndex: 'preResult',
|
dataIndex: 'preResult',
|
||||||
key: 'preResult',
|
key: 'preResult',
|
||||||
width: 120,
|
width: 120,
|
||||||
render: (text: string) => <span style={{ color: '#64748b' }}>{text || '-'}</span>,
|
render: (text: string) => <PreResultDisplay preResult={text} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '备注',
|
title: '备注',
|
||||||
|
|||||||
Reference in New Issue
Block a user