feat: 本次提交更新内容如下
用户信息修改完成
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
width: 56px;
|
width: 56px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #f5f5f5;
|
background: #666;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
.user-main-info {
|
.user-main-info {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-main-row {
|
.user-main-row {
|
||||||
@@ -87,6 +88,15 @@
|
|||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-setting{
|
||||||
|
font-size: 26px;
|
||||||
|
color: #666;
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-btn {
|
.icon-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -178,6 +188,7 @@
|
|||||||
.user-avatar {
|
.user-avatar {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
background: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-name {
|
.user-name {
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ const Mine: React.FC = () => {
|
|||||||
{/* 头像 */}
|
{/* 头像 */}
|
||||||
<div className={style["user-avatar"]}>
|
<div className={style["user-avatar"]}>
|
||||||
{currentUserInfo.avatar ? (
|
{currentUserInfo.avatar ? (
|
||||||
<img src={currentUserInfo.avatar} alt="头像" />
|
<img src={currentUserInfo.avatar} />
|
||||||
) : (
|
) : (
|
||||||
<div className={style["avatar-placeholder"]}>卡</div>
|
<div className={style["avatar-placeholder"]}>卡</div>
|
||||||
)}
|
)}
|
||||||
@@ -195,6 +195,12 @@ const Mine: React.FC = () => {
|
|||||||
<span className={style["role-badge"]}>
|
<span className={style["role-badge"]}>
|
||||||
{currentUserInfo.role}
|
{currentUserInfo.role}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<span className={style["icon-btn"]}>
|
||||||
|
<i className="iconfont icon-bell" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<span className={style["balance-label"]}>余额:</span>
|
<span className={style["balance-label"]}>余额:</span>
|
||||||
<span className={style["balance-value"]}>
|
<span className={style["balance-value"]}>
|
||||||
¥{Number(stats.balance || 0).toFixed(2)}
|
¥{Number(stats.balance || 0).toFixed(2)}
|
||||||
@@ -202,24 +208,18 @@ const Mine: React.FC = () => {
|
|||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
className={style["recharge-btn"]}
|
|
||||||
onClick={() => navigate("/recharge")}
|
onClick={() => navigate("/recharge")}
|
||||||
>
|
>
|
||||||
充值
|
充值
|
||||||
</Button>
|
</Button>
|
||||||
<span className={style["icon-btn"]}>
|
|
||||||
<i className="iconfont icon-bell" />
|
|
||||||
</span>
|
|
||||||
<span className={style["icon-btn"]}>
|
|
||||||
<i
|
|
||||||
className="iconfont icon-setting"
|
|
||||||
onClick={() => navigate("/settings")}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={style["last-login"]}>
|
<div className={style["last-login"]}>
|
||||||
最近登录:{currentUserInfo.lastLogin}
|
最近登录:{currentUserInfo.lastLogin}
|
||||||
</div>
|
</div>
|
||||||
|
<SettingOutlined
|
||||||
|
className={style["icon-setting"]}
|
||||||
|
onClick={() => navigate("/settings")}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
115
nkebao/src/pages/mine/userSet/index.module.scss
Normal file
115
nkebao/src/pages/mine/userSet/index.module.scss
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
.user-set-page {
|
||||||
|
background: #f7f8fa;
|
||||||
|
}
|
||||||
|
.user-card {
|
||||||
|
margin: 18px 16px 0 16px;
|
||||||
|
border-radius: 14px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
||||||
|
}
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 24px 20px 20px 20px;
|
||||||
|
}
|
||||||
|
.avatar {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1890ff;
|
||||||
|
margin-right: 22px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.avatar-placeholder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1890ff;
|
||||||
|
background: #e6f7ff;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.info-list {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
color: #888;
|
||||||
|
min-width: 70px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
color: #222;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 8px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
.avatar-upload {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f5f5f5;
|
||||||
|
transition: box-shadow 0.2s;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
|
||||||
|
}
|
||||||
|
.avatar-upload img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.avatar-edit {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(0,0,0,0.45);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 3px 0 2px 0;
|
||||||
|
border-radius: 0 0 32px 32px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.avatar-upload:hover .avatar-edit {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
.edit-input {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e5e6eb;
|
||||||
|
padding: 4px 10px;
|
||||||
|
background: #fafbfc;
|
||||||
|
}
|
||||||
|
.save-btn {
|
||||||
|
padding: 12px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
113
nkebao/src/pages/mine/userSet/index.tsx
Normal file
113
nkebao/src/pages/mine/userSet/index.tsx
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import React, { useRef, useState } from "react";
|
||||||
|
import { useUserStore } from "@/store/module/user";
|
||||||
|
import { Card, Button, Input, Toast } from "antd-mobile";
|
||||||
|
import style from "./index.module.scss";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import Layout from "@/components/Layout/Layout";
|
||||||
|
import NavCommon from "@/components/NavCommon";
|
||||||
|
|
||||||
|
const UserSetting: React.FC = () => {
|
||||||
|
const { user, setUser } = useUserStore();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [nickname, setNickname] = useState(user?.username || "");
|
||||||
|
const [avatar, setAvatar] = useState(user?.avatar || "");
|
||||||
|
const [uploading, setUploading] = useState(false);
|
||||||
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
// 头像上传
|
||||||
|
const handleAvatarChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const file = e.target.files?.[0];
|
||||||
|
if (!file) return;
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (ev) => {
|
||||||
|
setAvatar(ev.target?.result as string);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (!nickname.trim()) {
|
||||||
|
Toast.show({ content: "昵称不能为空", position: "top" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!user) return;
|
||||||
|
setUser({ ...user, id: user.id, username: nickname, avatar });
|
||||||
|
Toast.show({ content: "保存成功", position: "top" });
|
||||||
|
navigate(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout
|
||||||
|
header={<NavCommon title="用户信息修改" />}
|
||||||
|
footer={
|
||||||
|
<div className={style["save-btn"]}>
|
||||||
|
<Button
|
||||||
|
block
|
||||||
|
color="primary"
|
||||||
|
onClick={handleSave}
|
||||||
|
loading={uploading}
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={style["user-set-page"]}>
|
||||||
|
<Card className={style["user-card"]}>
|
||||||
|
<div className={style["user-info"]}>
|
||||||
|
<div className={style["avatar"]}>
|
||||||
|
<div
|
||||||
|
className={style["avatar-upload"]}
|
||||||
|
onClick={() => fileInputRef.current?.click()}
|
||||||
|
>
|
||||||
|
{avatar ? (
|
||||||
|
<img src={avatar} alt="头像" />
|
||||||
|
) : (
|
||||||
|
<div className={style["avatar-placeholder"]}>卡</div>
|
||||||
|
)}
|
||||||
|
<div className={style["avatar-edit"]}>更换头像</div>
|
||||||
|
<input
|
||||||
|
ref={fileInputRef}
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
style={{ display: "none" }}
|
||||||
|
onChange={handleAvatarChange}
|
||||||
|
disabled={uploading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={style["info-list"]}>
|
||||||
|
<div className={style["info-item"]}>
|
||||||
|
<span className={style["label"]}>昵称</span>
|
||||||
|
<Input
|
||||||
|
className={style["edit-input"]}
|
||||||
|
value={nickname}
|
||||||
|
onChange={setNickname}
|
||||||
|
maxLength={12}
|
||||||
|
placeholder="请输入昵称"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={style["info-item"]}>
|
||||||
|
<span className={style["label"]}>手机号</span>
|
||||||
|
<span className={style["value"]}>{user?.phone || "-"}</span>
|
||||||
|
</div>
|
||||||
|
<div className={style["info-item"]}>
|
||||||
|
<span className={style["label"]}>账号</span>
|
||||||
|
<span className={style["value"]}>{user?.account || "-"}</span>
|
||||||
|
</div>
|
||||||
|
<div className={style["info-item"]}>
|
||||||
|
<span className={style["label"]}>角色</span>
|
||||||
|
<span className={style["value"]}>
|
||||||
|
{user?.isAdmin === 1 ? "管理员" : "普通用户"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserSetting;
|
||||||
@@ -3,6 +3,7 @@ import Mine from "@/pages/mine/index";
|
|||||||
import WechatAccounts from "@/pages/wechat-accounts/list/index";
|
import WechatAccounts from "@/pages/wechat-accounts/list/index";
|
||||||
import WechatAccountDetail from "@/pages/wechat-accounts/detail/index";
|
import WechatAccountDetail from "@/pages/wechat-accounts/detail/index";
|
||||||
import Recharge from "@/pages/mine/recharge/index";
|
import Recharge from "@/pages/mine/recharge/index";
|
||||||
|
import UserSetting from "@/pages/mine/userSet/index";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
// 基础路由
|
// 基础路由
|
||||||
@@ -32,6 +33,11 @@ const routes = [
|
|||||||
element: <Recharge />,
|
element: <Recharge />,
|
||||||
auth: true,
|
auth: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/settings",
|
||||||
|
element: <UserSetting />,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default routes;
|
export default routes;
|
||||||
|
|||||||
Reference in New Issue
Block a user