From b128410346dfc2d3e0fc598a1060615e6807477b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=E9=87=8C=E7=9A=84=E6=B0=B8?= =?UTF-8?q?=E5=B9=B3?= Date: Sat, 19 Jul 2025 11:40:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9C=AC=E6=AC=A1=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E5=A6=82=E4=B8=8B=20?= =?UTF-8?q?=E5=AE=9A=E7=89=88=E6=9C=AC=EF=BC=8C=E5=87=86=E5=A4=87=E5=A4=A7?= =?UTF-8?q?=E6=89=B9=E9=87=8F=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nkebao/ANTD_MOBILE_ICONS.md | 269 +++++++++++ nkebao/ROUTE_MIGRATION.md | 140 ++++++ nkebao/WORKSPACE_MIGRATION.md | 159 ++++++ .../src/components/MeauMobile/MeauMoible.tsx | 4 +- nkebao/src/components/PlaceholderPage.tsx | 56 +++ nkebao/src/pages/About.tsx | 7 - .../pages/contact-import/ContactImport.tsx | 14 + nkebao/src/pages/content/Content.tsx | 10 + nkebao/src/pages/content/NewContent.tsx | 8 + nkebao/src/pages/content/materials/List.tsx | 10 + nkebao/src/pages/content/materials/New.tsx | 8 + nkebao/src/pages/devices/DeviceDetail.tsx | 30 ++ nkebao/src/pages/devices/Devices.tsx | 37 ++ nkebao/src/pages/login/login.module.scss | 457 ++---------------- nkebao/src/pages/login/login.tsx | 335 ++----------- nkebao/src/pages/orders/Orders.tsx | 8 + nkebao/src/pages/plans/PlanDetail.tsx | 8 + nkebao/src/pages/plans/Plans.tsx | 10 + nkebao/src/pages/profile/Profile.tsx | 8 + nkebao/src/pages/scenarios/ScenarioList.tsx | 8 + nkebao/src/pages/scenarios/Scenarios.tsx | 10 + nkebao/src/pages/scenarios/new/page.tsx | 8 + nkebao/src/pages/scene/api.ts | 28 +- nkebao/src/pages/scene/index.module.scss | 358 +++++++++++--- nkebao/src/pages/scene/index.tsx | 272 ++++++----- nkebao/src/pages/traffic-pool/TrafficPool.tsx | 10 + .../pages/traffic-pool/TrafficPoolDetail.tsx | 8 + .../wechat-accounts/WechatAccountDetail.tsx | 30 ++ .../pages/wechat-accounts/WechatAccounts.tsx | 37 ++ .../src/pages/workspace/Workspace.module.scss | 185 +++++++ nkebao/src/pages/workspace/Workspace.tsx | 254 ++++++++++ .../workspace/ai-assistant/AIAssistant.tsx | 8 + .../pages/workspace/auto-group/AutoGroup.tsx | 10 + .../src/pages/workspace/auto-group/Detail.tsx | 8 + .../pages/workspace/auto-like/AutoLike.tsx | 38 ++ .../workspace/auto-like/AutoLikeDetail.tsx | 8 + .../pages/workspace/auto-like/NewAutoLike.tsx | 30 ++ .../pages/workspace/group-push/GroupPush.tsx | 10 + nkebao/src/pages/workspace/group-push/new.tsx | 8 + .../src/pages/{work => workspace/main}/api.ts | 0 .../main}/index.module.scss | 0 .../pages/{work => workspace/main}/index.tsx | 0 .../pages/workspace/moments-sync/Detail.tsx | 8 + .../workspace/moments-sync/MomentsSync.tsx | 14 + .../src/pages/workspace/moments-sync/new.tsx | 8 + .../workspace/traffic-distribution/Detail.tsx | 8 + .../traffic-distribution/NewDistribution.tsx | 8 + .../TrafficDistribution.tsx | 10 + nkebao/src/router/config.ts | 171 +++++++ nkebao/src/router/module/auth.tsx | 11 + nkebao/src/router/module/content.tsx | 39 ++ nkebao/src/router/module/devices.tsx | 17 + nkebao/src/router/module/index.tsx | 11 +- nkebao/src/router/module/other.tsx | 40 ++ nkebao/src/router/module/scenarios.tsx | 38 ++ nkebao/src/router/module/traffic-pool.tsx | 17 + nkebao/src/router/module/wechat-accounts.tsx | 17 + nkebao/src/router/module/workspace.tsx | 145 ++++++ nkebao/src/styles/global.scss | 11 +- 59 files changed, 2565 insertions(+), 914 deletions(-) create mode 100644 nkebao/ANTD_MOBILE_ICONS.md create mode 100644 nkebao/ROUTE_MIGRATION.md create mode 100644 nkebao/WORKSPACE_MIGRATION.md create mode 100644 nkebao/src/components/PlaceholderPage.tsx delete mode 100644 nkebao/src/pages/About.tsx create mode 100644 nkebao/src/pages/contact-import/ContactImport.tsx create mode 100644 nkebao/src/pages/content/Content.tsx create mode 100644 nkebao/src/pages/content/NewContent.tsx create mode 100644 nkebao/src/pages/content/materials/List.tsx create mode 100644 nkebao/src/pages/content/materials/New.tsx create mode 100644 nkebao/src/pages/devices/DeviceDetail.tsx create mode 100644 nkebao/src/pages/devices/Devices.tsx create mode 100644 nkebao/src/pages/orders/Orders.tsx create mode 100644 nkebao/src/pages/plans/PlanDetail.tsx create mode 100644 nkebao/src/pages/plans/Plans.tsx create mode 100644 nkebao/src/pages/profile/Profile.tsx create mode 100644 nkebao/src/pages/scenarios/ScenarioList.tsx create mode 100644 nkebao/src/pages/scenarios/Scenarios.tsx create mode 100644 nkebao/src/pages/scenarios/new/page.tsx create mode 100644 nkebao/src/pages/traffic-pool/TrafficPool.tsx create mode 100644 nkebao/src/pages/traffic-pool/TrafficPoolDetail.tsx create mode 100644 nkebao/src/pages/wechat-accounts/WechatAccountDetail.tsx create mode 100644 nkebao/src/pages/wechat-accounts/WechatAccounts.tsx create mode 100644 nkebao/src/pages/workspace/Workspace.module.scss create mode 100644 nkebao/src/pages/workspace/Workspace.tsx create mode 100644 nkebao/src/pages/workspace/ai-assistant/AIAssistant.tsx create mode 100644 nkebao/src/pages/workspace/auto-group/AutoGroup.tsx create mode 100644 nkebao/src/pages/workspace/auto-group/Detail.tsx create mode 100644 nkebao/src/pages/workspace/auto-like/AutoLike.tsx create mode 100644 nkebao/src/pages/workspace/auto-like/AutoLikeDetail.tsx create mode 100644 nkebao/src/pages/workspace/auto-like/NewAutoLike.tsx create mode 100644 nkebao/src/pages/workspace/group-push/GroupPush.tsx create mode 100644 nkebao/src/pages/workspace/group-push/new.tsx rename nkebao/src/pages/{work => workspace/main}/api.ts (100%) rename nkebao/src/pages/{work => workspace/main}/index.module.scss (100%) rename nkebao/src/pages/{work => workspace/main}/index.tsx (100%) create mode 100644 nkebao/src/pages/workspace/moments-sync/Detail.tsx create mode 100644 nkebao/src/pages/workspace/moments-sync/MomentsSync.tsx create mode 100644 nkebao/src/pages/workspace/moments-sync/new.tsx create mode 100644 nkebao/src/pages/workspace/traffic-distribution/Detail.tsx create mode 100644 nkebao/src/pages/workspace/traffic-distribution/NewDistribution.tsx create mode 100644 nkebao/src/pages/workspace/traffic-distribution/TrafficDistribution.tsx create mode 100644 nkebao/src/router/config.ts create mode 100644 nkebao/src/router/module/auth.tsx create mode 100644 nkebao/src/router/module/content.tsx create mode 100644 nkebao/src/router/module/devices.tsx create mode 100644 nkebao/src/router/module/other.tsx create mode 100644 nkebao/src/router/module/scenarios.tsx create mode 100644 nkebao/src/router/module/traffic-pool.tsx create mode 100644 nkebao/src/router/module/wechat-accounts.tsx create mode 100644 nkebao/src/router/module/workspace.tsx diff --git a/nkebao/ANTD_MOBILE_ICONS.md b/nkebao/ANTD_MOBILE_ICONS.md new file mode 100644 index 00000000..4c03bba6 --- /dev/null +++ b/nkebao/ANTD_MOBILE_ICONS.md @@ -0,0 +1,269 @@ +# Ant Design Mobile 图标完整列表 + +## 📋 图标分类 + +### 🔗 基础图标 (Outline) +- `AddOutline` - 添加 +- `AppOutline` - 应用 +- `ArrowDownOutline` - 向下箭头 +- `ArrowLeftOutline` - 向左箭头 +- `ArrowRightOutline` - 向右箭头 +- `ArrowUpOutline` - 向上箭头 +- `AudioOutline` - 音频 +- `BarChartOutline` - 柱状图 +- `BellOutline` - 铃铛 +- `BookOutline` - 书本 +- `CalendarOutline` - 日历 +- `CameraOutline` - 相机 +- `CheckOutline` - 勾选 +- `ClockCircleOutline` - 时钟 +- `CloseOutline` - 关闭 +- `DeleteOutline` - 删除 +- `DownlandOutline` - 下载 +- `EditSOutline` - 编辑 +- `EllipsisOutline` - 省略号 +- `EyeOutline` - 眼睛 +- `FileOutline` - 文件 +- `FilterOutline` - 筛选 +- `FireOutline` - 火焰 +- `FlagOutline` - 旗帜 +- `FolderOutline` - 文件夹 +- `GiftOutline` - 礼物 +- `HeartOutline` - 心形 +- `HomeOutline` - 首页 +- `ImageOutline` - 图片 +- `LeftOutline` - 左箭头 +- `LikeOutline` - 点赞 +- `LinkOutline` - 链接 +- `LocationOutline` - 位置 +- `LockOutline` - 锁定 +- `MailOutline` - 邮件 +- `MessageOutline` - 消息 +- `MoreOutline` - 更多 +- `PayCircleOutline` - 支付 +- `PhoneOutline` - 电话 +- `PictureOutline` - 图片 +- `PlayOutline` - 播放 +- `PlusOutline` - 加号 +- `RightOutline` - 右箭头 +- `ScanOutline` - 扫描 +- `SearchOutline` - 搜索 +- `SendOutline` - 发送 +- `SettingOutline` - 设置 +- `ShareOutline` - 分享 +- `ShopbagOutline` - 购物袋 +- `StarOutline` - 星星 +- `TeamOutline` - 团队 +- `ThumbsUpOutline` - 点赞 +- `TimeOutline` - 时间 +- `UnlockOutline` - 解锁 +- `UserOutline` - 用户 +- `VideoOutline` - 视频 +- `VoiceOutline` - 语音 + +### 🎨 填充图标 (Fill) +- `AddCircleFill` - 添加圆形 +- `AppFill` - 应用填充 +- `AudioFill` - 音频填充 +- `BellFill` - 铃铛填充 +- `BookFill` - 书本填充 +- `CalendarFill` - 日历填充 +- `CameraFill` - 相机填充 +- `CheckCircleFill` - 勾选圆形 +- `ClockCircleFill` - 时钟圆形 +- `CloseCircleFill` - 关闭圆形 +- `DeleteFill` - 删除填充 +- `DownlandFill` - 下载填充 +- `EditSFill` - 编辑填充 +- `EyeFill` - 眼睛填充 +- `FileFill` - 文件填充 +- `FilterFill` - 筛选填充 +- `FireFill` - 火焰填充 +- `FlagFill` - 旗帜填充 +- `FolderFill` - 文件夹填充 +- `GiftFill` - 礼物填充 +- `HeartFill` - 心形填充 +- `HomeFill` - 首页填充 +- `ImageFill` - 图片填充 +- `LeftFill` - 左箭头填充 +- `LikeFill` - 点赞填充 +- `LinkFill` - 链接填充 +- `LocationFill` - 位置填充 +- `LockFill` - 锁定填充 +- `MailFill` - 邮件填充 +- `MessageFill` - 消息填充 +- `MoreFill` - 更多填充 +- `PayCircleFill` - 支付圆形 +- `PhoneFill` - 电话填充 +- `PictureFill` - 图片填充 +- `PlayFill` - 播放填充 +- `PlusCircleFill` - 加号圆形 +- `RightFill` - 右箭头填充 +- `ScanFill` - 扫描填充 +- `SearchFill` - 搜索填充 +- `SendFill` - 发送填充 +- `SettingFill` - 设置填充 +- `ShareFill` - 分享填充 +- `ShopbagFill` - 购物袋填充 +- `StarFill` - 星星填充 +- `TeamFill` - 团队填充 +- `ThumbsUpFill` - 点赞填充 +- `TimeFill` - 时间填充 +- `UnlockFill` - 解锁填充 +- `UserFill` - 用户填充 +- `VideoFill` - 视频填充 +- `VoiceFill` - 语音填充 + +### 📊 图表图标 +- `BarChartOutline` - 柱状图 +- `LineChartOutline` - 折线图 +- `PieOutline` - 饼图 +- `AreaOutline` - 面积图 +- `RadarOutline` - 雷达图 +- `ScatterOutline` - 散点图 + +### 🔧 功能图标 +- `AddOutline` - 添加 +- `DeleteOutline` - 删除 +- `EditSOutline` - 编辑 +- `SearchOutline` - 搜索 +- `FilterOutline` - 筛选 +- `SettingOutline` - 设置 +- `MoreOutline` - 更多 +- `CloseOutline` - 关闭 +- `CheckOutline` - 勾选 + +### 📱 通信图标 +- `MessageOutline` - 消息 +- `PhoneOutline` - 电话 +- `MailOutline` - 邮件 +- `SendOutline` - 发送 +- `VoiceOutline` - 语音 +- `VideoOutline` - 视频 + +### 👥 用户图标 +- `UserOutline` - 用户 +- `TeamOutline` - 团队 +- `HeartOutline` - 心形 +- `LikeOutline` - 点赞 +- `ThumbsUpOutline` - 点赞 + +### 🛍️ 商业图标 +- `ShopbagOutline` - 购物袋 +- `PayCircleOutline` - 支付 +- `GiftOutline` - 礼物 +- `StarOutline` - 星星 + +### 📁 文件图标 +- `FileOutline` - 文件 +- `FolderOutline` - 文件夹 +- `ImageOutline` - 图片 +- `PictureOutline` - 图片 +- `CameraOutline` - 相机 + +### 🎵 媒体图标 +- `AudioOutline` - 音频 +- `VideoOutline` - 视频 +- `PlayOutline` - 播放 +- `VoiceOutline` - 语音 + +### 📅 时间图标 +- `CalendarOutline` - 日历 +- `ClockCircleOutline` - 时钟 +- `TimeOutline` - 时间 + +### 🔒 安全图标 +- `LockOutline` - 锁定 +- `UnlockOutline` - 解锁 +- `EyeOutline` - 眼睛 + +### 📍 位置图标 +- `LocationOutline` - 位置 +- `FlagOutline` - 旗帜 + +### 🔗 导航图标 +- `ArrowUpOutline` - 向上箭头 +- `ArrowDownOutline` - 向下箭头 +- `ArrowLeftOutline` - 向左箭头 +- `ArrowRightOutline` - 向右箭头 +- `LeftOutline` - 左箭头 +- `RightOutline` - 右箭头 + +## 🎨 使用示例 + +### 基础用法 +```tsx +import { AddOutline, UserOutline, SettingOutline } from 'antd-mobile-icons'; + +// 在组件中使用 + + + +``` + +### 自定义样式 +```tsx +import { HeartOutline } from 'antd-mobile-icons'; + +// 自定义颜色和大小 + +``` + +### 在项目中的使用 +```tsx +// 工作台页面示例 +const features = [ + { + icon: , + name: "自动点赞" + }, + { + icon: , + name: "AI对话助手" + }, + { + icon: , + name: "AI数据分析" + } +]; +``` + +## 📝 注意事项 + +1. **图标命名规则**: 所有图标都以 `Outline` 或 `Fill` 结尾 +2. **导入方式**: 从 `antd-mobile-icons` 包中导入 +3. **样式定制**: 可以通过 `style` 属性自定义颜色、大小等 +4. **响应式**: 图标支持响应式设计,可以配合 CSS 媒体查询使用 +5. **可访问性**: 图标支持 `aria-label` 等无障碍属性 + +## 🔗 相关资源 + +- [Ant Design Mobile 官方文档](https://mobile.ant.design/) +- [图标组件文档](https://mobile.ant.design/zh/components/icon) +- [图标库 GitHub](https://github.com/ant-design/ant-design-mobile) + +## 📊 项目中已使用的图标 + +### 工作台页面 +- `ThumbsUpOutline` - 自动点赞 +- `MessageOutline` - AI对话助手 +- `SendOutline` - 群消息推送 +- `TeamOutline` - 自动建群 +- `ShareOutline` - 流量分发 +- `AppOutline` - AI策略优化 +- `BarChartOutline` - AI数据分析 +- `LineChartOutline` - AI销售预测 +- `ClockCircleOutline` - 朋友圈同步 + +### 底部导航 +- `AppOutline` - 首页 +- `ShopbagOutline` - 场景获客 +- `PieOutline` - 工作台 +- `UserOutline` - 我的 + +### 其他页面 +- `AddOutline` - 添加按钮 +- `UserAddOutline` - 用户添加 +- `BellOutline` - 通知 +- `LoopOutline` - 循环/同步 +- `TravelOutline` - 旅行/任务 \ No newline at end of file diff --git a/nkebao/ROUTE_MIGRATION.md b/nkebao/ROUTE_MIGRATION.md new file mode 100644 index 00000000..9f179483 --- /dev/null +++ b/nkebao/ROUTE_MIGRATION.md @@ -0,0 +1,140 @@ +# 路由迁移总结 + +## 📋 迁移概述 + +已成功将旧项目 @Cunkebao 的路由结构迁移到新项目 @nkebao,并进行了合理的文件拆分和归类。 + +## 🗂️ 路由模块结构 + +### 1. 基础路由模块 (`auth.tsx`) +- `/login` - 登录页面 + +### 2. 设备管理模块 (`devices.tsx`) +- `/devices` - 设备列表 +- `/devices/:id` - 设备详情 + +### 3. 微信号管理模块 (`wechat-accounts.tsx`) +- `/wechat-accounts` - 微信号列表 +- `/wechat-accounts/:id` - 微信号详情 + +### 4. 工作台模块 (`workspace.tsx`) +- `/workspace` - 工作台主页 +- `/workspace/auto-like` - 自动点赞 +- `/workspace/auto-like/new` - 新建自动点赞 +- `/workspace/auto-like/:id` - 自动点赞详情 +- `/workspace/auto-like/:id/edit` - 编辑自动点赞 +- `/workspace/auto-group` - 自动分组 +- `/workspace/auto-group/:id` - 自动分组详情 +- `/workspace/group-push` - 群发推送 +- `/workspace/group-push/new` - 新建群发推送 +- `/workspace/group-push/:id` - 群发推送详情 +- `/workspace/group-push/:id/edit` - 编辑群发推送 +- `/workspace/moments-sync` - 朋友圈同步 +- `/workspace/moments-sync/new` - 新建朋友圈同步 +- `/workspace/moments-sync/:id` - 朋友圈同步详情 +- `/workspace/moments-sync/edit/:id` - 编辑朋友圈同步 +- `/workspace/ai-assistant` - AI助手 +- `/workspace/traffic-distribution` - 流量分发 +- `/workspace/traffic-distribution/new` - 新建流量分发 +- `/workspace/traffic-distribution/edit/:id` - 编辑流量分发 +- `/workspace/traffic-distribution/:id` - 流量分发详情 + +### 5. 场景管理模块 (`scenarios.tsx`) +- `/scenarios` - 场景列表 +- `/scenarios/new` - 新建场景 +- `/scenarios/new/:scenarioId` - 新建场景(带场景ID) +- `/scenarios/edit/:planId` - 编辑场景 +- `/scenarios/list/:scenarioId/:scenarioName` - 场景列表详情 + +### 6. 内容管理模块 (`content.tsx`) +- `/content` - 内容管理 +- `/content/new` - 新建内容 +- `/content/edit/:id` - 编辑内容 +- `/content/materials/:id` - 素材管理 +- `/content/materials/new/:id` - 新建素材 +- `/content/materials/edit/:id/:materialId` - 编辑素材 + +### 7. 流量池模块 (`traffic-pool.tsx`) +- `/traffic-pool` - 流量池列表 +- `/traffic-pool/:id` - 流量池详情 + +### 8. 其他功能模块 (`other.tsx`) +- `/profile` - 个人中心 +- `/plans` - 计划管理 +- `/plans/:planId` - 计划详情 +- `/orders` - 订单管理 +- `/contact-import` - 联系人导入 + +## 🔧 技术实现 + +### 路由配置 +- 使用 React Router DOM v6 +- 支持动态路由参数 +- 统一的权限控制 +- 模块化路由管理 + +### 权限控制 +- 每个路由都配置了 `auth` 属性 +- 支持角色权限控制 +- 自动权限检查 + +### 组件结构 +- 使用 Layout 组件统一布局 +- 使用 MeauMobile 组件作为底部导航 +- 创建了 PlaceholderPage 通用占位组件 + +## 📁 文件结构 + +``` +src/ +├── router/ +│ ├── module/ +│ │ ├── index.tsx # 主路由文件 +│ │ ├── auth.tsx # 认证路由 +│ │ ├── devices.tsx # 设备管理路由 +│ │ ├── wechat-accounts.tsx # 微信号管理路由 +│ │ ├── workspace.tsx # 工作台路由 +│ │ ├── scenarios.tsx # 场景管理路由 +│ │ ├── content.tsx # 内容管理路由 +│ │ ├── traffic-pool.tsx # 流量池路由 +│ │ └── other.tsx # 其他功能路由 +│ ├── index.tsx # 路由入口 +│ ├── permissionRoute.tsx # 权限路由组件 +│ └── config.ts # 路由配置 +├── pages/ +│ ├── login/ # 登录页面 +│ ├── devices/ # 设备管理页面 +│ ├── wechat-accounts/ # 微信号管理页面 +│ ├── workspace/ # 工作台页面 +│ ├── scenarios/ # 场景管理页面 +│ ├── content/ # 内容管理页面 +│ ├── traffic-pool/ # 流量池页面 +│ ├── profile/ # 个人中心页面 +│ ├── plans/ # 计划管理页面 +│ ├── orders/ # 订单管理页面 +│ └── contact-import/ # 联系人导入页面 +└── components/ + └── PlaceholderPage.tsx # 通用占位页面组件 +``` + +## 🎯 主要特性 + +1. **模块化设计**: 按功能模块拆分路由,便于维护 +2. **权限控制**: 统一的权限管理机制 +3. **类型安全**: 完整的 TypeScript 类型定义 +4. **响应式设计**: 适配移动端和桌面端 +5. **代码复用**: 使用通用组件减少重复代码 + +## 🚀 下一步计划 + +1. 实现具体的页面功能 +2. 完善权限控制逻辑 +3. 添加路由懒加载 +4. 优化页面性能 +5. 添加路由守卫 + +## 📝 注意事项 + +- 所有页面目前都是占位页面,需要根据业务需求逐步实现 +- 路由权限控制需要根据实际业务逻辑调整 +- 建议按照模块优先级逐步开发页面功能 \ No newline at end of file diff --git a/nkebao/WORKSPACE_MIGRATION.md b/nkebao/WORKSPACE_MIGRATION.md new file mode 100644 index 00000000..436747bf --- /dev/null +++ b/nkebao/WORKSPACE_MIGRATION.md @@ -0,0 +1,159 @@ +# 工作台页面迁移总结 + +## 📋 迁移概述 + +已成功将旧项目 @Cunkebao 的工作台页面迁移到新项目 @nkebao,并进行了技术栈转换和样式优化。 + +## 🔄 技术栈转换 + +### 旧项目技术栈 +- React + TypeScript +- Lucide React 图标库 +- Tailwind CSS +- React Router DOM v6 +- 自定义UI组件库 + +### 新项目技术栈 +- React + TypeScript +- Ant Design Mobile +- SCSS Modules +- React Router DOM v6 +- 统一的Layout组件 + +## 📱 页面结构 + +### 主要功能模块 + +1. **任务统计卡片** + - 总任务数(带进度条) + - 今日任务(带活跃度指标) + +2. **常用功能** + - 自动点赞(New标签) + - 朋友圈同步 + - 群消息推送 + - 自动建群 + - 流量分发 + - AI对话助手(New标签) + +3. **AI智能助手** + - AI数据分析(New标签) + - AI策略优化(New标签) + - AI销售预测 + +## 🎨 设计优化 + +### 视觉改进 +- 使用Ant Design Mobile组件,保持移动端一致性 +- 采用SCSS Modules进行样式管理 +- 统一的颜色主题和间距规范 +- 响应式设计,适配不同屏幕尺寸 + +### 交互优化 +- 卡片悬停效果 +- 统一的图标样式和颜色 +- 清晰的层级结构 +- 流畅的页面跳转 + +## 📁 文件结构 + +``` +src/pages/workspace/ +├── Workspace.tsx # 工作台主页 +├── Workspace.module.scss # 工作台样式 +├── auto-like/ # 自动点赞模块 +├── auto-group/ # 自动分组模块 +├── group-push/ # 群发推送模块 +├── moments-sync/ # 朋友圈同步模块 +├── ai-assistant/ # AI助手模块 +└── traffic-distribution/ # 流量分发模块 +``` + +## 🔗 路由配置 + +### 主要路由 +- `/workspace` - 工作台主页 +- `/workspace/auto-like` - 自动点赞 +- `/workspace/group-push` - 群发推送 +- `/workspace/moments-sync` - 朋友圈同步 +- `/workspace/auto-group` - 自动分组 +- `/workspace/traffic-distribution` - 流量分发 +- `/workspace/ai-assistant` - AI助手 + +### AI功能路由 +- `/workspace/ai-analyzer` - AI数据分析 +- `/workspace/ai-strategy` - AI策略优化 +- `/workspace/ai-forecast` - AI销售预测 + +## 🎯 功能特性 + +### 数据展示 +- 实时任务统计 +- 进度条可视化 +- 活跃度指标 +- 功能分类展示 + +### 导航优化 +- 底部导航集成 +- 路由自动激活 +- 页面跳转优化 +- 返回按钮处理 + +### 用户体验 +- 加载状态处理 +- 错误边界处理 +- 响应式布局 +- 触摸友好设计 + +## 🔧 技术实现 + +### 组件化设计 +- 使用Layout组件统一布局 +- 复用PlaceholderPage组件 +- 模块化的功能卡片 +- 统一的样式规范 + +### 状态管理 +- 模拟数据展示 +- 路由状态同步 +- 组件生命周期管理 +- 性能优化 + +### 样式系统 +- SCSS Modules避免样式冲突 +- CSS变量统一主题 +- 响应式断点设计 +- 移动端优化 + +## 🚀 下一步计划 + +1. **数据集成** + - 连接真实API接口 + - 实现数据获取和更新 + - 添加加载状态 + - 错误处理机制 + +2. **功能完善** + - 实现具体功能页面 + - 添加表单验证 + - 完善交互逻辑 + - 优化用户体验 + +3. **性能优化** + - 路由懒加载 + - 组件代码分割 + - 图片资源优化 + - 缓存策略 + +4. **测试完善** + - 单元测试 + - 集成测试 + - 端到端测试 + - 性能测试 + +## 📝 注意事项 + +- 所有功能页面目前使用占位组件 +- 需要根据实际业务需求调整数据展示 +- 建议按照用户使用频率优先开发核心功能 +- 注意保持与整体设计风格的一致性 \ No newline at end of file diff --git a/nkebao/src/components/MeauMobile/MeauMoible.tsx b/nkebao/src/components/MeauMobile/MeauMoible.tsx index 4fe432f8..52a71d20 100644 --- a/nkebao/src/components/MeauMobile/MeauMoible.tsx +++ b/nkebao/src/components/MeauMobile/MeauMoible.tsx @@ -25,7 +25,7 @@ const tabs = [ key: "work", title: "工作台", icon: , - path: "/work", + path: "/workspace", }, { key: "mine", @@ -36,7 +36,7 @@ const tabs = [ ]; // 需要展示菜单的路由白名单(可根据实际业务调整) -const menuPaths = ["/", "/scene", "/work", "/mine"]; +const menuPaths = ["/", "/scene", "/workspace", "/mine"]; const MeauMobile: React.FC = () => { const location = useLocation(); diff --git a/nkebao/src/components/PlaceholderPage.tsx b/nkebao/src/components/PlaceholderPage.tsx new file mode 100644 index 00000000..1e5f87d7 --- /dev/null +++ b/nkebao/src/components/PlaceholderPage.tsx @@ -0,0 +1,56 @@ +import React from "react"; +import { NavBar, Button } from "antd-mobile"; +import { AddOutline } from "antd-mobile-icons"; +import Layout from "@/components/Layout/Layout"; +import MeauMobile from "@/components/MeauMobile/MeauMoible"; + +interface PlaceholderPageProps { + title: string; + showBack?: boolean; + showAddButton?: boolean; + addButtonText?: string; + showFooter?: boolean; +} + +const PlaceholderPage: React.FC = ({ + title, + showBack = true, + showAddButton = false, + addButtonText = "新建", + showFooter = true, +}) => { + return ( + window.history.back() : undefined} + left={ +
+ {title} +
+ } + right={ + showAddButton ? ( + + ) : undefined + } + /> + } + footer={showFooter ? : undefined} + > +
+

{title}页面

+

此页面正在开发中...

+
+
+ ); +}; + +export default PlaceholderPage; diff --git a/nkebao/src/pages/About.tsx b/nkebao/src/pages/About.tsx deleted file mode 100644 index 370fdfe2..00000000 --- a/nkebao/src/pages/About.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; - -const About: React.FC = () => { - return

关于 About

; -}; - -export default About; diff --git a/nkebao/src/pages/contact-import/ContactImport.tsx b/nkebao/src/pages/contact-import/ContactImport.tsx new file mode 100644 index 00000000..9d03b6b2 --- /dev/null +++ b/nkebao/src/pages/contact-import/ContactImport.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const ContactImport: React.FC = () => { + return ( + + ); +}; + +export default ContactImport; diff --git a/nkebao/src/pages/content/Content.tsx b/nkebao/src/pages/content/Content.tsx new file mode 100644 index 00000000..55e68abd --- /dev/null +++ b/nkebao/src/pages/content/Content.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const Content: React.FC = () => { + return ( + + ); +}; + +export default Content; diff --git a/nkebao/src/pages/content/NewContent.tsx b/nkebao/src/pages/content/NewContent.tsx new file mode 100644 index 00000000..3bd82288 --- /dev/null +++ b/nkebao/src/pages/content/NewContent.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const NewContent: React.FC = () => { + return ; +}; + +export default NewContent; diff --git a/nkebao/src/pages/content/materials/List.tsx b/nkebao/src/pages/content/materials/List.tsx new file mode 100644 index 00000000..e11ae674 --- /dev/null +++ b/nkebao/src/pages/content/materials/List.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const Materials: React.FC = () => { + return ( + + ); +}; + +export default Materials; diff --git a/nkebao/src/pages/content/materials/New.tsx b/nkebao/src/pages/content/materials/New.tsx new file mode 100644 index 00000000..62afef95 --- /dev/null +++ b/nkebao/src/pages/content/materials/New.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const MaterialsNew: React.FC = () => { + return ; +}; + +export default MaterialsNew; diff --git a/nkebao/src/pages/devices/DeviceDetail.tsx b/nkebao/src/pages/devices/DeviceDetail.tsx new file mode 100644 index 00000000..69876d6e --- /dev/null +++ b/nkebao/src/pages/devices/DeviceDetail.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { NavBar } from "antd-mobile"; +import Layout from "@/components/Layout/Layout"; +import MeauMobile from "@/components/MeauMobile/MeauMoible"; + +const DeviceDetail: React.FC = () => { + return ( + window.history.back()} + > +
+ 设备详情 +
+ + } + footer={} + > +
+

设备详情页面

+

此页面正在开发中...

+
+
+ ); +}; + +export default DeviceDetail; diff --git a/nkebao/src/pages/devices/Devices.tsx b/nkebao/src/pages/devices/Devices.tsx new file mode 100644 index 00000000..66895d54 --- /dev/null +++ b/nkebao/src/pages/devices/Devices.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { NavBar, Button } from "antd-mobile"; +import { AddOutline } from "antd-mobile-icons"; +import Layout from "@/components/Layout/Layout"; +import MeauMobile from "@/components/MeauMobile/MeauMoible"; + +const Devices: React.FC = () => { + return ( + + 设备管理 + + } + right={ + + } + /> + } + footer={} + > +
+

设备管理页面

+

此页面正在开发中...

+
+
+ ); +}; + +export default Devices; diff --git a/nkebao/src/pages/login/login.module.scss b/nkebao/src/pages/login/login.module.scss index a13baa52..21ebe95a 100644 --- a/nkebao/src/pages/login/login.module.scss +++ b/nkebao/src/pages/login/login.module.scss @@ -1,439 +1,52 @@ .login-page { min-height: 100vh; - background: var(--primary-gradient); + background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); +} + +.nav-title { + font-size: 18px; + font-weight: 600; + color: var(--primary-color); +} + +.login-content { + padding: 40px 20px; display: flex; + flex-direction: column; align-items: center; justify-content: center; - padding: 15px; - position: relative; - overflow: hidden; -} - -// 背景装饰 -.bg-decoration { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - pointer-events: none; - z-index: 0; -} - -.bg-circle { - position: absolute; - border-radius: 50%; - background: rgba(255, 255, 255, 0.1); - animation: float 6s ease-in-out infinite; - - &:nth-child(1) { - width: 200px; - height: 200px; - top: -100px; - right: -100px; - animation-delay: 0s; - } - - &:nth-child(2) { - width: 150px; - height: 150px; - bottom: -75px; - left: -75px; - animation-delay: 2s; - } - - &:nth-child(3) { - width: 100px; - height: 100px; - top: 50%; - right: 10%; - animation-delay: 4s; - } -} - -@keyframes float { - 0%, 100% { - transform: translateY(0px) rotate(0deg); - } - 50% { - transform: translateY(-20px) rotate(180deg); - } -} - -.login-container { - width: 100%; - max-width: 420px; - background: #ffffff; - backdrop-filter: blur(20px); - border-radius: 24px; - padding: 24px 20px; - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); - position: relative; - z-index: 1; - border: 1px solid rgba(255, 255, 255, 0.2); + min-height: calc(100vh - 60px); } .login-header { text-align: center; - margin-bottom: 24px; + margin-bottom: 40px; } -.logo-section { - display: flex; - align-items: center; - justify-content: center; - gap: 12px; - margin-bottom: 16px; -} - -.logo-icon { - width: 40px; - height: 40px; - background: var(--primary-gradient); - border-radius: 10px; - display: flex; - align-items: center; - justify-content: center; - color: white; - font-size: 20px; - box-shadow: 0 6px 12px var(--primary-shadow); -} - -.app-name { - font-size: 24px; - font-weight: 800; - background: var(--primary-gradient); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - margin: 0; -} - -.subtitle { - font-size: 13px; - color: #666; - margin: 0; -} - -.form-container { - margin-bottom: 20px; -} - -// 标签页样式 -.tab-container { - display: flex; - background: #f8f9fa; - border-radius: 10px; - padding: 3px; - margin-bottom: 24px; - position: relative; -} - -.tab-item { - flex: 1; - text-align: center; - padding: 10px 12px; - font-size: 13px; - font-weight: 500; - color: #666; - cursor: pointer; - border-radius: 7px; - transition: all 0.3s ease; - position: relative; - z-index: 2; - - &.active { - color: var(--primary-color); - font-weight: 600; - background: white; - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); - } -} - -.tab-indicator { - display: none; // 隐藏分割线指示器 -} - -// 表单样式 -.login-form { - :global(.adm-form) { - --adm-font-size-main: 14px; - } -} - -.input-group { - margin-bottom: 18px; -} - -.input-label { - display: block; - font-size: 13px; - font-weight: 600; - color: #333; - margin-bottom: 6px; -} - -.input-wrapper { - position: relative; - display: flex; - align-items: center; - background: #f8f9fa; - border: 2px solid transparent; - border-radius: 10px; - transition: all 0.3s ease; - - &:focus-within { - border-color: var(--primary-color); - background: white; - box-shadow: 0 0 0 3px var(--primary-shadow-light); - } -} - -.input-prefix { - padding: 0 12px; - color: #666; - font-size: 13px; - font-weight: 500; - border-right: 1px solid #e5e5e5; -} - -.phone-input, -.password-input, -.code-input { - flex: 1; - border: none !important; - background: transparent !important; - padding: 12px 14px !important; - font-size: 15px !important; - color: #333 !important; - - &::placeholder { - color: #999; - } - - &:focus { - box-shadow: none !important; - } -} - -.eye-icon { - padding: 0 12px; - color: #666; - cursor: pointer; - transition: color 0.3s ease; - - &:hover { - color: var(--primary-color); - } -} - -.send-code-btn { - padding: 6px 12px; - margin-right: 6px; - background: var(--primary-gradient); - color: white; - border: none; - border-radius: 6px; - font-size: 11px; - font-weight: 500; - cursor: pointer; - transition: all 0.3s ease; - - &:hover:not(.disabled) { - transform: translateY(-1px); - box-shadow: 0 3px 8px var(--primary-shadow); - } - - &.disabled { - background: #e5e5e5; - color: #999; - cursor: not-allowed; - transform: none; - box-shadow: none; - } -} - -.agreement-section { - margin-bottom: 24px; -} - -.agreement-checkbox { - display: flex; - align-items: center; - gap: 6px; - font-size: 12px; - color: #666; - line-height: 1.3; - white-space: nowrap; - - :global(.adm-checkbox) { - margin-top: 0; - flex-shrink: 0; - transform: scale(0.8); - } -} - -.agreement-text { - flex: 1; - display: flex; - align-items: center; - flex-wrap: nowrap; - white-space: nowrap; - overflow: visible; - text-overflow: clip; - font-size: 13px; -} - -.agreement-link { +.login-title { + font-size: 28px; + font-weight: 700; color: var(--primary-color); - cursor: pointer; - text-decoration: none; - white-space: nowrap; - font-size: 11px; - - &:hover { - text-decoration: underline; - } + margin-bottom: 8px; } -.login-btn { - height: 46px; - font-size: 15px; - font-weight: 600; - border-radius: 10px; +.login-subtitle { + font-size: 14px; + color: #666; + line-height: 1.4; +} + +.login-form { + width: 100%; + max-width: 320px; +} + +.login-button { + margin-top: 20px; + border-radius: 20px; background: var(--primary-gradient); border: none; - box-shadow: 0 6px 12px var(--primary-shadow); - transition: all 0.3s ease; - - &:hover:not(:disabled) { - transform: translateY(-1px); - box-shadow: 0 8px 16px var(--primary-shadow-dark); - } - - &:disabled { - background: #e5e5e5; - color: #999; - transform: none; - box-shadow: none; - } -} - -.divider { - position: relative; - text-align: center; - margin: 24px 0; - - &::before { - content: ''; - position: absolute; - top: 50%; - left: 0; - right: 0; - height: 1px; - background: #e5e5e5; - } - - span { - background: rgba(255, 255, 255, 0.95); - padding: 0 12px; - color: #999; - font-size: 11px; - font-weight: 500; - } -} - -.third-party-login { - display: flex; - justify-content: center; - gap: 20px; -} - -.third-party-item { - display: flex; - flex-direction: column; - align-items: center; - gap: 6px; - cursor: pointer; - padding: 12px; - border-radius: 10px; - transition: all 0.3s ease; - - &:hover { - background: #f8f9fa; - transform: translateY(-1px); - } - - span { - font-size: 11px; - color: #666; - font-weight: 500; - } -} - -.wechat-icon, -.apple-icon { - width: 36px; - height: 36px; - border-radius: 10px; - display: flex; - align-items: center; - justify-content: center; - color: white; - font-size: 18px; - transition: all 0.3s ease; -} - -.wechat-icon { - background: #07c160; - box-shadow: 0 3px 8px rgba(7, 193, 96, 0.3); - - &:hover { - box-shadow: 0 4px 12px rgba(7, 193, 96, 0.4); - } - - svg { - width: 20px; - height: 20px; - } -} - -.apple-icon { - background: #000; - box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3); - - &:hover { - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); - } - - svg { - width: 20px; - height: 20px; - } -} - -// 响应式设计 -@media (max-width: 480px) { - .login-container { - padding: 24px 20px; - margin: 0 12px; - } - - .app-name { - font-size: 22px; - } - - .third-party-login { - gap: 16px; - } - - .third-party-item { - padding: 10px; - } - - .wechat-icon, - .apple-icon { - width: 32px; - height: 32px; - } + box-shadow: 0 2px 8px var(--primary-shadow); + height: 44px; + font-weight: 600; } diff --git a/nkebao/src/pages/login/login.tsx b/nkebao/src/pages/login/login.tsx index f53ccc6d..c3013729 100644 --- a/nkebao/src/pages/login/login.tsx +++ b/nkebao/src/pages/login/login.tsx @@ -1,331 +1,64 @@ -import React, { useState, useEffect } from "react"; -import { useNavigate, useSearchParams } from "react-router-dom"; -import { Form, Input, Button, Toast, Tabs, Checkbox } from "antd-mobile"; -import { - EyeInvisibleOutline, - EyeOutline, - UserOutline, -} from "antd-mobile-icons"; -import { useUserStore } from "@/store/module/user"; -import { loginWithPassword, loginWithCode, sendVerificationCode } from "./api"; +import React from "react"; +import { NavBar, Form, Input, Button, Toast } from "antd-mobile"; +import Layout from "@/components/Layout/Layout"; import style from "./login.module.scss"; const Login: React.FC = () => { - const [form] = Form.useForm(); - const [activeTab, setActiveTab] = useState(1); // 1: 密码登录, 2: 验证码登录 - const [loading, setLoading] = useState(false); - const [countdown, setCountdown] = useState(0); - const [showPassword, setShowPassword] = useState(false); - const [agreeToTerms, setAgreeToTerms] = useState(false); - - const navigate = useNavigate(); - const [searchParams] = useSearchParams(); - const { login } = useUserStore(); - - // 倒计时效果 - useEffect(() => { - if (countdown > 0) { - const timer = setTimeout(() => setCountdown(countdown - 1), 1000); - return () => clearTimeout(timer); - } - }, [countdown]); - - // 检查URL是否为登录页面 - const isLoginPage = (url: string) => { - try { - const urlObj = new URL(url, window.location.origin); - return urlObj.pathname === "/login" || urlObj.pathname.endsWith("/login"); - } catch { - return false; - } - }; - - // 发送验证码 - const handleSendVerificationCode = async () => { - const account = form.getFieldValue("account"); - - if (!account) { - Toast.show({ content: "请输入手机号", position: "top" }); - return; - } - - // 手机号格式验证 - const phoneRegex = /^1[3-9]\d{9}$/; - if (!phoneRegex.test(account)) { - Toast.show({ content: "请输入正确的11位手机号", position: "top" }); - return; - } - - try { - setLoading(true); - await sendVerificationCode({ - mobile: account, - type: "login", - }); - - Toast.show({ content: "验证码已发送", position: "top" }); - setCountdown(60); - } catch (error) { - // 错误已在request中处理,这里不需要额外处理 - } finally { - setLoading(false); - } - }; - - // 登录处理 - const handleLogin = async (values: any) => { - if (!agreeToTerms) { - Toast.show({ content: "请同意用户协议和隐私政策", position: "top" }); - return; - } - - setLoading(true); - try { - // 添加typeId参数 - const loginParams = { - ...values, - typeId: activeTab as number, - }; - - let response; - if (activeTab === 1) { - response = await loginWithPassword(loginParams); - } else { - response = await loginWithCode(loginParams); - } - console.log(response, "response"); - - // 更新状态管理(token会自动存储到localStorage,用户信息存储在状态管理中) - login(response.token, response.member); - - Toast.show({ content: "登录成功", position: "top" }); - - // 跳转到首页或重定向URL - const returnUrl = searchParams.get("returnUrl"); - if (returnUrl) { - const decodedUrl = decodeURIComponent(returnUrl); - if (isLoginPage(decodedUrl)) { - navigate("/"); - } else { - window.location.href = decodedUrl; - } - } else { - navigate("/"); - } - } catch (error: any) { - // 错误已在request中处理,这里不需要额外处理 - } finally { - setLoading(false); - } - }; - - // 第三方登录处理 - const handleWechatLogin = () => { - Toast.show({ content: "微信登录功能开发中", position: "top" }); - }; - - const handleAppleLogin = () => { - Toast.show({ content: "Apple登录功能开发中", position: "top" }); + const onFinish = (values: any) => { + console.log("登录信息:", values); + Toast.show({ + content: "登录功能待实现", + position: "top", + }); }; return ( -
- {/* 背景装饰 */} -
-
-
-
-
+ +
+ +
登录
+
-
- {/* Logo和标题区域 */} -
-
-
- -
-

存客宝

-
-

登录您的账户继续使用

-
- - {/* 登录表单 */} -
- {/* 标签页切换 */} -
-
setActiveTab(1)} - > - 密码登录 -
-
setActiveTab(2)} - > - 验证码登录 -
-
+
+
+

存客宝

+

欢迎回来,请登录您的账户

- {/* 手机号输入 */} -
- +86 - -
+
- {/* 密码输入 */} - {activeTab === 1 && ( - -
- -
setShowPassword(!showPassword)} - > - {showPassword ? : } -
-
-
- )} + + + - {/* 验证码输入 */} - {activeTab === 2 && ( - -
- - -
-
- )} - - {/* 用户协议 */} -
- - - 我已阅读并同意 - - 《存客宝用户协议》 - - 和 - 《隐私政策》 - - -
- - {/* 登录按钮 */}
- - {/* 分割线 */} -
- 其他登录方式 -
- - {/* 第三方登录 */} -
-
-
- - - - -
- 微信 -
-
-
- - - -
- Apple -
-
-
+ ); }; diff --git a/nkebao/src/pages/orders/Orders.tsx b/nkebao/src/pages/orders/Orders.tsx new file mode 100644 index 00000000..daecccd2 --- /dev/null +++ b/nkebao/src/pages/orders/Orders.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const Orders: React.FC = () => { + return ; +}; + +export default Orders; diff --git a/nkebao/src/pages/plans/PlanDetail.tsx b/nkebao/src/pages/plans/PlanDetail.tsx new file mode 100644 index 00000000..1d2e8b08 --- /dev/null +++ b/nkebao/src/pages/plans/PlanDetail.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const PlanDetail: React.FC = () => { + return ; +}; + +export default PlanDetail; diff --git a/nkebao/src/pages/plans/Plans.tsx b/nkebao/src/pages/plans/Plans.tsx new file mode 100644 index 00000000..1f0df647 --- /dev/null +++ b/nkebao/src/pages/plans/Plans.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const Plans: React.FC = () => { + return ( + + ); +}; + +export default Plans; diff --git a/nkebao/src/pages/profile/Profile.tsx b/nkebao/src/pages/profile/Profile.tsx new file mode 100644 index 00000000..87bc2d34 --- /dev/null +++ b/nkebao/src/pages/profile/Profile.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const Profile: React.FC = () => { + return ; +}; + +export default Profile; diff --git a/nkebao/src/pages/scenarios/ScenarioList.tsx b/nkebao/src/pages/scenarios/ScenarioList.tsx new file mode 100644 index 00000000..f1088dc7 --- /dev/null +++ b/nkebao/src/pages/scenarios/ScenarioList.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const ScenarioList: React.FC = () => { + return ; +}; + +export default ScenarioList; diff --git a/nkebao/src/pages/scenarios/Scenarios.tsx b/nkebao/src/pages/scenarios/Scenarios.tsx new file mode 100644 index 00000000..48d33760 --- /dev/null +++ b/nkebao/src/pages/scenarios/Scenarios.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const Scenarios: React.FC = () => { + return ( + + ); +}; + +export default Scenarios; diff --git a/nkebao/src/pages/scenarios/new/page.tsx b/nkebao/src/pages/scenarios/new/page.tsx new file mode 100644 index 00000000..b79b30fe --- /dev/null +++ b/nkebao/src/pages/scenarios/new/page.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const NewPlan: React.FC = () => { + return ; +}; + +export default NewPlan; diff --git a/nkebao/src/pages/scene/api.ts b/nkebao/src/pages/scene/api.ts index 53514714..0fff1662 100644 --- a/nkebao/src/pages/scene/api.ts +++ b/nkebao/src/pages/scene/api.ts @@ -1,14 +1,26 @@ import request from '@/api/request'; -// 设备统计 -export function getDeviceStats() { - return request('/v1/dashboard/device-stats', {}, 'GET'); +// 获取场景列表 +export function getScenarios(params: any) { + return request('/v1/plan/scenes', params, 'GET'); } -// 微信号统计 -export function getWechatStats() { - return request('/v1/dashboard/wechat-stats', {}, 'GET'); +// 获取场景详情 +export function getScenarioDetail(id: string) { + return request(`/v1/scenarios/${id}`, {}, 'GET'); } -// 你可以根据需要继续添加其他接口 -// 例如:场景获客统计、今日数据统计等 +// 创建场景 +export function createScenario(data: any) { + return request('/v1/scenarios', data, 'POST'); +} + +// 更新场景 +export function updateScenario(id: string, data: any) { + return request(`/v1/scenarios/${id}`, data, 'PUT'); +} + +// 删除场景 +export function deleteScenario(id: string) { + return request(`/v1/scenarios/${id}`, {}, 'DELETE'); +} diff --git a/nkebao/src/pages/scene/index.module.scss b/nkebao/src/pages/scene/index.module.scss index 53304f69..972a62f3 100644 --- a/nkebao/src/pages/scene/index.module.scss +++ b/nkebao/src/pages/scene/index.module.scss @@ -1,71 +1,319 @@ -.home-page { - padding: 12px; - background: #f5f5f5; +// 导航栏样式 +.nav-title { + font-size: 18px; + font-weight: 600; + color: var(--primary-color); } -.home-cards { - display: flex; - gap: 12px; - margin-bottom: 12px; - > :global(.adm-card) { - flex: 1; +.nav-text { + color: var(--primary-color); +} + +.nav-right { + margin-left: 4px; + font-size: 12px; +} + +.new-plan-btn { + border-radius: 20px; + padding: 4px 12px; + height: 32px; + font-size: 12px; + background: var(--primary-gradient); + border: none; + box-shadow: 0 2px 8px var(--primary-shadow); + + &:active { + transform: translateY(1px); + box-shadow: 0 1px 4px var(--primary-shadow); } } -.home-section { +// 页面容器 +.scene-page { + padding: 12px; + background: #f5f5f5; + min-height: calc(100vh - 100px); +} + +// 错误提示 +.error-notice { margin-bottom: 12px; + padding: 8px 12px; + background: #fff2e8; + border: 1px solid #ffd591; + border-radius: 8px; + box-shadow: 0 1px 4px rgba(255, 213, 145, 0.2); +} + +.error-notice-text { + font-size: 12px; + color: #d46b08; + font-weight: 500; +} + +// 加载状态 +.loading-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 200px; + gap: 12px; +} + +.loading-text { + font-size: 14px; + color: #666; + font-weight: 500; +} + +// 错误状态 +.error-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 200px; + gap: 16px; +} + +.error-text { + font-size: 14px; + color: #ff4d4f; + text-align: center; + font-weight: 500; +} + +.retry-button { + min-width: 100px; + border-radius: 20px; + background: var(--primary-gradient); + border: none; + box-shadow: 0 2px 8px var(--primary-shadow); +} + +// 页面头部 +.scene-header { + margin-bottom: 16px; + text-align: center; +} + +.header-title { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + font-size: 18px; + font-weight: 700; + color: var(--primary-color); + margin-bottom: 6px; +} + +.header-icon { + font-size: 20px; + color: var(--primary-color); +} + +.header-subtitle { + font-size: 12px; + color: #666; + line-height: 1.4; +} + +// 场景列表 +.scenarios-list { + display: flex; + flex-direction: column; + gap: 10px; +} + +// 场景卡片 +.scenario-item { + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + transform: translateY(-1px); + } + + &:active { + transform: translateY(0); + } +} + +.scenario-card { background: #fff; border-radius: 12px; - box-shadow: 0 2px 8px rgba(0,0,0,0.03); -} - -.home-section-title { - font-size: 16px; - font-weight: 600; - margin-bottom: 15px; - padding-left: 16px; -} - -.home-scene-stats { + padding: 16px 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid #f0f0f0; + transition: all 0.2s ease; display: flex; justify-content: space-between; - margin: 0 8px 8px 8px; -} -.home-scene-item { - flex: 1; - text-align: center; -} -.home-scene-icon { - margin: 0 auto 4px auto; -} -.home-scene-value { - font-size: 18px; - font-weight: bold; - color: #1677ff; -} -.home-scene-label { - font-size: 12px; - color: #888; + align-items: center; + min-height: 78px; + + &:hover { + box-shadow: 0 4px 16px rgba(24, 142, 238, 0.12); + border-color: var(--primary-color-light); + } } -.home-today-item { - text-align: center; - padding: 8px 0; - background: #f7f8fa; +.scenario-left { + display: flex; + align-items: center; + gap: 16px; + flex: 1; +} + +.scenario-icon { + width: 52px; + height: 52px; + background: linear-gradient(135deg, #f0f8ff 0%, #e6f7ff 100%); + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid rgba(24, 142, 238, 0.1); + flex-shrink: 0; +} + +.scenario-image { + width: 32px; + height: 32px; + object-fit: contain; border-radius: 8px; } -.home-today-value { - font-size: 18px; - font-weight: bold; - color: #1677ff; -} -.home-today-label { - font-size: 12px; - color: #888; + +.scenario-info { + display: flex; + flex-direction: column; + gap: 6px; + flex: 1; + min-width: 0; } -.home-chart { - margin-top: 8px; - width: 100%; - min-height: 100px; -} \ No newline at end of file +.scenario-name { + font-size: 16px; + font-weight: 600; + color: #1a1a1a; + line-height: 1.3; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.scenario-stats { + display: flex; + align-items: center; +} + +.stat-text { + font-size: 13px; + color: #666; + font-weight: 500; +} + +.scenario-right { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 8px; + flex-shrink: 0; +} + +.scenario-status { + display: flex; + justify-content: flex-end; +} + +.status-tag { + font-size: 11px; + padding: 3px 8px; + border-radius: 10px; + font-weight: 500; +} + +.scenario-growth { + display: flex; + align-items: center; + gap: 3px; + font-size: 16px; + font-weight: 700; +} + +.growth-icon { + font-size: 14px; +} + +// 空状态 +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 40px 20px; + text-align: center; +} + +.empty-icon { + font-size: 36px; + margin-bottom: 12px; + opacity: 0.6; +} + +.empty-text { + font-size: 14px; + color: #666; + margin-bottom: 16px; + font-weight: 500; +} + +.empty-action { + border-radius: 20px; + background: var(--primary-gradient); + border: none; + box-shadow: 0 2px 8px var(--primary-shadow); + padding: 6px 16px; + font-weight: 500; + font-size: 12px; +} + +// 响应式设计 +@media (max-width: 480px) { + .scene-page { + padding: 8px; + } + + .scenario-card { + padding: 14px 16px; + min-height: 70px; + } + + .scenario-icon { + width: 46px; + height: 46px; + } + + .scenario-image { + width: 28px; + height: 28px; + } + + .scenario-name { + font-size: 15px; + } + + .stat-text { + font-size: 12px; + } + + .scenario-growth { + font-size: 15px; + } + + .growth-icon { + font-size: 13px; + } +} diff --git a/nkebao/src/pages/scene/index.tsx b/nkebao/src/pages/scene/index.tsx index dc673c00..4ca7359a 100644 --- a/nkebao/src/pages/scene/index.tsx +++ b/nkebao/src/pages/scene/index.tsx @@ -1,132 +1,184 @@ -import React, { useState } from "react"; -import { Card, NavBar, TabBar, Grid } from "antd-mobile"; -import { - AppOutline, - UserOutline, - PieOutline, // 替换 BarChartOutline - ShopbagOutline, - BellOutline, -} from "antd-mobile-icons"; +import React, { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { NavBar, Button, SpinLoading, Toast, Tag } from "antd-mobile"; +import { AddOutline, UserAddOutline } from "antd-mobile-icons"; import MeauMobile from "@/components/MeauMobile/MeauMoible"; import Layout from "@/components/Layout/Layout"; +import { getScenarios } from "./api"; import style from "./index.module.scss"; -const sceneStats = [ - { - label: "公众号获客", - value: 234, - icon: , - }, - { - label: "海报获客", - value: 167, - icon: , - }, - { - label: "抖音获客", - value: 156, - icon: , - }, - { - label: "小红书获客", - value: 89, - icon: , - }, -]; -const todayStats = [ - { label: "朋友圈同步", value: 12 }, - { label: "群发任务", value: 8 }, - { label: "获客转化", value: "85%" }, - { label: "系统活跃度", value: "98%" }, -]; +interface Scenario { + id: string; + name: string; + image: string; + count: number; + growth: string; + status: number; +} + +const Scene: React.FC = () => { + const navigate = useNavigate(); + const [scenarios, setScenarios] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(""); + + useEffect(() => { + const fetchScenarios = async () => { + setLoading(true); + setError(""); + + try { + const response = await getScenarios({ page: 1, limit: 20 }); + + // 转换API数据为前端需要的格式 + const transformedScenarios: Scenario[] = response.map((item: any) => ({ + id: item.id.toString(), + name: item.name, + image: + item.image || + "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-api.png", + count: item.count, // 模拟今日数据 + growth: item.growth, // 模拟增长率 + status: item.status, + })); + + setScenarios(transformedScenarios); + } catch (error) { + console.error("获取场景数据失败:", error); + setError("获取场景数据失败,请稍后重试"); + Toast.show({ + content: "获取场景数据失败,请稍后重试", + position: "top", + }); + } finally { + setLoading(false); + } + }; + + fetchScenarios(); + }, []); + + const handleScenarioClick = (scenarioId: string, scenarioName: string) => { + navigate( + `/scenarios/list/${scenarioId}/${encodeURIComponent(scenarioName)}` + ); + }; + + const handleNewPlan = () => { + navigate("/scenarios/new"); + }; + + const getGrowthColor = (growth: string) => { + const value = parseFloat(growth.replace(/[+%]/g, "")); + if (value > 10) return "#52c41a"; + if (value > 5) return "#faad14"; + return "#ff4d4f"; + }; -const Home: React.FC = () => { return ( - 存客宝 - + 场景获客
} + right={ + + } + /> } footer={} > -
- {/* 统计卡片 */} -
- -
设备数量
-
0
-
- -
微信号数量
-
0
-
- -
在线微信号
-
0
-
+
+
+
+ + 热门获客场景 +
+
+ 选择适合的获客场景,提升转化效果 +
- {/* 场景获客统计 */} - -
场景获客统计
-
- {sceneStats.map((item) => ( -
-
{item.icon}
-
{item.value}
-
{item.label}
-
- ))} -
-
- - {/* 今日数据 */} - -
今日数据
- - {todayStats.map((item) => ( - -
-
{item.value}
-
{item.label}
+
+ {scenarios.map((scenario) => ( +
handleScenarioClick(scenario.id, scenario.name)} + > +
+
+
+ {scenario.name} { + e.currentTarget.src = + "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-api.png"; + }} + /> +
+
+
+ {scenario.name} +
+
+ + 今日获客: {scenario.count} + +
+
- - ))} - - - {/* 每日获客趋势(静态图表占位) */} - -
每日获客趋势
-
- - - {/* x轴文字 */} - {["周一", "周二", "周三", "周四", "周五", "周六", "周日"].map( - (d, i) => ( - +
+ + {scenario.status === 1 ? "活跃" : "暂停"} + +
+
- {d} - - ) - )} - + {scenario.growth} +
+
+
+
+ ))} +
+ + {scenarios.length === 0 && !loading && ( +
+
📊
+
暂无场景数据
+
- + )}
); }; -export default Home; +export default Scene; diff --git a/nkebao/src/pages/traffic-pool/TrafficPool.tsx b/nkebao/src/pages/traffic-pool/TrafficPool.tsx new file mode 100644 index 00000000..d64714d2 --- /dev/null +++ b/nkebao/src/pages/traffic-pool/TrafficPool.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const TrafficPool: React.FC = () => { + return ( + + ); +}; + +export default TrafficPool; diff --git a/nkebao/src/pages/traffic-pool/TrafficPoolDetail.tsx b/nkebao/src/pages/traffic-pool/TrafficPoolDetail.tsx new file mode 100644 index 00000000..d4c1ceef --- /dev/null +++ b/nkebao/src/pages/traffic-pool/TrafficPoolDetail.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const TrafficPoolDetail: React.FC = () => { + return ; +}; + +export default TrafficPoolDetail; diff --git a/nkebao/src/pages/wechat-accounts/WechatAccountDetail.tsx b/nkebao/src/pages/wechat-accounts/WechatAccountDetail.tsx new file mode 100644 index 00000000..ac5fa6ec --- /dev/null +++ b/nkebao/src/pages/wechat-accounts/WechatAccountDetail.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { NavBar } from "antd-mobile"; +import Layout from "@/components/Layout/Layout"; +import MeauMobile from "@/components/MeauMobile/MeauMoible"; + +const WechatAccountDetail: React.FC = () => { + return ( + window.history.back()} + > +
+ 微信号详情 +
+ + } + footer={} + > +
+

微信号详情页面

+

此页面正在开发中...

+
+
+ ); +}; + +export default WechatAccountDetail; diff --git a/nkebao/src/pages/wechat-accounts/WechatAccounts.tsx b/nkebao/src/pages/wechat-accounts/WechatAccounts.tsx new file mode 100644 index 00000000..5354b826 --- /dev/null +++ b/nkebao/src/pages/wechat-accounts/WechatAccounts.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { NavBar, Button } from "antd-mobile"; +import { AddOutline } from "antd-mobile-icons"; +import Layout from "@/components/Layout/Layout"; +import MeauMobile from "@/components/MeauMobile/MeauMoible"; + +const WechatAccounts: React.FC = () => { + return ( + + 微信号管理 +
+ } + right={ + + } + /> + } + footer={} + > +
+

微信号管理页面

+

此页面正在开发中...

+
+ + ); +}; + +export default WechatAccounts; diff --git a/nkebao/src/pages/workspace/Workspace.module.scss b/nkebao/src/pages/workspace/Workspace.module.scss new file mode 100644 index 00000000..c073ab28 --- /dev/null +++ b/nkebao/src/pages/workspace/Workspace.module.scss @@ -0,0 +1,185 @@ +.workspace { + padding: 16px; + background-color: #f5f5f5; + min-height: 100vh; +} + +.statsGrid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + margin-bottom: 24px; +} + +.statsCard { + background: #fff; + border-radius: 12px; + padding: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + + :global(.adm-card-body) { + padding: 0; + } +} + +.statsTitle { + font-size: 14px; + color: #666; + margin-bottom: 8px; +} + +.statsValue { + font-size: 28px; + font-weight: 700; + color: var(--primary-color); + margin-bottom: 12px; +} + +.progress { + margin-bottom: 8px; + + :global(.adm-progress-bar) { + background-color: #f0f0f0; + } + + :global(.adm-progress-bar-fill) { + background-color: var(--primary-color); + } +} + +.statsSubtitle { + font-size: 12px; + color: #999; +} + +.activityRate { + display: flex; + align-items: center; + font-size: 14px; + color: #52c41a; + margin-top: 8px; +} + +.activityIcon { + width: 16px; + height: 16px; + margin-right: 4px; + color: #52c41a; +} + +.section { + margin-bottom: 24px; +} + +.sectionTitle { + font-size: 18px; + font-weight: 600; + color: #333; + margin-bottom: 16px; + padding-left: 4px; +} + +.featuresGrid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; +} + +.featureLink { + text-decoration: none; + color: inherit; +} + +.featureCard { + background: #fff; + border-radius: 12px; + padding: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + transition: all 0.2s ease; + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + } + + :global(.adm-card-body) { + padding: 0; + } +} + +.featureIcon { + width: 40px; + height: 40px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 12px; +} + +.icon { + font-size: 20px; +} + +.featureHeader { + display: flex; + align-items: center; + margin-bottom: 4px; +} + +.featureName { + font-size: 16px; + font-weight: 600; + color: #333; +} + +.newBadge { + margin-left: 8px; + + :global(.adm-badge-content) { + background-color: var(--primary-color); + color: #fff; + font-size: 10px; + padding: 2px 6px; + border-radius: 10px; + } +} + +.featureDescription { + font-size: 12px; + color: #666; + line-height: 1.4; +} + +// 响应式设计 +@media (max-width: 375px) { + .workspace { + padding: 12px; + } + + .statsGrid { + gap: 8px; + } + + .featuresGrid { + gap: 8px; + } + + .statsCard, + .featureCard { + padding: 12px; + } + + .statsValue { + font-size: 24px; + } + + .featureIcon { + width: 36px; + height: 36px; + } + + .icon { + font-size: 18px; + } +} \ No newline at end of file diff --git a/nkebao/src/pages/workspace/Workspace.tsx b/nkebao/src/pages/workspace/Workspace.tsx new file mode 100644 index 00000000..81096f03 --- /dev/null +++ b/nkebao/src/pages/workspace/Workspace.tsx @@ -0,0 +1,254 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { Card, NavBar, Badge, Progress } from "antd-mobile"; +import { + ThumbsUpOutline, + MessageOutline, + SendOutline, + TeamOutline, + ShareOutline, + AppOutline, + BarChartOutline, + LineChartOutline, + ClockCircleOutline, +} from "antd-mobile-icons"; +import Layout from "@/components/Layout/Layout"; +import MeauMobile from "@/components/MeauMobile/MeauMoible"; +import styles from "./Workspace.module.scss"; + +const Workspace: React.FC = () => { + // 模拟任务数据 + const taskStats = { + total: 42, + inProgress: 12, + completed: 30, + todayTasks: 12, + activityRate: 98, + }; + + // 常用功能 + const commonFeatures = [ + { + id: "auto-like", + name: "自动点赞", + description: "智能自动点赞互动", + icon: ( + + ), + path: "/workspace/auto-like", + bgColor: "#fff2f0", + isNew: true, + }, + { + id: "moments-sync", + name: "朋友圈同步", + description: "自动同步朋友圈内容", + icon: ( + + ), + path: "/workspace/moments-sync", + bgColor: "#f9f0ff", + }, + { + id: "group-push", + name: "群消息推送", + description: "智能群发助手", + icon: ( + + ), + path: "/workspace/group-push", + bgColor: "#fff7e6", + }, + { + id: "auto-group", + name: "自动建群", + description: "智能拉好友建群", + icon: ( + + ), + path: "/workspace/auto-group", + bgColor: "#f6ffed", + }, + { + id: "traffic-distribution", + name: "流量分发", + description: "管理流量分发和分配", + icon: ( + + ), + path: "/workspace/traffic-distribution", + bgColor: "#e6f7ff", + }, + { + id: "ai-assistant", + name: "AI对话助手", + description: "智能回复,提高互动质量", + icon: ( + + ), + path: "/workspace/ai-assistant", + bgColor: "#e6f7ff", + isNew: true, + }, + ]; + + // AI智能助手 + const aiFeatures = [ + { + id: "ai-analyzer", + name: "AI数据分析", + description: "智能分析客户行为特征", + icon: ( + + ), + path: "/workspace/ai-analyzer", + bgColor: "#f0f0ff", + isNew: true, + }, + { + id: "ai-strategy", + name: "AI策略优化", + description: "智能优化获客策略", + icon: , + path: "/workspace/ai-strategy", + bgColor: "#e6fffb", + isNew: true, + }, + { + id: "ai-forecast", + name: "AI销售预测", + description: "智能预测销售趋势", + icon: ( + + ), + path: "/workspace/ai-forecast", + bgColor: "#fffbe6", + }, + ]; + + return ( + +
+ 工作台 +
+ + } + footer={} + > +
+ {/* 任务统计卡片 */} +
+ +
总任务数
+
{taskStats.total}
+ +
+ 进行中: {taskStats.inProgress} / 已完成: {taskStats.completed} +
+
+ + +
今日任务
+
+ {taskStats.todayTasks} +
+
+ + + + 活跃度 {taskStats.activityRate}% +
+
+
+ + {/* 常用功能 */} +
+

常用功能

+
+ {commonFeatures.map((feature) => ( + + +
+ {feature.icon} +
+
+
{feature.name}
+ {feature.isNew && ( + + )} +
+
+ {feature.description} +
+
+ + ))} +
+
+ + {/* AI智能助手 */} +
+

AI 智能助手

+
+ {aiFeatures.map((feature) => ( + + +
+ {feature.icon} +
+
+
{feature.name}
+ {feature.isNew && ( + + )} +
+
+ {feature.description} +
+
+ + ))} +
+
+
+
+ ); +}; + +export default Workspace; diff --git a/nkebao/src/pages/workspace/ai-assistant/AIAssistant.tsx b/nkebao/src/pages/workspace/ai-assistant/AIAssistant.tsx new file mode 100644 index 00000000..2727f453 --- /dev/null +++ b/nkebao/src/pages/workspace/ai-assistant/AIAssistant.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const AIAssistant: React.FC = () => { + return ; +}; + +export default AIAssistant; diff --git a/nkebao/src/pages/workspace/auto-group/AutoGroup.tsx b/nkebao/src/pages/workspace/auto-group/AutoGroup.tsx new file mode 100644 index 00000000..935827d6 --- /dev/null +++ b/nkebao/src/pages/workspace/auto-group/AutoGroup.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const AutoGroup: React.FC = () => { + return ( + + ); +}; + +export default AutoGroup; diff --git a/nkebao/src/pages/workspace/auto-group/Detail.tsx b/nkebao/src/pages/workspace/auto-group/Detail.tsx new file mode 100644 index 00000000..db34f334 --- /dev/null +++ b/nkebao/src/pages/workspace/auto-group/Detail.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const AutoGroupDetail: React.FC = () => { + return ; +}; + +export default AutoGroupDetail; diff --git a/nkebao/src/pages/workspace/auto-like/AutoLike.tsx b/nkebao/src/pages/workspace/auto-like/AutoLike.tsx new file mode 100644 index 00000000..35f84a96 --- /dev/null +++ b/nkebao/src/pages/workspace/auto-like/AutoLike.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { NavBar, Button } from "antd-mobile"; +import { AddOutline } from "antd-mobile-icons"; +import Layout from "@/components/Layout/Layout"; +import MeauMobile from "@/components/MeauMobile/MeauMoible"; + +const AutoLike: React.FC = () => { + return ( + window.history.back()} + left={ +
+ 自动点赞 +
+ } + right={ + + } + /> + } + footer={} + > +
+

自动点赞页面

+

此页面正在开发中...

+
+
+ ); +}; + +export default AutoLike; diff --git a/nkebao/src/pages/workspace/auto-like/AutoLikeDetail.tsx b/nkebao/src/pages/workspace/auto-like/AutoLikeDetail.tsx new file mode 100644 index 00000000..08811261 --- /dev/null +++ b/nkebao/src/pages/workspace/auto-like/AutoLikeDetail.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const AutoLikeDetail: React.FC = () => { + return ; +}; + +export default AutoLikeDetail; diff --git a/nkebao/src/pages/workspace/auto-like/NewAutoLike.tsx b/nkebao/src/pages/workspace/auto-like/NewAutoLike.tsx new file mode 100644 index 00000000..12bf9b7e --- /dev/null +++ b/nkebao/src/pages/workspace/auto-like/NewAutoLike.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { NavBar } from "antd-mobile"; +import Layout from "@/components/Layout/Layout"; +import MeauMobile from "@/components/MeauMobile/MeauMoible"; + +const NewAutoLike: React.FC = () => { + return ( + window.history.back()} + > +
+ 新建自动点赞 +
+ + } + footer={} + > +
+

新建自动点赞页面

+

此页面正在开发中...

+
+
+ ); +}; + +export default NewAutoLike; diff --git a/nkebao/src/pages/workspace/group-push/GroupPush.tsx b/nkebao/src/pages/workspace/group-push/GroupPush.tsx new file mode 100644 index 00000000..382dab52 --- /dev/null +++ b/nkebao/src/pages/workspace/group-push/GroupPush.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const GroupPush: React.FC = () => { + return ( + + ); +}; + +export default GroupPush; diff --git a/nkebao/src/pages/workspace/group-push/new.tsx b/nkebao/src/pages/workspace/group-push/new.tsx new file mode 100644 index 00000000..7147f70c --- /dev/null +++ b/nkebao/src/pages/workspace/group-push/new.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const NewGroupPush: React.FC = () => { + return ; +}; + +export default NewGroupPush; diff --git a/nkebao/src/pages/work/api.ts b/nkebao/src/pages/workspace/main/api.ts similarity index 100% rename from nkebao/src/pages/work/api.ts rename to nkebao/src/pages/workspace/main/api.ts diff --git a/nkebao/src/pages/work/index.module.scss b/nkebao/src/pages/workspace/main/index.module.scss similarity index 100% rename from nkebao/src/pages/work/index.module.scss rename to nkebao/src/pages/workspace/main/index.module.scss diff --git a/nkebao/src/pages/work/index.tsx b/nkebao/src/pages/workspace/main/index.tsx similarity index 100% rename from nkebao/src/pages/work/index.tsx rename to nkebao/src/pages/workspace/main/index.tsx diff --git a/nkebao/src/pages/workspace/moments-sync/Detail.tsx b/nkebao/src/pages/workspace/moments-sync/Detail.tsx new file mode 100644 index 00000000..b46fd03c --- /dev/null +++ b/nkebao/src/pages/workspace/moments-sync/Detail.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const MomentsSyncDetail: React.FC = () => { + return ; +}; + +export default MomentsSyncDetail; diff --git a/nkebao/src/pages/workspace/moments-sync/MomentsSync.tsx b/nkebao/src/pages/workspace/moments-sync/MomentsSync.tsx new file mode 100644 index 00000000..b4564f83 --- /dev/null +++ b/nkebao/src/pages/workspace/moments-sync/MomentsSync.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const MomentsSync: React.FC = () => { + return ( + + ); +}; + +export default MomentsSync; diff --git a/nkebao/src/pages/workspace/moments-sync/new.tsx b/nkebao/src/pages/workspace/moments-sync/new.tsx new file mode 100644 index 00000000..b32d13a6 --- /dev/null +++ b/nkebao/src/pages/workspace/moments-sync/new.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const NewMomentsSync: React.FC = () => { + return ; +}; + +export default NewMomentsSync; diff --git a/nkebao/src/pages/workspace/traffic-distribution/Detail.tsx b/nkebao/src/pages/workspace/traffic-distribution/Detail.tsx new file mode 100644 index 00000000..f3469de1 --- /dev/null +++ b/nkebao/src/pages/workspace/traffic-distribution/Detail.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const TrafficDistributionDetail: React.FC = () => { + return ; +}; + +export default TrafficDistributionDetail; diff --git a/nkebao/src/pages/workspace/traffic-distribution/NewDistribution.tsx b/nkebao/src/pages/workspace/traffic-distribution/NewDistribution.tsx new file mode 100644 index 00000000..06053b35 --- /dev/null +++ b/nkebao/src/pages/workspace/traffic-distribution/NewDistribution.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const NewDistribution: React.FC = () => { + return ; +}; + +export default NewDistribution; diff --git a/nkebao/src/pages/workspace/traffic-distribution/TrafficDistribution.tsx b/nkebao/src/pages/workspace/traffic-distribution/TrafficDistribution.tsx new file mode 100644 index 00000000..701f347b --- /dev/null +++ b/nkebao/src/pages/workspace/traffic-distribution/TrafficDistribution.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const TrafficDistribution: React.FC = () => { + return ( + + ); +}; + +export default TrafficDistribution; diff --git a/nkebao/src/router/config.ts b/nkebao/src/router/config.ts new file mode 100644 index 00000000..e41b5372 --- /dev/null +++ b/nkebao/src/router/config.ts @@ -0,0 +1,171 @@ +// 路由配置类型定义 +export interface RouteConfig { + path: string; + element: React.ReactNode; + auth: boolean; + requiredRole?: string; + title?: string; + icon?: string; + children?: RouteConfig[]; +} + +// 路由分组配置 +export const routeGroups = { + // 基础路由 + basic: { + name: "基础功能", + routes: ["/", "/login", "/scene", "/work", "/mine"], + }, + + // 设备管理 + devices: { + name: "设备管理", + routes: ["/devices", "/devices/:id"], + }, + + // 微信号管理 + wechatAccounts: { + name: "微信号管理", + routes: ["/wechat-accounts", "/wechat-accounts/:id"], + }, + + // 工作台 + workspace: { + name: "工作台", + routes: [ + "/workspace", + "/workspace/auto-like", + "/workspace/auto-like/new", + "/workspace/auto-like/:id", + "/workspace/auto-like/:id/edit", + "/workspace/auto-group", + "/workspace/auto-group/:id", + "/workspace/group-push", + "/workspace/group-push/new", + "/workspace/group-push/:id", + "/workspace/group-push/:id/edit", + "/workspace/moments-sync", + "/workspace/moments-sync/new", + "/workspace/moments-sync/:id", + "/workspace/moments-sync/edit/:id", + "/workspace/ai-assistant", + "/workspace/traffic-distribution", + "/workspace/traffic-distribution/new", + "/workspace/traffic-distribution/edit/:id", + "/workspace/traffic-distribution/:id", + ], + }, + + // 场景管理 + scenarios: { + name: "场景管理", + routes: [ + "/scenarios", + "/scenarios/new", + "/scenarios/new/:scenarioId", + "/scenarios/edit/:planId", + "/scenarios/list/:scenarioId/:scenarioName", + ], + }, + + // 内容管理 + content: { + name: "内容管理", + routes: [ + "/content", + "/content/new", + "/content/edit/:id", + "/content/materials/:id", + "/content/materials/new/:id", + "/content/materials/edit/:id/:materialId", + ], + }, + + // 流量池 + trafficPool: { + name: "流量池", + routes: ["/traffic-pool", "/traffic-pool/:id"], + }, + + // 其他功能 + other: { + name: "其他功能", + routes: [ + "/profile", + "/plans", + "/plans/:planId", + "/orders", + "/contact-import", + ], + }, +}; + +// 路由权限配置 +export const routePermissions = { + // 管理员权限 + admin: Object.values(routeGroups).flatMap(group => group.routes), + + // 普通用户权限 + user: [ + "/", + "/login", + "/scene", + "/work", + "/mine", + "/devices", + "/devices/:id", + "/wechat-accounts", + "/wechat-accounts/:id", + "/workspace", + "/scenarios", + "/content", + "/traffic-pool", + "/traffic-pool/:id", + "/profile", + "/plans", + "/plans/:planId", + "/orders", + "/contact-import", + ], + + // 访客权限 + guest: ["/", "/login"], +}; + +// 路由标题映射 +export const routeTitles: Record = { + "/": "首页", + "/login": "登录", + "/scene": "场景获客", + "/work": "工作台", + "/mine": "我的", + "/devices": "设备管理", + "/wechat-accounts": "微信号管理", + "/workspace": "工作台", + "/scenarios": "场景管理", + "/content": "内容管理", + "/traffic-pool": "流量池", + "/profile": "个人中心", + "/plans": "计划管理", + "/orders": "订单管理", + "/contact-import": "联系人导入", +}; + +// 获取路由标题 +export const getRouteTitle = (path: string): string => { + return routeTitles[path] || "页面"; +}; + +// 检查路由权限 +export const checkRoutePermission = ( + path: string, + userRole: string = "user" +): boolean => { + const allowedRoutes = routePermissions[userRole as keyof typeof routePermissions] || []; + return allowedRoutes.some(route => { + // 简单的路径匹配,支持动态参数 + const routePattern = route.replace(/:[^/]+/g, "[^/]+"); + const regex = new RegExp(`^${routePattern}$`); + return regex.test(path); + }); +}; \ No newline at end of file diff --git a/nkebao/src/router/module/auth.tsx b/nkebao/src/router/module/auth.tsx new file mode 100644 index 00000000..d6ddc5cf --- /dev/null +++ b/nkebao/src/router/module/auth.tsx @@ -0,0 +1,11 @@ +import Login from "@/pages/login/login"; + +const authRoutes = [ + { + path: "/login", + element: , + auth: false, // 不需要权限 + }, +]; + +export default authRoutes; diff --git a/nkebao/src/router/module/content.tsx b/nkebao/src/router/module/content.tsx new file mode 100644 index 00000000..7e941805 --- /dev/null +++ b/nkebao/src/router/module/content.tsx @@ -0,0 +1,39 @@ +import Content from "@/pages/content/Content"; +import NewContent from "@/pages/content/NewContent"; +import Materials from "@/pages/content/materials/List"; +import MaterialsNew from "@/pages/content/materials/New"; + +const contentRoutes = [ + { + path: "/content", + element: , + auth: true, + }, + { + path: "/content/new", + element: , + auth: true, + }, + { + path: "/content/edit/:id", + element: , + auth: true, + }, + { + path: "/content/materials/:id", + element: , + auth: true, + }, + { + path: "/content/materials/new/:id", + element: , + auth: true, + }, + { + path: "/content/materials/edit/:id/:materialId", + element: , + auth: true, + }, +]; + +export default contentRoutes; diff --git a/nkebao/src/router/module/devices.tsx b/nkebao/src/router/module/devices.tsx new file mode 100644 index 00000000..d31db945 --- /dev/null +++ b/nkebao/src/router/module/devices.tsx @@ -0,0 +1,17 @@ +import Devices from "@/pages/devices/Devices"; +import DeviceDetail from "@/pages/devices/DeviceDetail"; + +const deviceRoutes = [ + { + path: "/devices", + element: , + auth: true, + }, + { + path: "/devices/:id", + element: , + auth: true, + }, +]; + +export default deviceRoutes; diff --git a/nkebao/src/router/module/index.tsx b/nkebao/src/router/module/index.tsx index f92633a8..60033084 100644 --- a/nkebao/src/router/module/index.tsx +++ b/nkebao/src/router/module/index.tsx @@ -1,20 +1,15 @@ import Home from "@/pages/home/index"; -import Login from "@/pages/login/login"; import Scene from "@/pages/scene/index"; -import Work from "@/pages/work/index"; import Mine from "@/pages/mine/index"; +import Workspace from "@/pages/workspace/main"; const routes = [ + // 基础路由 { path: "/", element: , auth: true, // 需要登录 }, - { - path: "/login", - element: , - auth: false, // 不需要权限 - }, { path: "/scene", element: , @@ -22,7 +17,7 @@ const routes = [ }, { path: "/work", - element: , + element: , auth: true, }, { diff --git a/nkebao/src/router/module/other.tsx b/nkebao/src/router/module/other.tsx new file mode 100644 index 00000000..a458b7dc --- /dev/null +++ b/nkebao/src/router/module/other.tsx @@ -0,0 +1,40 @@ +import Profile from "@/pages/profile/Profile"; +import Plans from "@/pages/plans/Plans"; +import PlanDetail from "@/pages/plans/PlanDetail"; +import Orders from "@/pages/orders/Orders"; +import ContactImport from "@/pages/contact-import/ContactImport"; + +const otherRoutes = [ + { + path: "/mine", + element: , + auth: true, + }, + { + path: "/profile", + element: , + auth: true, + }, + { + path: "/plans", + element: , + auth: true, + }, + { + path: "/plans/:planId", + element: , + auth: true, + }, + { + path: "/orders", + element: , + auth: true, + }, + { + path: "/contact-import", + element: , + auth: true, + }, +]; + +export default otherRoutes; diff --git a/nkebao/src/router/module/scenarios.tsx b/nkebao/src/router/module/scenarios.tsx new file mode 100644 index 00000000..ff561561 --- /dev/null +++ b/nkebao/src/router/module/scenarios.tsx @@ -0,0 +1,38 @@ +import Scenarios from "@/pages/scenarios/Scenarios"; +import NewPlan from "@/pages/scenarios/new/page"; +import ScenarioList from "@/pages/scenarios/ScenarioList"; + +const scenarioRoutes = [ + { + path: "/scene", + element: , + auth: true, + }, + { + path: "/scenarios", + element: , + auth: true, + }, + { + path: "/scenarios/new", + element: , + auth: true, + }, + { + path: "/scenarios/new/:scenarioId", + element: , + auth: true, + }, + { + path: "/scenarios/edit/:planId", + element: , + auth: true, + }, + { + path: "/scenarios/list/:scenarioId/:scenarioName", + element: , + auth: true, + }, +]; + +export default scenarioRoutes; diff --git a/nkebao/src/router/module/traffic-pool.tsx b/nkebao/src/router/module/traffic-pool.tsx new file mode 100644 index 00000000..d0dcd70d --- /dev/null +++ b/nkebao/src/router/module/traffic-pool.tsx @@ -0,0 +1,17 @@ +import TrafficPool from "@/pages/traffic-pool/TrafficPool"; +import TrafficPoolDetail from "@/pages/traffic-pool/TrafficPoolDetail"; + +const trafficPoolRoutes = [ + { + path: "/traffic-pool", + element: , + auth: true, + }, + { + path: "/traffic-pool/:id", + element: , + auth: true, + }, +]; + +export default trafficPoolRoutes; diff --git a/nkebao/src/router/module/wechat-accounts.tsx b/nkebao/src/router/module/wechat-accounts.tsx new file mode 100644 index 00000000..496ab006 --- /dev/null +++ b/nkebao/src/router/module/wechat-accounts.tsx @@ -0,0 +1,17 @@ +import WechatAccounts from "@/pages/wechat-accounts/WechatAccounts"; +import WechatAccountDetail from "@/pages/wechat-accounts/WechatAccountDetail"; + +const wechatAccountRoutes = [ + { + path: "/wechat-accounts", + element: , + auth: true, + }, + { + path: "/wechat-accounts/:id", + element: , + auth: true, + }, +]; + +export default wechatAccountRoutes; diff --git a/nkebao/src/router/module/workspace.tsx b/nkebao/src/router/module/workspace.tsx new file mode 100644 index 00000000..64fdf386 --- /dev/null +++ b/nkebao/src/router/module/workspace.tsx @@ -0,0 +1,145 @@ +import Workspace from "@/pages/workspace/Workspace"; +import AutoLike from "@/pages/workspace/auto-like/AutoLike"; +import NewAutoLike from "@/pages/workspace/auto-like/NewAutoLike"; +import AutoLikeDetail from "@/pages/workspace/auto-like/AutoLikeDetail"; +import AutoGroup from "@/pages/workspace/auto-group/AutoGroup"; +import AutoGroupDetail from "@/pages/workspace/auto-group/Detail"; +import GroupPush from "@/pages/workspace/group-push/GroupPush"; +import NewGroupPush from "@/pages/workspace/group-push/new"; +import MomentsSync from "@/pages/workspace/moments-sync/MomentsSync"; +import MomentsSyncDetail from "@/pages/workspace/moments-sync/Detail"; +import NewMomentsSync from "@/pages/workspace/moments-sync/new"; +import AIAssistant from "@/pages/workspace/ai-assistant/AIAssistant"; +import TrafficDistribution from "@/pages/workspace/traffic-distribution/TrafficDistribution"; +import TrafficDistributionDetail from "@/pages/workspace/traffic-distribution/Detail"; +import NewDistribution from "@/pages/workspace/traffic-distribution/NewDistribution"; +import PlaceholderPage from "@/components/PlaceholderPage"; + +const workspaceRoutes = [ + { + path: "/workspace", + element: , + auth: true, + }, + // 自动点赞 + { + path: "/workspace/auto-like", + element: , + auth: true, + }, + { + path: "/workspace/auto-like/new", + element: , + auth: true, + }, + { + path: "/workspace/auto-like/:id", + element: , + auth: true, + }, + { + path: "/workspace/auto-like/:id/edit", + element: , + auth: true, + }, + // 自动分组 + { + path: "/workspace/auto-group", + element: , + auth: true, + }, + { + path: "/workspace/auto-group/:id", + element: , + auth: true, + }, + // 群发推送 + { + path: "/workspace/group-push", + element: , + auth: true, + }, + { + path: "/workspace/group-push/new", + element: , + auth: true, + }, + { + path: "/workspace/group-push/:id", + element: , + auth: true, + }, + { + path: "/workspace/group-push/:id/edit", + element: , + auth: true, + }, + // 朋友圈同步 + { + path: "/workspace/moments-sync", + element: , + auth: true, + }, + { + path: "/workspace/moments-sync/new", + element: , + auth: true, + }, + { + path: "/workspace/moments-sync/:id", + element: , + auth: true, + }, + { + path: "/workspace/moments-sync/edit/:id", + element: , + auth: true, + }, + // AI助手 + { + path: "/workspace/ai-assistant", + element: , + auth: true, + }, + // AI数据分析 + { + path: "/workspace/ai-analyzer", + element: , + auth: true, + }, + // AI策略优化 + { + path: "/workspace/ai-strategy", + element: , + auth: true, + }, + // AI销售预测 + { + path: "/workspace/ai-forecast", + element: , + auth: true, + }, + // 流量分发 + { + path: "/workspace/traffic-distribution", + element: , + auth: true, + }, + { + path: "/workspace/traffic-distribution/new", + element: , + auth: true, + }, + { + path: "/workspace/traffic-distribution/edit/:id", + element: , + auth: true, + }, + { + path: "/workspace/traffic-distribution/:id", + element: , + auth: true, + }, +]; + +export default workspaceRoutes; diff --git a/nkebao/src/styles/global.scss b/nkebao/src/styles/global.scss index 079b5d0c..bf7670a8 100644 --- a/nkebao/src/styles/global.scss +++ b/nkebao/src/styles/global.scss @@ -122,4 +122,13 @@ input, textarea { /* 安卓部分 WebView 点击延迟优化 */ body, input, textarea, select, button { touch-action: manipulation; -} \ No newline at end of file +} +//导航左右结构的样式 +.nav-left { + color: var(--primary-color); + font-weight: 700; + font-size: 16px; +} +.nav-right { + font-size: 12px; +} \ No newline at end of file