Merge branch 'develop' of https://e.coding.net/g-xtcy5189/cunkebao/cunkebao_v3 into develop
This commit is contained in:
26
Cunkebao/dist/.vite/manifest.json
vendored
26
Cunkebao/dist/.vite/manifest.json
vendored
@@ -1,14 +1,18 @@
|
|||||||
{
|
{
|
||||||
"_charts-DN1cefc8.js": {
|
"_charts-aNYyX7D2.js": {
|
||||||
"file": "assets/charts-DN1cefc8.js",
|
"file": "assets/charts-aNYyX7D2.js",
|
||||||
"name": "charts",
|
"name": "charts",
|
||||||
"imports": [
|
"imports": [
|
||||||
"_ui-5V-xZWkf.js",
|
"_ui-DZwp85UP.js",
|
||||||
"_vendor-Bq99rrm8.js"
|
"_vendor-Bq99rrm8.js"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"_ui-5V-xZWkf.js": {
|
"_ui-D0C0OGrH.css": {
|
||||||
"file": "assets/ui-5V-xZWkf.js",
|
"file": "assets/ui-D0C0OGrH.css",
|
||||||
|
"src": "_ui-D0C0OGrH.css"
|
||||||
|
},
|
||||||
|
"_ui-DZwp85UP.js": {
|
||||||
|
"file": "assets/ui-DZwp85UP.js",
|
||||||
"name": "ui",
|
"name": "ui",
|
||||||
"imports": [
|
"imports": [
|
||||||
"_vendor-Bq99rrm8.js"
|
"_vendor-Bq99rrm8.js"
|
||||||
@@ -17,10 +21,6 @@
|
|||||||
"assets/ui-D0C0OGrH.css"
|
"assets/ui-D0C0OGrH.css"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"_ui-D0C0OGrH.css": {
|
|
||||||
"file": "assets/ui-D0C0OGrH.css",
|
|
||||||
"src": "_ui-D0C0OGrH.css"
|
|
||||||
},
|
|
||||||
"_utils-Ft3ushmX.js": {
|
"_utils-Ft3ushmX.js": {
|
||||||
"file": "assets/utils-Ft3ushmX.js",
|
"file": "assets/utils-Ft3ushmX.js",
|
||||||
"name": "utils",
|
"name": "utils",
|
||||||
@@ -33,18 +33,18 @@
|
|||||||
"name": "vendor"
|
"name": "vendor"
|
||||||
},
|
},
|
||||||
"index.html": {
|
"index.html": {
|
||||||
"file": "assets/index-9Clf2a7g.js",
|
"file": "assets/index-CCIZs36L.js",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
"src": "index.html",
|
"src": "index.html",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"imports": [
|
"imports": [
|
||||||
"_vendor-Bq99rrm8.js",
|
"_vendor-Bq99rrm8.js",
|
||||||
"_ui-5V-xZWkf.js",
|
"_ui-DZwp85UP.js",
|
||||||
"_utils-Ft3ushmX.js",
|
"_utils-Ft3ushmX.js",
|
||||||
"_charts-DN1cefc8.js"
|
"_charts-aNYyX7D2.js"
|
||||||
],
|
],
|
||||||
"css": [
|
"css": [
|
||||||
"assets/index-CK1wd128.css"
|
"assets/index-DRrzDMi4.css"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
8
Cunkebao/dist/index.html
vendored
8
Cunkebao/dist/index.html
vendored
@@ -11,13 +11,13 @@
|
|||||||
</style>
|
</style>
|
||||||
<!-- 引入 uni-app web-view SDK(必须) -->
|
<!-- 引入 uni-app web-view SDK(必须) -->
|
||||||
<script type="text/javascript" src="/websdk.js"></script>
|
<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/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/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/ui-D0C0OGrH.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-CK1wd128.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DRrzDMi4.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -43,33 +43,91 @@
|
|||||||
.headerRight {
|
.headerRight {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.userInfo {
|
.userInfo {
|
||||||
cursor: pointer;
|
display: flex;
|
||||||
padding: 8px 12px;
|
align-items: center;
|
||||||
border-radius: 6px;
|
gap: 16px;
|
||||||
transition: all 0.3s;
|
padding: 8px 0;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
.suanli {
|
.suanli {
|
||||||
font-size: 16px;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 14px;
|
||||||
color: #666;
|
color: #666;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 6px 12px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
|
||||||
.suanliIcon {
|
.suanliIcon {
|
||||||
font-size: 24px;
|
font-size: 16px;
|
||||||
|
color: #ffc107;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.messageButton {
|
||||||
border: 2px solid #f0f0f0;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 50%;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
border-color: #1890ff;
|
border-color: #1890ff;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 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;
|
||||||
|
border-radius: 24px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-color: #1890ff;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ const Login: React.FC = () => {
|
|||||||
const { login, login2 } = useUserStore();
|
const { login, login2 } = useUserStore();
|
||||||
const [verify, setVerify] = useState<{
|
const [verify, setVerify] = useState<{
|
||||||
verifyCodeImage: string;
|
verifyCodeImage: string;
|
||||||
verifyCode: string;
|
verifySessionId: string;
|
||||||
}>({
|
}>({
|
||||||
verifyCodeImage: "",
|
verifyCodeImage: "",
|
||||||
verifyCode: "",
|
verifySessionId: "",
|
||||||
});
|
});
|
||||||
// 倒计时效果
|
// 倒计时效果
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -45,7 +45,7 @@ const Login: React.FC = () => {
|
|||||||
const res = await getVerifyCode();
|
const res = await getVerifyCode();
|
||||||
setVerify({
|
setVerify({
|
||||||
verifyCodeImage: res.verifyCodeImage,
|
verifyCodeImage: res.verifyCodeImage,
|
||||||
verifyCode: res.verifyCode,
|
verifySessionId: res.verifySessionId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ const Login: React.FC = () => {
|
|||||||
// 添加typeId参数
|
// 添加typeId参数
|
||||||
const loginParams = {
|
const loginParams = {
|
||||||
...values,
|
...values,
|
||||||
typeId: activeTab as number,
|
verifySessionId: verify.verifySessionId,
|
||||||
};
|
};
|
||||||
|
|
||||||
const response =
|
const response =
|
||||||
@@ -98,10 +98,10 @@ const Login: React.FC = () => {
|
|||||||
|
|
||||||
response
|
response
|
||||||
.then(res => {
|
.then(res => {
|
||||||
const { member, kefuData, deviceTotal } = res;
|
const { member, kefuData } = res;
|
||||||
// 清空WebSocket连接状态
|
// 清空WebSocket连接状态
|
||||||
useWebSocketStore.getState().clearConnectionState();
|
useWebSocketStore.getState().clearConnectionState();
|
||||||
login(res.token, member, deviceTotal);
|
login(res.token, member);
|
||||||
const { self, token } = kefuData;
|
const { self, token } = kefuData;
|
||||||
login2(token.access_token);
|
login2(token.access_token);
|
||||||
setUserInfo(self);
|
setUserInfo(self);
|
||||||
@@ -218,7 +218,7 @@ const Login: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
{activeTab == 1 && verify.verifyCodeImage && (
|
{activeTab == 1 && verify.verifyCodeImage && (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="verificationCode"
|
name="verifyCode"
|
||||||
label="验证码"
|
label="验证码"
|
||||||
rules={[{ required: true, message: "请输入验证码" }]}
|
rules={[{ required: true, message: "请输入验证码" }]}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import request2 from "@/api/request2";
|
|||||||
|
|
||||||
// 密码登录
|
// 密码登录
|
||||||
export function loginWithPassword(params: any) {
|
export function loginWithPassword(params: any) {
|
||||||
return request("/v1/auth/login", params, "POST");
|
return request("/v1/kefu/login", params, "POST");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证码登录
|
// 验证码登录
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
|
import { BarChartOutlined, RobotOutlined } from "@ant-design/icons";
|
||||||
// 菜单项接口
|
// 菜单项接口
|
||||||
export interface MenuItem {
|
export interface MenuItem {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
icon: string;
|
icon: React.ReactNode;
|
||||||
path?: string;
|
path?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 菜单列表数据
|
// 菜单列表数据
|
||||||
export const menuList: MenuItem[] = [
|
export const menuList: MenuItem[] = [
|
||||||
{
|
{
|
||||||
id: "dashboard",
|
id: "wechat",
|
||||||
title: "数据面板",
|
title: "AI智能客服",
|
||||||
icon: "📊",
|
icon: <RobotOutlined className="menuIcon" style={{ fontSize: 20 }} />,
|
||||||
path: "/pc/dashboard",
|
path: "/pc/weChat",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "wechat",
|
id: "powerCenter",
|
||||||
title: "微信管理",
|
title: "功能中心",
|
||||||
icon: "💬",
|
icon: <BarChartOutlined className="menuIcon" style={{ fontSize: 20 }} />,
|
||||||
path: "/pc/weChat",
|
path: "/pc/powerCenter",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -29,10 +30,6 @@ export const drawerMenuData = {
|
|||||||
appName: "触客宝",
|
appName: "触客宝",
|
||||||
appDesc: "AI智能营销系统",
|
appDesc: "AI智能营销系统",
|
||||||
},
|
},
|
||||||
primaryButton: {
|
|
||||||
title: "AI智能客服",
|
|
||||||
icon: "🔒",
|
|
||||||
},
|
|
||||||
footer: {
|
footer: {
|
||||||
balanceIcon: "⚡",
|
balanceIcon: "⚡",
|
||||||
balanceLabel: "算力余额",
|
balanceLabel: "算力余额",
|
||||||
@@ -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 {
|
.header {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
@@ -7,69 +36,124 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
border-bottom: 1px solid #f0f0f0;
|
border-bottom: 1px solid #f0f0f0;
|
||||||
}
|
|
||||||
|
|
||||||
.headerLeft {
|
// Header 左侧区域
|
||||||
display: flex;
|
.headerLeft {
|
||||||
align-items: center;
|
display: flex;
|
||||||
gap: 12px;
|
align-items: center;
|
||||||
}
|
gap: 12px;
|
||||||
|
|
||||||
.menuButton {
|
.menuButton {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.anticon {
|
// Header 右侧区域
|
||||||
font-size: 18px;
|
.headerRight {
|
||||||
color: #666;
|
display: flex;
|
||||||
}
|
align-items: center;
|
||||||
}
|
padding-right: 10px;
|
||||||
|
|
||||||
.title {
|
.userInfo {
|
||||||
font-size: 18px;
|
display: flex;
|
||||||
color: #333;
|
align-items: center;
|
||||||
margin: 0;
|
padding: 8px 0;
|
||||||
}
|
.suanli {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
.headerRight {
|
.suanliIcon {
|
||||||
display: flex;
|
font-size: 20px;
|
||||||
align-items: center;
|
color: #ffc107;
|
||||||
}
|
}
|
||||||
|
|
||||||
.userInfo {
|
&:hover {
|
||||||
cursor: pointer;
|
color: #52c41a;
|
||||||
padding: 8px 12px;
|
transition: all 0.3s;
|
||||||
border-radius: 6px;
|
}
|
||||||
transition: all 0.3s;
|
}
|
||||||
|
|
||||||
&:hover {
|
.avatar {
|
||||||
background-color: #f5f5f5;
|
border: 2px solid #e9ecef;
|
||||||
}
|
transition: all 0.3s;
|
||||||
.suanli {
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
font-size: 16px;
|
}
|
||||||
color: #666;
|
}
|
||||||
.suanliIcon {
|
|
||||||
font-size: 24px;
|
.messageButton {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 80px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
background: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
&:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-color: #1890ff;
|
||||||
|
box-shadow: 0 0px 12px rgba(24, 144, 255, 0.15);
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 #f0f0f0;
|
.bell {
|
||||||
transition: all 0.3s;
|
cursor: pointer;
|
||||||
|
background: #f5f5f5;
|
||||||
&:hover {
|
|
||||||
border-color: #1890ff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
@@ -79,7 +163,8 @@
|
|||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 抽屉样式
|
// ===== Drawer 抽屉区域样式 =====
|
||||||
|
// 左侧菜单抽屉
|
||||||
.drawer {
|
.drawer {
|
||||||
:global(.ant-drawer-header) {
|
:global(.ant-drawer-header) {
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
@@ -89,142 +174,264 @@
|
|||||||
:global(.ant-drawer-body) {
|
:global(.ant-drawer-body) {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
// 抽屉头部
|
||||||
|
.drawerHeader {
|
||||||
.drawerContent {
|
padding: 20px;
|
||||||
height: 100%;
|
background: #fff;
|
||||||
display: flex;
|
border-bottom: none;
|
||||||
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;
|
|
||||||
padding: 20px;
|
|
||||||
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 {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.balanceIcon {
|
|
||||||
color: #666;
|
.logoSection {
|
||||||
.suanliIcon {
|
display: flex;
|
||||||
font-size: 20px;
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.logoIcon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
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: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.appDesc {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin: 2px 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.anticon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 抽屉内容容器
|
||||||
|
.drawerContent {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #f8f9fa;
|
||||||
|
|
||||||
|
// 抽屉主体内容
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.balanceText {
|
// 抽屉底部
|
||||||
color: #3d9c0d;
|
.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 {
|
.balanceLabel {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #999;
|
color: #999;
|
||||||
@@ -237,22 +444,3 @@
|
|||||||
color: #52c41a;
|
color: #52c41a;
|
||||||
margin: 2px 0 0 0;
|
margin: 2px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 响应式设计
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.header {
|
|
||||||
padding: 0 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.username {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drawer {
|
|
||||||
width: 280px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Layout, Drawer, Avatar, Space, Button } from "antd";
|
import { Layout, Drawer, Avatar, Space, Button, Badge, Dropdown } from "antd";
|
||||||
import { MenuOutlined, UserOutlined } from "@ant-design/icons";
|
import {
|
||||||
|
MenuOutlined,
|
||||||
|
UserOutlined,
|
||||||
|
BellOutlined,
|
||||||
|
CloseOutlined,
|
||||||
|
LogoutOutlined,
|
||||||
|
UserSwitchOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
import { useUserStore } from "@/store/module/user";
|
import { useUserStore } from "@/store/module/user";
|
||||||
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
|
// import { useCkChatStore } from "@/store/module/ckchat/ckchat";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
import { drawerMenuData, menuList } from "./index.data";
|
import { drawerMenuData, menuList } from "./index.data";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
@@ -19,10 +27,12 @@ const NavCommon: React.FC<NavCommonProps> = ({
|
|||||||
onMenuClick,
|
onMenuClick,
|
||||||
}) => {
|
}) => {
|
||||||
const [drawerVisible, setDrawerVisible] = useState(false);
|
const [drawerVisible, setDrawerVisible] = useState(false);
|
||||||
|
const [messageDrawerVisible, setMessageDrawerVisible] = useState(false);
|
||||||
|
const [messageCount] = useState(3); // 模拟消息数量
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { userInfo } = useCkChatStore();
|
const location = useLocation();
|
||||||
const { user } = useUserStore();
|
// const { userInfo } = useCkChatStore();
|
||||||
console.log(user);
|
const { user, logout } = useUserStore();
|
||||||
|
|
||||||
// 处理菜单图标点击
|
// 处理菜单图标点击
|
||||||
const handleMenuClick = () => {
|
const handleMenuClick = () => {
|
||||||
@@ -35,6 +45,49 @@ const NavCommon: React.FC<NavCommonProps> = ({
|
|||||||
setDrawerVisible(false);
|
setDrawerVisible(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理消息中心点击
|
||||||
|
const handleMessageClick = () => {
|
||||||
|
setMessageDrawerVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理消息抽屉关闭
|
||||||
|
const handleMessageDrawerClose = () => {
|
||||||
|
setMessageDrawerVisible(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理退出登录
|
||||||
|
const handleLogout = () => {
|
||||||
|
logout(); // 清除localStorage中的token和用户状态
|
||||||
|
navigate("/login"); // 跳转到登录页面
|
||||||
|
};
|
||||||
|
|
||||||
|
// 用户菜单项
|
||||||
|
const userMenuItems = [
|
||||||
|
{
|
||||||
|
key: "userInfo",
|
||||||
|
label: (
|
||||||
|
<div style={{ fontWeight: "bold", color: "#188eee" }}>
|
||||||
|
{user.username}({user.account})
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "profile",
|
||||||
|
icon: <UserSwitchOutlined style={{ fontSize: 16 }} />,
|
||||||
|
label: "个人资料",
|
||||||
|
onClick: () => {
|
||||||
|
console.log("个人资料点击");
|
||||||
|
// TODO: 跳转到个人资料页面
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "logout",
|
||||||
|
icon: <LogoutOutlined style={{ fontSize: 14 }} />,
|
||||||
|
label: "退出登录",
|
||||||
|
onClick: handleLogout,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// 默认抽屉内容
|
// 默认抽屉内容
|
||||||
const defaultDrawerContent = (
|
const defaultDrawerContent = (
|
||||||
<div className={styles.drawerContent}>
|
<div className={styles.drawerContent}>
|
||||||
@@ -52,30 +105,30 @@ const NavCommon: React.FC<NavCommonProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<span className={styles.anticon} onClick={handleDrawerClose}>
|
||||||
|
<CloseOutlined />
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.drawerBody}>
|
<div className={styles.drawerBody}>
|
||||||
<div className={styles.primaryButton}>
|
|
||||||
<div className={styles.buttonIcon}>
|
|
||||||
{drawerMenuData.primaryButton.icon}
|
|
||||||
</div>
|
|
||||||
<span>{drawerMenuData.primaryButton.title}</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.menuSection}>
|
<div className={styles.menuSection}>
|
||||||
{menuList.map((item, index) => (
|
{menuList.map((item, index) => {
|
||||||
<div
|
const isActive = location.pathname === item.path;
|
||||||
key={index}
|
return (
|
||||||
className={styles.menuItem}
|
<div
|
||||||
onClick={() => {
|
key={index}
|
||||||
if (item.path) {
|
className={`${styles.menuItem} ${isActive ? styles.menuItemActive : ""}`}
|
||||||
navigate(item.path);
|
onClick={() => {
|
||||||
setDrawerVisible(false);
|
if (item.path) {
|
||||||
}
|
navigate(item.path);
|
||||||
}}
|
setDrawerVisible(false);
|
||||||
>
|
}
|
||||||
<div className={styles.menuIcon}>{item.icon}</div>
|
}}
|
||||||
<span>{item.title}</span>
|
>
|
||||||
</div>
|
<div className={styles.menuIcon}>{item.icon}</div>
|
||||||
))}
|
<span>{item.title}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.drawerFooter}>
|
<div className={styles.drawerFooter}>
|
||||||
@@ -113,26 +166,119 @@ const NavCommon: React.FC<NavCommonProps> = ({
|
|||||||
<span className={styles.suanliIcon}>⚡</span>
|
<span className={styles.suanliIcon}>⚡</span>
|
||||||
9307.423
|
9307.423
|
||||||
</span>
|
</span>
|
||||||
<Avatar
|
<Dropdown
|
||||||
size={40}
|
menu={{ items: userMenuItems }}
|
||||||
icon={<UserOutlined />}
|
placement="bottomRight"
|
||||||
src={user?.avatar}
|
trigger={["click"]}
|
||||||
className={styles.avatar}
|
>
|
||||||
/>
|
<div className={styles.userSection}>
|
||||||
|
<Avatar
|
||||||
|
size={40}
|
||||||
|
icon={<UserOutlined />}
|
||||||
|
src={user?.avatar}
|
||||||
|
className={styles.avatar}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Dropdown>
|
||||||
|
<div className={styles.messageButton} onClick={handleMessageClick}>
|
||||||
|
<Badge count={messageCount} size="small">
|
||||||
|
<BellOutlined style={{ fontSize: 20 }} />
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
<Drawer
|
<Drawer
|
||||||
title="菜单"
|
|
||||||
placement="left"
|
placement="left"
|
||||||
onClose={handleDrawerClose}
|
onClose={handleDrawerClose}
|
||||||
open={drawerVisible}
|
open={drawerVisible}
|
||||||
width={300}
|
width={300}
|
||||||
className={styles.drawer}
|
className={styles.drawer}
|
||||||
|
closable={false}
|
||||||
>
|
>
|
||||||
{defaultDrawerContent}
|
{defaultDrawerContent}
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|
||||||
|
<Drawer
|
||||||
|
title="通知中心"
|
||||||
|
placement="right"
|
||||||
|
onClose={handleMessageDrawerClose}
|
||||||
|
open={messageDrawerVisible}
|
||||||
|
width={400}
|
||||||
|
className={styles.messageDrawer}
|
||||||
|
extra={
|
||||||
|
<Space>
|
||||||
|
<Button type="text" size="small">
|
||||||
|
全部已读
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={styles.messageContent}>
|
||||||
|
<div className={styles.messageItem}>
|
||||||
|
<div className={styles.messageAvatar}>
|
||||||
|
<Avatar size={40} style={{ backgroundColor: "#87d068" }}>
|
||||||
|
林
|
||||||
|
</Avatar>
|
||||||
|
</div>
|
||||||
|
<div className={styles.messageInfo}>
|
||||||
|
<div className={styles.messageTitle}>
|
||||||
|
<span className={styles.messageType}>新消息</span>
|
||||||
|
<div className={styles.messageStatus}></div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.messageText}>
|
||||||
|
林秀杰:关于自由主时间特惠,原价1999元,现在只需1699元
|
||||||
|
</div>
|
||||||
|
<div className={styles.messageTime}>
|
||||||
|
03-05
|
||||||
|
<Button type="link" size="small">
|
||||||
|
回复
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.messageItem}>
|
||||||
|
<div className={styles.messageAvatar}>
|
||||||
|
<Avatar size={40} style={{ backgroundColor: "#f56a00" }}>
|
||||||
|
E
|
||||||
|
</Avatar>
|
||||||
|
</div>
|
||||||
|
<div className={styles.messageInfo}>
|
||||||
|
<div className={styles.messageTitle}>
|
||||||
|
<span className={styles.messageType}>群提醒</span>
|
||||||
|
<div className={styles.messageStatus}></div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.messageText}>
|
||||||
|
Eric在「云归营私域银行项目群」中@了您
|
||||||
|
</div>
|
||||||
|
<div className={styles.messageTime}>03-05</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.messageItem}>
|
||||||
|
<div className={styles.messageAvatar}>
|
||||||
|
<Avatar size={40} style={{ backgroundColor: "#1890ff" }}>
|
||||||
|
李
|
||||||
|
</Avatar>
|
||||||
|
</div>
|
||||||
|
<div className={styles.messageInfo}>
|
||||||
|
<div className={styles.messageTitle}>
|
||||||
|
<span className={styles.messageType}>好友申请</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.messageText}>李翔想请求添加您为好友</div>
|
||||||
|
<div className={styles.messageTime}>03-04</div>
|
||||||
|
<div className={styles.messageActions}>
|
||||||
|
<Button type="primary" size="small">
|
||||||
|
接受
|
||||||
|
</Button>
|
||||||
|
<Button size="small">拒绝</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const AiTraining: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>AI模型训练</h1>
|
||||||
|
<p>自定义AI模型训练,打造专属智能客服助手</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>AI模型训练功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AiTraining;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const AutoGreeting: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>自动打招呼</h1>
|
||||||
|
<p>智能识别新好友,自动发送个性化欢迎消息</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>自动打招呼功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AutoGreeting;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const CommunicationRecord: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>沟通记录</h1>
|
||||||
|
<p>完整记录客户沟通历史,支持多维度查询分析</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>沟通记录功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CommunicationRecord;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const ContentManagement: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>内容管理</h1>
|
||||||
|
<p>素材管理、数据词汇库、关键词自动回复</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>内容管理功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ContentManagement;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const CustomerManagement: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>客户好友管理</h1>
|
||||||
|
<p>统一管理客户信息和好友关系,提升服务效率</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>客户好友管理功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomerManagement;
|
||||||
119
Touchkebao/src/pages/pc/ckbox/powerCenter/index.data.tsx
Normal file
119
Touchkebao/src/pages/pc/ckbox/powerCenter/index.data.tsx
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
AimOutlined,
|
||||||
|
SendOutlined,
|
||||||
|
CalendarOutlined,
|
||||||
|
TagsOutlined,
|
||||||
|
UserOutlined,
|
||||||
|
MessageOutlined,
|
||||||
|
FileTextOutlined,
|
||||||
|
RobotOutlined,
|
||||||
|
UserAddOutlined,
|
||||||
|
AppstoreOutlined,
|
||||||
|
SoundOutlined,
|
||||||
|
TeamOutlined,
|
||||||
|
FolderOutlined,
|
||||||
|
BarChartOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
|
export interface FeatureCard {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
color: string;
|
||||||
|
path?: string;
|
||||||
|
isNew?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TabItem {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
icon?: React.ReactNode;
|
||||||
|
active?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const featureCards: FeatureCard[] = [
|
||||||
|
{
|
||||||
|
id: "precision-send",
|
||||||
|
title: "精准群发",
|
||||||
|
description: "基于客户标签和行为数据进行精准群发",
|
||||||
|
icon: <AimOutlined />,
|
||||||
|
color: "#ff6b35",
|
||||||
|
path: "/pc/powerCenter/precision-send",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "sop-send",
|
||||||
|
title: "SOP群发",
|
||||||
|
description: "使用触客宝SOP标准化流程进行批量消息发送",
|
||||||
|
icon: <SendOutlined />,
|
||||||
|
color: "#4285f4",
|
||||||
|
path: "/pc/powerCenter/sop-send",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "moments-marketing",
|
||||||
|
title: "朋友圈营销",
|
||||||
|
description: "AI智能生成朋友圈内容,提升品牌曝光度",
|
||||||
|
icon: <CalendarOutlined />,
|
||||||
|
color: "#34a853",
|
||||||
|
path: "/pc/powerCenter/moments-marketing",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "tag-management",
|
||||||
|
title: "标签管理",
|
||||||
|
description: "智能客户标签分类,精准用户画像分析",
|
||||||
|
icon: <TagsOutlined />,
|
||||||
|
color: "#9c27b0",
|
||||||
|
path: "/pc/powerCenter/tag-management",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "customer-management",
|
||||||
|
title: "客户好友管理",
|
||||||
|
description: "统一管理客户信息和好友关系,提升服务效率",
|
||||||
|
icon: <UserOutlined />,
|
||||||
|
color: "#6366f1",
|
||||||
|
path: "/pc/powerCenter/customer-management",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "communication-record",
|
||||||
|
title: "沟通记录",
|
||||||
|
description: "完整记录客户沟通历史,支持多维度查询分析",
|
||||||
|
icon: <MessageOutlined />,
|
||||||
|
color: "#06b6d4",
|
||||||
|
path: "/pc/powerCenter/communication-record",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "content-management",
|
||||||
|
title: "内容管理",
|
||||||
|
description: "素材管理、数据词汇库、关键词自动回复",
|
||||||
|
icon: <FileTextOutlined />,
|
||||||
|
color: "#f59e0b",
|
||||||
|
path: "/pc/powerCenter/content-management",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "ai-training",
|
||||||
|
title: "AI模型训练",
|
||||||
|
description: "自定义AI模型训练,打造专属智能客服助手",
|
||||||
|
icon: <RobotOutlined />,
|
||||||
|
color: "#ec4899",
|
||||||
|
path: "/pc/powerCenter/ai-training",
|
||||||
|
isNew: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "auto-greeting",
|
||||||
|
title: "自动打招呼",
|
||||||
|
description: "智能识别新好友,自动发送个性化欢迎消息",
|
||||||
|
icon: <UserAddOutlined />,
|
||||||
|
color: "#10b981",
|
||||||
|
path: "/pc/powerCenter/auto-greeting",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const tabItems: TabItem[] = [
|
||||||
|
{ key: "all", label: "全部功能", icon: <AppstoreOutlined /> },
|
||||||
|
{ key: "marketing", label: "营销推广", icon: <SoundOutlined /> },
|
||||||
|
{ key: "customer", label: "客户管理", icon: <TeamOutlined /> },
|
||||||
|
{ key: "ai", label: "AI智能", icon: <RobotOutlined /> },
|
||||||
|
{ key: "content", label: "内容管理", icon: <FolderOutlined /> },
|
||||||
|
{ key: "data", label: "数据分析", icon: <BarChartOutlined /> },
|
||||||
|
];
|
||||||
237
Touchkebao/src/pages/pc/ckbox/powerCenter/index.module.scss
Normal file
237
Touchkebao/src/pages/pc/ckbox/powerCenter/index.module.scss
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
.powerCenter {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
min-height: 100vh;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
background: white;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.headerLeft {
|
||||||
|
.title {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerRight {
|
||||||
|
.tabs {
|
||||||
|
.tab {
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeTab {
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
box-shadow: 0 2px 4px rgba(24, 144, 255, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardGrid {
|
||||||
|
.featureCard {
|
||||||
|
border-radius: 16px;
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
height: 200px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardContent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.iconWrapper {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 28px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardInfo {
|
||||||
|
.cardTitle {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.newBadge {
|
||||||
|
background: linear-gradient(135deg, #ff6b6b, #ee5a24);
|
||||||
|
color: white;
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardDescription {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 0;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式设计
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.powerCenter {
|
||||||
|
.header {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.headerRight {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.powerCenter {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
.headerLeft {
|
||||||
|
.title {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardGrid {
|
||||||
|
.featureCard {
|
||||||
|
height: 160px;
|
||||||
|
|
||||||
|
.cardContent {
|
||||||
|
.iconWrapper {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardInfo {
|
||||||
|
.cardTitle {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardDescription {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 卡片颜色主题
|
||||||
|
.featureCard {
|
||||||
|
// 精准群发 - 橙色
|
||||||
|
&[data-color="#ff6b35"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #ff6b35, #f7931e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SOP群发 - 蓝色
|
||||||
|
&[data-color="#4285f4"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #4285f4, #1a73e8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 朋友圈营销 - 绿色
|
||||||
|
&[data-color="#34a853"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #34a853, #137333);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签管理 - 紫色
|
||||||
|
&[data-color="#9c27b0"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #9c27b0, #7b1fa2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 客户管理 - 靛蓝
|
||||||
|
&[data-color="#6366f1"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #6366f1, #4f46e5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 沟通记录 - 青色
|
||||||
|
&[data-color="#06b6d4"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #06b6d4, #0891b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 内容管理 - 黄色
|
||||||
|
&[data-color="#f59e0b"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #f59e0b, #d97706);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AI训练 - 粉色
|
||||||
|
&[data-color="#ec4899"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #ec4899, #db2777);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动打招呼 - 翠绿
|
||||||
|
&[data-color="#10b981"] .iconWrapper {
|
||||||
|
background: linear-gradient(135deg, #10b981, #059669);
|
||||||
|
}
|
||||||
|
}
|
||||||
103
Touchkebao/src/pages/pc/ckbox/powerCenter/index.tsx
Normal file
103
Touchkebao/src/pages/pc/ckbox/powerCenter/index.tsx
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import React, { useState, useMemo } from "react";
|
||||||
|
import { Card, Row, Col, Button, Space } from "antd";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { featureCards, tabItems, FeatureCard } from "./index.data";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const PowerCenter: React.FC = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [activeTab, setActiveTab] = useState("all");
|
||||||
|
|
||||||
|
const handleCardClick = (card: FeatureCard) => {
|
||||||
|
if (card.path) {
|
||||||
|
navigate(card.path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTabClick = (tabKey: string) => {
|
||||||
|
setActiveTab(tabKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根据选中的标签过滤功能卡片
|
||||||
|
const filteredCards = useMemo(() => {
|
||||||
|
if (activeTab === "all") {
|
||||||
|
return featureCards;
|
||||||
|
}
|
||||||
|
|
||||||
|
const categoryMap: { [key: string]: string[] } = {
|
||||||
|
marketing: ["precision-send", "sop-send", "moments-marketing"],
|
||||||
|
customer: ["customer-management", "tag-management"],
|
||||||
|
ai: ["ai-training", "auto-greeting"],
|
||||||
|
content: ["content-management"],
|
||||||
|
data: ["communication-record"],
|
||||||
|
};
|
||||||
|
|
||||||
|
const categoryIds = categoryMap[activeTab] || [];
|
||||||
|
return featureCards.filter(card => categoryIds.includes(card.id));
|
||||||
|
}, [activeTab]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.powerCenter}>
|
||||||
|
{/* 页面头部 */}
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.headerLeft}>
|
||||||
|
<h1 className={styles.title}>功能中心</h1>
|
||||||
|
<p className={styles.subtitle}>触客宝AI私域营销系统 - 所有功能一览</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.headerRight}>
|
||||||
|
<Space className={styles.tabs}>
|
||||||
|
{tabItems.map(item => (
|
||||||
|
<Button
|
||||||
|
key={item.key}
|
||||||
|
type={activeTab === item.key ? "primary" : "text"}
|
||||||
|
className={
|
||||||
|
activeTab === item.key ? styles.activeTab : styles.tab
|
||||||
|
}
|
||||||
|
onClick={() => handleTabClick(item.key)}
|
||||||
|
icon={item.icon}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 功能卡片网格 */}
|
||||||
|
<div className={styles.cardGrid}>
|
||||||
|
<Row gutter={[24, 24]}>
|
||||||
|
{filteredCards.map(card => (
|
||||||
|
<Col key={card.id} xs={24} sm={12} md={8} lg={6} xl={6}>
|
||||||
|
<Card
|
||||||
|
className={styles.featureCard}
|
||||||
|
hoverable
|
||||||
|
onClick={() => handleCardClick(card)}
|
||||||
|
bodyStyle={{ padding: "24px" }}
|
||||||
|
>
|
||||||
|
<div className={styles.cardContent}>
|
||||||
|
<div
|
||||||
|
className={styles.iconWrapper}
|
||||||
|
style={{ backgroundColor: card.color }}
|
||||||
|
>
|
||||||
|
<div className={styles.icon}>{card.icon}</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.cardInfo}>
|
||||||
|
<h3 className={styles.cardTitle}>
|
||||||
|
{card.title}
|
||||||
|
{card.isNew && (
|
||||||
|
<span className={styles.newBadge}>新功能</span>
|
||||||
|
)}
|
||||||
|
</h3>
|
||||||
|
<p className={styles.cardDescription}>{card.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PowerCenter;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const MomentsMarketing: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>朋友圈营销</h1>
|
||||||
|
<p>AI智能生成朋友圈内容,提升品牌曝光度</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>朋友圈营销功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MomentsMarketing;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const PrecisionSend: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>精准群发</h1>
|
||||||
|
<p>基于客户标签和行为数据进行精准群发</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>精准群发功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PrecisionSend;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
Touchkebao/src/pages/pc/ckbox/powerCenter/sop-send/index.tsx
Normal file
21
Touchkebao/src/pages/pc/ckbox/powerCenter/sop-send/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const SopSend: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>SOP群发</h1>
|
||||||
|
<p>使用触客宝SOP标准化流程进行批量消息发送</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>SOP群发功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SopSend;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 300px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const TagManagement: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<h1>标签管理</h1>
|
||||||
|
<p>智能客户标签分类,精准用户画像分析</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{/* 功能内容待开发 */}
|
||||||
|
<div className={styles.placeholder}>
|
||||||
|
<p>标签管理功能正在开发中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TagManagement;
|
||||||
@@ -26,26 +26,6 @@ const ChatWindow: React.FC<ChatWindowProps> = ({ contract }) => {
|
|||||||
const onToggleProfile = () => {
|
const onToggleProfile = () => {
|
||||||
setShowProfile(!showProfile);
|
setShowProfile(!showProfile);
|
||||||
};
|
};
|
||||||
const chatMenu = (
|
|
||||||
<Menu>
|
|
||||||
<Menu.Item key="profile" icon={<UserOutlined />}>
|
|
||||||
查看资料
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item key="call" icon={<PhoneOutlined />}>
|
|
||||||
语音通话
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item key="video" icon={<VideoCameraOutlined />}>
|
|
||||||
视频通话
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Divider />
|
|
||||||
<Menu.Item key="pin">置顶聊天</Menu.Item>
|
|
||||||
<Menu.Item key="mute">消息免打扰</Menu.Item>
|
|
||||||
<Menu.Divider />
|
|
||||||
<Menu.Item key="clear" danger>
|
|
||||||
清空聊天记录
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout className={styles.chatWindow}>
|
<Layout className={styles.chatWindow}>
|
||||||
@@ -76,13 +56,6 @@ const ChatWindow: React.FC<ChatWindowProps> = ({ contract }) => {
|
|||||||
className={styles.headerButton}
|
className={styles.headerButton}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Dropdown overlay={chatMenu} trigger={["click"]}>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
icon={<MoreOutlined />}
|
|
||||||
className={styles.headerButton}
|
|
||||||
/>
|
|
||||||
</Dropdown>
|
|
||||||
</Space>
|
</Space>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
import CkboxPage from "@/pages/pc/ckbox";
|
import CkboxPage from "@/pages/pc/ckbox";
|
||||||
import WeChatPage from "@/pages/pc/ckbox/weChat";
|
import WeChatPage from "@/pages/pc/ckbox/weChat";
|
||||||
import Dashboard from "@/pages/pc/ckbox/dashboard";
|
import Dashboard from "@/pages/pc/ckbox/dashboard";
|
||||||
|
import PowerCenter from "@/pages/pc/ckbox/powerCenter";
|
||||||
|
import PrecisionSend from "@/pages/pc/ckbox/powerCenter/precision-send";
|
||||||
|
import SopSend from "@/pages/pc/ckbox/powerCenter/sop-send";
|
||||||
|
import MomentsMarketing from "@/pages/pc/ckbox/powerCenter/moments-marketing";
|
||||||
|
import TagManagement from "@/pages/pc/ckbox/powerCenter/tag-management";
|
||||||
|
import CustomerManagement from "@/pages/pc/ckbox/powerCenter/customer-management";
|
||||||
|
import CommunicationRecord from "@/pages/pc/ckbox/powerCenter/communication-record";
|
||||||
|
import ContentManagement from "@/pages/pc/ckbox/powerCenter/content-management";
|
||||||
|
import AiTraining from "@/pages/pc/ckbox/powerCenter/ai-training";
|
||||||
|
import AutoGreeting from "@/pages/pc/ckbox/powerCenter/auto-greeting";
|
||||||
const ckboxRoutes = [
|
const ckboxRoutes = [
|
||||||
{
|
{
|
||||||
path: "/pc",
|
path: "/pc",
|
||||||
@@ -16,6 +25,46 @@ const ckboxRoutes = [
|
|||||||
path: "weChat",
|
path: "weChat",
|
||||||
element: <WeChatPage />,
|
element: <WeChatPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter",
|
||||||
|
element: <PowerCenter />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/precision-send",
|
||||||
|
element: <PrecisionSend />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/sop-send",
|
||||||
|
element: <SopSend />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/moments-marketing",
|
||||||
|
element: <MomentsMarketing />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/tag-management",
|
||||||
|
element: <TagManagement />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/customer-management",
|
||||||
|
element: <CustomerManagement />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/communication-record",
|
||||||
|
element: <CommunicationRecord />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/content-management",
|
||||||
|
element: <ContentManagement />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/ai-training",
|
||||||
|
element: <AiTraining />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "powerCenter/auto-greeting",
|
||||||
|
element: <AutoGreeting />,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export interface User {
|
|||||||
updateTime: string | null;
|
updateTime: string | null;
|
||||||
lastLoginIp: string;
|
lastLoginIp: string;
|
||||||
lastLoginTime: number;
|
lastLoginTime: number;
|
||||||
deviceTotal: number; // 设备总数
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserState {
|
interface UserState {
|
||||||
@@ -28,7 +27,7 @@ interface UserState {
|
|||||||
setToken: (token: string) => void;
|
setToken: (token: string) => void;
|
||||||
setToken2: (token2: string) => void;
|
setToken2: (token2: string) => void;
|
||||||
clearUser: () => void;
|
clearUser: () => void;
|
||||||
login: (token: string, userInfo: User, deviceTotal: number) => void;
|
login: (token: string, userInfo: User) => void;
|
||||||
login2: (token2: string) => void;
|
login2: (token2: string) => void;
|
||||||
logout: () => void;
|
logout: () => void;
|
||||||
}
|
}
|
||||||
@@ -44,7 +43,7 @@ export const useUserStore = createPersistStore<UserState>(
|
|||||||
setToken2: token2 => set({ token2 }),
|
setToken2: token2 => set({ token2 }),
|
||||||
clearUser: () =>
|
clearUser: () =>
|
||||||
set({ user: null, token: null, token2: null, isLoggedIn: false }),
|
set({ user: null, token: null, token2: null, isLoggedIn: false }),
|
||||||
login: (token, userInfo, deviceTotal) => {
|
login: (token, userInfo) => {
|
||||||
// 只将token存储到localStorage
|
// 只将token存储到localStorage
|
||||||
localStorage.setItem("token", token);
|
localStorage.setItem("token", token);
|
||||||
|
|
||||||
@@ -64,7 +63,6 @@ export const useUserStore = createPersistStore<UserState>(
|
|||||||
updateTime: userInfo.updateTime,
|
updateTime: userInfo.updateTime,
|
||||||
lastLoginIp: userInfo.lastLoginIp,
|
lastLoginIp: userInfo.lastLoginIp,
|
||||||
lastLoginTime: userInfo.lastLoginTime,
|
lastLoginTime: userInfo.lastLoginTime,
|
||||||
deviceTotal: deviceTotal,
|
|
||||||
};
|
};
|
||||||
set({ user, token, isLoggedIn: true });
|
set({ user, token, isLoggedIn: true });
|
||||||
|
|
||||||
|
|||||||
7
Touchkebao/src/utils/icon.tsx
Normal file
7
Touchkebao/src/utils/icon.tsx
Normal 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;
|
||||||
Reference in New Issue
Block a user