fix(plans): /v1/plans 500 修复 — plans 表无 name_zh/name_en 列
ListPlans 历来 SELECT name_zh/name_en,但 plans 表从未有这两列(各迁移/seed 均无)→ 该端点一直 500(无 live 测试故未暴露)。改为不查名称列(套餐名是 UI 文案,客户端 PlansScreen 按 code 取 l10n:free/pro/team)。价格等真实字段保留。 已在节点实测:/v1/plans 200,返回 free ¥0 / pro ¥25 / team ¥99。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,14 @@ class PlansScreen extends ConsumerWidget {
|
||||
_ => const [],
|
||||
};
|
||||
|
||||
// 套餐名是 UI 文案(后端 plans 表无名称列),按 code 取 l10n。
|
||||
String _name(String code) => switch (code) {
|
||||
'free' => t.freePlan,
|
||||
'pro' => t.proPlan,
|
||||
'team' => t.teamPlan,
|
||||
_ => code,
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final c = context.pangolin;
|
||||
@@ -80,7 +88,7 @@ class PlansScreen extends ConsumerWidget {
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 14, top: p.code == 'pro' ? 12 : 0),
|
||||
child: PlanCard(
|
||||
name: p.localizedName(t.lang),
|
||||
name: _name(p.code),
|
||||
price: p.priceLabel(),
|
||||
period: t.perMonth,
|
||||
features: _feats(p.code),
|
||||
|
||||
@@ -173,8 +173,6 @@ func (a *AccountAPI) weeklyGB(ctx context.Context, uid int64) []float64 {
|
||||
|
||||
type planResponse struct {
|
||||
Code string `json:"code"`
|
||||
NameZH string `json:"name_zh"`
|
||||
NameEN string `json:"name_en"`
|
||||
DailyMinutes *int64 `json:"daily_minutes"` // null = unlimited
|
||||
AdGate bool `json:"ad_gate"`
|
||||
PriceCents int `json:"price_cents"` // 价格(分);0 = 免费
|
||||
@@ -183,9 +181,10 @@ type planResponse struct {
|
||||
}
|
||||
|
||||
// ListPlans handles GET /v1/plans.
|
||||
// 套餐名为 UI 文案(客户端按 code 取 l10n),plans 表不含名称列,故不查 name_*。
|
||||
func (a *AccountAPI) ListPlans(w http.ResponseWriter, r *http.Request) {
|
||||
rows, err := a.db.QueryContext(r.Context(),
|
||||
`SELECT code, name_zh, name_en, daily_minutes, ad_gate, price_cents, currency, period FROM plans ORDER BY id`)
|
||||
`SELECT code, daily_minutes, ad_gate, price_cents, currency, period FROM plans ORDER BY id`)
|
||||
if err != nil {
|
||||
apierr.WriteJSON(w, http.StatusInternalServerError, apierr.ErrInternal)
|
||||
return
|
||||
@@ -196,7 +195,7 @@ func (a *AccountAPI) ListPlans(w http.ResponseWriter, r *http.Request) {
|
||||
for rows.Next() {
|
||||
var p planResponse
|
||||
var dm sql.NullInt64
|
||||
if err := rows.Scan(&p.Code, &p.NameZH, &p.NameEN, &dm, &p.AdGate, &p.PriceCents, &p.Currency, &p.Period); err != nil {
|
||||
if err := rows.Scan(&p.Code, &dm, &p.AdGate, &p.PriceCents, &p.Currency, &p.Period); err != nil {
|
||||
apierr.WriteJSON(w, http.StatusInternalServerError, apierr.ErrInternal)
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user