feat(NavCommon): 重构导航组件并优化样式结构

- 新增图标组件并替换原有emoji图标
- 重构导航菜单数据结构并移除无用代码
- 实现菜单项激活状态高亮效果
- 完善用户退出登录功能
- 优化样式文件结构并添加详细注释
- 更新构建产物文件版本
This commit is contained in:
超级老白兔
2025-09-12 17:49:23 +08:00
parent d3ee0bde5a
commit f2fb543f93
6 changed files with 453 additions and 377 deletions

View File

@@ -1,14 +1,18 @@
{
"_charts-DN1cefc8.js": {
"file": "assets/charts-DN1cefc8.js",
"_charts-aNYyX7D2.js": {
"file": "assets/charts-aNYyX7D2.js",
"name": "charts",
"imports": [
"_ui-5V-xZWkf.js",
"_ui-DZwp85UP.js",
"_vendor-Bq99rrm8.js"
]
},
"_ui-5V-xZWkf.js": {
"file": "assets/ui-5V-xZWkf.js",
"_ui-D0C0OGrH.css": {
"file": "assets/ui-D0C0OGrH.css",
"src": "_ui-D0C0OGrH.css"
},
"_ui-DZwp85UP.js": {
"file": "assets/ui-DZwp85UP.js",
"name": "ui",
"imports": [
"_vendor-Bq99rrm8.js"
@@ -17,10 +21,6 @@
"assets/ui-D0C0OGrH.css"
]
},
"_ui-D0C0OGrH.css": {
"file": "assets/ui-D0C0OGrH.css",
"src": "_ui-D0C0OGrH.css"
},
"_utils-Ft3ushmX.js": {
"file": "assets/utils-Ft3ushmX.js",
"name": "utils",
@@ -33,18 +33,18 @@
"name": "vendor"
},
"index.html": {
"file": "assets/index-9Clf2a7g.js",
"file": "assets/index-CCIZs36L.js",
"name": "index",
"src": "index.html",
"isEntry": true,
"imports": [
"_vendor-Bq99rrm8.js",
"_ui-5V-xZWkf.js",
"_ui-DZwp85UP.js",
"_utils-Ft3ushmX.js",
"_charts-DN1cefc8.js"
"_charts-aNYyX7D2.js"
],
"css": [
"assets/index-CK1wd128.css"
"assets/index-DRrzDMi4.css"
]
}
}

View File

@@ -11,13 +11,13 @@
</style>
<!-- 引入 uni-app web-view SDK必须 -->
<script type="text/javascript" src="/websdk.js"></script>
<script type="module" crossorigin src="/assets/index-9Clf2a7g.js"></script>
<script type="module" crossorigin src="/assets/index-CCIZs36L.js"></script>
<link rel="modulepreload" crossorigin href="/assets/vendor-Bq99rrm8.js">
<link rel="modulepreload" crossorigin href="/assets/ui-5V-xZWkf.js">
<link rel="modulepreload" crossorigin href="/assets/ui-DZwp85UP.js">
<link rel="modulepreload" crossorigin href="/assets/utils-Ft3ushmX.js">
<link rel="modulepreload" crossorigin href="/assets/charts-DN1cefc8.js">
<link rel="modulepreload" crossorigin href="/assets/charts-aNYyX7D2.js">
<link rel="stylesheet" crossorigin href="/assets/ui-D0C0OGrH.css">
<link rel="stylesheet" crossorigin href="/assets/index-CK1wd128.css">
<link rel="stylesheet" crossorigin href="/assets/index-DRrzDMi4.css">
</head>
<body>
<div id="root"></div>

View File

@@ -1,8 +1,9 @@
import { BarChartOutlined, RobotOutlined } from "@ant-design/icons";
// 菜单项接口
export interface MenuItem {
id: string;
title: string;
icon: string;
icon: React.ReactNode;
path?: string;
}
@@ -10,22 +11,16 @@ export interface MenuItem {
export const menuList: MenuItem[] = [
{
id: "wechat",
title: "微信管理",
icon: "💬",
title: "AI智能客服",
icon: <RobotOutlined className="menuIcon" style={{ fontSize: 20 }} />,
path: "/pc/weChat",
},
{
id: "powerCenter",
title: "功能中心",
icon: "📊",
icon: <BarChartOutlined className="menuIcon" style={{ fontSize: 20 }} />,
path: "/pc/powerCenter",
},
{
id: "dashboard",
title: "数据面板",
icon: "📊",
path: "/pc/dashboard",
},
];
// 抽屉菜单配置数据

View File

@@ -1,3 +1,32 @@
/**
* NavCommon 组件样式文件
*
* 文件结构说明:
* 1. Header 区域样式 - 顶部导航栏相关样式
* - headerLeft: 左侧菜单按钮和标题
* - headerRight: 右侧用户信息、算力显示、消息按钮等
*
* 2. Drawer 抽屉区域样式 - 左侧菜单抽屉相关样式
* - drawerContent: 抽屉内容容器
* - drawerHeader: 抽屉头部Logo区域
* - drawerBody: 抽屉主体(主要按钮和菜单项)
* - drawerFooter: 抽屉底部(余额显示)
*
* 3. 消息抽屉区域样式 - 右侧消息中心抽屉相关样式
* - messageContent: 消息列表容器
* - messageItem: 单个消息项样式
*
* 4. 兼容样式 - 保持向后兼容的独立样式类
*
* 5. 响应式设计 - 移动端适配样式
*
* 样式组织原则:
* - 按照 tsx 文件中的嵌套结构组织样式
* - 使用 SCSS 嵌套语法体现 DOM 层级关系
* - 相关样式就近放置,便于维护
*/
// ===== Header 区域样式 =====
.header {
background: #fff;
padding: 0 16px;
@@ -7,212 +36,129 @@
justify-content: space-between;
height: 64px;
border-bottom: 1px solid #f0f0f0;
}
.headerLeft {
display: flex;
align-items: center;
gap: 12px;
}
.menuButton {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 6px;
transition: all 0.3s;
&:hover {
background-color: #f5f5f5;
}
.anticon {
font-size: 18px;
color: #666;
}
}
.title {
font-size: 18px;
color: #333;
margin: 0;
}
.headerRight {
display: flex;
align-items: center;
gap: 16px;
padding-right: 10px;
}
.userInfo {
display: flex;
align-items: center;
gap: 16px;
padding: 8px 0;
.suanli {
// Header 左侧区域
.headerLeft {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
color: #666;
font-weight: 500;
cursor: pointer;
gap: 12px;
.suanliIcon {
font-size: 20px;
color: #ffc107;
}
&:hover {
color: #52c41a;
.menuButton {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 6px;
transition: all 0.3s;
&:hover {
background-color: #f5f5f5;
}
.anticon {
font-size: 18px;
color: #666;
}
}
.title {
font-size: 18px;
color: #333;
margin: 0;
}
}
// Header 右侧区域
.headerRight {
display: flex;
align-items: center;
gap: 16px;
padding-right: 10px;
.userInfo {
display: flex;
align-items: center;
gap: 16px;
padding: 8px 0;
.suanli {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
color: #666;
font-weight: 500;
cursor: pointer;
.suanliIcon {
font-size: 20px;
color: #ffc107;
}
&:hover {
color: #52c41a;
transition: all 0.3s;
}
}
.avatar {
border: 2px solid #e9ecef;
transition: all 0.3s;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
}
.messageButton {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 80px;
transition: all 0.3s;
border: 1px solid #e9ecef;
background: #fff;
cursor: pointer;
&:hover {
background-color: #f8f9fa;
border-color: #1890ff;
box-shadow: 0 0px 12px rgba(24, 144, 255, 0.15);
}
.anticon {
font-size: 18px;
color: #666;
}
}
.userSection {
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
padding: 8px 16px;
}
.userNickname {
font-size: 14px;
color: #333;
font-weight: 600;
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
// 兼容旧样式(避免破坏性更改)
.bell {
cursor: pointer;
background: #f5f5f5;
}
.messageButton {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 80px;
transition: all 0.3s;
border: 1px solid #e9ecef;
background: #fff;
cursor: pointer;
&:hover {
background-color: #f8f9fa;
border-color: #1890ff;
box-shadow: 0 0px 12px rgba(24, 144, 255, 0.15);
}
.anticon {
font-size: 18px;
color: #666;
}
}
.userSection {
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
padding: 8px 16px;
}
.userNickname {
font-size: 14px;
color: #333;
font-weight: 600;
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.avatar {
border: 2px solid #e9ecef;
transition: all 0.3s;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
// 消息抽屉样式
.messageDrawer {
:global(.ant-drawer-header) {
border-bottom: 1px solid #f0f0f0;
}
:global(.ant-drawer-body) {
padding: 0;
}
}
.messageContent {
height: 100%;
overflow-y: auto;
}
.messageItem {
display: flex;
padding: 16px;
border-bottom: 1px solid #f5f5f5;
transition: background-color 0.2s;
&:hover {
background-color: #fafafa;
}
&:last-child {
border-bottom: none;
}
}
.messageAvatar {
margin-right: 12px;
flex-shrink: 0;
}
.messageInfo {
flex: 1;
min-width: 0;
}
.messageTitle {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
.messageType {
font-size: 14px;
font-weight: 500;
color: #262626;
}
.messageStatus {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #1890ff;
}
.messageText {
font-size: 13px;
color: #595959;
line-height: 1.4;
margin-bottom: 8px;
word-break: break-word;
}
.messageTime {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 12px;
color: #8c8c8c;
}
.messageActions {
display: flex;
gap: 8px;
margin-top: 8px;
:global(.ant-btn) {
height: 24px;
padding: 0 8px;
font-size: 12px;
}
}
.username {
font-size: 14px;
color: #333;
@@ -220,7 +166,8 @@
margin-left: 8px;
}
// 抽屉样式
// ===== Drawer 抽屉区域样式 =====
// 左侧菜单抽屉
.drawer {
:global(.ant-drawer-header) {
background: #fafafa;
@@ -230,141 +177,259 @@
:global(.ant-drawer-body) {
padding: 0;
}
}
.drawerContent {
height: 100%;
display: flex;
flex-direction: column;
background: #f8f9fa;
}
.drawerHeader {
padding: 20px;
background: #fff;
border-bottom: none;
}
.logoSection {
display: flex;
align-items: center;
gap: 12px;
}
.logoIcon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: white;
}
.logoText {
display: flex;
flex-direction: column;
}
.appName {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 0;
}
.appDesc {
font-size: 12px;
color: #999;
margin: 2px 0 0 0;
}
.drawerBody {
flex: 1;
display: flex;
flex-direction: column;
gap: 16px;
}
.primaryButton {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
padding: 16px 20px;
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
transition: all 0.3s;
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
.buttonIcon {
font-size: 20px;
}
span {
font-size: 16px;
font-weight: 600;
color: white;
}
}
.menuSection {
margin-top: 8px;
}
.menuItem {
display: flex;
align-items: center;
padding: 16px 20px;
cursor: pointer;
transition: all 0.3s;
border-radius: 8px;
&:hover {
background-color: #f0f0f0;
}
span {
font-size: 16px;
color: #333;
font-weight: 500;
}
}
.menuIcon {
font-size: 20px;
margin-right: 12px;
width: 20px;
text-align: center;
}
.drawerFooter {
padding: 20px;
background: #fff;
border-top: 1px solid #f0f0f0;
.balanceSection {
// 抽屉内容容器
.drawerContent {
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.balanceIcon {
color: #666;
.suanliIcon {
font-size: 20px;
flex-direction: column;
background: #f8f9fa;
// 抽屉头部
.drawerHeader {
padding: 20px;
background: #fff;
border-bottom: none;
.logoSection {
display: flex;
align-items: center;
gap: 12px;
.logoIcon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, #3b81f6 0%, #9035ea 100%);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: white;
}
.logoText {
display: flex;
flex-direction: column;
.appName {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 0;
}
.appDesc {
font-size: 12px;
color: #999;
margin: 2px 0 0 0;
}
}
}
}
.balanceText {
color: #3d9c0d;
// 抽屉主体内容
.drawerBody {
flex: 1;
display: flex;
flex-direction: column;
gap: 16px;
.primaryButton {
background: linear-gradient(135deg, #3d80f6 0%, #764ba2 100%);
border-radius: 12px;
padding: 16px 20px;
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
transition: all 0.3s;
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
.buttonIcon {
font-size: 20px;
}
span {
font-size: 16px;
font-weight: 600;
color: white;
}
}
// 菜单区域
.menuSection {
padding: 0px 20px;
.menuItem {
display: flex;
align-items: center;
padding: 8px 20px;
cursor: pointer;
transition: all 0.3s;
border-radius: 8px;
margin: 4px 0;
&:hover {
background-color: #f0f0f0;
}
.menuIcon {
font-size: 20px;
margin-right: 12px;
width: 20px;
text-align: center;
}
span {
font-size: 16px;
color: #333;
font-weight: 500;
}
&.menuItemActive {
background: linear-gradient(to right, #3b82f6, #9333ea);
color: white;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
span {
color: white;
font-weight: 600;
}
.menuIcon {
color: white;
}
&:hover {
background: linear-gradient(to right, #3b82f6, #9333ea);
box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
}
}
}
}
}
// 抽屉底部
.drawerFooter {
padding: 20px;
background: #fff;
border-top: 1px solid #f0f0f0;
.balanceSection {
display: flex;
justify-content: space-between;
align-items: center;
.balanceIcon {
color: #666;
.suanliIcon {
font-size: 20px;
}
}
.balanceText {
color: #3d9c0d;
}
}
}
}
}
// ===== 消息抽屉区域样式 =====
.messageDrawer {
:global(.ant-drawer-header) {
border-bottom: 1px solid #f0f0f0;
}
:global(.ant-drawer-body) {
padding: 0;
}
.messageContent {
height: 100%;
overflow-y: auto;
.messageItem {
display: flex;
padding: 16px;
border-bottom: 1px solid #f5f5f5;
transition: background-color 0.2s;
&:hover {
background-color: #fafafa;
}
&:last-child {
border-bottom: none;
}
.messageAvatar {
margin-right: 12px;
flex-shrink: 0;
}
.messageInfo {
flex: 1;
min-width: 0;
.messageTitle {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
.messageType {
font-size: 14px;
font-weight: 500;
color: #262626;
}
.messageStatus {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #1890ff;
}
}
.messageText {
font-size: 13px;
color: #595959;
line-height: 1.4;
margin-bottom: 8px;
word-break: break-word;
}
.messageTime {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 12px;
color: #8c8c8c;
}
.messageActions {
display: flex;
gap: 8px;
margin-top: 8px;
:global(.ant-btn) {
height: 24px;
padding: 0 8px;
font-size: 12px;
}
}
}
}
}
}
// ===== 兼容样式 =====
.balanceLabel {
font-size: 12px;
color: #999;
@@ -378,18 +443,24 @@
margin: 2px 0 0 0;
}
// 响应式设计
// ===== 响应式设计 =====
@media (max-width: 768px) {
.header {
padding: 0 12px;
}
.title {
font-size: 16px;
}
.headerLeft {
.title {
font-size: 16px;
}
}
.username {
display: none;
.headerRight {
.userInfo {
.username {
display: none;
}
}
}
}
.drawer {

View File

@@ -7,9 +7,10 @@ import {
UserSwitchOutlined,
LogoutOutlined,
} from "@ant-design/icons";
import { useUserStore } from "@/store/module/user";
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
import { useNavigate } from "react-router-dom";
// import { useCkChatStore } from "@/store/module/ckchat/ckchat";
import { useNavigate, useLocation } from "react-router-dom";
import { drawerMenuData, menuList } from "./index.data";
import styles from "./index.module.scss";
@@ -28,9 +29,9 @@ const NavCommon: React.FC<NavCommonProps> = ({
const [messageDrawerVisible, setMessageDrawerVisible] = useState(false);
const [messageCount] = useState(3); // 模拟消息数量
const navigate = useNavigate();
const { userInfo } = useCkChatStore();
const { user } = useUserStore();
console.log(user);
const location = useLocation();
// const { userInfo } = useCkChatStore();
const { user, logout } = useUserStore();
// 处理菜单图标点击
const handleMenuClick = () => {
@@ -55,8 +56,8 @@ const NavCommon: React.FC<NavCommonProps> = ({
// 处理退出登录
const handleLogout = () => {
console.log("退出登录");
// TODO: 实现退出登录逻辑
logout(); // 清除localStorage中的token和用户状态
navigate("/login"); // 跳转到登录页面
};
// 用户菜单项
@@ -106,21 +107,24 @@ const NavCommon: React.FC<NavCommonProps> = ({
</div>
<div className={styles.drawerBody}>
<div className={styles.menuSection}>
{menuList.map((item, index) => (
<div
key={index}
className={styles.menuItem}
onClick={() => {
if (item.path) {
navigate(item.path);
setDrawerVisible(false);
}
}}
>
<div className={styles.menuIcon}>{item.icon}</div>
<span>{item.title}</span>
</div>
))}
{menuList.map((item, index) => {
const isActive = location.pathname === item.path;
return (
<div
key={index}
className={`${styles.menuItem} ${isActive ? styles.menuItemActive : ""}`}
onClick={() => {
if (item.path) {
navigate(item.path);
setDrawerVisible(false);
}
}}
>
<div className={styles.menuIcon}>{item.icon}</div>
<span>{item.title}</span>
</div>
);
})}
</div>
</div>
<div className={styles.drawerFooter}>
@@ -185,7 +189,6 @@ const NavCommon: React.FC<NavCommonProps> = ({
</Header>
<Drawer
title="菜单"
placement="left"
onClose={handleDrawerClose}
open={drawerVisible}

View File

@@ -0,0 +1,7 @@
import { createFromIconfontCN } from "@ant-design/icons";
const IconFont = createFromIconfontCN({
scriptUrl: "//at.alicdn.com/t/c/font_4272168_343o7l1hnhb.js",
});
export default IconFont;