fix:修复所有的包导入错误问题
This commit is contained in:
@@ -8,18 +8,18 @@
|
||||
*
|
||||
* 设计:
|
||||
* - **不**走 Server `redirect()`:避免把 fbid 暴露在 URL 里。
|
||||
* - deviceId 走 sync `authStorage.setDeviceId`(与 `token_interceptor.ts` 同源;
|
||||
* - deviceId 走 `AuthStorage.getInstance().setDeviceId`(与 `token_interceptor.ts` 同源;
|
||||
* 写入键 `cozsweet.deviceId`)。
|
||||
* - fbid 走 `localStorage.setItem("facebook_id", ...)`,对齐 async
|
||||
* `StorageKeys.facebookId`。Sync 单例**没有** `setFacebookId` 方法,本轮
|
||||
* 不重构 storage(见 plan §6.1),仅留 TODO。
|
||||
* - fbid 走 `window.localStorage.setItem(StorageKeys.facebookId, ...)`,
|
||||
* 与 async `AuthStorage.setFacebookId` 同键名。Sync 层暂未统一抽象,
|
||||
* 仅留 TODO。
|
||||
* - 写入完成后 `router.replace('/chat')`,URL 不留深链痕迹。
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { authStorage } from "@/data/storage/auth_storage";
|
||||
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
||||
import { StorageKeys } from "@/data/storage/storage_keys";
|
||||
import { ROUTES } from "@/lib/routes";
|
||||
|
||||
@@ -33,11 +33,12 @@ export default function DeepLinkPersist({ deviceId, fbid }: DeepLinkPersistProps
|
||||
const [done, setDone] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
void (async () => {
|
||||
try {
|
||||
authStorage.setDeviceId(deviceId);
|
||||
await AuthStorage.getInstance().setDeviceId(deviceId);
|
||||
if (fbid && fbid.length > 0) {
|
||||
// TODO: 统一 sync/async AuthStorage 后改为 `authStorage.setFacebookId(fbid)`。
|
||||
// 当前 sync 单例未暴露该方法;使用 `StorageKeys.facebookId` 保持与 async 层
|
||||
// TODO: 统一 sync/async AuthStorage 后改为 `AuthStorage.getInstance().setFacebookId(fbid)`。
|
||||
// 当前 sync 层未暴露该方法;使用 `StorageKeys.facebookId` 保持与 async 层
|
||||
// `src/data/storage/auth/auth_storage.ts` 键名一致。
|
||||
window.localStorage.setItem(StorageKeys.facebookId, fbid);
|
||||
}
|
||||
@@ -48,6 +49,7 @@ export default function DeepLinkPersist({ deviceId, fbid }: DeepLinkPersistProps
|
||||
setDone(true);
|
||||
router.replace(ROUTES.chat);
|
||||
}
|
||||
})();
|
||||
}, [deviceId, fbid, router]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* 原始 Dart: lib/data/repositories/chat_repository_impl.dart
|
||||
*/
|
||||
import { ChatApi, chatApi } from "@/data/api";
|
||||
import { ChatApi, chatApi } from "@/data/services/api";
|
||||
import { ChatHistoryResponse } from "@/data/dto/chat/chat_history_response";
|
||||
import { ChatMessage } from "@/data/dto/chat/chat_message";
|
||||
import { ChatSendResponse } from "@/data/dto/chat/chat_send_response";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* 原始 Dart: lib/data/repositories/metrics_repository_impl.dart
|
||||
*/
|
||||
import { MetricsApi, metricsApi } from "@/data/api";
|
||||
import { MetricsApi, metricsApi } from "@/data/services/api";
|
||||
import { AppEvent } from "@/data/dto/metrics/app_event";
|
||||
import { PwaEvent } from "@/data/dto/metrics/pwa_event";
|
||||
import { Result } from "@/utils/result";
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* 原始 Dart: lib/data/repositories/user_repository_impl.dart
|
||||
*/
|
||||
import { UserApi, userApi } from "@/data/api";
|
||||
import { UserApi, userApi } from "@/data/services/api";
|
||||
import { CreditsData } from "@/data/dto/user/credits_data";
|
||||
import { CreditsHistoryData } from "@/data/dto/user/credits_history_data";
|
||||
import { UpdateProfileRequest } from "@/data/dto/user/update_profile_request";
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
import { ofetch, type $Fetch, type FetchHook } from "ofetch";
|
||||
import { ApiError, ErrorCode } from "./api_result";
|
||||
import { getApiConfig } from "./config/api_config";
|
||||
import { getApiConfig } from "../../../core/net/config/api_config";
|
||||
import { authRefreshInterceptor } from "./interceptor/auth_refresh_interceptor";
|
||||
import { loggingInterceptor } from "./interceptor/logging_interceptor";
|
||||
import { tokenInterceptor } from "./interceptor/token_interceptor";
|
||||
|
||||
@@ -10,7 +10,7 @@ export * from "./http_client";
|
||||
export * from "./metrics_api";
|
||||
export * from "./response_helper";
|
||||
export * from "./user_api";
|
||||
export * from "./config/api_config";
|
||||
export * from "../../../core/net/config/api_config";
|
||||
export * from "./interceptor/auth_refresh_interceptor";
|
||||
export * from "./interceptor/logging_interceptor";
|
||||
export * from "./interceptor/token_interceptor";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
import type { FetchHook } from "ofetch";
|
||||
import { ApiPath } from "../api_path";
|
||||
import { authStorage } from "../../storage/auth_storage";
|
||||
import { AuthStorage } from "../../../storage/auth/auth_storage";
|
||||
|
||||
/**
|
||||
* 不需要 token 的路径
|
||||
@@ -40,11 +40,27 @@ function needsToken(path: string): boolean {
|
||||
return !NO_TOKEN_PATHS.some((noTokenPath) => path.includes(noTokenPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前可用的 auth token(登录 token 优先,其次游客 token)
|
||||
*/
|
||||
async function getAuthToken(): Promise<string | null> {
|
||||
const storage = AuthStorage.getInstance();
|
||||
const loginR = await storage.getLoginToken();
|
||||
if (loginR.success && loginR.data && loginR.data.length > 0) {
|
||||
return loginR.data;
|
||||
}
|
||||
const guestR = await storage.getGuestToken();
|
||||
if (guestR.success && guestR.data && guestR.data.length > 0) {
|
||||
return guestR.data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export const onRequestToken: FetchHook = async (ctx) => {
|
||||
const path = getRequestPath(ctx.request);
|
||||
if (!needsToken(path)) return;
|
||||
|
||||
const token = authStorage.getAuthToken();
|
||||
const token = await getAuthToken();
|
||||
if (token && ctx.request instanceof Request) {
|
||||
ctx.request.headers.set("Authorization", `Bearer ${token}`);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export * from "./api/http_client";
|
||||
export * from "./api/metrics_api";
|
||||
export * from "./api/response_helper";
|
||||
export * from "./api/user_api";
|
||||
export * from "./api/config/api_config";
|
||||
export * from "../../core/net/config/api_config";
|
||||
export * from "./api/interceptor/auth_refresh_interceptor";
|
||||
export * from "./api/interceptor/logging_interceptor";
|
||||
export * from "./api/interceptor/token_interceptor";
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* - onMoodUpdate(mood)
|
||||
* - onError(errorMessage)
|
||||
*/
|
||||
import { getApiConfig } from "@/data/api/config/api_config";
|
||||
import { getApiConfig } from "@/core/net/config/api_config";
|
||||
|
||||
export interface SentencePayload {
|
||||
index: number;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* 客户端鉴权门 hook
|
||||
*
|
||||
* 单一真值 = `authStorage`(与 `src/data/api/interceptor/token_interceptor.ts` 同源)。
|
||||
* 单一真值 = `window.localStorage[StorageKeys.loginToken]`。
|
||||
* 故意不引入 Context/Zustand:本轮只有 splash/auth 两处使用,直接 hook 调用更直白。
|
||||
*
|
||||
* 实现要点(React 19 / Next.js 16 约定):
|
||||
@@ -22,11 +22,14 @@
|
||||
*
|
||||
* 注:本轮不暴露 `ready` 标志——`useSyncExternalStore` 自身的 SSR / 客户端差异
|
||||
* 处理已经能保证水合首帧拿到 `false`(与 SSR 一致),无需调用方再判 ready。
|
||||
*
|
||||
* 注意:直接读 `window.localStorage` 是因为 `useSyncExternalStore.getSnapshot`
|
||||
* 必须是同步函数。`AuthStorage.hasLoginToken()` 是 async,无法在此处使用。
|
||||
*/
|
||||
|
||||
import { useSyncExternalStore } from "react";
|
||||
|
||||
import { authStorage } from "@/data/storage/auth_storage";
|
||||
import { StorageKeys } from "@/data/storage/storage_keys";
|
||||
|
||||
export interface AuthGateState {
|
||||
/** 已登录(持有非空 `cozsweet.loginToken`) */
|
||||
@@ -36,7 +39,14 @@ export interface AuthGateState {
|
||||
// 静态 subscribe:localStorage 在本应用生命周期内不会主动变化。
|
||||
const subscribe = (): (() => void) => () => {};
|
||||
|
||||
const getSnapshot = (): boolean => authStorage.hasLoginToken();
|
||||
/**
|
||||
* 同步读取 localStorage 中的 login_token(与 `AuthStorage.hasLoginToken` 语义一致)
|
||||
*/
|
||||
const getSnapshot = (): boolean => {
|
||||
if (typeof window === "undefined") return false;
|
||||
const token = window.localStorage.getItem(StorageKeys.loginToken);
|
||||
return token !== null && token.length > 0;
|
||||
};
|
||||
|
||||
const getServerSnapshot = (): boolean => false;
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
*
|
||||
* 注:仅在浏览器环境可用;SSR/Server Components 中调用会抛错。
|
||||
*/
|
||||
import { authStorage } from "../data/storage/auth_storage";
|
||||
import { AuthStorage } from "../data/storage/auth/auth_storage";
|
||||
import { SpAsyncUtil } from "./storage";
|
||||
import { StorageKeys } from "../data/storage/storage_keys";
|
||||
|
||||
export class DeviceIdentifier {
|
||||
private cachedId: string | null = null;
|
||||
@@ -30,16 +32,18 @@ export class DeviceIdentifier {
|
||||
/**
|
||||
* 重置缓存与持久化(用于测试或多账号切换)
|
||||
*/
|
||||
reset(): void {
|
||||
async reset(): Promise<void> {
|
||||
this.cachedId = null;
|
||||
this.initPromise = null;
|
||||
authStorage.removeDeviceId();
|
||||
await SpAsyncUtil.remove(StorageKeys.deviceId);
|
||||
}
|
||||
|
||||
private async initialize(): Promise<string> {
|
||||
// 1. 优先从 localStorage 读取
|
||||
const stored = authStorage.getDeviceId();
|
||||
if (stored) return stored;
|
||||
const storedR = await AuthStorage.getInstance().getDeviceId();
|
||||
if (storedR.success && storedR.data && storedR.data.length > 0) {
|
||||
return storedR.data;
|
||||
}
|
||||
|
||||
// 2. SSR/Node 环境守卫:调用方必须保证在浏览器中调用
|
||||
if (typeof window === "undefined") {
|
||||
@@ -55,7 +59,7 @@ export class DeviceIdentifier {
|
||||
const result = await fp.get();
|
||||
|
||||
// 4. 持久化
|
||||
authStorage.setDeviceId(result.visitorId);
|
||||
await AuthStorage.getInstance().setDeviceId(result.visitorId);
|
||||
return result.visitorId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
/**
|
||||
* SpAsyncUtil — 键值对持久化工具类(基于 unstorage)
|
||||
*
|
||||
* 原始 Dart: `lib/utils/src/sp_async_util.dart`(`SpAsyncUtil` 静态类)
|
||||
*
|
||||
* 设计目标:
|
||||
* - **完全静态类化**:所有状态/方法/函数均封装在 SpAsyncUtil 类内
|
||||
* - 底层基于 unstorage 抽象(浏览器 localStorage / SSR memory 自动切换)
|
||||
* - 保留 `Promise<Result<T>>` API 兼容(state machines、interceptor、repositories 零修改)
|
||||
*
|
||||
* 用法:
|
||||
* ```ts
|
||||
* import { SpAsyncUtil } from "@/utils/storage";
|
||||
|
||||
Reference in New Issue
Block a user