完成前测素材,模板列表

This commit is contained in:
Lrd
2026-07-06 18:07:45 +08:00
parent f4d278eae4
commit 4da83e4859
6 changed files with 431 additions and 107 deletions
+35 -35
View File
@@ -1,37 +1,37 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
<title>后台管理</title>
<script>
(function() {
var cached = localStorage.getItem('siteInfo');
if (cached) {
try {
var info = JSON.parse(cached);
if (info.siteName) {
document.title = info.siteName + ' - 管理后台';
}
if (info.siteLogo) {
var link = document.querySelector('link[rel="icon"]');
if (link) {
link.href = info.siteLogo;
link.type = 'image/png';
}
}
} catch (e) {}
}
})();
</script>
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
<title>后台管理</title>
<script>
(function() {
var cached = localStorage.getItem('siteInfo');
if (cached) {
try {
var info = JSON.parse(cached);
if (info.siteName) {
document.title = info.siteName + ' - 管理后台';
}
if (info.siteLogo) {
var link = document.querySelector('link[rel="icon"]');
if (link) {
link.href = info.siteLogo;
link.type = 'image/png';
}
}
} catch (e) {}
}
})();
</script>
<script type="module" crossorigin src="/assets/index-Dx-bvo36.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D7ShJUt4.css">
</head>
<body>
<div id="root"></div>
</body>
</html>
</head>
<body>
<div id="root"></div>
</body>
</html>
+17
View File
@@ -999,6 +999,23 @@ export async function getMaterialList(params: MaterialListParams): Promise<any>
return api.get(`/material-admin/material-list?${query.toString()}`);
}
export interface PreTestTemplateListParams {
id?: string;
phone?: string;
created_at?: [string, string];
page?: number;
page_size?: number;
}
export async function getPreTestTemplateList(params: PreTestTemplateListParams): Promise<any> {
const query = new URLSearchParams();
if (params.id) query.set('id', params.id);
if (params.phone) query.set('phone', params.phone);
if (params.created_at !== undefined) query.set('created_at', params.created_at[0] + ',' + params.created_at[1]);
if (params.page !== undefined) query.set('page', String(params.page));
if (params.page_size !== undefined) query.set('page_size', String(params.page_size));
return api.get(`/material-admin/pre-test-template-list?${query.toString()}`);
}
// ── Private Portrait Admin ────────────────────────────────
export async function adminGetPrivatePortraitProjects(params: { userId?: string; keyword?: string; status?: string; page?: number; pageSize?: number } = {}): Promise<PrivatePortraitProjectListOut> {
const query = new URLSearchParams();
@@ -0,0 +1,180 @@
import React, { useState } from 'react';
import { Popover, Tag, List, Descriptions, Typography } from 'antd';
interface PreResultData {
video_id: string;
advertiser_id: number;
material_id: string;
is_ad_high_quality_material: string;
is_ecp_high_quality_material: string;
is_inefficient_material: string;
is_first_publish_material: string;
is_local_high_quality_material: string;
not_ad_high_quality_reason: string[] | null;
not_ecp_high_quality_reason: string[] | null;
}
interface PreResultDisplayProps {
preResult: string;
}
const fieldConfig = [
{ key: 'is_ad_high_quality_material', label: 'AD优质', noLabel: 'AD非优质素材', unknownLabel: 'AD未知', yesColor: 'green', noColor: 'red', unknownColor: 'default' },
{ key: 'is_ecp_high_quality_material', label: '千川优质', noLabel: '千川非优质素材', unknownLabel: '千川未知', yesColor: 'green', noColor: 'red', unknownColor: 'default' },
{ key: 'is_local_high_quality_material', label: '本地推优质', noLabel: '本地推非优质', unknownLabel: '本地推未知', yesColor: 'green', noColor: 'red', unknownColor: 'default' },
{ key: 'is_inefficient_material', label: '低效', noLabel: '非低效', unknownLabel: '是否低效未知', yesColor: 'red', noColor: 'green', unknownColor: 'default' },
{ key: 'is_first_publish_material', label: '首发', noLabel: '非首发', unknownLabel: '是否首发未知', yesColor: 'blue', noColor: 'default', unknownColor: 'default' },
];
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 getIndicatorDisplay = (key: string) => {
const config = fieldConfig.find(c => c.key === key);
if (!config) return null;
const value = parsedData[key as keyof PreResultData];
const isYes = value === 'YES';
const isNo = value === 'NO';
const isUnknown = value === 'UNKNOWN';
if (isUnknown) return null;
let displayLabel, displayColor;
if (isYes) {
displayLabel = config.label;
displayColor = config.yesColor;
} else if (isNo) {
displayLabel = config.noLabel;
displayColor = config.noColor;
}
return {
tag: (
<Tag
key={key}
color={displayColor}
style={{ marginRight: 6, fontSize: 12, borderRadius: 4 }}
>
{displayLabel}
</Tag>
),
detail: {
label: config.label.replace('优质', '优质素材'),
value: displayLabel,
color: displayColor,
},
};
};
const content = (
<div style={{ maxWidth: 500, padding: '8px 0' }}>
<Typography.Text strong style={{ fontSize: 14, display: 'block', marginBottom: 12, color: '#1e293b' }}></Typography.Text>
<Descriptions column={1} size="small" style={{ marginBottom: 12 }}>
<Descriptions.Item label="视频ID" labelStyle={{ fontWeight: 500, color: '#64748b' }} contentStyle={{ color: '#1e293b' }}>{parsedData.video_id}</Descriptions.Item>
<Descriptions.Item label="广告主ID" labelStyle={{ fontWeight: 500, color: '#64748b' }} contentStyle={{ color: '#1e293b' }}>{parsedData.advertiser_id}</Descriptions.Item>
<Descriptions.Item label="素材ID" labelStyle={{ fontWeight: 500, color: '#64748b' }} contentStyle={{ color: '#1e293b' }}>{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 }}>
{fieldConfig.map(config => {
const value = parsedData[config.key as keyof PreResultData];
const isYes = value === 'YES';
const isNo = value === 'NO';
const isUnknown = value === 'UNKNOWN';
if (isUnknown) return null;
let displayLabel, displayColor;
if (isYes) {
displayLabel = config.label;
displayColor = config.yesColor;
} else if (isNo) {
displayLabel = config.noLabel;
displayColor = config.noColor;
}
return (
<Tag
key={config.key}
color={displayColor}
style={{ fontSize: 12, borderRadius: 4 }}
>
{displayLabel}
</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"
placement="topLeft"
overlayStyle={{ borderRadius: 12, boxShadow: '0 8px 24px rgba(0,0,0,0.12)' }}
>
<div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 4}}>
{fieldConfig.map(config => {
const display = getIndicatorDisplay(config.key);
return display?.tag;
})}
</div>
</Popover>
);
};
export default PreResultDisplay;
@@ -1,7 +1,8 @@
import React, { useEffect, useState } from 'react';
import { Button, Input, Select, Table, Pagination, Tag, Typography } from 'antd';
import { FileTextOutlined, SearchOutlined } from '@ant-design/icons';
import { Button, Input, Select, Table, Pagination, Tag, Typography, Tooltip } from 'antd';
import { FileTextOutlined } from '@ant-design/icons';
import { getMaterialList } from '../api';
import PreResultDisplay from '../components/PreResultDisplay';
const formatDateTime = (dateStr: string) => {
if (!dateStr) return '';
const date = new Date(dateStr);
@@ -48,6 +49,16 @@ const AdminMaterialList: React.FC = () => {
title: '备注',
dataIndex: 'note',
key: 'note',
width: 200,
render: (text: string) => (
<Input.TextArea
value={text || ''}
readOnly
autoSize={{ minRows: 1, maxRows: 4 }}
style={{ color: '#94a3b8', resize: 'none', border: 'none', background: 'transparent', padding: 0 }}
placeholder="-"
/>
),
},
{
title: '授权ID',
@@ -58,6 +69,8 @@ const AdminMaterialList: React.FC = () => {
title: '预测试结果',
dataIndex: 'preResult',
key: 'preResult',
width: 120,
render: (text: string) => <PreResultDisplay preResult={text} />,
},
{
title: '预测试模板ID',
@@ -94,7 +107,15 @@ const AdminMaterialList: React.FC = () => {
title: '上传ID',
dataIndex: 'uploadId',
key: 'uploadId',
width: 160,
render: (v: string) => {
if (!v) return '-';
const short = v.length > 12 ? `${v.slice(0, 6)}...${v.slice(-4)}` : v;
return (
<Tooltip title={v} placement="topLeft">
<Typography.Text style={{ fontSize: 12 }}>{short}</Typography.Text>
</Tooltip>
);
},
},
{
title: '资源类型',
@@ -145,13 +166,13 @@ const AdminMaterialList: React.FC = () => {
page: currentPage,
page_size: pageSize,
});
const data = res.items || [];
const data = res.data || [];
const tableData = data.map((item: any, index: number) => ({
...item,
index: (currentPage - 1) * pageSize + index + 1,
}));
setTableData(tableData);
setTotal(res.total || 0);
setTotal(res.pagination?.total || 0);
} catch (error) {
console.error('加载数据失败:', error);
} finally {
@@ -1,18 +1,29 @@
import React, { useEffect, useState } from 'react';
import { Button, Input, Select, Table, Pagination, Tag, Typography } from 'antd';
import { FileTextOutlined, SearchOutlined } from '@ant-design/icons';
import { Button, Input, Table, Pagination, Tag, Typography, DatePicker } from 'antd';
import { FileTextOutlined } from '@ant-design/icons';
import { getPreTestTemplateList } from '../api';
import dayjs from 'dayjs';
const formatDateTime = (dateStr: string) => {
if (!dateStr) return '';
const date = new Date(dateStr);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
const { Text } = Typography;
const AdminPreTestTemplates: React.FC = () => {
const [tableData, setTableData] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [total, setTotal] = useState(0);
const [searchPlatform, setSearchPlatform] = useState('');
const [searchName, setSearchName] = useState('');
const [searchId, setSearchId] = useState('');
const [searchPhone, setSearchPhone] = useState('');
const [searchCreatedAt, setSearchCreatedAt] = useState<[dayjs.Dayjs, dayjs.Dayjs] | undefined>();
const columns = [
{
title: '序号',
@@ -22,92 +33,180 @@ const AdminPreTestTemplates: React.FC = () => {
render: (text: number) => <span style={{ color: '#64748b' }}>{text}</span>,
},
{
title: '模板名称',
title: 'ID',
dataIndex: 'id',
key: 'id',
},
{
title: '手机号',
dataIndex: 'phone',
key: 'phone',
width: 150,
},
{
title: '受众年龄',
dataIndex: 'audienceAge',
key: 'audienceAge',
width: 100,
},
{
title: '受众性别',
dataIndex: 'audienceGender',
key: 'audienceGender',
width: 100,
},
{
title: '受众网络',
dataIndex: 'audienceNetwork',
key: 'audienceNetwork',
width: 100,
},
{
title: '受众区域',
dataIndex: 'audienceRegion',
key: 'audienceRegion',
width: 100,
},
{
title: '预算',
dataIndex: 'budget',
key: 'budget',
width: 100,
},
{
title: '成本上限',
dataIndex: 'costCap',
key: 'costCap',
width: 100,
},
{
title: 'CPA预算',
dataIndex: 'cpaBid',
key: 'cpaBid',
width: 100,
},
{
title: 'CPC预算',
dataIndex: 'cpcBid',
key: 'cpcBid',
width: 100,
},
{
title: '客户名称',
dataIndex: 'cusName',
key: 'cusName',
width: 150,
},
{
title: '外部操作',
dataIndex: 'externalAction',
key: 'externalAction',
width: 100,
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
width: 200,
width: 150,
},
{
title: '投放平台',
title: '名称',
dataIndex: 'nobid',
key: 'nobid',
width: 150,
},
{
title: '备注',
dataIndex: 'note',
key: 'note',
width: 150,
},
{
title: '平台',
dataIndex: 'platform',
key: 'platform',
width: 120,
render: (text: string) => (
<Tag color={text === 'AD' ? 'blue' : text === 'QIANCHUAN' ? 'green' : 'orange'}>
{text === 'AD' ? 'AD' : text === 'QIANCHUAN' ? '千川' : '本地推'}
</Tag>
),
width: 100,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
title: '定价类型',
dataIndex: 'pricingType',
key: 'pricingType',
width: 100,
render: (text: string) => (
<Tag color={text === 'active' ? 'green' : 'red'}>
{text === 'active' ? '启用' : '禁用'}
</Tag>
),
},
{
title: '目标成本',
dataIndex: 'targetCost',
key: 'targetCost',
width: 100,
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
width: 100,
},
{
title: '用户手机号',
dataIndex: 'userPhone',
key: 'userPhone',
width: 150,
},
{
title: '是否默认',
dataIndex: 'isDefault',
key: 'isDefault',
width: 100,
render: (text: boolean) => <Tag color={text ? 'green' : 'red'}>{text ? '是' : '否'}</Tag>,
},
{
title: '创建时间',
dataIndex: 'createdAt',
key: 'createdAt',
width: 180,
render: (text: string) => <span style={{ color: '#64748b' }}>{text}</span>,
render: (text: string) => <span style={{ color: '#64748b' }}>{formatDateTime(text)}</span>,
},
{
title: '更新时间',
dataIndex: 'updatedAt',
key: 'updatedAt',
width: 180,
render: (text: string) => <span style={{ color: '#64748b' }}>{text}</span>,
render: (text: string) => <span style={{ color: '#64748b' }}>{formatDateTime(text)}</span>,
},
];
const loadRecords = async () => {
setLoading(true);
try {
const params = new URLSearchParams();
params.set('page', String(currentPage));
params.set('page_size', String(pageSize));
if (searchPlatform) params.set('platform', searchPlatform);
if (searchName) params.set('name', searchName);
const mockData = {
items: Array.from({ length: pageSize }, (_, i) => ({
id: `${currentPage}-${i}`,
index: (currentPage - 1) * pageSize + i + 1,
name: `前测模板${(currentPage - 1) * pageSize + i + 1}`,
platform: ['AD', 'QIANCHUAN', 'LOCAL'][i % 3],
status: i % 5 === 0 ? 'inactive' : 'active',
createdAt: '2026-07-01 10:00:00',
updatedAt: '2026-07-02 14:30:00',
})),
total: 50,
};
setTableData(mockData.items);
setTotal(mockData.total);
const res = await getPreTestTemplateList({
id: searchId || undefined,
phone: searchPhone || undefined,
created_at: searchCreatedAt ? [searchCreatedAt[0].format('YYYY-MM-DD'), searchCreatedAt[1].format('YYYY-MM-DD')] : undefined,
page: currentPage,
page_size: pageSize,
});
const data = res.data || [];
const tableData = data.map((item: any, index: number) => ({
...item,
index: (currentPage - 1) * pageSize + index + 1,
}));
setTableData(tableData);
setTotal(res.pagination.total || 0);
} catch (error) {
console.error('加载数据失败:', error);
} finally {
setLoading(false);
}
};
useEffect(() => {
loadRecords();
}, [currentPage, pageSize]);
const handlePageChange = (page: number, size: number) => {
setCurrentPage(page);
setPageSize(size);
};
const handleSearch = () => {
setCurrentPage(1);
loadRecords();
};
return (
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
@@ -115,26 +214,34 @@ const AdminPreTestTemplates: React.FC = () => {
<Text strong style={{ fontSize: 16 }}></Text>
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
<div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
<div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
<Input
placeholder="模板名称"
value={searchName}
onChange={(e) => setSearchName(e.target.value)}
style={{ width: 180 }}
placeholder="ID"
value={searchId}
onChange={(e) => setSearchId(e.target.value)}
style={{ width: 160 }}
allowClear
onPressEnter={handleSearch}
/>
<Select
placeholder="投放平台"
value={searchPlatform}
onChange={(value) => setSearchPlatform(value)}
style={{ width: 140 }}
<Input
placeholder="手机号"
value={searchPhone}
onChange={(e) => setSearchPhone(e.target.value)}
style={{ width: 160 }}
allowClear
options={[
{ value: 'AD', label: 'AD' },
{ value: 'QIANCHUAN', label: '千川' },
{ value: 'LOCAL', label: '本地推' },
]}
onPressEnter={handleSearch}
/>
<DatePicker.RangePicker
placeholder={['开始日期', '结束日期']}
value={searchCreatedAt}
onChange={(dates) => {
if (dates && dates[0] && dates[1]) {
setSearchCreatedAt([dates[0], dates[1]]);
} else {
setSearchCreatedAt(undefined);
}
}}
style={{ width: 260 }}
/>
<Button
type="primary"
@@ -187,5 +294,4 @@ const AdminPreTestTemplates: React.FC = () => {
</div>
);
};
export default AdminPreTestTemplates;
+1 -1
View File
@@ -1 +1 @@
{"root":["./src/app.tsx","./src/env.d.ts","./src/main.tsx","./src/api/client.ts","./src/api/crypto.ts","./src/api/index.ts","./src/pages/adminauthoriz.tsx","./src/pages/adminconsume.tsx","./src/pages/admincontactrequests.tsx","./src/pages/admincreditratios.tsx","./src/pages/admincreditrecords.tsx","./src/pages/admindashboard.tsx","./src/pages/admingenerationairecords.tsx","./src/pages/admingenerationrecords.tsx","./src/pages/adminhomematerials.tsx","./src/pages/adminhotopeningreplicationdetail.tsx","./src/pages/adminhotopeningreplications.tsx","./src/pages/adminimageengines.tsx","./src/pages/adminindustries.tsx","./src/pages/adminlayout.tsx","./src/pages/adminloginpage.tsx","./src/pages/adminmateriallist.tsx","./src/pages/adminmenuconfig.tsx","./src/pages/adminmodels.tsx","./src/pages/adminnotificationmanager.tsx","./src/pages/adminoauthlist.tsx","./src/pages/adminoauthapplist.tsx","./src/pages/adminoperationlogs.tsx","./src/pages/adminpaymentconfig.tsx","./src/pages/adminpaymentstats.tsx","./src/pages/adminplatform.tsx","./src/pages/adminpretesttemplates.tsx","./src/pages/adminprivateportraitprojects.tsx","./src/pages/adminrechargepackages.tsx","./src/pages/adminreplicationprojectdetail.tsx","./src/pages/adminsettings.tsx","./src/pages/adminshotreplications.tsx","./src/pages/adminshottasksetdetail.tsx","./src/pages/adminteams.tsx","./src/pages/adminusers.tsx","./src/pages/adminvideoengines.tsx","./src/pages/adminvideopromptschemaconfig.tsx","./src/pages/adminreplication/components/jsoncollapse.tsx","./src/pages/adminreplication/components/mediapreview.tsx","./src/pages/adminreplication/components/statustag.tsx","./src/pages/adminreplication/components/videopromptschemaviewer.tsx","./src/pages/homematerials/homematerialassettable.tsx","./src/pages/homematerials/homematerialcategorypanel.tsx","./src/pages/homematerials/homematerialuploadmodal.tsx","./src/pages/homematerials/watermarkeditor.tsx","./src/pages/homematerials/watermarklibrarymodal.tsx","./src/pages/homematerials/watermarkpreview.tsx","./src/store/index.ts","./src/types/index.ts","./src/types/xlsx-js-style.d.ts","./src/utils/excelexport.ts","./src/utils/formatdate.ts","./src/utils/resourceurl.ts","./src/utils/videopromptschema.ts"],"version":"6.0.3"}
{"root":["./src/app.tsx","./src/env.d.ts","./src/main.tsx","./src/api/client.ts","./src/api/crypto.ts","./src/api/index.ts","./src/components/preresultdisplay.tsx","./src/pages/adminauthoriz.tsx","./src/pages/adminconsume.tsx","./src/pages/admincontactrequests.tsx","./src/pages/admincreditratios.tsx","./src/pages/admincreditrecords.tsx","./src/pages/admindashboard.tsx","./src/pages/admingenerationairecords.tsx","./src/pages/admingenerationrecords.tsx","./src/pages/adminhomematerials.tsx","./src/pages/adminhotopeningreplicationdetail.tsx","./src/pages/adminhotopeningreplications.tsx","./src/pages/adminimageengines.tsx","./src/pages/adminindustries.tsx","./src/pages/adminlayout.tsx","./src/pages/adminloginpage.tsx","./src/pages/adminmateriallist.tsx","./src/pages/adminmenuconfig.tsx","./src/pages/adminmodels.tsx","./src/pages/adminnotificationmanager.tsx","./src/pages/adminoauthlist.tsx","./src/pages/adminoauthapplist.tsx","./src/pages/adminoperationlogs.tsx","./src/pages/adminpaymentconfig.tsx","./src/pages/adminpaymentstats.tsx","./src/pages/adminplatform.tsx","./src/pages/adminpretesttemplates.tsx","./src/pages/adminprivateportraitprojects.tsx","./src/pages/adminrechargepackages.tsx","./src/pages/adminreplicationprojectdetail.tsx","./src/pages/adminsettings.tsx","./src/pages/adminshotreplications.tsx","./src/pages/adminshottasksetdetail.tsx","./src/pages/adminteams.tsx","./src/pages/adminusers.tsx","./src/pages/adminvideoengines.tsx","./src/pages/adminvideopromptschemaconfig.tsx","./src/pages/adminreplication/components/jsoncollapse.tsx","./src/pages/adminreplication/components/mediapreview.tsx","./src/pages/adminreplication/components/statustag.tsx","./src/pages/adminreplication/components/videopromptschemaviewer.tsx","./src/pages/homematerials/homematerialassettable.tsx","./src/pages/homematerials/homematerialcategorypanel.tsx","./src/pages/homematerials/homematerialuploadmodal.tsx","./src/pages/homematerials/watermarkeditor.tsx","./src/pages/homematerials/watermarklibrarymodal.tsx","./src/pages/homematerials/watermarkpreview.tsx","./src/store/index.ts","./src/types/index.ts","./src/types/xlsx-js-style.d.ts","./src/utils/excelexport.ts","./src/utils/formatdate.ts","./src/utils/resourceurl.ts","./src/utils/videopromptschema.ts"],"version":"6.0.3"}