小程序开发文档

This commit is contained in:
zpc 2026-02-09 08:02:54 +08:00
parent 9f8df3061a
commit 501bdcc999
5 changed files with 2891 additions and 0 deletions

101
uniapp/README.md Normal file
View File

@ -0,0 +1,101 @@
# 学业邑规划 - 小程序前端
## 项目概述
基于 UniApp + Vue 3 + TypeScript 开发的微信小程序,提供多元智能测评和学业规划服务。
## 技术栈
| 技术 | 版本 | 说明 |
|------|------|------|
| UniApp | 3.x | 跨平台框架 |
| Vue | 3.x | 前端框架 |
| TypeScript | 5.x | 类型系统 |
| Pinia | 2.x | 状态管理 |
| uni-ui | latest | UI 组件库 |
| Sass | latest | CSS 预处理器 |
## 快速开始
```bash
# 安装依赖
npm install
# 开发模式(微信小程序)
npm run dev:mp-weixin
# 构建生产版本
npm run build:mp-weixin
```
## 项目结构
```
uniapp/
├── src/
│ ├── api/ # API 接口
│ │ ├── request.ts # 请求封装
│ │ ├── user.ts # 用户接口
│ │ ├── home.ts # 首页接口
│ │ ├── assessment.ts # 测评接口
│ │ ├── order.ts # 订单接口
│ │ ├── planner.ts # 规划师接口
│ │ └── invite.ts # 分销接口
│ ├── components/ # 公共组件
│ │ ├── common/ # 通用组件
│ │ └── business/ # 业务组件
│ ├── composables/ # 组合式函数
│ │ ├── useAuth.ts # 认证相关
│ │ ├── usePayment.ts # 支付相关
│ │ └── useShare.ts # 分享相关
│ ├── pages/ # 页面
│ │ ├── index/ # 首页TabBar
│ │ ├── team/ # 团队TabBar
│ │ ├── mine/ # 我的TabBar
│ │ ├── login/ # 登录
│ │ ├── assessment/ # 测评相关
│ │ ├── order/ # 订单相关
│ │ ├── planner/ # 学业规划
│ │ ├── invite/ # 邀请分销
│ │ └── about/ # 关于/协议
│ ├── static/ # 静态资源
│ │ ├── images/ # 图片
│ │ └── icons/ # 图标
│ ├── stores/ # Pinia 状态管理
│ │ ├── user.ts # 用户状态
│ │ └── app.ts # 应用状态
│ ├── styles/ # 全局样式
│ │ ├── variables.scss # 变量定义
│ │ ├── mixins.scss # 混入
│ │ └── common.scss # 通用样式
│ ├── types/ # 类型定义
│ │ ├── api.d.ts # API 类型
│ │ ├── user.d.ts # 用户类型
│ │ └── assessment.d.ts # 测评类型
│ ├── utils/ # 工具函数
│ │ ├── storage.ts # 本地存储
│ │ ├── format.ts # 格式化
│ │ └── validate.ts # 验证
│ ├── App.vue # 根组件
│ ├── main.ts # 入口文件
│ ├── manifest.json # 应用配置
│ ├── pages.json # 页面配置
│ └── uni.scss # uni-app 样式变量
├── package.json
├── tsconfig.json
├── vite.config.ts
└── README.md
```
## 相关文档
- [开发规范](./docs/开发规范.md)
- [页面清单](./docs/页面清单.md)
- [组件文档](./docs/组件文档.md)
- [API 文档](./docs/API文档.md)
## 设计资源
- Figma 设计图https://www.figma.com/design/88edYGASUcyID6afiwILdf/项目?node-id=432-1991
- 本地设计图:`docs/设计图/`
- 切图资源:`docs/切图/`

920
uniapp/docs/API文档.md Normal file
View File

@ -0,0 +1,920 @@
# 学业邑规划 - 小程序 API 文档
本文档定义了小程序端调用的所有后端接口。
---
## 一、接口规范
### 1.1 基础信息
| 项目 | 说明 |
|------|------|
| 基础地址 | 开发环境:`http://localhost:5000`<br>生产环境:`https://api.example.com` |
| 请求方式 | GET / POST |
| 数据格式 | JSON |
| 认证方式 | Bearer Token |
### 1.2 请求头
```
Content-Type: application/json
Authorization: Bearer {token}
```
### 1.3 响应格式
```json
{
"code": 0,
"message": "success",
"data": {}
}
```
### 1.4 错误码
| 错误码 | 说明 |
|--------|------|
| 0 | 成功 |
| 1001 | 参数错误 |
| 1002 | 未登录 |
| 1003 | 登录已过期 |
| 1004 | 无权限 |
| 2001 | 业务错误 |
| 5000 | 系统错误 |
---
## 二、用户模块
### 2.1 微信登录
**接口**`POST /api/user/login`
**描述**:微信小程序登录
**请求参数**
```typescript
interface LoginRequest {
/** 微信 code */
code: string
/** 加密手机号数据 */
encryptedData: string
/** 加密向量 */
iv: string
/** 邀请人ID可选 */
inviteUserId?: number
}
```
**响应数据**
```typescript
interface LoginResponse {
/** 访问令牌 */
token: string
/** 刷新令牌 */
refreshToken: string
/** 用户信息 */
userInfo: UserInfo
}
interface UserInfo {
id: number
uid: string
nickname: string
avatar: string
phone: string
userLevel: number // 1普通用户 2合伙人 3渠道合伙人
createTime: string
}
```
---
### 2.2 获取用户信息
**接口**`GET /api/user/getProfile`
**描述**:获取当前登录用户信息
**响应数据**
```typescript
interface UserInfo {
id: number
uid: string
nickname: string
avatar: string
phone: string
userLevel: number
balance: number // 可提现余额
totalIncome: number // 累计收益
createTime: string
}
```
---
### 2.3 更新用户信息
**接口**`POST /api/user/updateProfile`
**描述**:更新用户昵称
**请求参数**
```typescript
interface UpdateProfileRequest {
nickname: string
}
```
**响应数据**`boolean`
---
### 2.4 更新头像
**接口**`POST /api/user/updateAvatar`
**描述**:更新用户头像
**请求参数**
```typescript
interface UpdateAvatarRequest {
/** 头像文件Base64 或 URL */
avatar: string
}
```
**响应数据**
```typescript
interface UpdateAvatarResponse {
/** 新头像 URL */
avatarUrl: string
}
```
---
## 三、首页模块
### 3.1 获取 Banner 列表
**接口**`GET /api/home/getBannerList`
**描述**:获取首页轮播图列表
**响应数据**
```typescript
interface BannerItem {
id: number
title: string
imageUrl: string
linkType: number // 0无跳转 1内部页面 2外部链接 3小程序
linkUrl: string
appId?: string // 小程序 AppId
}
type Response = BannerItem[]
```
---
### 3.2 获取测评入口列表
**接口**`GET /api/home/getAssessmentList`
**描述**:获取测评类型列表
**响应数据**
```typescript
interface AssessmentType {
id: number
name: string
code: string
imageUrl: string
price: number
status: number // 0已下线 1已上线 2即将上线
}
type Response = AssessmentType[]
```
---
### 3.3 获取宣传图列表
**接口**`GET /api/home/getPromotionList`
**描述**:获取首页底部宣传图
**响应数据**
```typescript
interface PromotionItem {
id: number
title: string
imageUrl: string
}
type Response = PromotionItem[]
```
---
## 四、团队模块
### 4.1 获取团队介绍
**接口**`GET /api/team/getInfo`
**描述**:获取团队介绍图片
**响应数据**
```typescript
interface TeamInfo {
images: string[] // 图片列表
}
```
---
## 五、测评模块
### 5.1 获取测评介绍
**接口**`GET /api/assessment/getIntro`
**描述**:获取测评介绍内容(基本信息页顶部)
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| typeId | number | 是 | 测评类型ID |
**响应数据**
```typescript
interface AssessmentIntro {
/** 介绍内容富文本或图片URL */
content: string
/** 内容类型text / image */
contentType: string
/** 测评价格 */
price: number
}
```
---
### 5.2 获取题目列表
**接口**`GET /api/assessment/getQuestionList`
**描述**:获取测评题目列表
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| typeId | number | 是 | 测评类型ID |
**响应数据**
```typescript
interface Question {
id: number
questionNo: number
content: string
}
type Response = Question[]
```
---
### 5.3 提交测评答案
**接口**`POST /api/assessment/submitAnswers`
**描述**:提交测评答案
**请求参数**
```typescript
interface SubmitAnswersRequest {
/** 测评记录ID */
recordId: number
/** 答案列表 */
answers: {
questionId: number
answerValue: number // 1-10
}[]
}
```
**响应数据**
```typescript
interface SubmitAnswersResponse {
/** 是否提交成功 */
success: boolean
/** 报告预计生成时间(秒) */
estimatedTime: number
}
```
---
### 5.4 查询报告生成状态
**接口**`GET /api/assessment/getResultStatus`
**描述**:查询测评报告生成状态
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| recordId | number | 是 | 测评记录ID |
**响应数据**
```typescript
interface ResultStatus {
/** 状态1待测评 2测评中 3生成中 4已完成 */
status: number
/** 是否完成 */
isCompleted: boolean
}
```
---
### 5.5 获取测评结果
**接口**`GET /api/assessment/getResult`
**描述**:获取测评报告详情
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| recordId | number | 是 | 测评记录ID |
**响应数据**
```typescript
interface AssessmentResult {
/** 基本信息 */
basicInfo: {
name: string
age: number
educationStage: string
testDate: string
}
/** 八大智能分析 */
intelligenceAnalysis: {
items: IntelligenceItem[]
topTwo: IntelligenceConclusion[]
bottomTwo: IntelligenceConclusion[]
}
/** 个人特质分析 */
traitAnalysis: {
items: TraitItem[]
topConclusion: string
}
/** 40项细分能力 */
abilityAnalysis: {
groups: AbilityGroup[]
topTen: AbilityItem[]
bottomTen: AbilityItem[]
}
/** 其他分析... */
}
interface IntelligenceItem {
name: string
code: string
score: number
maxScore: number
percentage: number
rank: number
}
interface IntelligenceConclusion {
name: string
rank: number
rankName: string // 最强五星 / 较强五星 / 相对较弱
conclusion: string
}
```
---
### 5.6 验证邀请码
**接口**`POST /api/assessment/verifyInviteCode`
**描述**:验证测评邀请码
**请求参数**
```typescript
interface VerifyInviteCodeRequest {
/** 邀请码5位大写字母 */
code: string
}
```
**响应数据**
```typescript
interface VerifyInviteCodeResponse {
/** 是否有效 */
isValid: boolean
/** 错误信息(无效时) */
errorMessage?: string // "邀请码有误" / "邀请码已被使用"
/** 邀请码ID有效时 */
inviteCodeId?: number
}
```
---
### 5.7 获取往期测评列表
**接口**`GET /api/assessment/getHistoryList`
**描述**:获取用户的往期测评记录
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | number | 否 | 页码默认1 |
| pageSize | number | 否 | 每页数量默认20 |
**响应数据**
```typescript
interface AssessmentHistory {
id: number
orderNo: string
assessmentName: string
status: number // 3生成中 4已完成
statusText: string
testDate: string
}
interface PageResponse {
list: AssessmentHistory[]
total: number
page: number
pageSize: number
totalPages: number
}
```
---
## 六、订单模块
### 6.1 获取订单列表
**接口**`GET /api/order/getList`
**描述**:获取用户订单列表
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | number | 否 | 页码默认1 |
| pageSize | number | 否 | 每页数量默认20 |
| orderType | number | 否 | 订单类型1测评 2学业规划 |
**响应数据**
```typescript
interface OrderItem {
id: number
orderNo: string
orderType: number
productName: string
amount: number
status: number
statusText: string
createTime: string
/** 测评记录ID测评订单 */
assessmentRecordId?: number
}
interface PageResponse {
list: OrderItem[]
total: number
page: number
pageSize: number
totalPages: number
}
```
---
### 6.2 获取订单详情
**接口**`GET /api/order/getDetail`
**描述**:获取订单详情
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderId | number | 是 | 订单ID |
**响应数据**
```typescript
interface OrderDetail {
id: number
orderNo: string
orderType: number
productId: number
productName: string
amount: number
payAmount: number
payType: number
status: number
statusText: string
payTime?: string
createTime: string
/** 测评相关 */
assessmentRecord?: {
id: number
status: number
name: string
phone: string
}
/** 学业规划相关 */
plannerBooking?: {
id: number
plannerName: string
bookingDate: string
bookingTime: string
}
}
```
---
### 6.3 创建订单
**接口**`POST /api/order/create`
**描述**:创建订单
**请求参数**
```typescript
interface CreateOrderRequest {
/** 订单类型1测评 2学业规划 */
orderType: number
/** 商品ID测评类型ID / 规划师ID */
productId: number
/** 测评基本信息(测评订单必填) */
assessmentInfo?: {
name: string
phone: string
gender: number
age: number
educationStage: number
province: string
city: string
district: string
}
/** 规划预约信息(学业规划订单必填) */
plannerInfo?: {
bookingDate: string
bookingTime: string
name: string
phone: string
gender: number
grade: number
majorName?: string
scoreChinese?: number
scoreMath?: number
scoreEnglish?: number
scorePhysics?: number
scoreChemistry?: number
scoreBiology?: number
scoreGeography?: number
scorePolitics?: number
}
/** 邀请码ID使用邀请码时 */
inviteCodeId?: number
}
```
**响应数据**
```typescript
interface CreateOrderResponse {
/** 订单ID */
orderId: number
/** 订单编号 */
orderNo: string
/** 支付金额 */
payAmount: number
/** 是否需要支付(使用邀请码时为 false */
needPay: boolean
/** 测评记录ID测评订单 */
assessmentRecordId?: number
}
```
---
### 6.4 发起支付
**接口**`POST /api/order/pay`
**描述**:发起微信支付
**请求参数**
```typescript
interface PayRequest {
/** 订单ID */
orderId: number
}
```
**响应数据**
```typescript
interface PayResponse {
/** 微信支付参数 */
timeStamp: string
nonceStr: string
package: string
signType: string
paySign: string
}
```
---
### 6.5 查询支付结果
**接口**`GET /api/order/getPayResult`
**描述**:查询订单支付结果
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderId | number | 是 | 订单ID |
**响应数据**
```typescript
interface PayResult {
/** 是否支付成功 */
isPaid: boolean
/** 订单状态 */
status: number
/** 测评记录ID测评订单 */
assessmentRecordId?: number
}
```
---
## 七、学业规划模块
### 7.1 获取规划师列表
**接口**`GET /api/planner/getList`
**描述**:获取规划师列表
**响应数据**
```typescript
interface PlannerInfo {
id: number
name: string
avatar: string
introduction: string
price: number
}
type Response = PlannerInfo[]
```
---
### 7.2 预约规划
**接口**`POST /api/planner/book`
**描述**:预约学业规划(创建订单并支付)
**请求参数**:同 `创建订单` 接口的 `plannerInfo`
**响应数据**:同 `创建订单` 接口
---
## 八、分销模块
### 8.1 获取邀请信息
**接口**`GET /api/invite/getInfo`
**描述**:获取邀请页面信息
**响应数据**
```typescript
interface InviteInfo {
/** 邀请链接 */
inviteUrl: string
/** 邀请码 */
inviteCode: string
/** 已提现金额 */
withdrawnAmount: number
/** 待提现金额 */
pendingAmount: number
/** 邀请人数 */
inviteCount: number
}
```
---
### 8.2 生成邀请二维码
**接口**`GET /api/invite/getQrcode`
**描述**:生成邀请二维码图片
**响应数据**
```typescript
interface QrcodeResponse {
/** 二维码图片 URL */
qrcodeUrl: string
}
```
---
### 8.3 获取邀请记录
**接口**`GET /api/invite/getRecordList`
**描述**:获取邀请记录列表
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | number | 否 | 页码 |
| pageSize | number | 否 | 每页数量 |
**响应数据**
```typescript
interface InviteRecord {
/** 用户ID */
userId: number
/** 用户昵称 */
nickname: string
/** 用户头像 */
avatar: string
/** 用户UID */
uid: string
/** 注册日期 */
registerDate: string
/** 贡献佣金 */
commission: number
}
interface PageResponse {
list: InviteRecord[]
total: number
page: number
pageSize: number
totalPages: number
}
```
---
### 8.4 获取佣金信息
**接口**`GET /api/invite/getCommission`
**描述**:获取佣金详情
**响应数据**
```typescript
interface CommissionInfo {
/** 累计收益 */
totalIncome: number
/** 已提现 */
withdrawnAmount: number
/** 待提现 */
pendingAmount: number
}
```
---
### 8.5 申请提现
**接口**`POST /api/invite/applyWithdraw`
**描述**:申请提现
**请求参数**
```typescript
interface ApplyWithdrawRequest {
/** 提现金额整数最低1元 */
amount: number
}
```
**响应数据**
```typescript
interface ApplyWithdrawResponse {
/** 是否成功 */
success: boolean
/** 错误信息 */
errorMessage?: string // "超出待提现金额"
/** 提现单号 */
withdrawalNo?: string
}
```
---
### 8.6 获取提现记录
**接口**`GET /api/invite/getWithdrawList`
**描述**:获取提现记录列表
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | number | 否 | 页码 |
| pageSize | number | 否 | 每页数量 |
**响应数据**
```typescript
interface WithdrawRecord {
id: number
withdrawalNo: string
amount: number
status: number // 1申请中 2提现中 3已提现 4已取消
statusText: string
createTime: string
payTime?: string
}
interface PageResponse {
list: WithdrawRecord[]
total: number
page: number
pageSize: number
totalPages: number
}
```
---
## 九、系统模块
### 9.1 获取用户协议
**接口**`GET /api/system/getAgreement`
**描述**:获取用户协议内容
**响应数据**
```typescript
interface AgreementResponse {
/** 协议内容(富文本) */
content: string
}
```
---
### 9.2 获取隐私政策
**接口**`GET /api/system/getPrivacy`
**描述**:获取隐私政策内容
**响应数据**
```typescript
interface PrivacyResponse {
/** 政策内容(富文本) */
content: string
}
```
---
### 9.3 获取关于我们
**接口**`GET /api/system/getAbout`
**描述**:获取关于我们内容
**响应数据**
```typescript
interface AboutResponse {
/** 内容(富文本) */
content: string
/** 版本号 */
version: string
}
```

895
uniapp/docs/开发规范.md Normal file
View File

@ -0,0 +1,895 @@
# 学业邑规划 - 小程序开发规范
本文档定义了小程序前端的开发规范和编码标准,所有开发工作必须遵循这些规范。
---
## 一、命名规范
### 1.1 文件命名
| 类型 | 规范 | 示例 |
|------|------|------|
| 页面文件夹 | kebab-case | `assessment-info/`, `order-list/` |
| 页面文件 | index.vue | `pages/login/index.vue` |
| 组件文件 | PascalCase | `UserAvatar.vue`, `OrderCard.vue` |
| 组合式函数 | use + camelCase | `useAuth.ts`, `usePayment.ts` |
| 工具函数 | camelCase | `format.ts`, `validate.ts` |
| 类型定义 | camelCase + .d.ts | `user.d.ts`, `api.d.ts` |
| 样式文件 | kebab-case | `variables.scss`, `common.scss` |
### 1.2 代码命名
| 类型 | 规范 | 示例 |
|------|------|------|
| 组件名 | PascalCase | `UserAvatar`, `OrderCard` |
| 变量/函数 | camelCase | `userInfo`, `handleSubmit` |
| 常量 | UPPER_SNAKE_CASE | `API_BASE_URL`, `MAX_PAGE_SIZE` |
| 类型/接口 | PascalCase | `UserInfo`, `OrderStatus` |
| 枚举 | PascalCase | `OrderStatus`, `UserLevel` |
| CSS 类名 | kebab-case | `user-avatar`, `order-card` |
| 事件名 | on + 动词 | `onClick`, `onSubmit`, `onChange` |
| Props | camelCase | `userId`, `showHeader` |
| Emits | kebab-case | `@update:value`, `@item-click` |
### 1.3 命名示例
```typescript
// ✅ 建议
const userInfo = ref<UserInfo | null>(null)
const isLoading = ref(false)
const orderList = ref<OrderItem[]>([])
function handleLogin() { }
function fetchUserInfo() { }
function formatPrice(price: number) { }
// ❌ 不建议
const user_info = ref(null) // 不使用下划线
const data = ref([]) // 命名太模糊
const info = ref(null) // 命名太模糊
function login() { } // 缺少动词前缀
```
---
## 二、项目结构规范
### 2.1 页面结构
每个页面文件夹包含:
```
pages/assessment/info/
├── index.vue # 页面主文件
├── components/ # 页面私有组件(可选)
│ └── InfoForm.vue
└── composables/ # 页面私有组合式函数(可选)
└── useInfoForm.ts
```
### 2.2 组件分类
```
components/
├── common/ # 通用组件(与业务无关)
│ ├── AppButton.vue # 按钮
│ ├── AppModal.vue # 弹窗
│ ├── AppEmpty.vue # 空状态
│ ├── AppLoading.vue # 加载
│ └── AppNavbar.vue # 导航栏
├── business/ # 业务组件(与业务相关)
│ ├── UserAvatar.vue # 用户头像
│ ├── OrderCard.vue # 订单卡片
│ ├── AssessmentCard.vue # 测评卡片
│ └── PlannerCard.vue # 规划师卡片
└── layout/ # 布局组件
└── TabBar.vue # 底部导航
```
---
## 三、Vue 组件规范
### 3.1 组件结构
```vue
<script setup lang="ts">
/**
* 组件名称
* @description 组件描述
*/
// 1. 导入
import { ref, computed, onMounted } from 'vue'
import type { UserInfo } from '@/types/user'
import { useUserStore } from '@/stores/user'
import { getUserInfo } from '@/api/user'
// 2. Props 定义
interface Props {
/** 用户ID */
userId: number
/** 是否显示头像 */
showAvatar?: boolean
}
const props = withDefaults(defineProps<Props>(), {
showAvatar: true
})
// 3. Emits 定义
interface Emits {
(e: 'click', user: UserInfo): void
(e: 'update:value', value: string): void
}
const emit = defineEmits<Emits>()
// 4. 响应式状态
const loading = ref(false)
const userInfo = ref<UserInfo | null>(null)
// 5. 计算属性
const displayName = computed(() => {
return userInfo.value?.nickname || '未知用户'
})
// 6. 方法
async function fetchData() {
loading.value = true
try {
userInfo.value = await getUserInfo(props.userId)
} finally {
loading.value = false
}
}
function handleClick() {
if (userInfo.value) {
emit('click', userInfo.value)
}
}
// 7. 生命周期
onMounted(() => {
fetchData()
})
// 8. 暴露方法(可选)
defineExpose({
refresh: fetchData
})
</script>
<template>
<view class="user-card" @click="handleClick">
<image
v-if="showAvatar"
class="user-card__avatar"
:src="userInfo?.avatar"
/>
<text class="user-card__name">{{ displayName }}</text>
</view>
</template>
<style lang="scss" scoped>
.user-card {
display: flex;
align-items: center;
padding: 24rpx;
&__avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
&__name {
margin-left: 16rpx;
font-size: 28rpx;
color: $text-color;
}
}
</style>
```
### 3.2 Props 规范
```typescript
// ✅ 建议:使用 TypeScript 接口定义
interface Props {
/** 用户ID必填 */
userId: number
/** 标题 */
title?: string
/** 是否显示 */
visible?: boolean
/** 列表数据 */
list?: OrderItem[]
}
const props = withDefaults(defineProps<Props>(), {
title: '默认标题',
visible: false,
list: () => []
})
// ❌ 不建议:使用运行时声明
const props = defineProps({
userId: {
type: Number,
required: true
}
})
```
### 3.3 Emits 规范
```typescript
// ✅ 建议:使用 TypeScript 接口定义
interface Emits {
(e: 'submit', data: FormData): void
(e: 'cancel'): void
(e: 'update:visible', value: boolean): void
}
const emit = defineEmits<Emits>()
// 触发事件
emit('submit', formData)
emit('update:visible', false)
```
---
## 四、TypeScript 规范
### 4.1 类型定义
```typescript
// types/user.d.ts
/** 用户等级 */
export enum UserLevel {
/** 普通用户 */
Normal = 1,
/** 合伙人 */
Partner = 2,
/** 渠道合伙人 */
ChannelPartner = 3
}
/** 用户信息 */
export interface UserInfo {
/** 用户ID */
id: number
/** 用户UID */
uid: string
/** 昵称 */
nickname: string
/** 头像 */
avatar: string
/** 手机号 */
phone: string
/** 用户等级 */
userLevel: UserLevel
/** 创建时间 */
createTime: string
}
/** 登录请求参数 */
export interface LoginRequest {
/** 微信 code */
code: string
/** 加密手机号数据 */
encryptedData: string
/** 加密向量 */
iv: string
}
/** 登录响应 */
export interface LoginResponse {
/** 访问令牌 */
token: string
/** 刷新令牌 */
refreshToken: string
/** 用户信息 */
userInfo: UserInfo
}
```
### 4.2 API 类型
```typescript
// types/api.d.ts
/** 通用响应结构 */
export interface ApiResponse<T = any> {
/** 状态码 */
code: number
/** 提示信息 */
message: string
/** 业务数据 */
data: T
}
/** 分页请求参数 */
export interface PageRequest {
/** 页码 */
page?: number
/** 每页数量 */
pageSize?: number
}
/** 分页响应 */
export interface PageResponse<T> {
/** 列表数据 */
list: T[]
/** 总数 */
total: number
/** 当前页 */
page: number
/** 每页数量 */
pageSize: number
/** 总页数 */
totalPages: number
}
```
### 4.3 类型使用
```typescript
// ✅ 建议:明确类型
const userInfo = ref<UserInfo | null>(null)
const orderList = ref<OrderItem[]>([])
const loading = ref<boolean>(false)
// ✅ 函数参数和返回值类型
function formatPrice(price: number): string {
return `¥${price.toFixed(2)}`
}
async function fetchOrders(params: PageRequest): Promise<PageResponse<OrderItem>> {
const res = await request.get<PageResponse<OrderItem>>('/api/order/getList', { params })
return res.data
}
// ❌ 不建议:使用 any
const data: any = {}
function handleData(data: any) { }
```
---
## 五、API 请求规范
### 5.1 请求封装
```typescript
// api/request.ts
import type { ApiResponse } from '@/types/api'
const BASE_URL = import.meta.env.VITE_API_BASE_URL
interface RequestOptions {
url: string
method?: 'GET' | 'POST'
data?: any
params?: any
showLoading?: boolean
showError?: boolean
}
class Request {
private getToken(): string {
return uni.getStorageSync('token') || ''
}
async request<T = any>(options: RequestOptions): Promise<ApiResponse<T>> {
const { url, method = 'GET', data, params, showLoading = true, showError = true } = options
if (showLoading) {
uni.showLoading({ title: '加载中...' })
}
try {
const res = await uni.request({
url: BASE_URL + url,
method,
data: method === 'POST' ? data : undefined,
header: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.getToken()}`
}
})
const result = res.data as ApiResponse<T>
if (result.code !== 0) {
if (showError) {
uni.showToast({ title: result.message, icon: 'none' })
}
throw new Error(result.message)
}
return result
} finally {
if (showLoading) {
uni.hideLoading()
}
}
}
get<T = any>(url: string, options?: Partial<RequestOptions>) {
return this.request<T>({ url, method: 'GET', ...options })
}
post<T = any>(url: string, data?: any, options?: Partial<RequestOptions>) {
return this.request<T>({ url, method: 'POST', data, ...options })
}
}
export const request = new Request()
```
### 5.2 API 模块
```typescript
// api/user.ts
import { request } from './request'
import type { LoginRequest, LoginResponse, UserInfo } from '@/types/user'
/**
* 微信登录
*/
export function login(data: LoginRequest) {
return request.post<LoginResponse>('/api/user/login', data)
}
/**
* 获取用户信息
*/
export function getUserProfile() {
return request.get<UserInfo>('/api/user/getProfile')
}
/**
* 更新用户信息
*/
export function updateProfile(data: Partial<UserInfo>) {
return request.post<boolean>('/api/user/updateProfile', data)
}
```
### 5.3 API 调用
```typescript
// 在组件中使用
import { getUserProfile } from '@/api/user'
async function fetchUserInfo() {
try {
const res = await getUserProfile()
userInfo.value = res.data
} catch (error) {
console.error('获取用户信息失败', error)
}
}
```
---
## 六、状态管理规范
### 6.1 Store 定义
```typescript
// stores/user.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { UserInfo } from '@/types/user'
import { getUserProfile, login } from '@/api/user'
export const useUserStore = defineStore('user', () => {
// 状态
const token = ref<string>('')
const userInfo = ref<UserInfo | null>(null)
// 计算属性
const isLoggedIn = computed(() => !!token.value)
const isPartner = computed(() => (userInfo.value?.userLevel ?? 0) >= 2)
// 方法
async function loginAction(code: string, encryptedData: string, iv: string) {
const res = await login({ code, encryptedData, iv })
token.value = res.data.token
userInfo.value = res.data.userInfo
uni.setStorageSync('token', res.data.token)
}
async function fetchUserInfo() {
if (!token.value) return
const res = await getUserProfile()
userInfo.value = res.data
}
function logout() {
token.value = ''
userInfo.value = null
uni.removeStorageSync('token')
}
// 初始化
function init() {
token.value = uni.getStorageSync('token') || ''
if (token.value) {
fetchUserInfo()
}
}
return {
token,
userInfo,
isLoggedIn,
isPartner,
loginAction,
fetchUserInfo,
logout,
init
}
})
```
### 6.2 Store 使用
```typescript
// 在组件中使用
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
// 访问状态
const { userInfo, isLoggedIn } = storeToRefs(userStore)
// 调用方法
await userStore.loginAction(code, encryptedData, iv)
userStore.logout()
```
---
## 七、样式规范
### 7.1 变量定义
```scss
// styles/variables.scss
// 主题色
$primary-color: #4A90E2;
$primary-color-light: #6BA3E8;
$primary-color-dark: #3A7BC8;
// 文字颜色
$text-color: #333333;
$text-color-secondary: #666666;
$text-color-placeholder: #999999;
$text-color-disabled: #CCCCCC;
// 背景色
$bg-color: #F5F5F5;
$bg-color-white: #FFFFFF;
$bg-color-gray: #F8F8F8;
// 边框
$border-color: #EEEEEE;
$border-radius: 8rpx;
$border-radius-lg: 16rpx;
// 间距
$spacing-xs: 8rpx;
$spacing-sm: 16rpx;
$spacing-md: 24rpx;
$spacing-lg: 32rpx;
$spacing-xl: 48rpx;
// 字体大小
$font-size-xs: 20rpx;
$font-size-sm: 24rpx;
$font-size-md: 28rpx;
$font-size-lg: 32rpx;
$font-size-xl: 36rpx;
// 安全区域
$safe-area-bottom: env(safe-area-inset-bottom);
```
### 7.2 BEM 命名
```scss
// ✅ 建议:使用 BEM 命名
.order-card {
// Block
padding: $spacing-md;
background: $bg-color-white;
// Element
&__header {
display: flex;
justify-content: space-between;
}
&__title {
font-size: $font-size-lg;
color: $text-color;
}
&__status {
font-size: $font-size-sm;
color: $text-color-secondary;
}
&__content {
margin-top: $spacing-sm;
}
&__footer {
margin-top: $spacing-md;
text-align: right;
}
// Modifier
&--active {
border-color: $primary-color;
}
&--disabled {
opacity: 0.5;
}
}
```
### 7.3 响应式单位
```scss
// ✅ 使用 rpx 作为主要单位
.container {
padding: 24rpx;
font-size: 28rpx;
border-radius: 8rpx;
}
// ✅ 固定尺寸使用 px
.icon {
width: 24px;
height: 24px;
}
// ❌ 不建议混用单位
.box {
padding: 12px 24rpx; // 不要混用
}
```
---
## 八、页面开发流程
### 8.1 开发步骤
1. **查看设计图** - 确认页面布局和交互
2. **定义类型** - 在 `types/` 下定义相关类型
3. **编写 API** - 在 `api/` 下编写接口调用
4. **创建页面** - 在 `pages/` 下创建页面文件夹
5. **配置路由** - 在 `pages.json` 中添加页面配置
6. **编写组件** - 抽取可复用组件
7. **编写样式** - 使用 BEM 命名,引用变量
8. **测试验证** - 在模拟器和真机测试
### 8.2 页面配置
```json
// pages.json
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"navigationStyle": "custom"
}
},
{
"path": "pages/assessment/info/index",
"style": {
"navigationBarTitleText": "填写信息"
}
}
],
"tabBar": {
"color": "#999999",
"selectedColor": "#4A90E2",
"backgroundColor": "#FFFFFF",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/icons/tab-home.png",
"selectedIconPath": "static/icons/tab-home-active.png"
},
{
"pagePath": "pages/team/index",
"text": "团队",
"iconPath": "static/icons/tab-team.png",
"selectedIconPath": "static/icons/tab-team-active.png"
},
{
"pagePath": "pages/mine/index",
"text": "我的",
"iconPath": "static/icons/tab-mine.png",
"selectedIconPath": "static/icons/tab-mine-active.png"
}
]
}
}
```
---
## 九、常用工具函数
### 9.1 格式化
```typescript
// utils/format.ts
/**
* 格式化价格
*/
export function formatPrice(price: number): string {
return `¥${price.toFixed(2)}`
}
/**
* 格式化日期
*/
export function formatDate(date: string | Date, format = 'YYYY-MM-DD'): string {
const d = new Date(date)
const year = d.getFullYear()
const month = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
const hour = String(d.getHours()).padStart(2, '0')
const minute = String(d.getMinutes()).padStart(2, '0')
return format
.replace('YYYY', String(year))
.replace('MM', month)
.replace('DD', day)
.replace('HH', hour)
.replace('mm', minute)
}
/**
* 格式化手机号隐藏中间4位
*/
export function formatPhone(phone: string): string {
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
```
### 9.2 验证
```typescript
// utils/validate.ts
/**
* 验证手机号
*/
export function isValidPhone(phone: string): boolean {
return /^1[3-9]\d{9}$/.test(phone)
}
/**
* 验证邀请码5位大写字母
*/
export function isValidInviteCode(code: string): boolean {
return /^[A-Z]{5}$/.test(code)
}
```
### 9.3 存储
```typescript
// utils/storage.ts
const TOKEN_KEY = 'token'
const USER_INFO_KEY = 'userInfo'
export const storage = {
getToken(): string {
return uni.getStorageSync(TOKEN_KEY) || ''
},
setToken(token: string): void {
uni.setStorageSync(TOKEN_KEY, token)
},
removeToken(): void {
uni.removeStorageSync(TOKEN_KEY)
},
getUserInfo<T>(): T | null {
const data = uni.getStorageSync(USER_INFO_KEY)
return data ? JSON.parse(data) : null
},
setUserInfo<T>(info: T): void {
uni.setStorageSync(USER_INFO_KEY, JSON.stringify(info))
},
clear(): void {
uni.clearStorageSync()
}
}
```
---
## 十、注意事项
### 10.1 性能优化
- 图片使用 CDN 地址,避免本地大图
- 列表使用虚拟滚动或分页加载
- 避免在 `onShow` 中频繁请求数据
- 使用 `v-if` 而非 `v-show` 控制大组件显示
### 10.2 兼容性
- 使用 `rpx` 作为主要单位
- 避免使用不支持的 CSS 属性
- 测试 iOS 和 Android 两端表现
- 注意安全区域适配
### 10.3 安全
- 敏感数据不存储在本地
- Token 过期自动刷新或跳转登录
- 支付相关操作需二次确认
- 用户输入需做 XSS 过滤
---
## 十一、Git 提交规范
### 11.1 提交信息格式
```
<type>(<scope>): <subject>
<body>
```
### 11.2 Type 类型
| Type | 说明 |
|------|------|
| feat | 新功能 |
| fix | 修复 bug |
| docs | 文档更新 |
| style | 代码格式(不影响功能) |
| refactor | 重构 |
| perf | 性能优化 |
| test | 测试 |
| chore | 构建/工具 |
### 11.3 示例
```
feat(assessment): 添加测评答题页面
- 实现题目列表展示
- 实现选项选择交互
- 添加提交答案功能
```

501
uniapp/docs/组件文档.md Normal file
View File

@ -0,0 +1,501 @@
# 学业邑规划 - 组件文档
本文档定义了小程序中需要开发的公共组件和业务组件。
---
## 一、组件分类
```
components/
├── common/ # 通用组件(与业务无关)
├── business/ # 业务组件(与业务相关)
└── layout/ # 布局组件
```
---
## 二、通用组件
### 2.1 AppButton 按钮
**文件**`components/common/AppButton.vue`
**功能**:统一的按钮组件,支持多种样式和状态
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| type | string | 'primary' | 按钮类型primary / secondary / text |
| size | string | 'medium' | 按钮大小small / medium / large |
| disabled | boolean | false | 是否禁用 |
| loading | boolean | false | 是否加载中 |
| block | boolean | false | 是否块级按钮 |
**使用示例**
```vue
<AppButton type="primary" @click="handleSubmit">提交</AppButton>
<AppButton type="secondary" size="small">取消</AppButton>
<AppButton :disabled="!isValid" :loading="submitting">
支付¥99元 开始测评
</AppButton>
```
---
### 2.2 AppModal 弹窗
**文件**`components/common/AppModal.vue`
**功能**:统一的弹窗组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| visible | boolean | false | 是否显示 |
| title | string | '' | 标题 |
| showClose | boolean | true | 是否显示关闭按钮 |
| maskClosable | boolean | true | 点击遮罩是否关闭 |
**Emits**
| 事件 | 参数 | 说明 |
|------|------|------|
| update:visible | boolean | 显示状态变化 |
| close | - | 关闭事件 |
**使用示例**
```vue
<AppModal v-model:visible="showModal" title="提示">
<text>确定要退出登录吗?</text>
<template #footer>
<AppButton type="secondary" @click="showModal = false">取消</AppButton>
<AppButton type="primary" @click="handleConfirm">确定</AppButton>
</template>
</AppModal>
```
---
### 2.3 AppEmpty 空状态
**文件**`components/common/AppEmpty.vue`
**功能**:列表为空时的占位组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| image | string | 默认图片 | 空状态图片 |
| text | string | '暂无数据' | 提示文字 |
| showButton | boolean | false | 是否显示按钮 |
| buttonText | string | '' | 按钮文字 |
**使用示例**
```vue
<AppEmpty text="暂无订单" />
<AppEmpty
text="暂无测评记录"
:showButton="true"
buttonText="去测评"
@click="goAssessment"
/>
```
---
### 2.4 AppLoading 加载
**文件**`components/common/AppLoading.vue`
**功能**:加载状态组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| loading | boolean | false | 是否加载中 |
| text | string | '加载中...' | 加载文字 |
| fullscreen | boolean | false | 是否全屏 |
**使用示例**
```vue
<AppLoading :loading="isLoading" />
<AppLoading :loading="isLoading" text="报告生成中..." :fullscreen="true" />
```
---
### 2.5 AppNavbar 导航栏
**文件**`components/common/AppNavbar.vue`
**功能**:自定义导航栏(用于 navigationStyle: custom 的页面)
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| title | string | '' | 标题 |
| showBack | boolean | true | 是否显示返回按钮 |
| showHome | boolean | false | 是否显示首页按钮 |
| bgColor | string | '#fff' | 背景色 |
| textColor | string | '#333' | 文字颜色 |
**使用示例**
```vue
<AppNavbar title="测评结果" :showBack="true" />
<AppNavbar title="首页" :showBack="false" bgColor="transparent" textColor="#fff" />
```
---
### 2.6 AppInput 输入框
**文件**`components/common/AppInput.vue`
**功能**:统一的输入框组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| modelValue | string | '' | 输入值 |
| type | string | 'text' | 输入类型 |
| placeholder | string | '' | 占位文字 |
| disabled | boolean | false | 是否禁用 |
| maxlength | number | -1 | 最大长度 |
| error | string | '' | 错误提示 |
**使用示例**
```vue
<AppInput
v-model="form.name"
placeholder="请输入姓名"
:error="errors.name"
/>
```
---
### 2.7 AppPicker 选择器
**文件**`components/common/AppPicker.vue`
**功能**:统一的选择器组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| modelValue | any | null | 选中值 |
| options | array | [] | 选项列表 |
| placeholder | string | '请选择' | 占位文字 |
| labelKey | string | 'label' | 显示字段 |
| valueKey | string | 'value' | 值字段 |
**使用示例**
```vue
<AppPicker
v-model="form.age"
:options="ageOptions"
placeholder="请选择年龄"
/>
```
---
### 2.8 AppRegionPicker 地区选择器
**文件**`components/common/AppRegionPicker.vue`
**功能**:省市区三级联动选择器
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| province | string | '' | 省份 |
| city | string | '' | 城市 |
| district | string | '' | 区县 |
**Emits**
| 事件 | 参数 | 说明 |
|------|------|------|
| change | { province, city, district } | 选择变化 |
**使用示例**
```vue
<AppRegionPicker
:province="form.province"
:city="form.city"
:district="form.district"
@change="handleRegionChange"
/>
```
---
## 三、业务组件
### 3.1 UserAvatar 用户头像
**文件**`components/business/UserAvatar.vue`
**功能**:用户头像展示组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| src | string | '' | 头像地址 |
| size | string | 'medium' | 大小small / medium / large |
| showLevel | boolean | false | 是否显示等级标识 |
| level | number | 1 | 用户等级 |
**使用示例**
```vue
<UserAvatar :src="userInfo.avatar" size="large" />
<UserAvatar :src="userInfo.avatar" :showLevel="true" :level="userInfo.userLevel" />
```
---
### 3.2 OrderCard 订单卡片
**文件**`components/business/OrderCard.vue`
**功能**:订单列表项组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| order | OrderItem | required | 订单数据 |
**Emits**
| 事件 | 参数 | 说明 |
|------|------|------|
| action | { type, order } | 操作按钮点击 |
**使用示例**
```vue
<OrderCard
v-for="order in orderList"
:key="order.id"
:order="order"
@action="handleOrderAction"
/>
```
---
### 3.3 AssessmentCard 测评入口卡片
**文件**`components/business/AssessmentCard.vue`
**功能**:首页测评入口组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| assessment | AssessmentType | required | 测评类型数据 |
**Emits**
| 事件 | 参数 | 说明 |
|------|------|------|
| click | AssessmentType | 点击事件 |
**使用示例**
```vue
<AssessmentCard
v-for="item in assessmentList"
:key="item.id"
:assessment="item"
@click="handleAssessmentClick"
/>
```
---
### 3.4 PlannerCard 规划师卡片
**文件**`components/business/PlannerCard.vue`
**功能**:规划师列表项组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| planner | PlannerInfo | required | 规划师数据 |
| selected | boolean | false | 是否选中 |
**Emits**
| 事件 | 参数 | 说明 |
|------|------|------|
| select | PlannerInfo | 选择事件 |
**使用示例**
```vue
<PlannerCard
v-for="planner in plannerList"
:key="planner.id"
:planner="planner"
:selected="selectedId === planner.id"
@select="handleSelect"
/>
```
---
### 3.5 QuestionItem 题目组件
**文件**`components/business/QuestionItem.vue`
**功能**:测评答题页的题目组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| question | Question | required | 题目数据 |
| answer | number | null | 当前答案 |
| index | number | required | 题目序号 |
**Emits**
| 事件 | 参数 | 说明 |
|------|------|------|
| change | { questionId, value } | 答案变化 |
**使用示例**
```vue
<QuestionItem
v-for="(question, index) in questionList"
:key="question.id"
:question="question"
:answer="answers[question.id]"
:index="index"
@change="handleAnswerChange"
/>
```
---
### 3.6 InviteRecord 邀请记录项
**文件**`components/business/InviteRecord.vue`
**功能**:邀请记录列表项组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| record | InviteRecord | required | 邀请记录数据 |
**使用示例**
```vue
<InviteRecord
v-for="record in recordList"
:key="record.id"
:record="record"
/>
```
---
### 3.7 WithdrawRecord 提现记录项
**文件**`components/business/WithdrawRecord.vue`
**功能**:提现记录列表项组件
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| record | WithdrawRecord | required | 提现记录数据 |
**使用示例**
```vue
<WithdrawRecord
v-for="record in withdrawList"
:key="record.id"
:record="record"
/>
```
---
## 四、布局组件
### 4.1 PageContainer 页面容器
**文件**`components/layout/PageContainer.vue`
**功能**:统一的页面容器,处理安全区域
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| safeBottom | boolean | true | 是否适配底部安全区域 |
| bgColor | string | '#f5f5f5' | 背景色 |
**使用示例**
```vue
<PageContainer>
<!-- 页面内容 -->
</PageContainer>
```
---
### 4.2 ListContainer 列表容器
**文件**`components/layout/ListContainer.vue`
**功能**:带下拉刷新和上拉加载的列表容器
**Props**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| loading | boolean | false | 是否加载中 |
| finished | boolean | false | 是否加载完成 |
| emptyText | string | '暂无数据' | 空状态文字 |
**Emits**
| 事件 | 参数 | 说明 |
|------|------|------|
| refresh | - | 下拉刷新 |
| loadMore | - | 上拉加载 |
**使用示例**
```vue
<ListContainer
:loading="loading"
:finished="finished"
@refresh="handleRefresh"
@loadMore="handleLoadMore"
>
<OrderCard v-for="order in orderList" :key="order.id" :order="order" />
</ListContainer>
```
---
## 五、组件开发规范
### 5.1 组件命名
- 通用组件以 `App` 开头:`AppButton`, `AppModal`
- 业务组件使用业务名词:`UserAvatar`, `OrderCard`
- 布局组件以 `Container` 结尾:`PageContainer`, `ListContainer`
### 5.2 Props 规范
- 使用 TypeScript 接口定义
- 必填属性标注 `required`
- 提供合理的默认值
- 添加 JSDoc 注释
### 5.3 样式规范
- 使用 BEM 命名
- 使用 `scoped` 限制作用域
- 引用全局变量
- 避免使用 `!important`
### 5.4 事件规范
- 使用 `emit` 定义类型
- 事件名使用 kebab-case
- 提供完整的事件参数类型

474
uniapp/docs/页面清单.md Normal file
View File

@ -0,0 +1,474 @@
# 学业邑规划 - 小程序页面清单
本文档列出所有小程序页面的详细信息,包括路由、功能、状态和开发优先级。
---
## 一、页面总览
| 序号 | 页面名称 | 路由 | 优先级 | 状态 |
|------|----------|------|--------|------|
| 1 | 首页 | /pages/index/index | P0 | 待开发 |
| 2 | 团队页 | /pages/team/index | P0 | 待开发 |
| 3 | 我的页 | /pages/mine/index | P0 | 待开发 |
| 4 | 登录页 | /pages/login/index | P0 | 待开发 |
| 5 | 个人资料页 | /pages/mine/profile/index | P1 | 待开发 |
| 6 | 业务详情页 | /pages/business/detail/index | P1 | 待开发 |
| 7 | 测评-信息填写 | /pages/assessment/info/index | P0 | 待开发 |
| 8 | 测评-答题页 | /pages/assessment/questions/index | P0 | 待开发 |
| 9 | 测评-生成中 | /pages/assessment/loading/index | P0 | 待开发 |
| 10 | 测评-结果页 | /pages/assessment/result/index | P0 | 待开发 |
| 11 | 我的订单 | /pages/order/list/index | P1 | 待开发 |
| 12 | 往期测评 | /pages/assessment/history/index | P1 | 待开发 |
| 13 | 学业规划-规划师 | /pages/planner/list/index | P2 | 待开发 |
| 14 | 学业规划-预约 | /pages/planner/book/index | P2 | 待开发 |
| 15 | 邀请新用户 | /pages/invite/index | P2 | 待开发 |
| 16 | 关于页 | /pages/about/index | P3 | 待开发 |
| 17 | 用户协议 | /pages/agreement/user/index | P3 | 待开发 |
| 18 | 隐私政策 | /pages/agreement/privacy/index | P3 | 待开发 |
**优先级说明**
- P0核心功能必须首先完成
- P1重要功能核心功能完成后开发
- P2扩展功能可延后开发
- P3辅助功能最后开发
---
## 二、TabBar 页面
### 2.1 首页 (P0)
**路由**`/pages/index/index`
**设计图**`docs/设计图/首页.png`
**功能描述**
- 展示公司介绍性内容
- Banner 轮播图(可跳转)
- 测评入口列表
- 底部宣传长图
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| Banner 列表 | GET /api/home/getBannerList | 轮播图数据 |
| 测评入口 | GET /api/home/getAssessmentList | 测评类型列表 |
| 宣传图 | GET /api/home/getPromotionList | 底部宣传图 |
**交互逻辑**
- 点击 Banner → 根据跳转类型跳转
- 点击已上线测评 → 进入测评流程
- 点击即将上线测评 → 弹出提示"该测评暂未开放"
---
### 2.2 团队页 (P0)
**路由**`/pages/team/index`
**设计图**`docs/设计图/团队.png`
**功能描述**
- 展示团队介绍图片
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 团队介绍 | GET /api/team/getInfo | 团队介绍图片 |
---
### 2.3 我的页 (P0)
**路由**`/pages/mine/index`
**设计图**
- `docs/设计图/我的-未登录.png`
- `docs/设计图/我的-登录页.png`
- `docs/设计图/我的-退出登录.png`
**功能描述**
- 未登录:显示"点击登录"
- 已登录显示头像、昵称、UID
- 常用功能:我的订单、往期测评、联系我们、邀请新用户(合伙人可见)
- 其他功能:关于、用户协议、隐私政策、退出登录
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 用户信息 | GET /api/user/getProfile | 用户基本信息 |
**交互逻辑**
- 未登录点击头像区域 → 跳转登录页
- 点击各功能入口 → 跳转对应页面
- 点击退出登录 → 弹出二次确认弹窗
---
## 三、登录相关
### 3.1 登录页 (P0)
**路由**`/pages/login/index`
**设计图**`docs/设计图/登录页.png`
**功能描述**
- 微信一键登录(获取手机号)
- 用户协议和隐私政策勾选
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 登录 | POST /api/user/login | 微信登录 |
**交互逻辑**
1. 用户点击登录按钮
2. 调用 `wx.login()` 获取 code
3. 调用 `wx.getPhoneNumber()` 获取加密手机号
4. 调用后端登录接口
5. 保存 token跳转回原页面
---
### 3.2 个人资料页 (P1)
**路由**`/pages/mine/profile/index`
**设计图**`docs/设计图/个人资料.png`
**功能描述**
- 查看/修改头像
- 查看/修改昵称
- 查看 UID不可修改
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 用户信息 | GET /api/user/getProfile | 获取用户信息 |
| 更新信息 | POST /api/user/updateProfile | 更新昵称 |
| 更新头像 | POST /api/user/updateAvatar | 更新头像 |
---
## 四、测评相关
### 4.1 测评-信息填写页 (P0)
**路由**`/pages/assessment/info/index`
**设计图**
- `docs/设计图/测评-个人信息填写.png`
- `docs/设计图/测评-个人信息填写2.png`
- `docs/设计图/测评-个人信息填写3.png`
- `docs/设计图/测评-个人信息填写4.png`
**功能描述**
- 顶部测评介绍(后台配置)
- 填写基本信息:姓名、手机号、性别、年龄、学业阶段、省市区
- 两个入口按钮:支付测评、邀请码免费测评
**表单字段**
| 字段 | 类型 | 必填 | 验证规则 |
|------|------|------|----------|
| 姓名 | 文本 | 是 | 非空 |
| 手机号 | 文本 | 是 | 11位手机号格式 |
| 性别 | 单选 | 是 | 男/女 |
| 年龄 | 下拉 | 是 | 10-50岁 |
| 学业阶段 | 下拉 | 是 | 6个选项 |
| 省份 | 下拉 | 是 | 省份列表 |
| 城市 | 下拉 | 是 | 城市列表 |
| 区县 | 下拉 | 是 | 区县列表 |
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 测评介绍 | GET /api/assessment/getIntro | 顶部介绍内容 |
| 验证邀请码 | POST /api/assessment/verifyInviteCode | 验证邀请码 |
| 创建订单 | POST /api/order/create | 创建测评订单 |
| 发起支付 | POST /api/order/pay | 拉起微信支付 |
**交互逻辑**
- 有未填写项 → 按钮灰色不可点击
- 点击支付按钮 → 验证信息 → 创建订单 → 拉起支付
- 点击邀请码按钮 → 验证信息 → 弹出邀请码输入框 → 验证邀请码
---
### 4.2 测评-答题页 (P0)
**路由**`/pages/assessment/questions/index`
**设计图**
- `docs/设计图/测评-题目.png`
- `docs/设计图/测评-提交题目检验空题.png`
**功能描述**
- 展示所有题目80道
- 每题10个选项
- 底部提交按钮
- 提交时检测未答题目
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 题目列表 | GET /api/assessment/getQuestionList | 获取所有题目 |
| 提交答案 | POST /api/assessment/submitAnswers | 提交测评答案 |
**交互逻辑**
- 点击提交 → 检测未答题目
- 有未答题 → 弹窗显示未答题号
- 全部已答 → 提交答案 → 跳转生成中页面
---
### 4.3 测评-生成中页 (P0)
**路由**`/pages/assessment/loading/index`
**设计图**`docs/设计图/测评-等待测评.png`
**功能描述**
- 显示加载动画
- 提示文字
- 轮询查询报告状态
- 生成完成自动跳转
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 报告状态 | GET /api/assessment/getResultStatus | 查询报告生成状态 |
---
### 4.4 测评-结果页 (P0)
**路由**`/pages/assessment/result/index`
**设计图**:(需补充)
**功能描述**
- 展示测评报告
- 八大智能分析(雷达图)
- 个人特质分析
- 40项细分能力
- 其他分析报告
- 保存到本地PDF
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 测评结果 | GET /api/assessment/getResult | 获取完整测评报告 |
---
### 4.5 往期测评页 (P1)
**路由**`/pages/assessment/history/index`
**设计图**`docs/设计图/往期测评-空状态.png`
**功能描述**
- 展示已完成的测评列表
- 显示测评日期、订单编号、测评项目、报告状态
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 测评记录 | GET /api/assessment/getHistoryList | 获取往期测评列表 |
---
## 五、订单相关
### 5.1 我的订单页 (P1)
**路由**`/pages/order/list/index`
**设计图**
- `docs/设计图/我的订单.png`
- `docs/设计图/我的订单-空状态.png`
**功能描述**
- 展示所有订单
- 显示订单日期、编号、项目、金额、状态
- 根据状态显示不同操作按钮
**订单状态**
| 状态 | 说明 | 操作 |
|------|------|------|
| 待测评 | 已支付,未答题 | 开始测评 |
| 测评生成中 | 已答题,生成中 | - |
| 已测评 | 报告已生成 | 查看结果 |
| 退款中 | 申请退款中 | - |
| 已退款 | 退款完成 | - |
| 已支付 | 学业规划订单 | - |
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 订单列表 | GET /api/order/getList | 获取订单列表 |
---
## 六、学业规划
### 6.1 规划师选择页 (P2)
**路由**`/pages/planner/list/index`
**设计图**`docs/设计图/学业规划.png`
**功能描述**
- 展示规划师列表
- 显示照片、姓名、介绍、价格
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 规划师列表 | GET /api/planner/getList | 获取规划师列表 |
---
### 6.2 规划预约页 (P2)
**路由**`/pages/planner/book/index`
**设计图**
- `docs/设计图/学业规划2.png`
- `docs/设计图/学业规划3.png`
- `docs/设计图/学业规划4.png`
**功能描述**
- 选择预约日期和时间
- 填写个人信息
- 根据年级动态显示成绩字段
- 支付预约费
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 预约 | POST /api/planner/book | 提交预约信息 |
---
## 七、分销相关
### 7.1 邀请新用户页 (P2)
**路由**`/pages/invite/index`
**设计图**
- `docs/设计图/邀请新用户.png`
- `docs/设计图/邀请新用户-二维码.png`
- `docs/设计图/邀请新用户-提现金额.png`
- `docs/设计图/邀请新用户-提现记录.png`
**功能描述**
- 邀请规则说明
- 生成邀请二维码
- 分享邀请链接
- 已提现/待提现金额
- 申请提现
- 提现记录
- 邀请记录列表
**访问权限**:仅合伙人及以上可见
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 邀请信息 | GET /api/invite/getInfo | 获取邀请信息 |
| 生成二维码 | GET /api/invite/getQrcode | 生成邀请二维码 |
| 邀请记录 | GET /api/invite/getRecordList | 获取邀请记录 |
| 佣金信息 | GET /api/invite/getCommission | 获取佣金信息 |
| 申请提现 | POST /api/invite/applyWithdraw | 申请提现 |
| 提现记录 | GET /api/invite/getWithdrawList | 获取提现记录 |
---
## 八、其他页面
### 8.1 业务详情页 (P1)
**路由**`/pages/business/detail/index`
**设计图**`docs/设计图/业务详情页.png`
**功能描述**
- 展示业务介绍长图
- 底部"点击参与"按钮(可选)
---
### 8.2 关于页 (P3)
**路由**`/pages/about/index`
**设计图**`docs/设计图/关于.png`
**功能描述**
- 显示 LOGO
- 显示版本号
---
### 8.3 用户协议页 (P3)
**路由**`/pages/agreement/user/index`
**设计图**`docs/设计图/用户/隐私协议.png`
**功能描述**
- 显示用户协议内容
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 用户协议 | GET /api/system/getAgreement | 获取用户协议 |
---
### 8.4 隐私政策页 (P3)
**路由**`/pages/agreement/privacy/index`
**设计图**`docs/设计图/用户/隐私协议.png`
**功能描述**
- 显示隐私政策内容
**数据来源**
| 数据 | 接口 | 说明 |
|------|------|------|
| 隐私政策 | GET /api/system/getPrivacy | 获取隐私政策 |
---
## 九、开发顺序建议
### 第一阶段P0 核心功能)
1. 项目初始化 + 基础框架
2. TabBar 框架(首页、团队、我的骨架)
3. 登录页 + 登录流程
4. 首页完整功能
5. 测评流程(信息填写 → 答题 → 生成中 → 结果)
### 第二阶段P1 重要功能)
6. 我的页完整功能
7. 个人资料页
8. 我的订单页
9. 往期测评页
10. 业务详情页
11. 团队页
### 第三阶段P2 扩展功能)
12. 学业规划-规划师选择
13. 学业规划-预约
14. 邀请新用户(分销功能)
### 第四阶段P3 辅助功能)
15. 关于页
16. 用户协议页
17. 隐私政策页