# X-Swap
**Repository Path**: lancemorii-git/x-swap
## Basic Information
- **Project Name**: X-Swap
- **Description**: X-Swap 是一个面向高校场景的多租户校园二手交易 SaaS 平台,支持学校级租户隔离、角色权限控制、商品发布审核、线下预约交易、信用评价与举报治理。后端基于 Spring Boot + Sa-Token,前端支持 Web 管理端与 uni-app 用户端,开箱即用,支持多学校快速部署。
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2026-02-10
- **Last Updated**: 2026-03-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
CampusSwap SaaS
多租户校园二手交易平台
一套系统服务多个大学,支持 Web 管理端 + 用户端(H5 / 微信小程序)
以纯线下交易为核心,构建完整的校园二手交易闭环
快速启动 •
技术栈 •
架构 •
演示 •
API
---
## 项目亮点
| 特性 | 说明 |
|:---:|:---|
| **多租户 SaaS** | 一套部署服务多所大学,共享库共享表 + tenant_id 隔离 |
| **纯线下交易** | 系统负责撮合、预约、状态流转、评价、举报,不接入支付 |
| **三端覆盖** | 管理端 Web + 用户端 H5 + 微信小程序 |
| **安全优先** | 鉴权、多租户隔离、审计日志、限流、输入校验全部落地 |
---
## 系统架构
```
┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ admin-web │ │ client-app │ │ client-app │
│ Vue3+ElementPlus│ │ uni-app H5 │ │ uni-app 微信小程序 │
└────────┬────────┘ └────────┬─────────┘ └────────┬─────────┘
└────────────────────┼─────────────────────┘
▼
┌──────────────────────────┐
│ Spring Boot 3.2 + Sa-Token │
│ MyBatis-Plus 多租户拦截 │
└──────────┬───────────────┘
┌──────┴──────┐
▼ ▼
MySQL 8.0 Redis 7
│
▼
┌─────────────────────┐
│ 文件存储(可选) │
│ Local/MinIO/OSS/COS │
└─────────────────────┘
```
---
## 技术栈
|
**后端技术**
- Java 17 + Spring Boot 3.2.5
- Sa-Token 1.38(Redis 会话)
- MyBatis-Plus 3.5.6(多租户拦截)
- MySQL 8.0 + Redis 7
- Springdoc OpenAPI 2.5
- Docker Compose
|
**前端技术**
- Vue 3 + TypeScript + Element Plus
- uni-app(Vue 3)→ H5 + 小程序
- Pinia 状态管理
- Vue Router
|
**文件存储**:本地 / MinIO / 阿里云 OSS / 腾讯云 COS(策略模式,配置切换)
---
## 多租户设计
```
┌─────────────────────────────────────────────────────────────┐
│ 共享数据库 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 清华大学 │ │ 北京大学 │ │ 复旦大学 │ │ ... │ │
│ │tenant=1 │ │tenant=2 │ │tenant=3 │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ 数据完全隔离 │
└─────────────────────────────────────────────────────────────┘
```
- **隔离方式**:共享数据库共享表,所有核心业务表包含 `tenant_id` 字段
- **租户识别**:登录时通过 `tenantCode` 确定租户,登录后 tenantId 存入 Sa-Token Session
- **自动过滤**:MyBatis-Plus `TenantLineInnerInterceptor` 自动为所有 SQL 追加 `tenant_id` 条件
- **安全原则**:租户信息仅从 Session 获取,禁止从 URL/请求参数传入
### 角色体系
| 角色 | 说明 | 接口前缀 |
|:---:|:---|:---|
| SUPER_ADMIN | 平台超管,管理所有租户 | `/api/platform/**` |
| TENANT_ADMIN | 学校管理员,管理本校数据 | `/api/admin/**` |
| USER | 学生用户 | `/api/app/**` |
---
## 安全设计
鉴权与会话
- Sa-Token 登录体系,`StpUtil.login(userId)` 签发 Token
- Token 通过 `Authorization: Bearer ` 传递
- 会话存储于 Redis,支持分布式部署
- Token 有效期 7 天,登出即失效
限流与风控
- **IP 级限流**:登录接口 Redis 滑动窗口限流,防暴力破解
- **用户级限流**:发布商品频率限制,防刷
- 限流触发返回 `429` 错误码,前端友好提示
输入安全
- `@Valid` 统一参数校验(JSR-380)
- 排序字段白名单,防 SQL 注入
- 文件上传 MIME 白名单(jpg/png/webp)+ 5MB 大小限制 + 路径穿越防护
- BCrypt 密码加密存储
- 统一返回体,禁止暴露异常堆栈
审计与追踪
- 每个请求生成 `traceId`(MDC),响应头返回 `X-Trace-Id`
- 关键业务操作写入 `audit_log`(谁、何时、做了什么、对象、租户)
- 安全事件写入 `security_event`(登录失败、限流触发等)
---
## 交易状态机
```
┌──────────────────────────────────────────┐
│ 商品状态流转 │
└──────────────────────────────────────────┘
发布商品 创建预约单
│ │
▼ ▼
┌────────┐ 审核通过 ┌──────────┐ 下单锁定 ┌──────────┐
│PENDING │ ──────────▶ │ APPROVED │ ────────▶ │ RESERVED │
└────────┘ └──────────┘ └──────────┘
│ │ │
│ 审核拒绝 │ 卖家下架 │ 创建订单
▼ ▼ ▼
┌────────┐ ┌──────────┐ ┌────────┐
│REJECTED│ │OFF_SHELF │ │ INIT │ ◀─── 订单状态
└────────┘ └──────────┘ └────────┘
│
┌──────────┴──────────┐
│ │
双方确认 取消
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│CONFIRMED │ │CANCELLED │
└──────────┘ └──────────┘
│ │
线下完成 商品恢复 APPROVED
│
▼
┌──────────┐
│COMPLETED │
└──────────┘
│
评价
│
▼
┌──────────┐
│ REVIEWED │
└──────────┘
```
> **关键安全点**:下单原子锁定、状态变更严格校验、取消自动释放商品、一单一评信用分机制
---
## 快速启动
### 前置条件
| 工具 | 版本要求 |
|:---:|:---:|
| Java | 17+ |
| Maven | 3.8+ |
| Node.js | 18+ |
| Docker | 最新版 |
### 一键启动
```bash
# 1. 克隆项目
git clone https://github.com/your-org/campusswap-saas.git
cd campusswap-saas
# 2. 启动 MySQL + Redis
docker-compose up -d
# 3. 启动后端
cd backend && mvn spring-boot:run
# 4. 启动管理端
cd admin-web && npm install && npm run dev
# 5. 启动用户端 H5
cd client-app && npm install && npm run dev:h5
```
启动 MinIO(可选)
```bash
docker-compose --profile minio up -d
```
MinIO 控制台:http://localhost:9001(minioadmin / minioadmin)
启动微信小程序
```bash
cd client-app
npm run dev:mp-weixin
```
用微信开发者工具打开 `dist/dev/mp-weixin` 目录
### 访问地址
| 服务 | 地址 |
|:---:|:---|
| Swagger API | http://localhost:8080/swagger-ui.html |
| 管理端 | http://localhost:5173 |
| 用户端 H5 | http://localhost:3000 |
---
## 演示账号
> 密码均为 `password123`
| 角色 | 租户编码 | 用户名 | 说明 |
|:---:|:---:|:---:|:---|
| 平台超管 | platform | superadmin | 管理所有租户 |
| 学校管理员 | demo | demoadmin | 管理 demo 大学 |
| 学生用户 | demo | alice | 普通学生 |
| 学生用户 | demo | bob | 普通学生 |
---
## 接口文档
### 接口分区
| 前缀 | 说明 | 权限 |
|:---|:---|:---:|
| `/api/public/**` | 公开接口(登录、注册、租户列表) | 无需登录 |
| `/api/app/**` | 用户端接口(商品、订单、评价、举报) | USER+ |
| `/api/admin/**` | 学校管理接口(审核、举报处理、用户管理) | TENANT_ADMIN+ |
| `/api/platform/**` | 平台管理接口(租户管理) | SUPER_ADMIN |
### 统一返回体
```json
{
"code": 0,
"message": "ok",
"data": {},
"traceId": "a1b2c3d4",
"timestamp": 1700000000000
}
```
### 错误码速查
| 错误码 | 说明 | | 错误码 | 说明 |
|:---:|:---|:---:|:---:|:---|
| `0` | 成功 | | `40400` | 资源不存在 |
| `40001` | 参数错误 | | `40900` | 状态冲突 |
| `40100` | 未登录 / Token 失效 | | `42900` | 限流触发 |
| `40300` | 无权限 | | `50000` | 系统错误 |
---
## 项目结构
```
campusswap-saas/
├── backend/ # Spring Boot 后端
│ └── src/main/java/com/campusswap/
│ ├── common/ # 通用模块(auth/enums/exception/ratelimit/tenant)
│ ├── config/ # 配置(CORS/MyBatis-Plus/Redis/Sa-Token/Swagger)
│ ├── controller/ # 控制器(admin/app/platform)
│ ├── dto/ # 数据传输对象
│ ├── entity/ # 实体类
│ ├── mapper/ # MyBatis-Plus Mapper
│ └── service/ # 业务逻辑 + 存储策略
│
├── admin-web/ # Vue3 管理端
│ └── src/
│ ├── layout/ # 布局组件
│ ├── router/ # 路由
│ ├── stores/ # Pinia 状态管理
│ └── views/ # 页面组件
│
├── client-app/ # uni-app 用户端(H5 + 小程序)
│ └── src/
│ ├── pages/ # 页面
│ ├── stores/ # Pinia 状态管理
│ └── utils/ # 请求封装
│
├── sql/ # 数据库脚本
├── docs/ # 设计文档
├── docker-compose.yml # Docker 编排
├── .env.example # 环境变量模板
└── README.md
```
---
## 环境变量
复制 `.env.example` 为 `.env` 并按需修改:
数据库配置
| 变量 | 默认值 | 说明 |
|:---|:---:|:---|
| `DB_HOST` | localhost | MySQL 地址 |
| `DB_PORT` | 3306 | MySQL 端口 |
| `DB_USER` | root | MySQL 用户名 |
| `DB_PASS` | root123 | MySQL 密码 |
| `REDIS_HOST` | localhost | Redis 地址 |
| `REDIS_PORT` | 6379 | Redis 端口 |
| `REDIS_PASS` | (空) | Redis 密码 |
存储配置
| 变量 | 默认值 | 说明 |
|:---|:---:|:---|
| `STORAGE_TYPE` | local | 存储类型:local / minio / aliyun / tencent |
| `UPLOAD_PATH` | ./uploads | 本地存储路径 |
| `MINIO_ENDPOINT` | http://localhost:9000 | MinIO 地址 |
| `MINIO_ACCESS_KEY` | minioadmin | MinIO 访问密钥 |
| `MINIO_SECRET_KEY` | minioadmin | MinIO 秘密密钥 |
| `MINIO_BUCKET` | campusswap | MinIO 桶名 |
云存储配置
| 变量 | 说明 |
|:---|:---|
| `ALIYUN_OSS_ENDPOINT` | 阿里云 OSS Endpoint |
| `ALIYUN_OSS_ACCESS_KEY_ID` | 阿里云 AccessKeyId |
| `ALIYUN_OSS_ACCESS_KEY_SECRET` | 阿里云 AccessKeySecret |
| `ALIYUN_OSS_BUCKET` | 阿里云 OSS 桶名 |
| `TENCENT_COS_SECRET_ID` | 腾讯云 SecretId |
| `TENCENT_COS_SECRET_KEY` | 腾讯云 SecretKey |
| `TENCENT_COS_REGION` | 腾讯云 COS 地域 |
| `TENCENT_COS_BUCKET` | 腾讯云 COS 桶名 |
---
## Roadmap
### 已完成
- [x] 多租户数据隔离
- [x] Sa-Token 鉴权与权限
- [x] 商品发布与审核
- [x] 预约单与交易状态机
- [x] 评价与信用分
- [x] 举报与运营处理
- [x] 审计日志与安全事件
- [x] IP / 用户级限流
- [x] 多存储支持(Local / MinIO / 阿里云 OSS / 腾讯云 COS)
- [x] 管理端 Web(Vue3 + Element Plus)
- [x] 用户端 uni-app(H5 + 微信小程序)
### 规划中
- [ ] 担保交易 / 支付插件
- [ ] IM 即时通讯
- [ ] 短信 / 邮箱验证码
- [ ] 商品推荐算法
- [ ] 数据导出
- [ ] 敏感词过滤增强
- [ ] Kubernetes 部署方案
---
## 参与贡献
欢迎提交 Issue 和 Pull Request!
- [贡献指南](CONTRIBUTING.md)
- [安全漏洞报告](SECURITY.md)
---
## License
本项目基于 [MIT License](LICENSE) 开源。