feat(database): 实现数据库功能并优化数据导出
- 新增数据库相关 API 和服务 - 实现数据导出功能,支持导出到 JSON 文件 - 优化数据导入流程,增加数据校验 - 新增数据库页面,展示解析数据和统计信息 - 更新捕获页面,支持导入数据到数据库
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import React, {useEffect, useRef, useState} from 'react';
|
import React, {useEffect, useRef, useState} from 'react';
|
||||||
import {Button, Card, Layout, message, Select, Spin, Table} from 'antd';
|
import {Button, Card, Layout, message, Select, Spin, Table} from 'antd';
|
||||||
import {DownloadOutlined, PlayCircleOutlined, SettingOutlined, StopOutlined, UploadOutlined} from '@ant-design/icons';
|
import {DownloadOutlined, PlayCircleOutlined, StopOutlined, UploadOutlined} from '@ant-design/icons';
|
||||||
import '../App.css';
|
import '../App.css';
|
||||||
import {
|
import {
|
||||||
GetNetworkInterfaces,
|
GetNetworkInterfaces,
|
||||||
@@ -355,132 +355,115 @@ function CapturePage() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout style={{ minHeight: '100vh' }}>
|
<Layout>
|
||||||
<Header style={{ background: '#fff', padding: '0 16px', height: 48, lineHeight: '48px' }}>
|
<Sider width={220} style={{ background: '#f5f5f5' }}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', height: 48 }}>
|
<div style={{ padding: '16px 0px 12px 12px' }}>
|
||||||
<h1 style={{ margin: 0, fontSize: 20 }}>装备数据导出工具</h1>
|
<Card title="抓包控制" size="small" style={{ marginBottom: 12, marginTop: 0 }}>
|
||||||
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
<div style={{ marginBottom: 12 }}>
|
||||||
<Button
|
<label>网络接口:</label>
|
||||||
type="primary"
|
<Select
|
||||||
icon={<SettingOutlined />}
|
style={{ width: '100%', marginTop: 6 }}
|
||||||
onClick={handleRefreshParsedData}
|
value={selectedInterface}
|
||||||
loading={loading}
|
onChange={setSelectedInterface}
|
||||||
style={{ flex: 1, height: 32 }}
|
placeholder="选择网络接口"
|
||||||
>刷新数据</Button>
|
loading={interfaceLoading}
|
||||||
</div>
|
>
|
||||||
</div>
|
{interfaces.map((iface) => (
|
||||||
</Header>
|
<Select.Option key={iface.name} value={iface.name}>
|
||||||
|
{iface.addresses}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Layout>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||||
<Sider width={220} style={{ background: '#fff' }}>
|
<div style={{ display: 'flex', gap: 8 }}>
|
||||||
<div style={{ padding: '12px' }}>
|
<Button
|
||||||
<Card title="抓包控制" size="small">
|
type="primary"
|
||||||
<div style={{ marginBottom: 12 }}>
|
icon={<PlayCircleOutlined />}
|
||||||
<label>网络接口:</label>
|
onClick={startCapture}
|
||||||
<Select
|
disabled={isCapturing || !selectedInterface}
|
||||||
style={{ width: '100%', marginTop: 6 }}
|
loading={loading}
|
||||||
value={selectedInterface}
|
style={{ flex: 1, height: 32, minWidth: 0, fontSize: 12 }}
|
||||||
onChange={setSelectedInterface}
|
|
||||||
placeholder="选择网络接口"
|
|
||||||
loading={interfaceLoading}
|
|
||||||
>
|
>
|
||||||
{interfaces.map((iface) => (
|
开始抓包
|
||||||
<Select.Option key={iface.name} value={iface.name}>
|
|
||||||
{iface.addresses}
|
|
||||||
</Select.Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
|
||||||
<div style={{ display: 'flex', gap: 8 }}>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
icon={<PlayCircleOutlined />}
|
|
||||||
onClick={startCapture}
|
|
||||||
disabled={isCapturing || !selectedInterface}
|
|
||||||
loading={loading}
|
|
||||||
style={{ flex: 1, height: 32, minWidth: 0, fontSize: 12 }}
|
|
||||||
>
|
|
||||||
开始抓包
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
danger
|
|
||||||
icon={<StopOutlined />}
|
|
||||||
onClick={stopCapture}
|
|
||||||
disabled={!isCapturing}
|
|
||||||
loading={loading}
|
|
||||||
style={{ flex: 1, height: 32, minWidth: 0, fontSize: 12 }}
|
|
||||||
>
|
|
||||||
停止抓包
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
icon={<DownloadOutlined />}
|
|
||||||
onClick={exportData}
|
|
||||||
disabled={!parsedData || !Array.isArray(parsedData.items) || parsedData.items.length === 0}
|
|
||||||
style={{ width: '100%', height: 32, fontSize: 14 }}>
|
|
||||||
导出数据
|
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
icon={<UploadOutlined />}
|
danger
|
||||||
onClick={handleUploadButtonClick}
|
icon={<StopOutlined />}
|
||||||
style={{ width: '100%', height: 32, fontSize: 14 }}>
|
onClick={stopCapture}
|
||||||
导入数据
|
disabled={!isCapturing}
|
||||||
|
loading={loading}
|
||||||
|
style={{ flex: 1, height: 32, minWidth: 0, fontSize: 12 }}
|
||||||
|
>
|
||||||
|
停止抓包
|
||||||
</Button>
|
</Button>
|
||||||
<input
|
</div>
|
||||||
ref={fileInputRef}
|
<Button
|
||||||
type="file"
|
icon={<DownloadOutlined />}
|
||||||
accept=".json,.txt"
|
onClick={exportData}
|
||||||
style={{ display: 'none' }}
|
disabled={!parsedData || !Array.isArray(parsedData.items) || parsedData.items.length === 0}
|
||||||
onChange={handleFileUpload}
|
style={{ width: '100%', height: 32, fontSize: 14 }}>
|
||||||
/>
|
导出数据
|
||||||
{uploadedFileName && (
|
</Button>
|
||||||
<span style={{ marginTop: 4, color: '#888', fontSize: 10, textAlign: 'center', display: 'block' }}>
|
<Button
|
||||||
{uploadedFileName}
|
icon={<UploadOutlined />}
|
||||||
</span>
|
onClick={handleUploadButtonClick}
|
||||||
)}
|
style={{ width: '100%', height: 32, fontSize: 14 }}>
|
||||||
|
导入数据
|
||||||
|
</Button>
|
||||||
|
<input
|
||||||
|
ref={fileInputRef}
|
||||||
|
type="file"
|
||||||
|
accept=".json,.txt"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
onChange={handleFileUpload}
|
||||||
|
/>
|
||||||
|
{uploadedFileName && (
|
||||||
|
<span style={{ marginTop: 4, color: '#888', fontSize: 10, textAlign: 'center', display: 'block' }}>
|
||||||
|
{uploadedFileName}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card title="抓包状态" size="small" style={{ marginTop: 12 }}>
|
||||||
|
<div>
|
||||||
|
<p style={{ marginBottom: 4 }}>状态: {isCapturing ? '正在抓包...' : '准备就绪'}</p>
|
||||||
|
{/*<p style={{ marginBottom: 4 }}>捕获数据: {capturedData.length} 条</p>*/}
|
||||||
|
<p style={{ marginBottom: 4 }}>英雄数目: {Array.isArray(parsedData?.heroes) ? parsedData.heroes.length : 0} 个</p>
|
||||||
|
{parsedData && (
|
||||||
|
<p style={{ marginBottom: 0 }}>解析装备: {Array.isArray(parsedData?.items) ? parsedData.items.length : 0} 件</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Sider>
|
||||||
|
|
||||||
|
<Content style={{ padding: '16px' }}>
|
||||||
|
<Spin spinning={loading}>
|
||||||
|
{Array.isArray(parsedData?.items) && parsedData.items.length > 0 ? (
|
||||||
|
<Card title="装备数据">
|
||||||
|
<Table
|
||||||
|
dataSource={parsedData.items}
|
||||||
|
columns={equipmentColumns}
|
||||||
|
rowKey="id"
|
||||||
|
pagination={{ pageSize: 10 }}
|
||||||
|
scroll={{ x: true }}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
) : (
|
||||||
|
<Card title="数据预览">
|
||||||
|
<div style={{ textAlign: 'center', padding: '40px' }}>
|
||||||
|
<p>暂无数据</p>
|
||||||
|
<p style={{ color: '#999', fontSize: '12px' }}>
|
||||||
|
{parsedData ? '数据为空,请检查数据源或上传文件' : '请开始抓包或上传JSON文件'}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
)}
|
||||||
<Card title="抓包状态" size="small" style={{ marginTop: 12 }}>
|
</Spin>
|
||||||
<div>
|
</Content>
|
||||||
<p style={{ marginBottom: 4 }}>状态: {isCapturing ? '正在抓包...' : '准备就绪'}</p>
|
|
||||||
{/*<p style={{ marginBottom: 4 }}>捕获数据: {capturedData.length} 条</p>*/}
|
|
||||||
<p style={{ marginBottom: 4 }}>英雄数目: {Array.isArray(parsedData?.heroes) ? parsedData.heroes.length : 0} 个</p>
|
|
||||||
{parsedData && (
|
|
||||||
<p style={{ marginBottom: 0 }}>解析装备: {Array.isArray(parsedData?.items) ? parsedData.items.length : 0} 件</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</Sider>
|
|
||||||
|
|
||||||
<Content style={{ padding: '16px' }}>
|
|
||||||
<Spin spinning={loading}>
|
|
||||||
{Array.isArray(parsedData?.items) && parsedData.items.length > 0 ? (
|
|
||||||
<Card title="装备数据">
|
|
||||||
<Table
|
|
||||||
dataSource={parsedData.items}
|
|
||||||
columns={equipmentColumns}
|
|
||||||
rowKey="id"
|
|
||||||
pagination={{ pageSize: 10 }}
|
|
||||||
scroll={{ x: true }}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
) : (
|
|
||||||
<Card title="数据预览">
|
|
||||||
<div style={{ textAlign: 'center', padding: '40px' }}>
|
|
||||||
<p>暂无数据</p>
|
|
||||||
<p style={{ color: '#999', fontSize: '12px' }}>
|
|
||||||
{parsedData ? '数据为空,请检查数据源或上传文件' : '请开始抓包或上传JSON文件'}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
</Spin>
|
|
||||||
</Content>
|
|
||||||
</Layout>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import React, {useEffect, useState} from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import {Button, Card, Col, Row, Space, Statistic, Table, Tag,} from 'antd';
|
import {Button, Card, Col, Layout, Row, Space, Statistic, Table, Tag} from 'antd';
|
||||||
import {BarChartOutlined, DatabaseOutlined, ReloadOutlined, SettingOutlined,} from '@ant-design/icons';
|
import {BarChartOutlined, DatabaseOutlined, ReloadOutlined, SettingOutlined,} from '@ant-design/icons';
|
||||||
import * as App from '../../wailsjs/go/service/App';
|
import * as App from '../../wailsjs/go/service/App';
|
||||||
import {model} from '../../wailsjs/go/models';
|
import {model} from '../../wailsjs/go/models';
|
||||||
import {useMessage} from '../utils/useMessage';
|
import {useMessage} from '../utils/useMessage';
|
||||||
|
|
||||||
|
const { Content } = Layout;
|
||||||
|
|
||||||
// 定义Equipment接口
|
// 定义Equipment接口
|
||||||
interface Equipment {
|
interface Equipment {
|
||||||
id: string | number;
|
id: string | number;
|
||||||
@@ -121,82 +123,84 @@ const DatabasePage: React.FC = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: '24px' }}>
|
<Layout style={{ minHeight: '100vh' }}>
|
||||||
{/* 统计卡片 */}
|
<Content style={{ padding: 16 }}>
|
||||||
<Row gutter={16} style={{ marginBottom: '24px' }}>
|
{/* 统计卡片 */}
|
||||||
<Col span={8}>
|
<Row gutter={16} style={{ marginBottom: '24px' }}>
|
||||||
<Card>
|
<Col span={8}>
|
||||||
<Statistic
|
<Card>
|
||||||
title="数据库状态"
|
<Statistic
|
||||||
value="SQLite"
|
title="数据库状态"
|
||||||
prefix={<DatabaseOutlined />}
|
value="SQLite"
|
||||||
suffix="已连接"
|
prefix={<DatabaseOutlined />}
|
||||||
/>
|
suffix="已连接"
|
||||||
</Card>
|
/>
|
||||||
</Col>
|
</Card>
|
||||||
<Col span={8}>
|
</Col>
|
||||||
<Card>
|
<Col span={8}>
|
||||||
<Statistic
|
<Card>
|
||||||
title="装备数量"
|
<Statistic
|
||||||
value={latestData?.items?.length || 0}
|
title="装备数量"
|
||||||
prefix={<BarChartOutlined />}
|
value={latestData?.items?.length || 0}
|
||||||
/>
|
prefix={<BarChartOutlined />}
|
||||||
</Card>
|
/>
|
||||||
</Col>
|
</Card>
|
||||||
<Col span={8}>
|
</Col>
|
||||||
<Card>
|
<Col span={8}>
|
||||||
<Statistic
|
<Card>
|
||||||
title="英雄数量"
|
<Statistic
|
||||||
value={latestData?.heroes?.length || 0}
|
title="英雄数量"
|
||||||
prefix={<SettingOutlined />}
|
value={latestData?.heroes?.length || 0}
|
||||||
/>
|
prefix={<SettingOutlined />}
|
||||||
</Card>
|
/>
|
||||||
</Col>
|
</Card>
|
||||||
</Row>
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
{/* 操作栏 */}
|
{/* 操作栏 */}
|
||||||
<Card style={{ marginBottom: '16px' }}>
|
<Card style={{ marginBottom: '16px' }}>
|
||||||
<Space>
|
<Space>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<ReloadOutlined />}
|
icon={<ReloadOutlined />}
|
||||||
onClick={loadLatestData}
|
onClick={loadLatestData}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
>
|
>
|
||||||
刷新数据
|
刷新数据
|
||||||
</Button>
|
</Button>
|
||||||
<span style={{ color: '#666' }}>
|
<span style={{ color: '#666' }}>
|
||||||
显示最新一次抓包解析的数据
|
显示最新一次抓包解析的数据
|
||||||
</span>
|
</span>
|
||||||
</Space>
|
</Space>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* 装备表格 */}
|
{/* 装备表格 */}
|
||||||
<Card title="最新解析的装备数据">
|
<Card title="最新解析的装备数据">
|
||||||
{latestData?.items && latestData.items.length > 0 ? (
|
{latestData?.items && latestData.items.length > 0 ? (
|
||||||
<Table
|
<Table
|
||||||
columns={equipmentColumns}
|
columns={equipmentColumns}
|
||||||
dataSource={latestData.items}
|
dataSource={latestData.items}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
pagination={{
|
pagination={{
|
||||||
showSizeChanger: true,
|
showSizeChanger: true,
|
||||||
showQuickJumper: true,
|
showQuickJumper: true,
|
||||||
showTotal: (total, range) =>
|
showTotal: (total, range) =>
|
||||||
`第 ${range[0]}-${range[1]} 条,共 ${total} 条`,
|
`第 ${range[0]}-${range[1]} 条,共 ${total} 条`,
|
||||||
}}
|
}}
|
||||||
scroll={{ x: 800 }}
|
scroll={{ x: 800 }}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ textAlign: 'center', padding: '40px' }}>
|
<div style={{ textAlign: 'center', padding: '40px' }}>
|
||||||
<p>暂无解析数据</p>
|
<p>暂无解析数据</p>
|
||||||
<p style={{ color: '#999', fontSize: '12px' }}>
|
<p style={{ color: '#999', fontSize: '12px' }}>
|
||||||
请先进行抓包操作,解析后的数据会自动保存到数据库
|
请先进行抓包操作,解析后的数据会自动保存到数据库
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</Content>
|
||||||
|
</Layout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,140 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import {Avatar, Button, Card, Col, Divider, Input, Layout, Pagination, Row, Select, Table, Tag} from 'antd';
|
||||||
|
import {AppstoreOutlined, FilterOutlined, UserOutlined} from '@ant-design/icons';
|
||||||
|
|
||||||
function OptimizerPage() {
|
const { Content } = Layout;
|
||||||
|
|
||||||
|
// 静态数据示例
|
||||||
|
const heroList = [
|
||||||
|
{ id: 1, name: '雅娜凯', avatar: 'https://api.dicebear.com/7.x/miniavs/svg?seed=1' },
|
||||||
|
{ id: 2, name: '艾莉丝', avatar: 'https://api.dicebear.com/7.x/miniavs/svg?seed=2' },
|
||||||
|
];
|
||||||
|
const hero = heroList[0];
|
||||||
|
const attributes = [
|
||||||
|
{ label: '攻击', value: 1567 },
|
||||||
|
{ label: '防御', value: 1654 },
|
||||||
|
{ label: '生命', value: 24447 },
|
||||||
|
{ label: '速度', value: 188 },
|
||||||
|
{ label: '暴击', value: 49 },
|
||||||
|
{ label: '爆伤', value: 166 },
|
||||||
|
{ label: '命中', value: 46 },
|
||||||
|
{ label: '抵抗', value: 52 },
|
||||||
|
];
|
||||||
|
const setOptions = [
|
||||||
|
{ label: '任意套装', value: 'any' },
|
||||||
|
{ label: '暴击套', value: 'crit' },
|
||||||
|
{ label: '速度套', value: 'speed' },
|
||||||
|
];
|
||||||
|
const filterOptions = [
|
||||||
|
{ label: '攻击', value: 'atk' },
|
||||||
|
{ label: '防御', value: 'def' },
|
||||||
|
{ label: '生命', value: 'hp' },
|
||||||
|
{ label: '速度', value: 'spd' },
|
||||||
|
{ label: '暴击', value: 'cr' },
|
||||||
|
{ label: '爆伤', value: 'cd' },
|
||||||
|
{ label: '命中', value: 'acc' },
|
||||||
|
{ label: '抵抗', value: 'res' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const resultColumns = [
|
||||||
|
{ title: '套装', dataIndex: 'set', key: 'set', render: (v: string) => <Tag>{v}</Tag> },
|
||||||
|
{ title: '攻击', dataIndex: 'atk', key: 'atk' },
|
||||||
|
{ title: '防御', dataIndex: 'def', key: 'def' },
|
||||||
|
{ title: '生命', dataIndex: 'hp', key: 'hp' },
|
||||||
|
{ title: '速度', dataIndex: 'spd', key: 'spd' },
|
||||||
|
{ title: '暴击', dataIndex: 'cr', key: 'cr' },
|
||||||
|
{ title: '爆伤', dataIndex: 'cd', key: 'cd' },
|
||||||
|
{ title: '命中', dataIndex: 'acc', key: 'acc' },
|
||||||
|
{ title: '抵抗', dataIndex: 'res', key: 'res' },
|
||||||
|
];
|
||||||
|
const resultData = [
|
||||||
|
{ key: 1, set: '暴击套', atk: 2000, def: 1500, hp: 20000, spd: 200, cr: 100, cd: 250, acc: 30, res: 20 },
|
||||||
|
{ key: 2, set: '速度套', atk: 1800, def: 1400, hp: 21000, spd: 220, cr: 80, cd: 200, acc: 40, res: 30 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function OptimizerPage() {
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: 24 }}>
|
<Layout style={{ minHeight: '100vh' }}>
|
||||||
<h2>配装优化</h2>
|
<Content style={{ padding: 16 }}>
|
||||||
<p>请选择一个角色后点击开始配装。后续将在此页面实现配装计算与展示。</p>
|
{/* 顶部选项区 */}
|
||||||
</div>
|
<Card style={{ marginBottom: 16 }}>
|
||||||
|
<Row gutter={16}>
|
||||||
|
{/* 角色头像与选择 */}
|
||||||
|
<Col span={4} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
||||||
|
<Avatar size={64} src={hero.avatar} icon={<UserOutlined />} />
|
||||||
|
<div style={{ marginTop: 8, fontWeight: 500 }}>{hero.name}</div>
|
||||||
|
<Select style={{ width: '100%', marginTop: 8 }} defaultValue={hero.id}>
|
||||||
|
{heroList.map(h => <Select.Option key={h.id} value={h.id}>{h.name}</Select.Option>)}
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
{/* 角色属性 */}
|
||||||
|
<Col span={6}>
|
||||||
|
<div style={{ fontWeight: 500, marginBottom: 8 }}>属性</div>
|
||||||
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
|
||||||
|
{attributes.map(attr => (
|
||||||
|
<div key={attr.label} style={{ minWidth: 60 }}>{attr.label}: <b>{attr.value}</b></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
{/* 属性过滤 */}
|
||||||
|
<Col span={7}>
|
||||||
|
<div style={{ fontWeight: 500, marginBottom: 8 }}>属性过滤</div>
|
||||||
|
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
||||||
|
{filterOptions.map(opt => (
|
||||||
|
<Input key={opt.value} addonBefore={opt.label} placeholder="最小值" style={{ width: 100 }} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
{/* 套装选择与操作 */}
|
||||||
|
<Col span={7}>
|
||||||
|
<div style={{ fontWeight: 500, marginBottom: 8 }}>指定套装</div>
|
||||||
|
<Select style={{ width: '100%', marginBottom: 8 }} defaultValue={setOptions[0].value}>
|
||||||
|
{setOptions.map(opt => <Select.Option key={opt.value} value={opt.value}>{opt.label}</Select.Option>)}
|
||||||
|
</Select>
|
||||||
|
<div style={{ display: 'flex', gap: 8 }}>
|
||||||
|
<Button type="primary" icon={<AppstoreOutlined />}>开始配装</Button>
|
||||||
|
<Button icon={<FilterOutlined />}>重置筛选</Button>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 配装结果列表区 */}
|
||||||
|
<Card title="配装结果" style={{ marginBottom: 16 }}>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
|
||||||
|
<div>全部排列组合:<b>123,456</b> 条 | 筛选结果:<b>2</b> 条</div>
|
||||||
|
<Pagination size="small" total={2} pageSize={10} current={1} showSizeChanger={false} />
|
||||||
|
</div>
|
||||||
|
<Table
|
||||||
|
dataSource={resultData}
|
||||||
|
columns={resultColumns}
|
||||||
|
pagination={false}
|
||||||
|
scroll={{ x: true }}
|
||||||
|
rowKey="key"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 单个配装详情区 */}
|
||||||
|
<Card title="配装详情">
|
||||||
|
<div style={{ display: 'flex', gap: 24 }}>
|
||||||
|
<div>
|
||||||
|
<Avatar size={48} src={hero.avatar} />
|
||||||
|
<div style={{ marginTop: 8 }}>{hero.name}</div>
|
||||||
|
</div>
|
||||||
|
<Divider type="vertical" style={{ height: 80 }} />
|
||||||
|
<div>
|
||||||
|
<div>套装:<Tag color="blue">暴击套</Tag></div>
|
||||||
|
<div>攻击:2000,防御:1500,生命:20000,速度:200</div>
|
||||||
|
<div>暴击:100%,爆伤:250%,命中:30%,抵抗:20%</div>
|
||||||
|
</div>
|
||||||
|
<Divider type="vertical" style={{ height: 80 }} />
|
||||||
|
<div>
|
||||||
|
<Button type="primary">保存配置</Button>
|
||||||
|
<Button style={{ marginLeft: 8 }}>删除配置</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</Content>
|
||||||
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OptimizerPage;
|
|
||||||
Reference in New Issue
Block a user