fix(admin): 行业选择500修复 + 管理员切换订阅计划
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

- fix(industry): list_industries SQL参数编号错位 — count查询和items查询
  共用WHERE子句但参数从$3开始,sqlx bind按$1/$2顺序绑定导致500
- feat(billing): 新增 PUT /admin/accounts/:id/subscription 端点 (super_admin)
  验证目标计划 → 取消当前订阅 → 创建新订阅(30天) → 同步配额
- feat(admin-v2): Accounts.tsx 编辑弹窗新增「订阅计划」选择区
  显示所有活跃计划,保存时调用admin switch plan API
This commit is contained in:
iven
2026-04-14 19:06:58 +08:00
parent d2a0c8efc0
commit 6721a1cc6e
8 changed files with 218 additions and 13 deletions

View File

@@ -7,6 +7,7 @@ use axum::{
use serde::Deserialize;
use crate::auth::types::AuthContext;
use crate::auth::handlers::{log_operation, check_permission};
use crate::error::{SaasError, SaasResult};
use crate::state::AppState;
use super::service;
@@ -115,6 +116,41 @@ pub async fn increment_usage_dimension(
})))
}
/// POST /api/v1/billing/payments — 创建支付订单
/// PUT /api/v1/admin/accounts/:id/subscription — 管理员切换用户订阅计划(仅 super_admin
pub async fn admin_switch_subscription(
State(state): State<AppState>,
Extension(ctx): Extension<AuthContext>,
Path(account_id): Path<String>,
Json(req): Json<AdminSwitchPlanRequest>,
) -> SaasResult<Json<serde_json::Value>> {
// 仅 super_admin 可操作
check_permission(&ctx, "admin:full")?;
// 验证 plan_id 非空
if req.plan_id.trim().is_empty() {
return Err(SaasError::InvalidInput("plan_id 不能为空".into()));
}
let sub = service::admin_switch_plan(&state.db, &account_id, &req.plan_id).await?;
log_operation(
&state.db,
&ctx.account_id,
"billing.admin_switch_plan",
"account",
&account_id,
Some(serde_json::json!({ "plan_id": req.plan_id })),
None,
).await.ok(); // 日志失败不影响主流程
Ok(Json(serde_json::json!({
"success": true,
"subscription": sub,
})))
}
/// POST /api/v1/billing/payments — 创建支付订单
pub async fn create_payment(
State(state): State<AppState>,