feat: 美化界面并统一列表分页为 10 条
CI / lint-and-build (push) Has been cancelled

- 左上角名称改为火炬VOD管理器

- 登录页使用渐变背景、LOGO、圆角卡片

- 视频列表、操作日志默认每页 10 条

- 布局增加底部版权信息 © meshel.cn · MIT 开源
This commit is contained in:
2026-06-29 18:12:03 +06:00
parent 10c5c0cb03
commit b84bac5828
4 changed files with 71 additions and 13 deletions
+12 -2
View File
@@ -9,7 +9,7 @@ import {
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import { useAuthStore } from '../store/auth';
const { Header, Sider, Content } = AntLayout;
const { Header, Sider, Content, Footer } = AntLayout;
export default function Layout() {
const location = useLocation();
@@ -54,7 +54,7 @@ export default function Layout() {
fontSize: 16,
}}
>
VOD
VOD管理器
</div>
<Menu
mode="inline"
@@ -87,6 +87,16 @@ export default function Layout() {
>
<Outlet />
</Content>
<Footer
style={{
textAlign: 'center',
background: colorBgContainer,
color: '#888',
fontSize: 13,
}}
>
© {new Date().getFullYear()} meshel.cn · VOD管理器 · MIT
</Footer>
</AntLayout>
</AntLayout>
);
+57 -9
View File
@@ -1,9 +1,12 @@
import { useState } from 'react';
import { Form, Input, Button, Card, message } from 'antd';
import { Form, Input, Button, Card, message, Typography, Space } from 'antd';
import { VideoCameraOutlined, LockOutlined, UserOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import { useAuthStore } from '../store/auth';
import { login } from '../api/auth';
const { Title, Text } = Typography;
export default function LoginPage() {
const navigate = useNavigate();
const setAuth = useAuthStore((state) => state.setAuth);
@@ -30,32 +33,77 @@ export default function LoginPage() {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#f0f2f5',
background: 'linear-gradient(135deg, #1677ff 0%, #0958d9 100%)',
}}
>
<Card title="阿里云 VOD 媒体库管理器" style={{ width: 400 }}>
<Card
style={{
width: 420,
borderRadius: 16,
boxShadow: '0 20px 50px rgba(0, 0, 0, 0.15)',
overflow: 'hidden',
}}
bodyStyle={{ padding: '40px 32px' }}
>
<Space direction="vertical" align="center" style={{ width: '100%', marginBottom: 32 }}>
<div
style={{
width: 64,
height: 64,
borderRadius: '50%',
background: 'linear-gradient(135deg, #1677ff 0%, #0958d9 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<VideoCameraOutlined style={{ fontSize: 32, color: '#fff' }} />
</div>
<Title level={3} style={{ margin: 0 }}>VOD管理器</Title>
<Text type="secondary"></Text>
</Space>
<Form name="login" onFinish={handleSubmit} autoComplete="off" layout="vertical">
<Form.Item
label="用户名"
name="username"
rules={[{ required: true, message: '请输入用户名' }]}
>
<Input placeholder="admin" />
<Input
prefix={<UserOutlined />}
placeholder="用户名"
size="large"
/>
</Form.Item>
<Form.Item
label="密码"
name="password"
rules={[{ required: true, message: '请输入密码' }]}
>
<Input.Password placeholder="admin" />
<Input.Password
prefix={<LockOutlined />}
placeholder="密码"
size="large"
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={loading} block>
<Form.Item style={{ marginBottom: 12 }}>
<Button
type="primary"
htmlType="submit"
loading={loading}
size="large"
block
style={{ borderRadius: 8 }}
>
</Button>
</Form.Item>
<div style={{ textAlign: 'center' }}>
<Text type="secondary" style={{ fontSize: 12 }}>
admin / admin
</Text>
</div>
</Form>
</Card>
</div>
+1 -1
View File
@@ -20,7 +20,7 @@ export default function LogsPage() {
const [loading, setLoading] = useState(false);
const [total, setTotal] = useState(0);
const [pageNo, setPageNo] = useState(1);
const [pageSize, setPageSize] = useState(20);
const [pageSize, setPageSize] = useState(10);
const fetchLogs = async (page: number, size: number) => {
setLoading(true);
+1 -1
View File
@@ -48,7 +48,7 @@ export default function VideosPage() {
const [selectedRows, setSelectedRows] = useState<VideoItem[]>([]);
const [total, setTotal] = useState(0);
const [pageNo, setPageNo] = useState(1);
const [pageSize, setPageSize] = useState(20);
const [pageSize, setPageSize] = useState(10);
const [categories, setCategories] = useState<Record<string, unknown>[]>([]);
const [detail, setDetail] = useState<VideoItem | null>(null);
const [drawerOpen, setDrawerOpen] = useState(false);