授权管理新增消耗列表
This commit is contained in:
+1
-1
@@ -21,4 +21,4 @@ video-gen-api/dist/
|
|||||||
|
|
||||||
# 忽略特定类型文件但保留目录
|
# 忽略特定类型文件但保留目录
|
||||||
# *.pyc
|
# *.pyc
|
||||||
# !dir/*.pyc
|
# !dir/*.pycnode_modules/
|
||||||
|
|||||||
@@ -13,10 +13,6 @@ import InitialReplication from './pages/InitialReplication';
|
|||||||
import RemoveLens from './pages/RemoveLens';
|
import RemoveLens from './pages/RemoveLens';
|
||||||
import GeneratedRecord from './pages/GeneratedRecord';
|
import GeneratedRecord from './pages/GeneratedRecord';
|
||||||
import AuthorizationPage from './pages/AuthorizationPage';
|
import AuthorizationPage from './pages/AuthorizationPage';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { useAuthStore } from './store/useAuthStore';
|
import { useAuthStore } from './store/useAuthStore';
|
||||||
|
|
||||||
const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
|
const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
|
||||||
@@ -96,10 +92,6 @@ const App = () => {
|
|||||||
<Route path="generated" element={<GeneratedRecord />} />
|
<Route path="generated" element={<GeneratedRecord />} />
|
||||||
<Route path="authorization" element={<AuthorizationPage />} />
|
<Route path="authorization" element={<AuthorizationPage />} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="*" element={<Navigate to="/projects" replace />} />
|
<Route path="*" element={<Navigate to="/projects" replace />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import React, { useEffect, useState, useLayoutEffect, useRef, useCallback } from 'react';
|
import React, { useEffect, useState, useLayoutEffect, useRef, useCallback } from 'react';
|
||||||
import { Button, Table, Checkbox, Tag, Space, message } from 'antd';
|
import { Button, Table, Checkbox, Tag, Space, message, Modal } from 'antd';
|
||||||
import { PlusOutlined, CheckCircleOutlined, ClockCircleOutlined, CiCircleOutlined } from '@ant-design/icons';
|
import { PlusOutlined, CheckCircleOutlined, ClockCircleOutlined, CiCircleOutlined, EyeOutlined, XOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
// 模拟授权数据
|
// 模拟授权数据
|
||||||
const mockAuthorizations = [
|
const mockAuthorizations = [
|
||||||
{ id: '1867060028363785', status: 'active', description: '用户张三的API授权' },
|
{ id: '1867060028363785', status: 'active', description: '用户张三的API授权' },
|
||||||
{ id: '1867059757929740', status: 'pending', description: '用户李四的API授权' },
|
{ id: '1867059757929740', status: 'pending', description: '用户李四的API授权' },
|
||||||
{ id: '1867059808785418', status: 'active', description: '用户王五的API授权' },
|
{ id: '1867059808785418', status: 'active', description: '用户王五的API授权' },
|
||||||
];
|
];
|
||||||
|
|
||||||
// 状态配置
|
// 状态配置
|
||||||
const statusConfig = {
|
const statusConfig = {
|
||||||
active: { label: '已授权', color: 'green', icon: CheckCircleOutlined },
|
active: { label: '已授权', color: 'green', icon: CheckCircleOutlined },
|
||||||
@@ -17,10 +15,27 @@ const statusConfig = {
|
|||||||
revoked: { label: '已撤销', color: 'gray', icon: CiCircleOutlined },
|
revoked: { label: '已撤销', color: 'gray', icon: CiCircleOutlined },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 模拟消耗记录数据
|
||||||
|
const mockConsumptionRecords = [
|
||||||
|
{ id: 'C001', authorizationId: '1867060028363785', amount: 100, type: 'video', description: '视频生成消耗', createdAt: '2024-01-15 10:30:00' },
|
||||||
|
{ id: 'C002', authorizationId: '1867060028363785', amount: 50, type: 'audio', description: '音频转换消耗', createdAt: '2024-01-15 11:20:00' },
|
||||||
|
{ id: 'C003', authorizationId: '1867059808785418', amount: 200, type: 'video', description: '视频生成消耗', createdAt: '2024-01-14 14:45:00' },
|
||||||
|
{ id: 'C004', authorizationId: '1867060028363785', amount: 75, type: 'image', description: '图片处理消耗', createdAt: '2024-01-14 09:15:00' },
|
||||||
|
{ id: 'C005', authorizationId: '1867059757929740', amount: 150, type: 'video', description: '视频生成消耗', createdAt: '2024-01-13 16:00:00' },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 消耗类型配置
|
||||||
|
const consumptionTypeConfig = {
|
||||||
|
video: { label: '视频生成', color: 'blue' },
|
||||||
|
audio: { label: '音频转换', color: 'purple' },
|
||||||
|
image: { label: '图片处理', color: 'green' },
|
||||||
|
};
|
||||||
const AuthorizationPage: React.FC = () => {
|
const AuthorizationPage: React.FC = () => {
|
||||||
const [authorizations, setAuthorizations] = useState(mockAuthorizations);
|
const [authorizations, setAuthorizations] = useState(mockAuthorizations);
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [showConsumptionModal, setShowConsumptionModal] = useState(false);
|
||||||
|
const [consumptionRecords, setConsumptionRecords] = useState(mockConsumptionRecords);
|
||||||
|
|
||||||
// 状态标签渲染
|
// 状态标签渲染
|
||||||
const renderStatus = (status: string) => {
|
const renderStatus = (status: string) => {
|
||||||
@@ -77,6 +92,26 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
width: 140,
|
width: 140,
|
||||||
render: (text: string) => renderStatus(text),
|
render: (text: string) => renderStatus(text),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
key: 'operation',
|
||||||
|
width: 120,
|
||||||
|
render: (_: any, record: typeof mockAuthorizations[0]) => (
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
style={{
|
||||||
|
borderRadius: 8,
|
||||||
|
// background: 'linear-gradient(135deg, #6366f1, #8b5cf6)',
|
||||||
|
border: 'none',
|
||||||
|
}}
|
||||||
|
onClick={() => setShowConsumptionModal(true)}
|
||||||
|
>
|
||||||
|
查款消耗
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
// 处理点击授权按钮
|
// 处理点击授权按钮
|
||||||
@@ -85,7 +120,6 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
message.warning('请先选择需要授权的记录');
|
message.warning('请先选择需要授权的记录');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
// 模拟授权操作
|
// 模拟授权操作
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -107,6 +141,13 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
key: item.id,
|
key: item.id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// 准备消耗记录表格数据(添加序号)
|
||||||
|
const consumptionTableData = consumptionRecords.map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
index: index + 1,
|
||||||
|
key: item.id,
|
||||||
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: 24, minHeight: '94vh', background: '#f8fafc' }}>
|
<div style={{ padding: 24, minHeight: '94vh', background: '#f8fafc' }}>
|
||||||
{/* 页面标题 */}
|
{/* 页面标题 */}
|
||||||
@@ -118,7 +159,7 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 操作栏 */}
|
{/* 操作栏 */}
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 16 }}>
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12, marginBottom: 16 }}>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="large"
|
size="large"
|
||||||
@@ -159,6 +200,81 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
{/* <div style={{ marginTop: 16, textAlign: 'center', color: '#94a3b8', fontSize: 13 }}>
|
{/* <div style={{ marginTop: 16, textAlign: 'center', color: '#94a3b8', fontSize: 13 }}>
|
||||||
提示:勾选记录后点击"点击授权"按钮可批量授权
|
提示:勾选记录后点击"点击授权"按钮可批量授权
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
|
{/* 消耗记录弹窗 */}
|
||||||
|
<Modal
|
||||||
|
title="消耗记录"
|
||||||
|
open={showConsumptionModal}
|
||||||
|
onCancel={() => setShowConsumptionModal(false)}
|
||||||
|
footer={null}
|
||||||
|
width={800}
|
||||||
|
destroyOnClose={true}
|
||||||
|
>
|
||||||
|
<div style={{ padding: 16 }}>
|
||||||
|
<Table
|
||||||
|
dataSource={consumptionTableData}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
dataIndex: 'index',
|
||||||
|
key: 'index',
|
||||||
|
width: 80,
|
||||||
|
render: (text: number) => <span style={{ color: '#94a3b8' }}>{text}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '消耗ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
ellipsis: true,
|
||||||
|
render: (text: string) => <span style={{ fontWeight: 500, color: '#1e293b' }}>{text}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '授权ID',
|
||||||
|
dataIndex: 'authorizationId',
|
||||||
|
key: 'authorizationId',
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '消耗类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
width: 120,
|
||||||
|
render: (text: string) => {
|
||||||
|
const config = consumptionTypeConfig[text as keyof typeof consumptionTypeConfig];
|
||||||
|
return <Tag color={config?.color}>{config?.label}</Tag>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '消耗金额',
|
||||||
|
dataIndex: 'amount',
|
||||||
|
key: 'amount',
|
||||||
|
width: 120,
|
||||||
|
render: (text: number) => <span style={{ color: '#ef4444', fontWeight: 500 }}>{text} 元</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '消耗描述',
|
||||||
|
dataIndex: 'description',
|
||||||
|
key: 'description',
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '消耗时间',
|
||||||
|
dataIndex: 'createdAt',
|
||||||
|
key: 'createdAt',
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
pagination={{
|
||||||
|
pageSize: 10,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showTotal: (total) => `共 ${total} 条记录`,
|
||||||
|
}}
|
||||||
|
rowKey="id"
|
||||||
|
bordered={false}
|
||||||
|
scroll={{ x: 'max-content' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -154,9 +154,6 @@ const RecordsPage: React.FC = () => {
|
|||||||
const isGenerating = generating[record.id];
|
const isGenerating = generating[record.id];
|
||||||
const isExpanded = expandedId === record.id;
|
const isExpanded = expandedId === record.id;
|
||||||
const type: any = record.genType || 'image';
|
const type: any = record.genType || 'image';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={record.id} className="animate-slideInCard" style={{ animationDelay: `${i * 0.04}s` }}>
|
<div key={record.id} className="animate-slideInCard" style={{ animationDelay: `${i * 0.04}s` }}>
|
||||||
{/* Record summary row */}
|
{/* Record summary row */}
|
||||||
|
|||||||
Reference in New Issue
Block a user