refactor: 修复 modules 三层架构违规

- auth: actionDeleteAccount 改用 service+repo,forgot-password 完整三层实现
- card: serviceCheckCardOwnership 替代直接调用 repository
- deck: 移除 service 层的 use server 指令
- dictionary: 数据转换逻辑从 repository 移到 service
- ocr: 认证移到 action 层,跨模块调用改用 service
- translator: genIPA/genLanguage 改用 service 层
This commit is contained in:
2026-03-11 09:40:53 +08:00
parent e68e24a9fb
commit 804c28ada9
34 changed files with 599 additions and 235 deletions

View File

@@ -1,5 +1,3 @@
import { TSharedItem } from "@/shared/dictionary-type";
export type RepoInputCreateDictionaryLookUp = {
userId?: string;
text: string;
@@ -8,7 +6,29 @@ export type RepoInputCreateDictionaryLookUp = {
dictionaryItemId?: number;
};
export type RepoOutputSelectLastLookUpResult = TSharedItem & {id: number} | null;
export type RepoOutputSelectLastLookUpResultEntry = {
id: number;
itemId: number;
ipa: string | null;
definition: string;
partOfSpeech: string | null;
example: string;
createdAt: Date;
updatedAt: Date;
};
export type RepoOutputSelectLastLookUpResultItem = {
id: number;
frequency: number;
standardForm: string;
queryLang: string;
definitionLang: string;
createdAt: Date;
updatedAt: Date;
entries: RepoOutputSelectLastLookUpResultEntry[];
};
export type RepoOutputSelectLastLookUpResult = RepoOutputSelectLastLookUpResultItem | null;
export type RepoInputCreateDictionaryItem = {
standardForm: string;

View File

@@ -1,6 +1,5 @@
import { stringNormalize } from "@/utils/string";
import {
RepoInputCreateDictionaryEntry,
RepoInputCreateDictionaryEntryWithoutItemId,
RepoInputCreateDictionaryItem,
RepoInputCreateDictionaryLookUp,
@@ -30,22 +29,12 @@ export async function repoSelectLastLookUpResult(dto: RepoInputSelectLastLookUpR
createdAt: 'desc'
}
});
if (result && result.dictionaryItem) {
const item = result.dictionaryItem;
return {
id: item.id,
standardForm: item.standardForm,
entries: item.entries.filter(v => !!v).map(v => {
return {
ipa: v.ipa || undefined,
definition: v.definition,
partOfSpeech: v.partOfSpeech || undefined,
example: v.example
};
})
};
if (!result?.dictionaryItem) {
return null;
}
return null;
return result.dictionaryItem;
}
export async function repoCreateLookUp(content: RepoInputCreateDictionaryLookUp) {

View File

@@ -2,9 +2,23 @@ import { executeDictionaryLookup } from "@/lib/bigmodel/dictionary/orchestrator"
import { repoCreateLookUp, repoCreateLookUpWithItemAndEntries, repoSelectLastLookUpResult } from "./dictionary-repository";
import { ServiceInputLookUp } from "./dictionary-service-dto";
import { createLogger } from "@/lib/logger";
import { RepoOutputSelectLastLookUpResultItem } from "./dictionary-repository-dto";
const log = createLogger("dictionary-service");
function transformRawItemToSharedItem(rawItem: RepoOutputSelectLastLookUpResultItem) {
return {
id: rawItem.id,
standardForm: rawItem.standardForm,
entries: rawItem.entries.map(entry => ({
ipa: entry.ipa ?? undefined,
definition: entry.definition,
partOfSpeech: entry.partOfSpeech ?? undefined,
example: entry.example
}))
};
}
export const serviceLookUp = async (dto: ServiceInputLookUp) => {
const {
text,
@@ -27,7 +41,6 @@ export const serviceLookUp = async (dto: ServiceInputLookUp) => {
definitionLang
);
// 使用事务确保数据一致性
repoCreateLookUpWithItemAndEntries(
{
standardForm: response.standardForm,
@@ -47,18 +60,20 @@ export const serviceLookUp = async (dto: ServiceInputLookUp) => {
return response;
} else {
const transformedResult = transformRawItemToSharedItem(lastLookUpResult);
repoCreateLookUp({
userId: userId,
text: text,
queryLang: queryLang,
definitionLang: definitionLang,
dictionaryItemId: lastLookUpResult.id
dictionaryItemId: transformedResult.id
}).catch(error => {
log.error("Failed to save dictionary data", { error: error instanceof Error ? error.message : String(error) });
});
return {
standardForm: lastLookUpResult.standardForm,
entries: lastLookUpResult.entries
standardForm: transformedResult.standardForm,
entries: transformedResult.entries
};
}
};