打包用户端和管理后台

This commit is contained in:
Lrd
2026-07-03 14:22:11 +08:00
parent 7e6318742c
commit b5538ee27a
7 changed files with 79 additions and 65 deletions
File diff suppressed because one or more lines are too long
+36 -36
View File
@@ -1,37 +1,37 @@
<!doctype html> <!doctype html>
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <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.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <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" /> <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
<title>后台管理</title> <title>后台管理</title>
<script> <script>
(function() { (function() {
var cached = localStorage.getItem('siteInfo'); var cached = localStorage.getItem('siteInfo');
if (cached) { if (cached) {
try { try {
var info = JSON.parse(cached); var info = JSON.parse(cached);
if (info.siteName) { if (info.siteName) {
document.title = info.siteName + ' - 管理后台'; document.title = info.siteName + ' - 管理后台';
} }
if (info.siteLogo) { if (info.siteLogo) {
var link = document.querySelector('link[rel="icon"]'); var link = document.querySelector('link[rel="icon"]');
if (link) { if (link) {
link.href = info.siteLogo; link.href = info.siteLogo;
link.type = 'image/png'; link.type = 'image/png';
} }
} }
} catch (e) {} } catch (e) {}
} }
})(); })();
</script> </script>
<script type="module" crossorigin src="/assets/index-kmFIWx83.js"></script> <script type="module" crossorigin src="/assets/index-CqR2fJH3.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D7ShJUt4.css"> <link rel="stylesheet" crossorigin href="/assets/index-D7ShJUt4.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
</body> </body>
</html> </html>
+1 -1
View File
@@ -487,7 +487,7 @@ export async function createOauthApp(data: {
app_id: string; app_id: string;
secret: string; secret: string;
open_type: number; open_type: number;
count?: number; max_count?: number;
auth_url?: string; auth_url?: string;
company?: string; company?: string;
}): Promise<any> { }): Promise<any> {
+24 -24
View File
@@ -10,16 +10,16 @@ import { formatDate } from '../utils/formatDate';
interface OAuthApp { interface OAuthApp {
id: string; id: string;
app_id: string; appId: string;
secret: string; secret: string;
status: number; status: number;
max_count: number; maxCount: number;
open_type: number; openType: number;
auth_url?: string; authUrl?: string;
company?: string; company?: string;
create_by: string; createBy: string;
created_at: string; createdAt: string;
updated_at: string; updatedAt: string;
} }
const AdminOauthAppList: React.FC = () => { const AdminOauthAppList: React.FC = () => {
@@ -54,7 +54,7 @@ const AdminOauthAppList: React.FC = () => {
app_id: values.app_id, app_id: values.app_id,
secret: values.secret, secret: values.secret,
open_type: values.open_type, open_type: values.open_type,
count: values.count, max_count: values.max_count,
auth_url: values.auth_url, auth_url: values.auth_url,
company: values.company, company: values.company,
}); });
@@ -82,11 +82,11 @@ const AdminOauthAppList: React.FC = () => {
const app = await getOauthApp(id); const app = await getOauthApp(id);
setCurrentApp(app); setCurrentApp(app);
updateForm.setFieldsValue({ updateForm.setFieldsValue({
app_id: app.app_id, appId: app.appId,
secret: app.secret, secret: app.secret,
open_type: app.open_type, openType: app.openType,
count: app.max_count, maxCount: app.maxCount,
auth_url: app.auth_url, authUrl: app.authUrl,
company: app.company, company: app.company,
}); });
setUpdateModalVisible(true); setUpdateModalVisible(true);
@@ -298,7 +298,7 @@ const AdminOauthAppList: React.FC = () => {
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="count" name="max_count"
label="最大授权用户数" label="最大授权用户数"
initialValue={100} initialValue={100}
> >
@@ -334,22 +334,22 @@ const AdminOauthAppList: React.FC = () => {
{currentApp && ( {currentApp && (
<div style={{ lineHeight: '2' }}> <div style={{ lineHeight: '2' }}>
<p><strong>ID:</strong> {currentApp.id}</p> <p><strong>ID:</strong> {currentApp.id}</p>
<p><strong>ID:</strong> {currentApp.app_id}</p> <p><strong>ID:</strong> {currentApp.appId}</p>
<p><strong>:</strong> {currentApp.secret}</p> <p><strong>:</strong> {currentApp.secret}</p>
<p><strong>:</strong> {(() => { <p><strong>:</strong> {(() => {
const typeMap: Record<number, string> = { const typeMap: Record<number, string> = {
1: '千川', 2: '广告', 3: '本地推', 4: '星图', 5: '快手代理商', 1: '千川', 2: '广告', 3: '本地推', 4: '星图', 5: '快手代理商',
6: '巨量星图', 7: '巨量服务单', 8: '腾讯服务单', 9: '腾讯营销K2', 10: '腾讯营销K3' 6: '巨量星图', 7: '巨量服务单', 8: '腾讯服务单', 9: '腾讯营销K2', 10: '腾讯营销K3'
}; };
return typeMap[currentApp.open_type] || currentApp.open_type; return typeMap[currentApp.openType] || currentApp.openType;
})()}</p> })()}</p>
<p><strong>:</strong> {currentApp.company || '-'}</p> <p><strong>:</strong> {currentApp.company || '-'}</p>
<p><strong>:</strong> {currentApp.max_count}</p> <p><strong>:</strong> {currentApp.maxCount}</p>
<p><strong>:</strong> {currentApp.status === 1 ? '正常' : '禁用'}</p> <p><strong>:</strong> {currentApp.status === 1 ? '正常' : '禁用'}</p>
<p><strong>URL:</strong> {currentApp.auth_url || '-'}</p> <p><strong>URL:</strong> {currentApp.authUrl || '-'}</p>
<p><strong>:</strong> {currentApp.create_by}</p> <p><strong>:</strong> {currentApp.createBy}</p>
<p><strong>:</strong> {formatDate(currentApp.created_at)}</p> <p><strong>:</strong> {formatDate(currentApp.createdAt)}</p>
<p><strong>:</strong> {formatDate(currentApp.updated_at)}</p> <p><strong>:</strong> {formatDate(currentApp.updatedAt)}</p>
</div> </div>
)} )}
</Modal> </Modal>
@@ -369,7 +369,7 @@ const AdminOauthAppList: React.FC = () => {
> >
<Form form={updateForm} layout="vertical"> <Form form={updateForm} layout="vertical">
<Form.Item <Form.Item
name="app_id" name="appId"
label="应用ID" label="应用ID"
rules={[{ required: true, message: '请输入应用ID' }, { max: 64, message: '应用ID不能超过64个字符' }]} rules={[{ required: true, message: '请输入应用ID' }, { max: 64, message: '应用ID不能超过64个字符' }]}
> >
@@ -383,7 +383,7 @@ const AdminOauthAppList: React.FC = () => {
<Input placeholder="请输入应用密钥" /> <Input placeholder="请输入应用密钥" />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="open_type" name="openType"
label="开户方式" label="开户方式"
rules={[{ required: true, message: '请选择开户方式' }]} rules={[{ required: true, message: '请选择开户方式' }]}
> >
@@ -401,13 +401,13 @@ const AdminOauthAppList: React.FC = () => {
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="count" name="maxCount"
label="最大授权用户数" label="最大授权用户数"
> >
<InputNumber min={1} placeholder="应用最大可以授权多少个用户" /> <InputNumber min={1} placeholder="应用最大可以授权多少个用户" />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="auth_url" name="authUrl"
label="应用授权链接" label="应用授权链接"
> >
<Input placeholder="请输入应用授权链接" /> <Input placeholder="请输入应用授权链接" />
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -28,7 +28,7 @@
} }
})(); })();
</script> </script>
<script type="module" crossorigin src="/assets/index-CyYhkNba.js"></script> <script type="module" crossorigin src="/assets/index-Bof1g4Ez.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D9_3MPsN.css"> <link rel="stylesheet" crossorigin href="/assets/index-D9_3MPsN.css">
</head> </head>
<body> <body>
+15 -1
View File
@@ -82,6 +82,7 @@ interface MaterialData {
const MaterialListPage: React.FC = () => { const MaterialListPage: React.FC = () => {
const { message } = App.useApp(); const { message } = App.useApp();
const navigate = useNavigate(); const navigate = useNavigate();
const videoRef = React.createRef<HTMLVideoElement>();
const [records, setRecords] = useState<any[]>([]); const [records, setRecords] = useState<any[]>([]);
const [materials, setMaterials] = useState<MaterialData[]>([]); const [materials, setMaterials] = useState<MaterialData[]>([]);
const [listLoading, setListLoading] = useState(false); const [listLoading, setListLoading] = useState(false);
@@ -93,6 +94,18 @@ const MaterialListPage: React.FC = () => {
const [previewModalOpen, setPreviewModalOpen] = useState(false); const [previewModalOpen, setPreviewModalOpen] = useState(false);
const [previewUrl, setPreviewUrl] = useState(''); const [previewUrl, setPreviewUrl] = useState('');
const [previewType, setPreviewType] = useState<'image' | 'video'>('image'); const [previewType, setPreviewType] = useState<'image' | 'video'>('image');
const handleClosePreview = () => {
if (videoRef.current) {
videoRef.current.pause();
videoRef.current.currentTime = 0;
}
const videoElements = document.querySelectorAll('video');
videoElements.forEach(video => {
video.pause();
video.currentTime = 0;
});
setPreviewModalOpen(false);
};
const [pushPreTestTemplate, setPushPreTestTemplate] = useState<string>(''); const [pushPreTestTemplate, setPushPreTestTemplate] = useState<string>('');
const [pushTemplates, setPushTemplates] = useState<any[]>([]); const [pushTemplates, setPushTemplates] = useState<any[]>([]);
const [pushTemplatesLoading, setPushTemplatesLoading] = useState(false); const [pushTemplatesLoading, setPushTemplatesLoading] = useState(false);
@@ -528,7 +541,7 @@ const MaterialListPage: React.FC = () => {
<Modal <Modal
title="预览" title="预览"
open={previewModalOpen} open={previewModalOpen}
onCancel={() => setPreviewModalOpen(false)} onCancel={handleClosePreview}
footer={null} footer={null}
width={600} width={600}
style={{ borderRadius: 16 }} style={{ borderRadius: 16 }}
@@ -536,6 +549,7 @@ const MaterialListPage: React.FC = () => {
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: 400 }}> <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: 400 }}>
{previewType === 'video' ? ( {previewType === 'video' ? (
<video <video
ref={videoRef}
src={previewUrl} src={previewUrl}
controls controls
style={{ maxWidth: '100%', maxHeight: 400, borderRadius: 8 }} style={{ maxWidth: '100%', maxHeight: 400, borderRadius: 8 }}