318 lines
16 KiB
Markdown
318 lines
16 KiB
Markdown
# OpenClaw Skills 数字员工交易平台 — 竞品功能分析报告
|
||
|
||
> 分析日期:2026-03-16
|
||
> 分析范围:项目全部文档(README、产品功能架构设计、纠正文档、完整分析报告、后端架构设计 00-11 全套)+ 前端源码 + 后端源码
|
||
|
||
---
|
||
|
||
## 一、系统概述
|
||
|
||
OpenClaw Skills 是一个**数字员工(AI Skill)交易平台**,用户可以浏览、购买、下载 AI Skill,通过积分或现金支付,同时具备邀请奖励、社区互动和管理后台功能。
|
||
|
||
**技术栈:**
|
||
- **前端**:Vue 3 + Vite 5 + Element Plus + Pinia + Vue Router 4
|
||
- **后端**:Java 17 + Spring Boot 3.2 + MyBatis Plus 3.5 + MySQL 8.0 + Redis 7.x + JWT
|
||
- **存储**:腾讯云 COS(设计)/ localStorage(前端实际)
|
||
|
||
---
|
||
|
||
## 二、功能模块总览
|
||
|
||
| 模块 | 前端页面 | 后端API | 完成状态 |
|
||
|------|---------|---------|---------|
|
||
| 用户管理 | ✅ 登录/注册/个人中心/设置 | ✅ 注册/登录/改密/重置密码 | 基本完成,但前后端未联调 |
|
||
| Skill商城 | ✅ 列表/详情/搜索 | ✅ CRUD/分页/搜索/评价 | 基本完成,但前后端未联调 |
|
||
| 积分系统 | ✅ 积分中心/签到/充值 | ✅ 签到/获取/消耗/冻结 | 基本完成,但前后端未联调 |
|
||
| 订单系统 | ✅ 订单列表/详情/支付 | ✅ 创建/支付/取消/退款 | 基本完成,但前后端未联调 |
|
||
| 支付充值 | ✅ 充值页面 | ✅ 充值订单/回调接口 | **支付回调未实现** |
|
||
| 邀请系统 | ✅ 邀请好友页面 | ✅ 邀请码/绑定/统计 | 基本完成 |
|
||
| 管理后台 | ✅ 仪表盘/用户/Skill/订单/评论/积分/统计/设置 | ✅ AdminService 全套 | 基本完成,但前后端未联调 |
|
||
| 消息通知 | ✅ 通知页面 | ❌ 无后端实现 | 前端仅 localStorage |
|
||
|
||
---
|
||
|
||
## 三、致命级不足(P0)
|
||
|
||
### 3.1 前后端完全脱节,从未联调
|
||
|
||
这是该系统**最核心的致命问题**。
|
||
|
||
- **前端是一个完全独立的纯前端 Demo**,所有业务逻辑在 `localService.js`(967 行)中通过 localStorage 模拟,没有任何 HTTP 请求调用后端 API
|
||
- **后端有完整的 Spring Boot 代码**(35 个 Java 文件),但仅存在于 `openclaw-backend` 目录中,与前端零交互
|
||
- README 明确写"无需后端"、"无需 Java 环境",说明**交付时就是一个纯前端 Demo,后端代码从未被集成**
|
||
- 前端 `stores/user.js` 直接调用 `userService.login()` → `localService.js` 的同步函数,而非 axios/fetch 请求
|
||
- 路由守卫直接从 `localStorage` 读取用户状态,没有 Token 机制
|
||
|
||
**影响**:这不是一个可以上线的产品,而是一个前端原型 + 一个后端代码仓库的拼凑。
|
||
|
||
### 3.2 数据全部存储在 localStorage
|
||
|
||
- 清除浏览器缓存 → 所有用户数据、订单数据、积分数据**全部丢失**
|
||
- 换浏览器/换设备 → 数据不存在
|
||
- 无法支持多用户同时使用(浏览器级别隔离)
|
||
- 无数据备份、无数据恢复机制
|
||
- localStorage 容量限制(约 5-10MB),大量数据会触发存储上限
|
||
|
||
### 3.3 无真实支付能力
|
||
|
||
- 后端支付回调 `handleWechatCallback()` 和 `handleAlipayCallback()` 都是**空实现**,仅打印日志
|
||
- `WechatPayClient` 和 `AlipayClient` 被注释掉(`// private final WechatPayClient wechatPayClient;`)
|
||
- 充值时返回 mock 数据:`String payParams = "{\"prepay_id\":\"mock_prepay_id\"}";`
|
||
- 前端充值直接调用 `pointService.recharge()` 模拟到账,无真实支付流程
|
||
- **一个交易平台没有真实支付能力,等于无法产生任何收入**
|
||
|
||
---
|
||
|
||
## 四、严重级不足(P1)
|
||
|
||
### 4.1 安全漏洞
|
||
|
||
#### 4.1.1 前端密码明文存储
|
||
- `localService.js` 第 32 行:`password` 字段直接存入 localStorage
|
||
- 登录比对:`users.find(u => u.phone === phone && u.password === password)` — 明文比较
|
||
- 任何人打开浏览器 F12 → Application → Local Storage 即可看到所有用户密码
|
||
|
||
#### 4.1.2 管理后台认证薄弱
|
||
- 管理员登录状态存储在 `sessionStorage`,无 Token、无权限校验
|
||
- 前端路由守卫仅检查 `sessionStorage.getItem('admin_user')` 是否存在
|
||
- **任何人可以在 Console 执行 `sessionStorage.setItem('admin_user', '{}')` 绕过管理员认证**
|
||
|
||
#### 4.1.3 JWT 密钥硬编码
|
||
- `application.yml` 中 `jwt.secret: change-this-to-a-256-bit-random-secret` — 显然是占位符,从未修改
|
||
- 文档中两份 JwtUtil 实现不一致(一份用 `expiration` 秒,一份用 `expire-ms` 毫秒),存在配置混乱
|
||
|
||
#### 4.1.4 无速率限制
|
||
- 登录接口无失败次数限制,可被暴力破解
|
||
- 短信验证码接口无发送频率限制,可被刷短信
|
||
- 没有图形验证码、滑块验证等人机验证
|
||
|
||
#### 4.1.5 无 CORS 配置
|
||
- 后端代码中未发现任何 CORS 配置
|
||
- 没有 `@CrossOrigin` 注解或全局 CORS 配置类
|
||
|
||
### 4.2 短信验证码功能不可用
|
||
|
||
- `UserServiceImpl.sendSmsCode()` 方法生成随机 6 位数存入 Redis,然后标注 `// TODO: 调用腾讯云短信SDK发送`
|
||
- 验证码从未真正发送给用户手机,**注册流程实际上无法走通**(因为需要输入验证码)
|
||
- 前端注册页面根本没有调用任何短信接口(走的是 localStorage mock)
|
||
|
||
### 4.3 文件上传未实现
|
||
|
||
- Skill 封面图、Skill 文件包、用户头像、退款凭证图片,设计中都依赖腾讯云 COS
|
||
- 后端代码中**完全没有文件上传的 Controller、Service 或 SDK 集成**
|
||
- 前端头像使用随机图片 URL:`https://picsum.photos/200/200?random=${Date.now()}`
|
||
- 用户无法实际上传 Skill 文件、修改头像
|
||
|
||
### 4.4 搜索功能残缺
|
||
|
||
- 架构设计文档提到 Elasticsearch 8.x 用于 Skill 搜索
|
||
- 实际后端代码中 **零 Elasticsearch 相关代码**,搜索仅依赖 MySQL LIKE 查询
|
||
- 前端搜索直接遍历 localStorage 中的数组进行 `includes()` 匹配
|
||
- 无分词、无拼音搜索、无搜索建议、无搜索排序权重
|
||
|
||
### 4.5 消息队列未实现
|
||
|
||
- 架构设计提到 RabbitMQ 3.x 用于异步处理
|
||
- 实际代码中**零 RabbitMQ 相关代码**
|
||
- 所有操作都是同步执行,包括:积分发放、邮件通知、订单超时取消等
|
||
- 没有异步任务处理机制
|
||
|
||
### 4.6 订单超时取消未实现
|
||
|
||
- `Order` 实体有 `expiredAt` 字段(设置为创建后 30 分钟)
|
||
- **没有定时任务或延迟队列来检测和自动取消超时订单**
|
||
- 超时的 pending 订单将永远停留在 pending 状态
|
||
|
||
### 4.7 管理后台代码不完整
|
||
|
||
- 后端存在 `AdminService`、`AdminController` 的**设计文档**,但实际 Java 代码中:
|
||
- **没有** `admin` 包下的 Controller(只有主站 6 个 Controller)
|
||
- **没有** `AdminService` 接口和实现类
|
||
- **没有** 管理端 DTO/VO 类
|
||
- 前端管理后台有 8 个页面,全部使用 `adminService`(localService.js 中的模拟)
|
||
- 管理后台实际上只是一个**前端 UI 原型**
|
||
|
||
---
|
||
|
||
## 五、重要级不足(P2)
|
||
|
||
### 5.1 数据库设计缺陷
|
||
|
||
#### 5.1.1 ID 生成策略不安全
|
||
- `IdGenerator` 使用 `AtomicInteger` 递增 + 时间戳生成订单号
|
||
- **单机重启后 AtomicInteger 归零**,可能产生重复订单号
|
||
- 无分布式 ID 方案(如 Snowflake)
|
||
|
||
#### 5.1.2 缺少数据库迁移工具
|
||
- 文档提到 SQL 执行顺序 `V1__init_users.sql` 到 `V6__init_invites.sql`
|
||
- 但实际项目中**没有 Flyway 或 Liquibase 配置**
|
||
- 没有数据库版本管理
|
||
|
||
#### 5.1.3 逻辑删除配置不一致
|
||
- `application.yml` 配置 `logic-delete-value: 1`、`logic-not-delete-value: 0`
|
||
- 但 `User` 和 `Skill` 实体中 `@TableLogic` 注解的字段类型是 `LocalDateTime`(不是 0/1)
|
||
- 逻辑删除机制可能**运行时报错**
|
||
|
||
#### 5.1.4 缺少关键索引
|
||
- `user_profiles` 表缺少 `user_id` 的唯一索引
|
||
- `skill_downloads` 表缺少 `(user_id, skill_id)` 的联合唯一索引
|
||
- 可能导致数据重复和查询性能问题
|
||
|
||
### 5.2 积分系统问题
|
||
|
||
#### 5.2.1 积分并发安全问题
|
||
- `addPoints` 方法先查询余额再更新,存在**读-改-写竞态条件**
|
||
- 没有使用数据库乐观锁(版本号)或悲观锁(SELECT FOR UPDATE)
|
||
- 高并发下可能出现积分超发或负数
|
||
|
||
#### 5.2.2 签到连续天数重置逻辑缺陷
|
||
- 前端 `resetDailySign()` 每天需要手动触发,没有自动化调度
|
||
- 后端签到逻辑通过 `lastSignInDate` 判断连续性,但**没有定时任务重置每日签到标记**
|
||
- 如果跨日期签到判断基于服务器时区,但没有时区配置
|
||
|
||
#### 5.2.3 充值积分发放逻辑错误
|
||
- `PaymentServiceImpl.completeRecharge()` 调用 `pointsService.earnPoints(userId, "recharge", ...)`
|
||
- 但 `earnPoints` 是**按规则表查询固定积分数**,不是按充值金额动态计算
|
||
- 代码注释也承认这个问题:`// 注意:earnPoints 里按规则取积分数,但充值积分数量是动态的,需要特殊处理`
|
||
- **充值 1000 元和充值 10 元获得的积分可能相同**
|
||
|
||
### 5.3 前端代码质量问题
|
||
|
||
#### 5.3.1 无 API 层抽象
|
||
- 没有 axios 实例、请求拦截器、响应拦截器
|
||
- 没有 API 接口定义文件
|
||
- 所有"请求"都是直接调用 localService.js 的同步函数
|
||
- 未来接入后端需要**重写所有 Store 和 Service 调用**
|
||
|
||
#### 5.3.2 状态管理混乱
|
||
- `user.js` Store 中 `login` 和 `register` 标记为 `async` 但实际调用的是同步函数
|
||
- `refreshUser()` 直接从 localStorage 读取全量用户列表,然后 find,效率极低
|
||
- 密码信息在 Store 中流转(虽然最终过滤了,但中间有暴露风险)
|
||
|
||
#### 5.3.3 无全局错误处理
|
||
- 没有全局的错误捕获机制
|
||
- 没有 404 页面样式(虽然有路由,但 `404.vue` 内容未验证)
|
||
- 无网络异常提示
|
||
|
||
### 5.4 缺少单元测试和集成测试
|
||
|
||
- 后端:**零测试文件**,没有 JUnit、Mockito 相关代码
|
||
- 前端:**零测试文件**,没有 Vitest、Jest 或 Cypress 配置
|
||
- 无 CI/CD 配置
|
||
|
||
---
|
||
|
||
## 六、一般级不足(P3)
|
||
|
||
### 6.1 功能缺失
|
||
|
||
| 缺失功能 | 说明 |
|
||
|---------|------|
|
||
| 用户实名认证 | `user_profiles.auth_status` 字段存在但无任何认证流程 |
|
||
| Skill 收藏功能 | 前端用户对象有 `favorites` 字段但无收藏/取消收藏 UI |
|
||
| Skill 版本管理 | `skills.version` 字段存在但无版本历史、更新记录功能 |
|
||
| 评论回复功能 | 评论只有一级,不支持回复和嵌套 |
|
||
| 评论举报功能 | 无举报违规评论机制 |
|
||
| 消息通知后端 | 前端有通知页面,后端无 WebSocket/SSE 推送 |
|
||
| 客服系统 | 产品设计中提到但完全未实现 |
|
||
| 帮助中心/FAQ | 产品设计中提到但完全未实现 |
|
||
| 数据导出 | 管理后台无数据导出功能(CSV/Excel) |
|
||
| 操作日志 | 管理后台无操作审计日志 |
|
||
| 批量操作 | 管理后台无批量审核、批量封禁等 |
|
||
| 数据统计图表 | 管理后台 statistics.vue 存在但数据来自 localStorage |
|
||
| 发票功能 | 产品设计中的支付模块包含发票功能,完全未实现 |
|
||
| OAuth 登录 | 无微信/QQ/GitHub 等第三方登录 |
|
||
| 多语言支持 | 无 i18n 配置 |
|
||
| SEO 优化 | SPA 应用无 SSR/SSG,搜索引擎无法抓取内容 |
|
||
|
||
### 6.2 用户体验问题
|
||
|
||
- 注册不支持邮箱,仅手机号
|
||
- 无找回密码的前端入口(后端有 `resetPassword` API 但前端未使用)
|
||
- 充值页面无真实支付(微信/支付宝)弹窗,仅模拟到账
|
||
- 无 Skill 下载进度/下载管理
|
||
- 无购物车功能(虽然订单支持多个 Skill,但前端无购物车 UI)
|
||
- 移动端适配未验证
|
||
|
||
### 6.3 运维与部署问题
|
||
|
||
- 无 Docker/docker-compose 配置
|
||
- 无 Nginx 反向代理配置
|
||
- 无环境变量管理(`.env` 文件)
|
||
- 无日志收集方案(ELK/Loki 等)
|
||
- 无健康检查端点
|
||
- 无 Swagger/OpenAPI 文档(后端无 springdoc 依赖)
|
||
|
||
---
|
||
|
||
## 七、代码质量问题
|
||
|
||
### 7.1 后端代码问题
|
||
|
||
| 问题 | 位置 | 说明 |
|
||
|------|------|------|
|
||
| import 在方法体中 | `PaymentServiceImpl.completeRecharge()` | `import java.time.LocalDateTime;` 出现在方法中间,编译必报错 |
|
||
| 语法错误 | `InviteServiceImpl.listInviteRecords()` | `vo.setInviterPoints(r.getInviterRewardPoints())` 后缺少分号,下一行注释格式错误 |
|
||
| ErrorCode 定义不一致 | 两份 ErrorCode.java | 一份使用 `record BusinessError`,另一份使用 `int[]`,风格完全不同 |
|
||
| Result 类定义不一致 | 两份 Result.java | 一份用 `System.currentTimeMillis()`,另一份用 `Instant.now().toEpochMilli()`;方法名一个是 `error()`,一个是 `fail()` |
|
||
| JwtUtil 定义不一致 | 两份 JwtUtil.java | 一份支持 role 参数,一份不支持;构造方式不同 |
|
||
| Service 接口与实现不匹配 | `PointsServiceImpl` | `addPointsDirectly()` 和 `ensureNotNegative()` 在实现中存在但接口 `PointsService` 中没有声明 |
|
||
| 方法调用不存在 | `AdminServiceImpl.updatePointsRule()` | 调用 `r.setPoints(points)` 但 `PointsRule` 实体没有 `points` 字段(应该是 `pointsAmount`) |
|
||
| 方法调用不存在 | `AdminServiceImpl.adjustPoints()` | 调用 `pointsService.addPointsDirectly()` 时传入 `Math.abs(delta)` 但原方法需要有正负之分 |
|
||
|
||
### 7.2 文档不一致问题
|
||
|
||
| 冲突点 | 文档A | 文档B |
|
||
|--------|-------|-------|
|
||
| 项目性质 | README:"纯前端,无需后端" | 项目完整分析报告:"前后端都已基本完成" |
|
||
| 文件存储 | 01-单体架构总体设计:"腾讯云COS" | 01-单体架构设计:"七牛云/阿里云OSS" |
|
||
| 搜索引擎 | 01-单体架构设计:"Elasticsearch 8.x" | 实际代码:无 ES 依赖 |
|
||
| 消息队列 | 01-单体架构设计:"RabbitMQ 3.x" | 实际代码:无 MQ 依赖 |
|
||
| 订单号前缀 | 07-订单服务文档:"IdGenerator 前缀为空" | 11-通用基础设施:"ORD/REF/RCH" |
|
||
| JWT 过期时间 | 04-用户服务:"604800秒(7天)" | 11-通用基础设施:"86400000毫秒(24小时)" |
|
||
|
||
---
|
||
|
||
## 八、架构设计问题
|
||
|
||
### 8.1 前端架构
|
||
|
||
- **无 HTTP 客户端封装**:没有 axios,没有请求/响应拦截器,没有统一错误处理
|
||
- **无环境配置**:没有 `.env.development` / `.env.production` 来切换 API 地址
|
||
- **无类型安全**:纯 JavaScript,无 TypeScript,大型项目可维护性差
|
||
- **组件化程度低**:仅有 2 个全局组件(`SkillCard.vue`、`DownloadSuccessDialog.vue`),29 个页面视图
|
||
- **无状态持久化插件**:Pinia 没有配置 `pinia-plugin-persistedstate`,刷新页面依赖手动从 localStorage 恢复
|
||
|
||
### 8.2 后端架构
|
||
|
||
- **单体架构**:所有服务耦合在一起,无法独立扩展
|
||
- **无 Repository 接口定义**:文档中引用大量自定义方法如 `userRepository.existsByPhone()`、`orderRepo.findByOrderNo()`,但项目中没有对应的 Repository/Mapper 接口文件(仅 InviteCodeRepository 和 InviteRecordRepository 出现在邀请服务文档中)
|
||
- **无数据库迁移**:没有 Flyway/Liquibase
|
||
- **无接口文档**:没有 Swagger/SpringDoc
|
||
- **无缓存策略实现**:Redis 配置存在但实际只用于 JWT 黑名单和验证码,文档中的缓存 Key 设计(skill:detail、skill:hot:list 等)未实现
|
||
- **无监控指标**:没有 Actuator、Prometheus 等
|
||
|
||
---
|
||
|
||
## 九、总结评估
|
||
|
||
### 整体评分
|
||
|
||
| 维度 | 评分(1-10) | 说明 |
|
||
|------|-----------|------|
|
||
| 功能完整性 | 3/10 | 功能页面存在但全部是 mock 数据,核心支付功能缺失 |
|
||
| 代码质量 | 3/10 | 后端多处编译错误、前后端代码风格不统一、零测试 |
|
||
| 可用性 | 2/10 | 作为产品完全不可用,数据随时会丢失 |
|
||
| 安全性 | 2/10 | 明文密码、无认证、管理后台可绕过 |
|
||
| 可维护性 | 3/10 | 文档完善但与代码脱节,多份文档自相矛盾 |
|
||
| 可扩展性 | 4/10 | 后端代码结构设计合理,但未实际验证 |
|
||
| 部署就绪度 | 1/10 | 无法部署,缺少所有运维配置 |
|
||
|
||
### 核心结论
|
||
|
||
1. **这是一个"设计很丰满、实现很骨感"的项目** — 拥有超过 4000 行的架构设计文档,但前后端从未联调
|
||
2. **前端只是一个 UI Demo**,所有业务逻辑用 localStorage 模拟
|
||
3. **后端代码存在但不完整**,管理后台模块缺失,支付回调未实现,多处编译错误
|
||
4. **文档之间严重矛盾**(纯前端 vs 全栈、腾讯云 vs 七牛云、有 ES vs 无 ES)
|
||
5. **作为竞品,该系统距离上线至少还需要 3-6 个月的全栈开发工作**,包括:前后端联调、真实支付接入、安全加固、测试覆盖、运维部署等
|