# 2026-04-12 工作日志

## 项目：小程序改造规划

### 背景
用户需要为 websopy-mp 小程序增加：
- 🛠️ **开发者中心** - 面向开发者，围绕项目展开
- 🏢 **企业控制台** - 面向企业客户

### 关键决策
1. **用户角色分两类**：
   - 开发者 (Developer)：独立于企业存在，申请审核制
   - 企业客户 (Enterprise)：属于企业组织，购买产品开通

2. **开发模式**：独立开发，不复用现有模块（商城/分销/用户订单）

3. **核心围绕"项目"展开**：
   - 项目类型：基础/专业/企业
   - 项目成员、API Key、应用关联

### Phase 1 开发完成 ✅
已完成以下功能开发：

#### 新增目录结构
```
src/
├── developer/          # 🛠️ 开发者模块
│   ├── index.tsx       # 开发者工作台
│   ├── project/        # 项目管理
│   │   ├── index.tsx   # 项目列表
│   │   ├── create.tsx  # 创建项目
│   │   └── [id]/       # 项目详情
│   ├── app/            # 应用管理
│   │   ├── index.tsx   # 应用列表
│   │   ├── create.tsx  # 创建应用
│   │   ├── [id]/       # 应用详情
│   │   └── api-keys/   # API Key 管理
│   └── docs/           # 开发者文档
│
├── enterprise/         # 🏢 企业模块
│   ├── index.tsx       # 企业工作台
│   ├── apps/           # 企业应用
│   │   ├── index.tsx   # 应用列表
│   │   ├── [id]/       # 应用详情
│   │   └── purchase/   # 购买应用
│   ├── members/        # 成员管理
│   │   ├── index.tsx   # 成员列表
│   │   └── invite/     # 邀请成员
│   ├── orders/         # 订单账单
│   │   ├── index.tsx   # 订单列表
│   │   └── detail/     # 订单详情
│   ├── billing/        # 费用中心
│   └── settings/       # 企业设置
│
├── api/developer/      # API 模块
│   ├── index.ts
│   ├── developer.ts    # 开发者 API
│   └── enterprise.ts   # 企业 API
│
└── types/developer.ts  # 类型定义
```

#### 新增页面
- 首页角色入口卡片（开发者中心/企业控制台）
- 开发者工作台 + 统计卡片 + 快捷操作
- 项目列表/创建/详情
- 应用列表/创建/详情
- 企业工作台 + 统计卡片 + 快捷操作
- 企业应用列表/购买/详情
- 成员列表/邀请
- 订单列表/详情（占位）
- 费用中心/企业设置（占位）

#### 新增 API
- 项目管理 API
- 应用管理 API
- API Key 管理 API
- 企业成员 API
- 订单账单 API

### 待确认
- 后端 API 接口地址是否正确
- 是否需要权限验证
- 微信小程序码支持

---

## Phase 2 开发完成 ✅ (2026-04-12 19:49)

### 新增功能模块

#### 1. API Key 完整管理
- 列表展示（名称/类型/状态/创建时间）
- 创建 Key（名称/类型/备注）
- 复制 AppId/AppSecret
- 删除 Key
- 状态筛选

#### 2. 项目成员管理
- 成员列表展示（头像/名称/角色）
- 角色统计（所有者/管理员/开发者/查看者）
- 邀请成员（用户名/角色选择）
- 修改成员角色
- 移除成员

#### 3. 应用版本发布
- 版本列表（版本号/状态/环境）
- 环境 Tab 筛选（全部/开发/预发布/生产）
- 发布新版本（名称/版本号/环境/更新日志）
- 状态标签（构建中/已发布/已回滚/构建失败）

#### 4. 消息通知中心
- 通知列表（类型/标题/内容/时间）
- 类型筛选（全部/系统/应用/成员/订单）
- 未读数量徽标
- 标记已读/全部已读
- 删除通知
- 点击跳转详情

#### 5. 开发者申请
- 申请表单（姓名/手机/邮箱/公司/职位/经验）
- 申请记录列表
- 状态筛选（待审核/已通过/已拒绝）
- 审核备注展示

#### 6. 权限审批
- 申请列表（申请人/类型/目标/状态）
- Tab 筛选（待审核/已通过/已拒绝/全部）
- 待审核数量徽标
- 通过/拒绝操作
- 审核备注展示

### 新增/扩展的页面
```
src/developer/
├── project/[id]/
│   ├── members.tsx       # 项目成员管理 ✅
│   ├── members.scss
│   ├── api-keys.tsx      # 项目级 API Key
│   ├── api-keys.scss
│   ├── api-keys.config.ts
│   ├── settings.tsx      # 项目设置
│   └── settings.scss
├── app/[id]/
│   ├── version.tsx       # 版本管理 ✅
│   ├── version.scss
│   ├── config.tsx        # 应用配置
│   ├── publish.tsx       # 发布管理
│   └── *.config.ts
├── notification/         # 消息通知 ✅
│   ├── index.tsx
│   └── index.scss
├── developer/
│   ├── apply.tsx         # 开发者申请 ✅
│   ├── apply.scss
│   └── profile.tsx       # 开发者资料
├── docs/
│   ├── quickstart.tsx    # 快速开始
│   └── api-docs.tsx      # API 文档
└── market/               # 开发者市场
    └── index.tsx

src/enterprise/
├── apps/[id]/
│   ├── monitor.tsx        # 运营监控
│   ├── analytics.tsx      # 数据分析
│   └── settings.tsx       # 应用设置
├── members/
│   ├── roles.tsx         # 角色权限
│   └── audit.tsx         # 权限审批 ✅
├── orders/
│   ├── invoice.tsx       # 发票管理
│   └── bills.tsx          # 账单明细
├── billing/
│   ├── consumption.tsx   # 消费明细
│   ├── recharge.tsx      # 充值中心
│   └── coupons.tsx       # 优惠券
├── settings/
│   ├── info.tsx          # 企业信息
│   ├── domain.tsx        # 域名配置
│   └── security.tsx      # 安全设置
└── developer/
    ├── index.tsx         # 开发者入口
    └── apply.tsx         # 申请开发者
```

### 扩展的类型定义
```typescript
// 消息通知
interface Notification {
  id, type, title, content, data, isRead, readTime, createTime
}

// 权限申请
interface Apply {
  id, type, applicantId, applicantName, applicantAvatar,
  targetId, targetName, reason, status, reviewerId,
  reviewerName, reviewTime, reviewRemark, createTime
}
```

### 扩展的 API
```typescript
// 通知相关
pageNotification, getUnreadCount, markAsRead, markAllAsRead, deleteNotification

// 申请相关
pageApply, pageMyApply, createApply, reviewApply
```

### 路由配置更新
新增 20+ 个页面路由

---

## Phase 3 开发完成 ✅ (2026-04-12 20:15)

### 新增功能模块

#### 1. CI/CD 流水线
- **构建任务列表**：状态筛选/触发构建/取消构建/查看详情
- **构建详情**：构建信息/Git 信息/构建日志/构建产物
- **部署列表**：环境筛选/部署统计/触发部署/回滚操作
- **部署详情**：部署进度/日志/回滚功能
- **流水线配置**：启用/禁用、自动部署、分支规则、环境变量、Webhook

#### 2. 运营监控/数据分析
- **实时数据看板**：UV/PV/API 调用/错误数/Live 指示器
- **今日概览**：UV/PV/API 调用统计卡片
- **数据趋势**：图表占位（可集成 ECharts）
- **性能指标**：核心指标展示/趋势标签/错误统计
- **用户分析**：活跃用户/新增用户/留存率/地域分布/流量来源
- **页面排行**：PV/UV 排行

#### 3. 发票管理
- **发票列表**：状态筛选/发票详情/取消申请
- **可开票金额**：实时金额展示
- **申请发票**：抬头选择/金额输入/提交申请
- **发票抬头管理**：增删改查/默认设置
- **发票统计**：申请总数/已开票数量

#### 4. SSO 单点登录
- **SSO 配置**：OIDC/SAML/CAS/LDAP/OAuth2 提供商支持
- **连接配置**：Issuer/Client ID/Client Secret/授权 URL 等
- **用户同步**：同步开关/自动创建/默认角色
- **服务提供商信息**：Entity ID/ACS URL（可复制）
- **操作日志**：登录/登出/错误记录

### 新增类型定义
```
src/types/
├── index.ts         # 统一导出
├── cicd.ts          # CI/CD 流水线类型
├── analytics.ts     # 数据分析类型
├── invoice.ts       # 发票管理类型
└── sso.ts           # SSO 单点登录类型
```

### 新增 API
```
src/api/
├── cicd.ts          # CI/CD 流水线 API
├── analytics.ts      # 数据分析 API
├── invoice.ts       # 发票管理 API
└── sso.ts           # SSO 单点登录 API
```

### 新增页面
```
src/developer/app/[id]/
├── builds.tsx           # 构建列表
├── builds.scss
├── build/[id].tsx       # 构建详情
├── build/[id].scss
├── deploys.tsx          # 部署列表
├── deploys.scss
├── deploy/[id].tsx      # 部署详情
├── deploy/[id].scss
├── pipeline.tsx         # 流水线配置
├── pipeline.scss
├── analytics.tsx        # 运营监控
└── analytics.scss

src/enterprise/
├── orders/
│   ├── invoice.tsx      # 发票管理
│   └── invoice.scss
└── settings/
    ├── sso.tsx          # SSO 配置
    └── sso.scss
```

### Phase 3 完成的功能
| 功能 | 页面 | 状态 |
|------|------|------|
| **CI/CD 构建** | 构建列表/详情 | ✅ 完整 |
| **CI/CD 部署** | 部署列表/详情/回滚 | ✅ 完整 |
| **流水线配置** | 流水线设置 | ✅ 完整 |
| **运营监控** | 数据看板/趋势 | ✅ 完整 |
| **发票管理** | 发票列表/申请/抬头 | ✅ 完整 |
| **SSO 单点登录** | SSO 配置/日志 | ✅ 完整 |

---

### 待开发 (Phase 4)
| 功能 | 说明 |
|------|------|
| SDK 下载 | 各语言 SDK 下载页面 |
| 工单系统 | 客服工单/技术支持 |
| 账单导出 | 账单 Excel 导出 |
| 数据导入 | 企业数据批量导入 |

---

## Phase 4 开发完成 ✅ (2026-04-12 20:25)

### 新增功能模块

#### 1. SDK 下载中心
- **SDK 分类浏览**：Web/移动/服务端/小程序
- **SDK 列表展示**：图标/版本/下载量/Star
- **搜索功能**：按名称/描述搜索
- **SDK 详情弹窗**：版本/依赖/更新日志
- **一键安装**：NPM 命令复制/直接下载

#### 2. 工单系统
- **工单列表**：状态/类型/优先级筛选
- **工单统计**：总数/待处理/处理中/已解决
- **创建工单**：类型/优先级/标题/内容
- **工单详情**：沟通记录/解决方案/回复
- **工单评价**：满意度评分/反馈

#### 3. FAQ 常见问题
- **分类浏览**：API/账单/账户/SDK 等分类
- **搜索功能**：关键词搜索
- **展开查看**：问题详情/回答
- **有帮助/没帮助**：用户反馈

#### 4. 数据导入
- **导入记录列表**：状态/进度/错误统计
- **模板下载**：各类数据导入模板
- **字段说明**：必填/类型/示例
- **错误详情**：行号/字段/错误原因/建议

#### 5. 账单导出
- **导出记录**：任务列表/状态/文件信息
- **新建导出**：类型/格式/时间范围
- **下载管理**：文件下载/过期提醒
- **格式支持**：Excel/CSV/PDF

### 新增类型定义
```
src/types/
├── sdk.ts          # SDK 下载类型
├── ticket.ts       # 工单系统类型
└── import.ts       # 导入导出类型
```

### 新增 API
```
src/api/
├── sdk.ts           # SDK 下载 API
├── ticket.ts        # 工单系统 API
└── import.ts        # 导入导出 API
```

### 新增页面
```
src/developer/
├── sdk/
│   └── index.tsx       # SDK 下载中心
├── ticket/
│   ├── index.tsx       # 工单中心
│   ├── detail.tsx      # 工单详情
│   └── faq.tsx         # FAQ 常见问题

src/enterprise/
├── settings/
│   └── import.tsx      # 数据导入
└── orders/
    └── bills.tsx       # 账单导出
```

### Phase 4 完成的功能
| 功能 | 页面 | 状态 |
|------|------|------|
| **SDK 下载中心** | 列表/详情/下载 | ✅ 完整 |
| **工单系统** | 列表/创建/详情/评价 | ✅ 完整 |
| **FAQ 常见问题** | 分类/搜索/反馈 | ✅ 完整 |
| **数据导入** | 导入记录/模板下载 | ✅ 完整 |
| **账单导出** | 导出记录/新建导出 | ✅ 完整 |

---

## 📊 四个 Phase 累计完成

| Phase | 功能数 | 页面数 | API 数 |
|-------|--------|--------|--------|
| Phase 1 | 基础框架 | 15+ | 10+ |
| Phase 2 | API Key/成员/通知等 | 20+ | 15+ |
| Phase 3 | CI-CD/监控/发票/SSO | 10+ | 20+ |
| Phase 4 | SDK/工单/导入/导出 | 10+ | 15+ |
| **合计** | - | **55+** | **60+** |

---

## Bug 修复 (2026-04-12 21:00)

### 已修复的问题

#### 1. JSX 语法错误
- 修复 8 个被截断的 `.tsx` 文件（appCredential、appEvent、appUser、appVersion）
- 修复 `user/apps/index.tsx` 中的 `>` token 问题

#### 2. API 导入问题
- 修复 `analytics.ts`、`cicd.ts`、`invoice.ts`、`sso.ts` 的 request 导入
- 添加缺失的 `ImportType` 导入
- 修复 `sdk.ts` 未使用的导入

#### 3. Config 文件错误
- 修复所有 `defineComponentConfig` → `definePageConfig`
- 涉及 12 个 config 文件

#### 4. 组件命名错误
- 修复 `PullRefresh` → `PullToRefresh`（nutui 组件）
- 涉及 4 个文件

#### 5. taro-ui 依赖问题
- 将 `taro-ui` 替换为 `nutui-react-taro`
- 重写 `invoice.tsx`、`sso.tsx` 页面

#### 6. SCSS 导入问题
- 修复 `notification/index.tsx` 的 scss 导入路径

#### 7. 类型定义
- 创建 `src/types/developer.ts` 缺失类型文件
- 修复 `RequestConfig` 缺少 `params` 属性

### 项目状态
- ✅ 编译成功
- ✅ 开发服务器运行中 (端口: dist)

---

## 任务：改造 invite/index.tsx 登录流程

### 需求
- `loginByOpenId` 已注册 → 显示**「确认加入」**按钮
- `loginByOpenId` 未注册 → 显示**「微信手机号快速加入」**按钮（走授权流程）

### 关键逻辑
1. `checkLoginStatus`：调用 `loginByOpenId` 检查用户是否已注册
2. 已注册：`isLoggedIn = true`，显示「确认加入」按钮
3. 未注册：`isLoggedIn = false`，显示「微信手机号授权」按钮
4. 授权成功 → 调用 `loginByMpWxPhone` 完成注册/登录 → 自动执行加入应用

### 文件修改
- `src/passport/invite/index.tsx` - 完整重写，区分已登录/未注册两种按钮状态

---

## 任务：未注册用户在邀请页内完成授权注册，不跳登录页

### 需求
- loginByOpenId 未注册 → 在页面内显示「微信手机号授权」按钮
- 授权成功 → 调用 `loginByMpWxPhone` 注册/登录 → 自动执行加入应用
- 不再跳转 passport/login 页面

### 关键逻辑
1. `checkLoginStatus`：已注册 isLoggedIn=true，未注册 isLoggedIn=false，**两种情况都显示邀请页**
2. 未注册按钮：`open-type="getPhoneNumber"` → `handleGetPhoneNumber`
   - 授权码调 `SERVER_API_URL/wx-login/loginByMpWxPhone` 完成注册登录
   - 保存 token → isLoggedIn=true → 立即调 `doJoinApp`
3. 已注册按钮：普通 `onClick` → `handleConfirmJoin` → `doJoinApp(access_token)`
4. `doJoinApp`：统一加入接口，请求头带 `Authorization: Bearer {access_token}`

### 文件修改
- `src/passport/invite/index.tsx` - 完整重写（彻底移除跳登录页逻辑）

---

## 修复：「授权码不能为空」报错

### 问题
后端 `/api/_app/developer/invite/accept` 接口强制要求传 `code`（微信授权码），不传就报「授权码不能为空」。

### 解决
统一用一个 `getPhoneNumber` 按钮处理两种场景：
- **已注册**：文字「确认加入」→ 触发 getPhoneNumber → `doJoinApp(code, accessToken)`
- **未注册**：文字「微信手机号快速加入」→ 触发 getPhoneNumber → 先 `loginByMpWxPhone` 注册 → 再 `wx.login()` 获 code → `doJoinApp(newCode, access_token)`

### doJoinApp 参数
```ts
doJoinApp(wxCode: string, accessToken: string)
// 请求体带 code，请求头带 Authorization: Bearer xxx
```

---

## 优化：已登录用户不弹手机号授权

### 改动
- 已登录按钮：普通 `onClick`，文字「确认加入」
- 未注册按钮：`getPhoneNumber` 授权，文字「微信手机号快速加入」

### 逻辑差异
| 用户状态 | 按钮类型 | 获取 code 方式 |
|------|------|------|
| 已登录 | 普通 onClick | `wx.login()` |
| 未注册 | getPhoneNumber | 授权回调的 `code` |

### 文件修改
- `src/passport/invite/index.tsx` - 按钮区分两种类型，已登录用普通 onClick

---

## 优化：已登录用户不强制勾选协议

### 改动
- 已登录用户点击「确认加入」时，不再检查 `agreementChecked`
- 未注册用户仍需勾选协议后才能授权手机号

### 文件修改
- `src/passport/invite/index.tsx` - `handleConfirmJoin` 移除协议检查

---

## 修复：后端需要手机号授权码

### 问题
后端 `invite/accept` 接口只接受 `getPhoneNumber` 获取的手机号授权码，用 `wx.login()` 的 code 会报「获取手机号失败」。

### 解决
两种用户状态都走 `getPhoneNumber` 按钮：
- 已登录：文字「确认加入」，回调 `handleConfirmJoinGetPhoneNumber`
- 未注册：文字「微信手机号快速加入」，回调 `handleGetPhoneNumber`

### 差异
| 用户状态 | 回调 | 行为 |
|------|------|------|
| 已登录 | `handleConfirmJoinGetPhoneNumber` | 直接用 `code + access_token` 调加入接口 |
| 未注册 | `handleGetPhoneNumber` | 先 `loginByMpWxPhone` 注册登录，再调加入接口 |

### 文件修改
- `src/passport/invite/index.tsx` - 两种状态都用 getPhoneNumber 按钮

---

## 任务：后端改造支持已登录用户直接加入

### 问题
后端 `/api/_app/developer/invite/accept` 接口强制要求传 `code`（手机号授权码），导致已登录用户也需要弹手机号授权。

### 后端改造方案
修改 `AppMpInviteController.acceptInvite` 方法：

#### 1. 参数校验调整
- `code` 改为可选参数
- 不传 `code` 时，从 `Authorization` 头获取当前登录用户

#### 2. 双模式支持
```java
if (StrUtil.isBlank(code)) {
    // 模式一：已登录用户（通过 Authorization 头识别）
    userId = getCurrentUserId();
} else {
    // 模式二：未注册用户（通过手机号授权码获取手机号，创建用户）
    String phone = getPhoneByCode(code);
    userId = getOrCreateUserByPhone(phone);
}
```

#### 3. getCurrentUserId 方法
- 尝试从 Spring Security Context 获取
- 如果获取不到（免登录接口），手动解析 `Authorization` 头的 JWT Token

### 前端配合改造
- 已登录用户：普通 `onClick` 按钮 → `handleConfirmJoin` → `doJoinAppForLoggedInUser`（不传 `code`）
- 未注册用户：`getPhoneNumber` 按钮 → `handleGetPhoneNumber` → `doJoinAppForNewUser`（传 `code`）

### 文件修改
**后端：**
- `/Users/gxwebsoft/JAVA/websopy-java/src/main/java/com/gxwebsoft/app/controller/AppMpInviteController.java`
  - `acceptInvite` 方法支持 `code` 可选
  - 使用 `BaseController.getLoginUserId()` 获取当前登录用户（无需额外方法）

**前端：**
- `/Users/gxwebsoft/VUE/websopy-mp/src/passport/invite/index.tsx`
  - 已登录按钮改为普通 `onClick`
  - 新增 `handleConfirmJoin` 方法
  - 拆分 `doJoinApp` 为 `doJoinAppForLoggedInUser` 和 `doJoinAppForNewUser`

---

## 修复：开发者中心加载不到应用

### 问题
用户通过邀请加入应用后，开发者中心显示「加载中...」，无法显示应用列表。

### 原因
- 前端 `developer/index.tsx` 只调用了 `pageMyApp` 接口（查询用户**创建**的应用）
- 用户通过邀请加入的应用属于**参与**的应用，不是创建的应用
- 后端 `loginByOpenId` 返回了应用列表，但前端没有使用这个数据

### 解决
1. **前端改造**：`loadData` 同时调用两个接口：
   - `pageMyApp` - 查询创建的应用
   - `pageJoinedApp` - 查询参与的应用（新增 API）
   - 合并两个列表，根据 `productId` 去重

2. **新增 API**：`src/api/developer/developer.ts` 添加 `pageJoinedApp` 方法

### 文件修改
- `src/developer/index.tsx` - `loadData` 同时查询创建和参与的应用
- `src/api/developer/developer.ts` - 新增 `pageJoinedApp` 方法
