296 lines
7.9 KiB
TypeScript
296 lines
7.9 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
||
import { useNavigate } from "react-router-dom";
|
||
import { Card, NavBar, List, Button, Dialog, Toast } from "antd-mobile";
|
||
import {
|
||
LogoutOutlined,
|
||
PhoneOutlined,
|
||
MessageOutlined,
|
||
DatabaseOutlined,
|
||
FolderOpenOutlined,
|
||
BellOutlined,
|
||
SettingOutlined,
|
||
} from "@ant-design/icons";
|
||
import MeauMobile from "@/components/MeauMobile/MeauMoible";
|
||
import Layout from "@/components/Layout/Layout";
|
||
import style from "./index.module.scss";
|
||
import { useUserStore } from "@/store/module/user";
|
||
import { getDashboard } from "./api";
|
||
const Mine: React.FC = () => {
|
||
const navigate = useNavigate();
|
||
const { user } = useUserStore();
|
||
const [stats, setStats] = useState({
|
||
devices: 12,
|
||
wechat: 25,
|
||
traffic: 8,
|
||
content: 156,
|
||
balance: 0,
|
||
});
|
||
const [showLogoutDialog, setShowLogoutDialog] = useState(false);
|
||
|
||
// 用户信息
|
||
const currentUserInfo = {
|
||
name: user?.username || "-",
|
||
email: user?.account || "-",
|
||
role: user?.isAdmin === 1 ? "管理员" : "普通用户",
|
||
lastLogin: user?.lastLoginTime
|
||
? new Date(user.lastLoginTime * 1000).toLocaleString()
|
||
: "-",
|
||
avatar: user?.avatar || "",
|
||
};
|
||
|
||
// 功能模块数据
|
||
const functionModules = [
|
||
{
|
||
id: "devices",
|
||
title: "设备管理",
|
||
description: "管理您的设备和微信账号",
|
||
icon: <PhoneOutlined />,
|
||
count: stats.devices,
|
||
path: "/devices",
|
||
bgColor: "#e6f7ff",
|
||
iconColor: "#1890ff",
|
||
},
|
||
{
|
||
id: "wechat",
|
||
title: "微信号管理",
|
||
description: "管理微信账号和好友",
|
||
icon: <MessageOutlined />,
|
||
count: stats.wechat,
|
||
path: "/wechat-accounts",
|
||
bgColor: "#f6ffed",
|
||
iconColor: "#52c41a",
|
||
},
|
||
{
|
||
id: "traffic",
|
||
title: "流量池",
|
||
description: "管理用户流量池和分组",
|
||
icon: <DatabaseOutlined />,
|
||
count: stats.traffic,
|
||
path: "/traffic-pool",
|
||
bgColor: "#f9f0ff",
|
||
iconColor: "#722ed1",
|
||
},
|
||
{
|
||
id: "content",
|
||
title: "内容库",
|
||
description: "管理营销内容和素材",
|
||
icon: <FolderOpenOutlined />,
|
||
count: stats.content,
|
||
path: "/content",
|
||
bgColor: "#fff7e6",
|
||
iconColor: "#fa8c16",
|
||
},
|
||
];
|
||
|
||
// 加载统计数据
|
||
const loadStats = async () => {
|
||
try {
|
||
const res = await getDashboard();
|
||
setStats({
|
||
devices: res.deviceNum,
|
||
wechat: res.wechatNum,
|
||
traffic: 999,
|
||
content: 999,
|
||
balance: res.balance || 0,
|
||
});
|
||
} catch (error) {
|
||
console.error("加载统计数据失败:", error);
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
loadStats();
|
||
}, []);
|
||
|
||
const handleLogout = () => {
|
||
// 清除本地存储的用户信息
|
||
localStorage.removeItem("token");
|
||
localStorage.removeItem("token_expired");
|
||
localStorage.removeItem("s2_accountId");
|
||
localStorage.removeItem("userInfo");
|
||
setShowLogoutDialog(false);
|
||
navigate("/login");
|
||
Toast.show({
|
||
content: "退出成功",
|
||
position: "top",
|
||
});
|
||
};
|
||
|
||
const handleFunctionClick = (path: string) => {
|
||
navigate(path);
|
||
};
|
||
|
||
// 渲染用户头像
|
||
const renderUserAvatar = () => {
|
||
if (currentUserInfo.avatar) {
|
||
return <img src={currentUserInfo.avatar} alt="头像" />;
|
||
}
|
||
return (
|
||
<div
|
||
style={{
|
||
width: "100%",
|
||
height: "100%",
|
||
backgroundColor: "#1890ff",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
color: "white",
|
||
fontSize: "24px",
|
||
fontWeight: "bold",
|
||
}}
|
||
>
|
||
售
|
||
</div>
|
||
);
|
||
};
|
||
|
||
// 渲染功能模块图标
|
||
const renderModuleIcon = (module: any) => (
|
||
<div
|
||
style={{
|
||
width: "40px",
|
||
height: "40px",
|
||
backgroundColor: module.bgColor,
|
||
borderRadius: "8px",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
color: module.iconColor,
|
||
fontSize: "20px",
|
||
}}
|
||
>
|
||
{module.icon}
|
||
</div>
|
||
);
|
||
|
||
return (
|
||
<Layout
|
||
header={
|
||
<NavBar back={null} style={{ background: "#fff" }}>
|
||
<div style={{ color: "var(--primary-color)", fontWeight: 600 }}>
|
||
我的
|
||
</div>
|
||
</NavBar>
|
||
}
|
||
footer={<MeauMobile activeKey="mine" />}
|
||
>
|
||
<div className={style["mine-page"]}>
|
||
{/* 用户信息卡片(严格按图片风格) */}
|
||
<Card className={style["user-card"]}>
|
||
<div className={style["user-info-row"]}>
|
||
{/* 头像 */}
|
||
<div className={style["user-avatar"]}>
|
||
{currentUserInfo.avatar ? (
|
||
<img src={currentUserInfo.avatar} />
|
||
) : (
|
||
<div className={style["avatar-placeholder"]}>卡</div>
|
||
)}
|
||
</div>
|
||
{/* 右侧内容 */}
|
||
<div className={style["user-main-info"]}>
|
||
<div className={style["user-main-row"]}>
|
||
<span className={style["user-name"]}>
|
||
{currentUserInfo.name}
|
||
</span>
|
||
<span className={style["role-badge"]}>
|
||
{currentUserInfo.role}
|
||
</span>
|
||
|
||
<span className={style["icon-btn"]}>
|
||
<i className="iconfont icon-bell" />
|
||
</span>
|
||
</div>
|
||
<div>
|
||
<span className={style["balance-label"]}>余额:</span>
|
||
<span className={style["balance-value"]}>
|
||
¥{Number(stats.balance || 0).toFixed(2)}
|
||
</span>
|
||
<Button
|
||
size="small"
|
||
color="primary"
|
||
onClick={() => navigate("/recharge")}
|
||
>
|
||
充值
|
||
</Button>
|
||
</div>
|
||
<div className={style["last-login"]}>
|
||
最近登录:{currentUserInfo.lastLogin}
|
||
</div>
|
||
<SettingOutlined
|
||
className={style["icon-setting"]}
|
||
onClick={() => navigate("/settings")}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</Card>
|
||
|
||
{/* 我的功能 */}
|
||
<Card className={style["menu-card"]}>
|
||
<List>
|
||
{functionModules.map((module) => (
|
||
<List.Item
|
||
key={module.id}
|
||
prefix={renderModuleIcon(module)}
|
||
title={module.title}
|
||
description={module.description}
|
||
extra={
|
||
<span
|
||
style={{
|
||
padding: "2px 8px",
|
||
backgroundColor: "#f0f0f0",
|
||
borderRadius: "12px",
|
||
fontSize: "12px",
|
||
color: "#666",
|
||
}}
|
||
>
|
||
{module.count}
|
||
</span>
|
||
}
|
||
arrow
|
||
onClick={() => handleFunctionClick(module.path)}
|
||
/>
|
||
))}
|
||
</List>
|
||
</Card>
|
||
|
||
{/* 退出登录按钮 */}
|
||
<Button
|
||
block
|
||
color="danger"
|
||
fill="outline"
|
||
className={style["logout-btn"]}
|
||
onClick={() => setShowLogoutDialog(true)}
|
||
>
|
||
<LogoutOutlined style={{ marginRight: "8px" }} />
|
||
退出登录
|
||
</Button>
|
||
</div>
|
||
|
||
{/* 退出登录确认对话框 */}
|
||
<Dialog
|
||
content="您确定要退出登录吗?退出后需要重新登录才能使用完整功能。"
|
||
visible={showLogoutDialog}
|
||
closeOnAction
|
||
actions={[
|
||
[
|
||
{
|
||
key: "cancel",
|
||
text: "取消",
|
||
},
|
||
{
|
||
key: "confirm",
|
||
text: "确认退出",
|
||
bold: true,
|
||
danger: true,
|
||
onClick: handleLogout,
|
||
},
|
||
],
|
||
]}
|
||
onClose={() => setShowLogoutDialog(false)}
|
||
/>
|
||
</Layout>
|
||
);
|
||
};
|
||
|
||
export default Mine;
|