feat(功能中心重構與樣式優化): 將功能卡片結構重組為分類展示,新增熱門與新功能標籤,並優化樣式以提升用戶體驗。同時,新增通用配置頁面路由。

This commit is contained in:
超级老白兔
2025-09-25 11:08:03 +08:00
parent 664d86838d
commit 88653c1656
7 changed files with 629 additions and 355 deletions

View File

@@ -0,0 +1,60 @@
/* common-config page styles */
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
padding: 16px;
}
.tabsBar {
display: grid;
grid-template-columns: repeat(5, max-content);
gap: 24px;
padding: 12px 16px 0 16px;
color: #667085;
}
.tab {
padding: 10px 16px;
border-radius: 8px;
background: #f7f9fc;
cursor: pointer;
}
.tabActive {
padding: 10px 16px;
border-radius: 8px;
background: #eef5ff;
color: #1677ff;
box-shadow: inset 0 0 0 1px #d6e6ff;
}
.left,
.right {
min-height: 420px;
}
.tip {
color: #98a2b3;
margin-bottom: 16px;
}
.formItem {
margin-bottom: 16px;
}
.label {
margin-bottom: 8px;
color: #344054;
}
.primaryBtn {
height: 40px;
border-radius: 8px;
}
.actions {
padding: 12px 16px;
background: #fff;
border-top: 1px solid #eee;
}

View File

@@ -0,0 +1,139 @@
import React, { useState } from "react";
import Layout from "@/components/Layout/LayoutFiexd";
import PowerNavigation from "@/components/PowerNavtion";
import { Card, Select, Button, Space, Tag, List } from "antd";
import { SettingOutlined, DatabaseOutlined } from "@ant-design/icons";
import styles from "./index.module.scss";
const { Option } = Select;
const CommonConfig: React.FC = () => {
const [pool, setPool] = useState<string | undefined>();
const [mode, setMode] = useState<string>("人工接待");
const pools = ["官网咨询", "朋友推荐", "展会获客"];
return (
<Layout
header={
<>
<PowerNavigation
title="全局配置"
subtitle="系统全局设置和配置管理"
showBackButton={true}
backButtonText="返回功能中心"
/>
<div className={styles.tabsBar}>
<div className={styles.tabActive}></div>
<div className={styles.tab}></div>
<div className={styles.tab}></div>
<div className={styles.tab}></div>
<div className={styles.tab}></div>
</div>
</>
}
footer={
<div className={styles.actions}>
<Space>
<Button
onClick={() => {
setPool(undefined);
setMode("人工接待");
}}
>
</Button>
<Button type="primary"></Button>
</Space>
</div>
}
>
<div className={styles.container}>
<div className={styles.left}>
<Card
title={
<Space size={8}>
<DatabaseOutlined />
<span></span>
</Space>
}
>
<div className={styles.tip}>
</div>
<div className={styles.formItem}>
<div className={styles.label}></div>
<Select
placeholder="请选择流量池"
value={pool}
onChange={setPool}
style={{ width: "100%" }}
>
{pools.map(p => (
<Option key={p} value={p}>
{p}
</Option>
))}
</Select>
</div>
<div className={styles.formItem}>
<div className={styles.label}></div>
<Select value={mode} onChange={setMode} style={{ width: "100%" }}>
<Option value="人工接待"></Option>
<Option value="AI接待">AI接待</Option>
<Option value="AI辅助">AI辅助</Option>
</Select>
</div>
<Button type="primary" block className={styles.primaryBtn}>
</Button>
</Card>
</div>
<div className={styles.right}>
<Card
title={
<Space size={8}>
<SettingOutlined />
<span></span>
</Space>
}
>
<List
itemLayout="horizontal"
dataSource={pools}
renderItem={(item, index) => (
<List.Item>
<List.Item.Meta
title={item}
description={`${Math.floor(Math.random() * 300) + 50} 个客户`}
/>
<Tag
color={
index % 3 === 0
? "blue"
: index % 3 === 1
? "orange"
: "green"
}
>
{index % 3 === 0
? "AI辅助"
: index % 3 === 1
? "人工接待"
: "AI接管"}
</Tag>
</List.Item>
)}
/>
</Card>
</div>
</div>
</Layout>
);
};
export default CommonConfig;

View File

@@ -124,7 +124,12 @@ const NavCommon: React.FC<NavCommonProps> = ({ title = "触客宝" }) => {
<BellOutlined style={{ fontSize: 20 }} />
</Badge>
</div>
<div className={styles.messageButton}>
<div
className={styles.messageButton}
onClick={() => {
navigate("/pc/commonConfig");
}}
>
<SettingOutlined style={{ fontSize: 20 }} />
</div>
<Dropdown

View File

@@ -1,21 +1,15 @@
import React from "react";
import {
AimOutlined,
SendOutlined,
CalendarOutlined,
TagsOutlined,
UserOutlined,
MessageOutlined,
FileTextOutlined,
RobotOutlined,
UserAddOutlined,
AppstoreOutlined,
SoundOutlined,
ThunderboltOutlined,
RiseOutlined,
TeamOutlined,
FolderOutlined,
BarChartOutlined,
CommentOutlined,
FileTextOutlined,
SoundOutlined,
EditOutlined,
} from "@ant-design/icons";
// 数据类型定义
export interface FeatureCard {
id: string;
title: string;
@@ -24,96 +18,87 @@ export interface FeatureCard {
color: string;
path?: string;
isNew?: boolean;
isHot?: boolean;
}
export interface TabItem {
key: string;
label: string;
icon?: React.ReactNode;
active?: boolean;
export interface FeatureCategory {
id: string;
title: string;
icon: React.ReactNode;
color: string;
count: number;
features: FeatureCard[];
}
export const featureCards: FeatureCard[] = [
// 功能数据
export const featureCategories: FeatureCategory[] = [
{
id: "precision-send",
title: "精准群发",
description: "基于客户标签和行为数据进行精准群发",
id: "core",
title: "核心功能",
icon: <AimOutlined />,
color: "#ff6b35",
path: "/pc/powerCenter/precision-send",
color: "#1890ff",
count: 2,
features: [
{
id: "customer-management",
title: "客户好友管理",
description: "管理客户关系,维护好友信息,提升客户满意度",
icon: <TeamOutlined />,
color: "#1890ff",
path: "/pc/powerCenter/customer-management",
isHot: true,
},
{
id: "communication-record",
title: "沟通记录",
description: "记录和分析所有客户沟通历史,优化服务质量",
icon: <CommentOutlined />,
color: "#52c41a",
path: "/pc/powerCenter/communication-record",
},
],
},
{
id: "sop-send",
title: "SOP群发",
description: "使用触客宝SOP标准化流程进行批量消息发送",
icon: <SendOutlined />,
color: "#4285f4",
path: "/pc/powerCenter/sop-send",
id: "ai",
title: "AI智能功能",
icon: <ThunderboltOutlined />,
color: "#722ed1",
count: 2,
features: [
{
id: "ai-training",
title: "AI模型训练",
description: "训练专属AI模型,提升智能服务能力",
icon: <FileTextOutlined />,
color: "#fa8c16",
path: "/pc/powerCenter/ai-training",
isNew: true,
},
{
id: "auto-greeting",
title: "自动问候",
description: "设置智能问候规则,自动化客户接待流程",
icon: <SoundOutlined />,
color: "#722ed1",
path: "/pc/powerCenter/auto-greeting",
},
],
},
{
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",
id: "marketing",
title: "营销管理",
icon: <RiseOutlined />,
color: "#52c41a",
count: 1,
features: [
{
id: "content-management",
title: "内容管理",
description: "管理营销内容,素材库,提升内容创作效率",
icon: <EditOutlined />,
color: "#722ed1",
path: "/pc/powerCenter/content-management",
},
],
},
];
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 /> },
];

View File

@@ -1,127 +1,174 @@
.powerCenter {
padding: 24px;
background-color: #f5f5f5;
padding: 40px;
background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
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);
// 功能分类区域
.categorySection {
margin-bottom: 48px;
.headerLeft {
.title {
font-size: 28px;
font-weight: 600;
color: #1a1a1a;
margin: 0 0 8px 0;
.categoryHeader {
display: flex;
align-items: center;
margin-bottom: 24px;
padding: 0 8px;
.categoryIcon {
width: 48px;
height: 48px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
.anticon {
font-size: 24px;
color: white;
}
}
.subtitle {
font-size: 14px;
color: #666;
margin: 0;
.categoryInfo {
.categoryTitle {
font-size: 24px;
font-weight: 600;
color: #1a1a1a;
margin: 0 0 4px 0;
}
.categoryCount {
font-size: 14px;
color: #666;
background: #f0f0f0;
padding: 4px 12px;
border-radius: 12px;
border: 1px solid #e0e0e0;
}
}
}
.headerRight {
.tabs {
.tab {
border-radius: 8px;
border: 1px solid #e0e0e0;
color: #666;
.featureCards {
display: flex;
justify-content: flex-start;
gap: 24px;
flex-wrap: wrap;
&:hover {
color: #1890ff;
border-color: #1890ff;
}
.featureCard {
border-radius: 16px;
border: none;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
width: 30%;
cursor: pointer;
position: relative;
overflow: hidden;
background: white;
padding: 20px;
box-sizing: border-box;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.activeTab {
border-radius: 8px;
background: #1890ff;
border-color: #1890ff;
box-shadow: 0 2px 4px rgba(24, 144, 255, 0.2);
.cardContent {
.cardHeader {
position: relative;
display: flex;
justify-content: space-between;
margin-bottom: 10px;
.cardIcon {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
.anticon {
font-size: 24px;
color: white;
}
}
.badge {
background: #ff6b35;
color: white;
font-size: 11px;
font-weight: 500;
padding: 4px 8px;
border-radius: 12px;
z-index: 2;
box-shadow: 0 1px 4px rgba(255, 107, 53, 0.3);
height: 24px;
// 新功能标签样式
&[data-type="new"] {
background: #52c41a;
box-shadow: 0 1px 4px rgba(82, 196, 26, 0.3);
}
}
}
.cardInfo {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.cardTitle {
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
margin: 0 0 8px 0;
line-height: 1.3;
}
.cardDescription {
font-size: 14px;
color: #666;
line-height: 1.5;
margin: 0 0 12px 0;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
}
.cardAction {
display: flex;
justify-content: space-between;
color: #979797;
font-size: 12px;
font-weight: 500;
.arrow {
font-size: 14px;
transition: transform 0.3s ease;
}
&:hover .arrow {
transform: translateX(4px);
}
}
}
}
}
}
}
.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;
// 页面底部
.footer {
text-align: center;
margin-top: 60px;
padding: 24px 0;
&: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;
}
}
}
p {
font-size: 16px;
color: #666;
margin: 0;
font-weight: 500;
}
}
}
@@ -129,16 +176,65 @@
// 响应式设计
@media (max-width: 1200px) {
.powerCenter {
.header {
flex-direction: column;
gap: 16px;
align-items: flex-start;
padding: 32px 24px;
.headerRight {
width: 100%;
.categorySection {
.categoryHeader {
.categoryIcon {
width: 44px;
height: 44px;
.tabs {
flex-wrap: wrap;
.anticon {
font-size: 22px;
}
}
.categoryInfo {
.categoryTitle {
font-size: 22px;
}
}
}
.featureCards {
.featureCard {
height: 180px;
width: 260px;
padding: 20px;
.cardContent {
.cardIcon {
width: 44px;
height: 44px;
margin: 18px auto 14px;
.anticon {
font-size: 22px;
}
}
.cardInfo {
padding: 0 14px 14px;
.cardTitle {
font-size: 15px;
margin-bottom: 6px;
}
.cardDescription {
font-size: 11px;
margin-bottom: 10px;
}
.cardAction {
font-size: 11px;
.arrow {
font-size: 12px;
}
}
}
}
}
}
}
@@ -147,91 +243,89 @@
@media (max-width: 768px) {
.powerCenter {
padding: 16px;
padding: 24px 16px;
.header {
padding: 16px;
.categorySection {
margin-bottom: 32px;
.headerLeft {
.title {
font-size: 24px;
.categoryHeader {
.categoryIcon {
width: 40px;
height: 40px;
.anticon {
font-size: 20px;
}
}
}
}
.cardGrid {
.featureCard {
height: 160px;
.cardContent {
.iconWrapper {
width: 48px;
height: 48px;
.icon {
font-size: 20px;
}
.categoryInfo {
.categoryTitle {
font-size: 20px;
}
.cardInfo {
.cardTitle {
font-size: 14px;
.categoryCount {
font-size: 12px;
padding: 3px 10px;
}
}
}
.featureCards {
.featureCard {
height: 160px;
width: 240px;
padding: 16px;
.cardContent {
.badge {
top: 10px;
right: 10px;
font-size: 10px;
padding: 3px 6px;
}
.cardDescription {
font-size: 11px;
.cardIcon {
width: 40px;
height: 40px;
margin: 16px auto 12px;
.anticon {
font-size: 20px;
}
}
.cardInfo {
padding: 0 12px 12px;
.cardTitle {
font-size: 14px;
margin-bottom: 6px;
}
.cardDescription {
font-size: 10px;
margin-bottom: 8px;
}
.cardAction {
font-size: 10px;
.arrow {
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);
.footer {
margin-top: 40px;
p {
font-size: 14px;
}
}
}
}

View File

@@ -1,12 +1,10 @@
import React, { useState, useMemo } from "react";
import { Card, Row, Col, Button, Space } from "antd";
import React from "react";
import { useNavigate } from "react-router-dom";
import { featureCards, tabItems, FeatureCard } from "./index.data";
import styles from "./index.module.scss";
import { FeatureCard, featureCategories } from "./index.data.tsx";
const PowerCenter: React.FC = () => {
const navigate = useNavigate();
const [activeTab, setActiveTab] = useState("all");
const handleCardClick = (card: FeatureCard) => {
if (card.path) {
@@ -14,87 +12,75 @@ const PowerCenter: React.FC = () => {
}
};
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>
{/* 功能分类展示 */}
{featureCategories.map(category => (
<div key={category.id} className={styles.categorySection}>
{/* 分类标题 */}
<div className={styles.categoryHeader}>
<div
className={styles.categoryIcon}
style={{ backgroundColor: category.color }}
>
{category.icon}
</div>
<div className={styles.categoryInfo}>
<h2 className={styles.categoryTitle}>{category.title}</h2>
<span className={styles.categoryCount}>
{category.count}
</span>
</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
{/* 功能卡片 */}
<div className={styles.featureCards}>
{category.features.map(card => (
<div
key={card.id}
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 className={styles.cardHeader}>
<div
className={styles.cardIcon}
style={{ backgroundColor: card.color }}
>
{card.icon}
</div>
{/* 热门/新功能标签 */}
{(card.isHot || card.isNew) && (
<div
className={styles.badge}
data-type={card.isNew ? "new" : "hot"}
>
{card.isHot ? "热门" : "新功能"}
</div>
)}
{/* 功能图标 */}
</div>
{/* 功能信息 */}
<div className={styles.cardInfo}>
<h3 className={styles.cardTitle}>
{card.title}
{card.isNew && (
<span className={styles.newBadge}></span>
)}
</h3>
<h3 className={styles.cardTitle}>{card.title}</h3>
<p className={styles.cardDescription}>{card.description}</p>
<div className={styles.cardAction}>
<span></span>
<span className={styles.arrow}></span>
</div>
</div>
</div>
</Card>
</Col>
))}
</Row>
</div>
))}
</div>
</div>
))}
{/* 页面底部 */}
<div className={styles.footer}>
<p> AI私域营销系统 - </p>
</div>
</div>
);

View File

@@ -11,12 +11,17 @@ import CommunicationRecord from "@/pages/pc/ckbox/powerCenter/communication-reco
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";
import CommonConfig from "@/pages/pc/ckbox/commonConfig";
const ckboxRoutes = [
{
path: "/pc",
element: <CkboxPage />,
auth: true,
children: [
{
path: "commonConfig",
element: <CommonConfig />,
},
{
path: "dashboard",
element: <Dashboard />,