chore: remove wechat remnants
This commit is contained in:
@@ -650,7 +650,7 @@ paths:
|
|||||||
type: number
|
type: number
|
||||||
method:
|
method:
|
||||||
type: string
|
type: string
|
||||||
enum: [wechat, alipay]
|
enum: [alipay]
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Recharge initiated
|
description: Recharge initiated
|
||||||
@@ -939,7 +939,7 @@ paths:
|
|||||||
properties:
|
properties:
|
||||||
method:
|
method:
|
||||||
type: string
|
type: string
|
||||||
enum: [wechat, alipay, balance]
|
enum: [alipay, balance]
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
content:
|
content:
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ type OrderCreateResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OrderPayForm struct {
|
type OrderPayForm struct {
|
||||||
// Method 支付方式(wechat/alipay/balance)。
|
// Method 支付方式(alipay/balance)。
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ type Transaction struct {
|
|||||||
type RechargeForm struct {
|
type RechargeForm struct {
|
||||||
// Amount 充值金额(单位元)。
|
// Amount 充值金额(单位元)。
|
||||||
Amount float64 `json:"amount"`
|
Amount float64 `json:"amount"`
|
||||||
// Method 充值方式(wechat/alipay)。
|
// Method 充值方式(alipay)。
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8029,7 +8029,7 @@ const docTemplate = `{
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"method": {
|
"method": {
|
||||||
"description": "Method 支付方式(wechat/alipay/balance)。",
|
"description": "Method 支付方式(alipay/balance)。",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8180,7 +8180,7 @@ const docTemplate = `{
|
|||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
"method": {
|
"method": {
|
||||||
"description": "Method 充值方式(wechat/alipay)。",
|
"description": "Method 充值方式(alipay)。",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8023,7 +8023,7 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"method": {
|
"method": {
|
||||||
"description": "Method 支付方式(wechat/alipay/balance)。",
|
"description": "Method 支付方式(alipay/balance)。",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8174,7 +8174,7 @@
|
|||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
"method": {
|
"method": {
|
||||||
"description": "Method 充值方式(wechat/alipay)。",
|
"description": "Method 充值方式(alipay)。",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -899,7 +899,7 @@ definitions:
|
|||||||
dto.OrderPayForm:
|
dto.OrderPayForm:
|
||||||
properties:
|
properties:
|
||||||
method:
|
method:
|
||||||
description: Method 支付方式(wechat/alipay/balance)。
|
description: Method 支付方式(alipay/balance)。
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
dto.OrderPayResponse:
|
dto.OrderPayResponse:
|
||||||
@@ -1002,7 +1002,7 @@ definitions:
|
|||||||
description: Amount 充值金额(单位元)。
|
description: Amount 充值金额(单位元)。
|
||||||
type: number
|
type: number
|
||||||
method:
|
method:
|
||||||
description: Method 充值方式(wechat/alipay)。
|
description: Method 充值方式(alipay)。
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
dto.RechargeResponse:
|
dto.RechargeResponse:
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
- **提交按钮**: "获取验证码" (Primary Button, Full Width, `h-12`)。
|
- **提交按钮**: "获取验证码" (Primary Button, Full Width, `h-12`)。
|
||||||
- **第三方登录 (Footer)**:
|
- **第三方登录 (Footer)**:
|
||||||
- 分隔线: "其他方式登录" (text-xs text-slate-400)
|
- 分隔线: "其他方式登录" (text-xs text-slate-400)
|
||||||
- 图标组: 微信、GitHub 等圆型图标按钮。
|
- 图标组: 预留第三方登录入口(暂不展示)。
|
||||||
|
|
||||||
### 2.2 第二步:输入验证码 (OTP Input)
|
### 2.2 第二步:输入验证码 (OTP Input)
|
||||||
*用户点击获取验证码成功后,表单区域平滑切换(或水平滑入)至验证码输入界面。*
|
*用户点击获取验证码成功后,表单区域平滑切换(或水平滑入)至验证码输入界面。*
|
||||||
|
|||||||
@@ -50,8 +50,7 @@
|
|||||||
### 2.2 支付方式 (Payment Methods)
|
### 2.2 支付方式 (Payment Methods)
|
||||||
- **布局**: 左侧选择方式,右侧展示二维码 (PC端)。
|
- **布局**: 左侧选择方式,右侧展示二维码 (PC端)。
|
||||||
- **选项**:
|
- **选项**:
|
||||||
- **微信支付**: 绿色图标,推荐。
|
- **支付宝**: 蓝色图标,推荐。
|
||||||
- **支付宝**: 蓝色图标。
|
|
||||||
- **余额支付**: 显示当前余额,若不足则置灰并提示。
|
- **余额支付**: 显示当前余额,若不足则置灰并提示。
|
||||||
- **二维码区域**:
|
- **二维码区域**:
|
||||||
- **尺寸**: `200x200px` (加大,方便扫码)。
|
- **尺寸**: `200x200px` (加大,方便扫码)。
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
- 超管统计/订单详情/退款等均为空:`backend/app/services/super.go`。
|
- 超管统计/订单详情/退款等均为空:`backend/app/services/super.go`。
|
||||||
- 超管内容/订单列表 DTO 映射 TODO:`backend/app/services/super.go`。
|
- 超管内容/订单列表 DTO 映射 TODO:`backend/app/services/super.go`。
|
||||||
|
|
||||||
5) 认证方式与规格偏离:现实现 OTP 登录 + JWT;规格为 WeChat OAuth + Cookie(已经移除,仅使用jwt认证)。
|
5) 认证方式与规格偏离:现实现 OTP 登录 + JWT;需统一规格文档与实现保持一致。
|
||||||
- 认证流程:`backend/app/http/v1/auth/auth.go`、`backend/app/services/user.go`。
|
- 认证流程:`backend/app/http/v1/auth/auth.go`、`backend/app/services/user.go`。
|
||||||
- 前端调用 OTP 登录:`frontend/portal/src/api/auth.js`。
|
- 前端调用 OTP 登录:`frontend/portal/src/api/auth.js`。
|
||||||
|
|
||||||
@@ -72,8 +72,8 @@
|
|||||||
- 控制器签名支持 `@Bind id path` + `int64` 或 `@Bind tenant model(id)` 进行 model 注入。
|
- 控制器签名支持 `@Bind id path` + `int64` 或 `@Bind tenant model(id)` 进行 model 注入。
|
||||||
- swagger `@Router` 必须使用 `:id<int>` / `:tenantID<int>`。
|
- swagger `@Router` 必须使用 `:id<int>` / `:tenantID<int>`。
|
||||||
|
|
||||||
### 4) 规格一致性修复 (仅使用JWT
|
### 4) 规格一致性修复(仅使用 JWT)
|
||||||
- 统一认证模型(OTP vs WeChat):要么按规格实现 WeChat OAuth,要么更新规格文档。
|
- 统一认证模型(OTP + JWT),同步规格文档与实现。
|
||||||
- 统一存储方案(OSS + tenant_uuid + md5 命名);当前本地存储仅作开发 fallback。
|
- 统一存储方案(OSS + tenant_uuid + md5 命名);当前本地存储仅作开发 fallback。
|
||||||
- 将 `specs/DB.sql` 迁入真实迁移文件并补齐中文字段注释。
|
- 将 `specs/DB.sql` 迁入真实迁移文件并补齐中文字段注释。
|
||||||
|
|
||||||
@@ -117,4 +117,3 @@
|
|||||||
3) ID 类型统一与 `:id<int>` 路由规范
|
3) ID 类型统一与 `:id<int>` 路由规范
|
||||||
4) 规格一致性(认证/存储/迁移)
|
4) 规格一致性(认证/存储/迁移)
|
||||||
5) 性能优化(N+1/聚合)与可维护性补齐
|
5) 性能优化(N+1/聚合)与可维护性补齐
|
||||||
|
|
||||||
|
|||||||
@@ -233,13 +233,13 @@
|
|||||||
**测试方案**
|
**测试方案**
|
||||||
- 不同筛选维度下内容列表正确;空内容/无简介时展示兜底。
|
- 不同筛选维度下内容列表正确;空内容/无简介时展示兜底。
|
||||||
|
|
||||||
### 15) 微信生态清理(若仍存在)
|
### 15) 微信生态清理(已完成)
|
||||||
**需求目标**
|
**需求目标**
|
||||||
- 移除微信登录/分享/支付相关逻辑,降低维护成本。
|
- 移除微信登录/分享/支付相关逻辑,降低维护成本。
|
||||||
|
|
||||||
**技术方案(后端/前端/文档)**
|
**技术方案(后端/前端/文档)**
|
||||||
- 后端:清理 `auth` 路由与服务中的微信授权/回调逻辑(如存在)。
|
- 后端:清理 `auth` 路由与服务中的微信授权/回调逻辑(如存在)。
|
||||||
- 前端:移除 Portal 登录页/分享中的 `wx.*` 依赖与 UI。
|
- 前端:移除 Portal 登录页/分享中的微信依赖与 UI。
|
||||||
- 配置/文档:清理 `config.toml`、`specs/*`、`docs/*` 的微信配置与说明;移除无用 SDK 依赖。
|
- 配置/文档:清理 `config.toml`、`specs/*`、`docs/*` 的微信配置与说明;移除无用 SDK 依赖。
|
||||||
|
|
||||||
**测试方案**
|
**测试方案**
|
||||||
|
|||||||
@@ -146,27 +146,8 @@ const login = async () => {
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="mt-8">
|
<div class="mt-8 text-center text-xs text-slate-400">
|
||||||
<div class="relative">
|
当前仅支持手机验证码登录
|
||||||
<div class="absolute inset-0 flex items-center">
|
|
||||||
<div class="w-full border-t border-slate-200"></div>
|
|
||||||
</div>
|
|
||||||
<div class="relative flex justify-center text-sm">
|
|
||||||
<span class="px-2 bg-white text-slate-500">其他方式登录</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mt-6 flex justify-center gap-6">
|
|
||||||
<button
|
|
||||||
class="w-10 h-10 rounded-full bg-slate-50 border border-slate-200 flex items-center justify-center hover:bg-slate-100 text-green-600"
|
|
||||||
>
|
|
||||||
<i class="pi pi-wechat text-xl"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="w-10 h-10 rounded-full bg-slate-50 border border-slate-200 flex items-center justify-center hover:bg-slate-100 text-slate-800"
|
|
||||||
>
|
|
||||||
<i class="pi pi-github text-xl"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ const likeComment = async (comment) => {
|
|||||||
>
|
>
|
||||||
<i class="pi pi-lock"></i> 购买解锁全文 ¥ {{ content.price }}
|
<i class="pi pi-lock"></i> 购买解锁全文 ¥ {{ content.price }}
|
||||||
</button>
|
</button>
|
||||||
<p class="text-xs text-slate-400 mt-3">支持微信 / 支付宝</p>
|
<p class="text-xs text-slate-400 mt-3">支持支付宝</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ const confirmRefund = async () => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span class="text-slate-500">支付方式</span>
|
<span class="text-slate-500">支付方式</span>
|
||||||
<span>微信支付</span>
|
<span>支付宝</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between pt-2 border-t border-slate-200">
|
<div class="flex justify-between pt-2 border-t border-slate-200">
|
||||||
<span class="font-bold text-slate-900">实付</span>
|
<span class="font-bold text-slate-900">实付</span>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const orderId = route.params.id || "82934712";
|
|||||||
const amount = "9.90"; // Should fetch order details first
|
const amount = "9.90"; // Should fetch order details first
|
||||||
const productName = "《霸王别姬》全本实录珍藏版";
|
const productName = "《霸王别姬》全本实录珍藏版";
|
||||||
|
|
||||||
const paymentMethod = ref("wechat");
|
const paymentMethod = ref("alipay");
|
||||||
const timeLeft = ref(900); // 15 minutes
|
const timeLeft = ref(900); // 15 minutes
|
||||||
const isScanning = ref(false);
|
const isScanning = ref(false);
|
||||||
const isSuccess = ref(false);
|
const isSuccess = ref(false);
|
||||||
@@ -20,7 +20,7 @@ let timer = null;
|
|||||||
let pollTimer = null;
|
let pollTimer = null;
|
||||||
|
|
||||||
const paymentMethodName = computed(() => {
|
const paymentMethodName = computed(() => {
|
||||||
return paymentMethod.value === "wechat" ? "微信" : "支付宝";
|
return paymentMethod.value === "alipay" ? "支付宝" : "余额";
|
||||||
});
|
});
|
||||||
|
|
||||||
const formatTime = (seconds) => {
|
const formatTime = (seconds) => {
|
||||||
@@ -114,31 +114,6 @@ onUnmounted(() => {
|
|||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<h3 class="font-bold text-slate-900 mb-4">选择支付方式</h3>
|
<h3 class="font-bold text-slate-900 mb-4">选择支付方式</h3>
|
||||||
|
|
||||||
<label
|
|
||||||
class="flex items-center gap-4 p-4 border rounded-xl cursor-pointer transition-all relative overflow-hidden"
|
|
||||||
:class="
|
|
||||||
paymentMethod === 'wechat'
|
|
||||||
? 'border-green-500 bg-green-50/30 ring-1 ring-green-500'
|
|
||||||
: 'border-slate-200 hover:border-slate-300'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
v-model="paymentMethod"
|
|
||||||
value="wechat"
|
|
||||||
class="hidden"
|
|
||||||
/>
|
|
||||||
<i class="pi pi-wechat text-3xl text-green-600"></i>
|
|
||||||
<div class="flex-1">
|
|
||||||
<div class="font-bold text-slate-900">微信支付</div>
|
|
||||||
<div class="text-xs text-slate-500">推荐使用</div>
|
|
||||||
</div>
|
|
||||||
<i
|
|
||||||
v-if="paymentMethod === 'wechat'"
|
|
||||||
class="pi pi-check-circle text-green-600 text-xl"
|
|
||||||
></i>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label
|
<label
|
||||||
class="flex items-center gap-4 p-4 border rounded-xl cursor-pointer transition-all"
|
class="flex items-center gap-4 p-4 border rounded-xl cursor-pointer transition-all"
|
||||||
:class="
|
:class="
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const customAmount = ref("");
|
|||||||
const balance = ref(0);
|
const balance = ref(0);
|
||||||
const transactions = ref([]);
|
const transactions = ref([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const paymentMethod = ref("wechat");
|
const paymentMethod = ref("alipay");
|
||||||
|
|
||||||
const displayAmount = computed(() => {
|
const displayAmount = computed(() => {
|
||||||
return customAmount.value
|
return customAmount.value
|
||||||
@@ -152,17 +152,6 @@ onMounted(() => {
|
|||||||
|
|
||||||
<h3 class="font-bold text-slate-900 mb-4">支付方式</h3>
|
<h3 class="font-bold text-slate-900 mb-4">支付方式</h3>
|
||||||
<div class="flex gap-4 mb-8">
|
<div class="flex gap-4 mb-8">
|
||||||
<button
|
|
||||||
@click="paymentMethod = 'wechat'"
|
|
||||||
class="flex items-center gap-2 px-6 py-3 border-2 rounded-lg font-medium cursor-pointer active:scale-95 transition-transform"
|
|
||||||
:class="
|
|
||||||
paymentMethod === 'wechat'
|
|
||||||
? 'border-blue-600 bg-blue-50 text-blue-700'
|
|
||||||
: 'border-slate-200 text-slate-600 hover:bg-white hover:border-slate-300'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<i class="pi pi-wechat text-xl text-green-600"></i> 微信支付
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
@click="paymentMethod = 'alipay'"
|
@click="paymentMethod = 'alipay'"
|
||||||
class="flex items-center gap-2 px-6 py-3 border-2 rounded-lg font-medium cursor-pointer active:scale-95 transition-transform"
|
class="flex items-center gap-2 px-6 py-3 border-2 rounded-lg font-medium cursor-pointer active:scale-95 transition-transform"
|
||||||
|
|||||||
15
specs/API.md
15
specs/API.md
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
### 0.4 当前实现说明
|
### 0.4 当前实现说明
|
||||||
|
|
||||||
- 当前端到端实现已切换为 OTP + JWT;以下 WeChat OAuth/H5 内容为历史规格,待后续统一重写
|
- 当前实现以 OTP 登录 + JWT 认证为准;本文仅保留已落地接口说明
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ Body:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. WeChat H5 内容与用户
|
## 2. Portal 用户端内容与用户
|
||||||
|
|
||||||
### 2.1 曲谱列表(仅已发布)
|
### 2.1 曲谱列表(仅已发布)
|
||||||
|
|
||||||
@@ -75,8 +75,7 @@ Response(示例结构):
|
|||||||
"likes": 0,
|
"likes": 0,
|
||||||
"tags": ["tag"],
|
"tags": ["tag"],
|
||||||
"head_images": ["https://signed-url..."],
|
"head_images": ["https://signed-url..."],
|
||||||
"bought": false,
|
"bought": false
|
||||||
"recharge_wechat": "联系微信(可选)"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total": 123,
|
"total": 123,
|
||||||
@@ -141,14 +140,6 @@ Body:
|
|||||||
|
|
||||||
约束:trim 后不能为空;最大 12 个字符(按 rune 计)。
|
约束:trim 后不能为空;最大 12 个字符(按 rune 计)。
|
||||||
|
|
||||||
### 2.8 JS-SDK 配置
|
|
||||||
|
|
||||||
`GET /wechats/js-sdk?url=<current_page_url_without_hash>`
|
|
||||||
|
|
||||||
Response:JS-SDK 签名数据(结构按前端 `weixin-js-sdk` 需要输出)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. Admin(租户后台)
|
## 3. Admin(租户后台)
|
||||||
|
|
||||||
### 3.1 登录
|
### 3.1 登录
|
||||||
|
|||||||
21
specs/PRD.md
21
specs/PRD.md
@@ -1,8 +1,8 @@
|
|||||||
# 新项目 PRD(多租户 + 微信登录/分享 + 余额支付)
|
# 新项目 PRD(多租户 + OTP 登录 + 余额支付)
|
||||||
|
|
||||||
## 当前实现说明
|
## 当前实现说明
|
||||||
|
|
||||||
- 认证方式已切换为 OTP + JWT;WeChat OAuth/JS-SDK 暂未落地,保留为规划
|
- 认证方式为 OTP + JWT;不包含第三方 OAuth/JS-SDK
|
||||||
- 路由当前使用 `/v1` 前缀,多租户 `/t/:tenant_code` 待统一改造
|
- 路由当前使用 `/v1` 前缀,多租户 `/t/:tenant_code` 待统一改造
|
||||||
|
|
||||||
## 1. 范围与约束
|
## 1. 范围与约束
|
||||||
@@ -15,10 +15,10 @@
|
|||||||
- OSS Key:`quyun/<tenant_uuid>/<md5>.<ext>`
|
- OSS Key:`quyun/<tenant_uuid>/<md5>.<ext>`
|
||||||
- 数据隔离:所有业务表均包含 `tenant_id`,所有查询必须带 `tenant_id` 过滤
|
- 数据隔离:所有业务表均包含 `tenant_id`,所有查询必须带 `tenant_id` 过滤
|
||||||
|
|
||||||
### 1.2 微信能力
|
### 1.2 认证能力
|
||||||
|
|
||||||
- 保留:微信网页授权登录(OAuth)、JS-SDK 签名与分享
|
- 仅支持:手机 OTP 登录 + JWT
|
||||||
- 移除:微信支付/退款/回调(多租户版本完全不支持,历史也不兼容)
|
- 不包含:第三方 OAuth/JS-SDK 与相关分享能力
|
||||||
|
|
||||||
### 1.3 支付能力
|
### 1.3 支付能力
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
## 2. 角色与端
|
## 2. 角色与端
|
||||||
|
|
||||||
### 2.1 WeChat H5 端(C 端用户)
|
### 2.1 Portal 用户端(C 端用户)
|
||||||
|
|
||||||
- 访问曲谱列表、搜索
|
- 访问曲谱列表、搜索
|
||||||
- 查看曲谱详情
|
- 查看曲谱详情
|
||||||
@@ -43,7 +43,6 @@
|
|||||||
- 余额购买
|
- 余额购买
|
||||||
- 查看已购列表(快速播放)
|
- 查看已购列表(快速播放)
|
||||||
- 查看个人资料与余额
|
- 查看个人资料与余额
|
||||||
- 分享(JS-SDK)
|
|
||||||
|
|
||||||
### 2.2 Admin 管理端(租户运营人员)
|
### 2.2 Admin 管理端(租户运营人员)
|
||||||
|
|
||||||
@@ -94,11 +93,11 @@
|
|||||||
- code 存在且启用
|
- code 存在且启用
|
||||||
- 解析成功后,将 `tenant_id`、`tenant_uuid` 注入到请求上下文
|
- 解析成功后,将 `tenant_id`、`tenant_uuid` 注入到请求上下文
|
||||||
|
|
||||||
### 4.2 微信登录
|
### 4.2 OTP 登录
|
||||||
|
|
||||||
1) 未登录请求 API → 401(XHR)或 302 → `/t/:tenant/v1/auth/wechat?redirect=...`
|
1) 未登录请求 API → 401(XHR),前端引导到登录页
|
||||||
2) `/auth/wechat` 生成微信授权地址(回调到 `/t/:tenant/v1/auth/login` 并透传 redirect)
|
2) `/auth/otp` 发送验证码
|
||||||
3) `/auth/login` 换取 openid + 用户信息,按 `(tenant_id, open_id)` 获取或创建用户,签发会话 token(cookie)
|
3) `/auth/login` 使用手机号 + OTP 换取 JWT,并在前端保存
|
||||||
|
|
||||||
### 4.3 播放策略(预览/完整版)
|
### 4.3 播放策略(预览/完整版)
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
- 租户前缀:`/t/:tenant_code/`(不区分大小写;服务端统一按 `lower()` 识别)
|
- 租户前缀:`/t/:tenant_code/`(不区分大小写;服务端统一按 `lower()` 识别)
|
||||||
- API:`/t/:tenant_code/v1/...`
|
- API:`/t/:tenant_code/v1/...`
|
||||||
- Admin SPA:`/t/:tenant_code/admin/...`
|
- Admin SPA:`/t/:tenant_code/admin/...`
|
||||||
- WeChat SPA:`/t/:tenant_code/...`(除 `v1` 与 `admin` 子路径)
|
- Portal SPA:`/t/:tenant_code/...`(除 `v1` 与 `admin` 子路径)
|
||||||
|
|
||||||
### 1.2 为什么必须这样分层
|
### 1.2 为什么必须这样分层
|
||||||
|
|
||||||
- WeChat/后台前端都是 SPA,通常需要一个 catch-all 回退到 `index.html`
|
- Portal/后台前端都是 SPA,通常需要一个 catch-all 回退到 `index.html`
|
||||||
- 同时 API 又需要精确匹配,必须确保 API 路由优先于静态路由
|
- 同时 API 又需要精确匹配,必须确保 API 路由优先于静态路由
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
1) `GET /t/:tenant_code/v1/...`:注册所有 API(并注入 TenantContext 中间件)
|
1) `GET /t/:tenant_code/v1/...`:注册所有 API(并注入 TenantContext 中间件)
|
||||||
2) `GET /t/:tenant_code/admin*`:回退到 Admin 的 `index.html`(并正确设置静态资源 base)
|
2) `GET /t/:tenant_code/admin*`:回退到 Admin 的 `index.html`(并正确设置静态资源 base)
|
||||||
3) `GET /t/:tenant_code/*`:回退到 WeChat 的 `index.html`
|
3) `GET /t/:tenant_code/*`:回退到 Portal 的 `index.html`
|
||||||
|
|
||||||
> 重点:不要用全局 `GET /*` 直接接管,否则会吞掉 API 与 admin。
|
> 重点:不要用全局 `GET /*` 直接接管,否则会吞掉 API 与 admin。
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. 前端(WeChat H5)
|
## 4. 前端(Portal 用户端)
|
||||||
|
|
||||||
### 4.1 Router base
|
### 4.1 Router base
|
||||||
|
|
||||||
@@ -55,13 +55,12 @@
|
|||||||
### 4.2 API baseURL 与 Cookie
|
### 4.2 API baseURL 与 Cookie
|
||||||
|
|
||||||
- axios `baseURL = "/t/<tenant_code>/v1"`
|
- axios `baseURL = "/t/<tenant_code>/v1"`
|
||||||
- `withCredentials = true`(历史 WeChat 方案)
|
- 当前实现使用 JWT:`Authorization: Bearer <token>`
|
||||||
- 当前实现改为 JWT:`Authorization: Bearer <token>`
|
|
||||||
|
|
||||||
### 4.3 未登录跳转
|
### 4.3 未登录跳转
|
||||||
|
|
||||||
- 401 时跳:`/t/<tenant_code>/v1/auth/wechat?redirect=<encodeURIComponent(currentUrl)>`
|
- 401 时跳:`/t/<tenant_code>/auth/login?redirect=<encodeURIComponent(currentUrl)>`
|
||||||
- 当前实现为 OTP 登录,不走微信授权回调
|
- 当前实现为 OTP 登录,无第三方授权回调
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user