refactor: remove unused subscription plans and router files
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* VIP 订阅套餐常量
|
||||
*
|
||||
* Mock 阶段硬编码,后续可改为从 `ApiPath.paymentProducts` 拉取。
|
||||
*
|
||||
* 原始 Dart: lib/ui/subscription/...
|
||||
*
|
||||
* 当前订阅页优先使用后端 `/api/payment/plans` 返回的套餐。
|
||||
* 本常量仅保留给旧 UI / fallback 代码参考。
|
||||
*/
|
||||
export type SubscriptionPlanId = "monthly" | "quarterly" | "annual";
|
||||
|
||||
export interface SubscriptionPlan {
|
||||
id: SubscriptionPlanId;
|
||||
/** 卡片顶部名称,例如 "Monthly" */
|
||||
name: string;
|
||||
/** 当前价格 */
|
||||
price: number;
|
||||
/** 划线原价 */
|
||||
originalPrice: number;
|
||||
/** 每日折算价字符串,e.g. "$0.66/day" */
|
||||
perDay: string;
|
||||
/** 是否高亮(默认推荐:月付) */
|
||||
highlight: boolean;
|
||||
/** 该套餐每天补充的语音聊天分钟数(业务常量) */
|
||||
voiceMinutesPerDay: number;
|
||||
}
|
||||
|
||||
export const SUBSCRIPTION_PLANS: readonly SubscriptionPlan[] = [
|
||||
{
|
||||
id: "monthly",
|
||||
name: "Monthly",
|
||||
price: 19.9,
|
||||
originalPrice: 24.9,
|
||||
perDay: "$0.66/day",
|
||||
highlight: true,
|
||||
voiceMinutesPerDay: 30, // 30 分钟/天
|
||||
},
|
||||
{
|
||||
id: "quarterly",
|
||||
name: "Quarterly",
|
||||
price: 49.9,
|
||||
originalPrice: 59.9,
|
||||
perDay: "$0.55/day",
|
||||
highlight: false,
|
||||
voiceMinutesPerDay: 45, // 45 分钟/天(比月付多,性价比)
|
||||
},
|
||||
{
|
||||
id: "annual",
|
||||
name: "Annual",
|
||||
price: 169.9,
|
||||
originalPrice: 199.9,
|
||||
perDay: "$0.47/day",
|
||||
highlight: false,
|
||||
voiceMinutesPerDay: 60, // 60 分钟/天(年度最多)
|
||||
},
|
||||
] as const;
|
||||
@@ -1,20 +1,5 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* ChatRepository
|
||||
*
|
||||
* 聊天仓库:编排远程 ChatApi + 本地 LocalChatStorage(Dexie/IndexedDB)。
|
||||
* 行为对齐原 Dart `lib/data/repositories/chat_repository_impl.dart`:
|
||||
* - `saveMessagesToLocal` 保留「先清后写」语义(Dart `box.clear()` + bulk add)
|
||||
* - 替代 Dart 同步 `int get localMessageCount`,改为异步 `getLocalMessageCount()`
|
||||
* (Dexie 异步 API 决定)
|
||||
*
|
||||
* ChatMessage ↔ LocalMessage 的字段映射在仓库内 inline 完成(用户决策):
|
||||
* - 写:ChatMessage 的 id/role/content/createdAt → LocalMessage(sessionId="")
|
||||
* - 读:LocalMessage 的 id/role/content/createdAt → ChatMessage(丢弃 sessionId)
|
||||
*
|
||||
* 原始 Dart: lib/data/repositories/chat_repository_impl.dart
|
||||
*/
|
||||
import { ChatApi, chatApi } from "@/data/services/api";
|
||||
import {
|
||||
ChatHistoryResponse,
|
||||
|
||||
@@ -30,12 +30,14 @@ export interface IChatRepository {
|
||||
/** 获取聊天历史,分页参数默认 limit=50, offset=0。 */
|
||||
getHistory(limit?: number, offset?: number): Promise<Result<ChatHistoryResponse>>;
|
||||
|
||||
//TODO remove
|
||||
/** 解锁私密消息。 */
|
||||
unlockPrivateMessage(messageId: string): Promise<Result<UnlockPrivateResponse>>;
|
||||
|
||||
/** 一键解锁历史锁定消息。 */
|
||||
unlockHistory(): Promise<Result<UnlockHistoryResponse>>;
|
||||
|
||||
//TODO remove
|
||||
/** 把本地缓存中的私密消息标记为已解锁。 */
|
||||
markPrivateMessageUnlockedInLocal(
|
||||
messageId: string,
|
||||
|
||||
@@ -75,8 +75,6 @@ export class AuthStorage implements IAuthStorage {
|
||||
}
|
||||
|
||||
// ---- refresh token ----
|
||||
// TODO(security): 升级到 HttpOnly Cookie 方案
|
||||
// SECURITY: 明文存储,仅供本轮与 Dart 行为对齐
|
||||
|
||||
getRefreshToken(): Promise<ResultT<string | null>> {
|
||||
return SpAsyncUtil.getString(StorageKeys.refreshToken);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
// /
|
||||
// * Router 公共导出
|
||||
// *
|
||||
// * 集中管理:
|
||||
// * - 路由常量(ROUTES、ROUTE_BUILDERS、AUTH_ONLY_ROUTES、PUBLIC_ROUTES、ALL_STATIC_ROUTES)
|
||||
// * - Next.js 16 Proxy(CDN 端鉴权重定向)
|
||||
// *
|
||||
// * 业务层导入示例:
|
||||
// * ```ts
|
||||
// * import { ROUTES, AUTH_ONLY_ROUTES, type Route } from "@/router";
|
||||
// * ```
|
||||
// */
|
||||
// export * from "./routes";
|
||||
// export { proxy, config as proxyConfig } from "./proxy";
|
||||
@@ -1,101 +0,0 @@
|
||||
// /
|
||||
// * Next.js 16 Proxy(原 `middleware.ts`)
|
||||
// *
|
||||
// * 行为(鉴权路由统一在此处理,业务层组件不再做 auth-driven 跳转):
|
||||
// * - 已登录(NextAuth `next-auth.session-token` cookie 存在)访问 `/splash` 或 `/auth`
|
||||
// * → 308 重定向到 `/chat`
|
||||
// * - 未登录(cookie 缺失)访问 `/chat` 或 `/sidebar`
|
||||
// * → 308 重定向到 `/splash`(首界面)
|
||||
// * - 其他情况透传(`NextResponse.next()`)
|
||||
// *
|
||||
// * 重要约束:
|
||||
// * - 不做自定义 cookie 持久化:统一用 NextAuth 内置 `next-auth.session-token` /
|
||||
// * `__Secure-next-auth.session-token`(v5 默认 httpOnly + secure)作信号。
|
||||
// * - 真正的鉴权门在 Client 侧 `useSession()`(next-auth/react),用于 UI 状态。
|
||||
// * - 路由跳转(唯一鉴权跳转点)由本 proxy 集中处理。
|
||||
// * - 副作用:邮箱登录用户(不走 NextAuth)不会被本 proxy 识别为已登录。
|
||||
// * 邮箱登录在后续轮次若要恢复 proxy 行为,需引入 NextAuth EmailProvider 或独立
|
||||
// * email-session 体系。
|
||||
// *
|
||||
// * Next 16 重要变更(参见 `node_modules/next/dist/docs/01-app/03-api-reference/03-file-conventions/proxy.md`):
|
||||
// * - 文件从 `middleware.ts` 重命名为 `proxy.ts`;`middleware` 仍可用但已 deprecated。
|
||||
// * - 默认 Node.js runtime;不支持 `runtime` 配置(设置会抛错)。
|
||||
// * - 函数导出名建议为 `proxy`(可默认导出)。
|
||||
// *
|
||||
// * 用 `src/` 时 proxy 必须放在 `src/` 内(参见 `src-folder.md`)。
|
||||
// */
|
||||
|
||||
// import { NextResponse } from "next/server";
|
||||
// import type { NextRequest } from "next/server";
|
||||
|
||||
// import { Logger } from "@/utils/logger";
|
||||
|
||||
// import {
|
||||
// AUTH_ONLY_ROUTES,
|
||||
// PROTECTED_ROUTES,
|
||||
// ROUTES,
|
||||
// } from "@/router/routes";
|
||||
|
||||
// / NextAuth 内置 session cookie 名(v5 默认 httpOnly) */
|
||||
// const SESSION_COOKIE_NAMES = [
|
||||
// "next-auth.session-token",
|
||||
// "__Secure-next-auth.session-token",
|
||||
// ];
|
||||
|
||||
// / proxy 入口日志(Node.js runtime 跑,pino 兼容)—— 排查 / 监控路由用 */
|
||||
// const log = new Logger("Proxy");
|
||||
|
||||
// function isAuthOnlyRoute(pathname: string): boolean {
|
||||
// return (AUTH_ONLY_ROUTES as readonly string[]).includes(pathname);
|
||||
// }
|
||||
|
||||
// function isProtectedRoute(pathname: string): boolean {
|
||||
// return (PROTECTED_ROUTES as readonly string[]).includes(pathname);
|
||||
// }
|
||||
|
||||
// /
|
||||
// * Proxy 入口
|
||||
// */
|
||||
// export function proxy(request: NextRequest) {
|
||||
// const { pathname } = request.nextUrl;
|
||||
|
||||
// // 检查 NextAuth session cookie 存在性
|
||||
// const hasSession = SESSION_COOKIE_NAMES.some(
|
||||
// (name) => Boolean(request.cookies.get(name)?.value),
|
||||
// );
|
||||
|
||||
// // 已登录访问未登录专属页 → /chat
|
||||
// if (hasSession && isAuthOnlyRoute(pathname)) {
|
||||
// log.info(
|
||||
// { pathname, target: ROUTES.chat, reason: "logged-in → auth-only" },
|
||||
// "[proxy] redirect",
|
||||
// );
|
||||
// const url = request.nextUrl.clone();
|
||||
// url.pathname = ROUTES.chat;
|
||||
// return NextResponse.redirect(url, 308);
|
||||
// }
|
||||
|
||||
// // 未登录访问登录态专属页 → /splash(首界面)
|
||||
// if (!hasSession && isProtectedRoute(pathname)) {
|
||||
// log.info(
|
||||
// { pathname, target: ROUTES.splash, reason: "not-logged-in → protected" },
|
||||
// "[proxy] redirect",
|
||||
// );
|
||||
// const url = request.nextUrl.clone();
|
||||
// url.pathname = ROUTES.splash;
|
||||
// return NextResponse.redirect(url, 308);
|
||||
// }
|
||||
|
||||
// return NextResponse.next();
|
||||
// }
|
||||
|
||||
// /
|
||||
// * 匹配器:排除 API、Next 静态资源、图标与常见静态文件扩展名。
|
||||
// * 不排除 `_next/data`,因为 proxy 文档明确说明"即使在排除列表中 proxy 仍会跑"
|
||||
// * (安全兜底)。
|
||||
// */
|
||||
// export const config = {
|
||||
// matcher: [
|
||||
// "/((?!api|_next/static|_next/image|_next/data|favicon.ico|icons|.*\\.(?:png|jpg|jpeg|gif|svg|webp|ico|css|js|woff2?|ttf|otf)$).*)",
|
||||
// ],
|
||||
// };
|
||||
Reference in New Issue
Block a user