This commit is contained in:
2026-02-02 23:57:01 +08:00
parent 76749549ff
commit eaf97b8279
67 changed files with 106 additions and 134 deletions

View File

@@ -4,7 +4,7 @@ import { useState, useEffect, useCallback } from "react";
import { useTranslations } from "next-intl";
import { Letter, SupportedAlphabets } from "@/lib/interfaces";
import { IconClick } from "@/components/ui/buttons";
import IMAGES from "@/config/images";
import { IMAGES } from "@/config/images";
import { ChevronLeft, ChevronRight } from "lucide-react";
interface AlphabetCardProps {
@@ -13,7 +13,7 @@ interface AlphabetCardProps {
onBack: () => void;
}
export default function AlphabetCard({ alphabet, alphabetType, onBack }: AlphabetCardProps) {
export function AlphabetCard({ alphabet, alphabetType, onBack }: AlphabetCardProps) {
const t = useTranslations("alphabet");
const [currentIndex, setCurrentIndex] = useState(0);
const [showIPA, setShowIPA] = useState(true);

View File

@@ -1,6 +1,6 @@
import { LightButton } from "@/components/ui/buttons";
import { IconClick } from "@/components/ui/buttons";
import IMAGES from "@/config/images";
import { IMAGES } from "@/config/images";
import { Letter, SupportedAlphabets } from "@/lib/interfaces";
import {
Dispatch,
@@ -12,7 +12,7 @@ import {
} from "react";
import { useTranslations } from "next-intl";
export default function MemoryCard({
export function MemoryCard({
alphabet,
setChosenAlphabet,
}: {

View File

@@ -3,9 +3,9 @@
import { useState, useEffect } from "react";
import { useTranslations } from "next-intl";
import { Letter, SupportedAlphabets } from "@/lib/interfaces";
import Container from "@/components/ui/Container";
import { Container } from "@/components/ui/Container";
import { LightButton } from "@/components/ui/buttons";
import AlphabetCard from "./AlphabetCard";
import { AlphabetCard } from "./AlphabetCard";
export default function Alphabet() {
const t = useTranslations("alphabet");

View File

@@ -1,4 +1,4 @@
import { TSharedEntry } from "@/shared";
import { TSharedEntry } from "@/shared/dictionary-type";
interface DictionaryEntryProps {
entry: TSharedEntry;

View File

@@ -4,9 +4,9 @@ import { authClient } from "@/lib/auth-client";
import { DictionaryEntry } from "./DictionaryEntry";
import { useTranslations } from "next-intl";
import { performDictionaryLookup } from "./utils";
import { TSharedItem } from "@/shared";
import { TSharedItem } from "@/shared/dictionary-type";
import { TSharedFolder } from "@/shared/folder-type";
import { actionCreatePair } from "@/modules/folder";
import { actionCreatePair } from "@/modules/folder/folder-aciton";
interface SearchResultProps {
searchResult: TSharedItem;

View File

@@ -1,15 +1,15 @@
"use client";
import { useState, useEffect } from "react";
import Container from "@/components/ui/Container";
import { Container } from "@/components/ui/Container";
import { authClient } from "@/lib/auth-client";
import { SearchForm } from "./SearchForm";
import { SearchResult } from "./SearchResult";
import { useTranslations } from "next-intl";
import { POPULAR_LANGUAGES } from "./constants";
import { performDictionaryLookup } from "./utils";
import { TSharedItem } from "@/shared";
import { actionGetFoldersByUserId } from "@/modules/folder";
import { TSharedItem } from "@/shared/dictionary-type";
import { actionGetFoldersByUserId } from "@/modules/folder/folder-aciton";
import { TSharedFolder } from "@/shared/folder-type";
import { toast } from "sonner";

View File

@@ -1,7 +1,7 @@
import { toast } from "sonner";
import { actionLookUpDictionary } from "@/modules/dictionary/dictionary-action";
import { ActionInputLookUpDictionary, ActionOutputLookUpDictionary } from "@/modules/dictionary";
import { TSharedItem } from "@/shared";
import { ActionInputLookUpDictionary, ActionOutputLookUpDictionary } from "@/modules/dictionary/dictionary-action-dto";
import { TSharedItem } from "@/shared/dictionary-type";
export async function performDictionaryLookup(
options: ActionInputLookUpDictionary,

View File

@@ -93,4 +93,4 @@ const FolderSelector: React.FC<FolderSelectorProps> = ({ folders }) => {
);
};
export default FolderSelector;
export { FolderSelector };

View File

@@ -208,4 +208,4 @@ const Memorize: React.FC<MemorizeProps> = ({ textPairs }) => {
);
};
export default Memorize;
export { Memorize };

View File

@@ -1,11 +1,11 @@
import { redirect } from "next/navigation";
import { getTranslations } from "next-intl/server";
import { isNonNegativeInteger } from "@/utils/random";
import FolderSelector from "./FolderSelector";
import Memorize from "./Memorize";
import { FolderSelector } from "./FolderSelector";
import { Memorize } from "./Memorize";
import { auth } from "@/auth";
import { headers } from "next/headers";
import { actionGetFoldersWithTotalPairsByUserId, actionGetPairsByFolderId } from "@/modules/folder";
import { actionGetFoldersWithTotalPairsByUserId, actionGetPairsByFolderId } from "@/modules/folder/folder-aciton";
export default async function MemorizePage({
searchParams,

View File

@@ -1,4 +1,4 @@
export default function SubtitleDisplay({ subtitle }: { subtitle: string }) {
export function SubtitleDisplay({ subtitle }: { subtitle: string }) {
const words = subtitle.match(/\b[\w']+(?:-[\w']+)*\b/g) || [];
let i = 0;
return (

View File

@@ -1,5 +1,5 @@
import { useState, useRef, forwardRef, useEffect, useCallback } from "react";
import SubtitleDisplay from "./SubtitleDisplay";
import { SubtitleDisplay } from "./SubtitleDisplay";
import { LightButton } from "@/components/ui/buttons";
import { getIndex, parseSrt, getNearistIndex } from "../subtitle";
import { useTranslations } from "next-intl";
@@ -213,4 +213,4 @@ const VideoPanel = forwardRef<HTMLVideoElement, VideoPanelProps>(
VideoPanel.displayName = "VideoPanel";
export default VideoPanel;
export { VideoPanel };

View File

@@ -7,7 +7,7 @@ interface FileInputComponentProps extends FileInputProps {
children: React.ReactNode;
}
export default function FileInput({ accept, onFileSelect, disabled, className, children }: FileInputComponentProps) {
export function FileInput({ accept, onFileSelect, disabled, className, children }: FileInputComponentProps) {
const inputRef = useRef<HTMLInputElement>(null);
const handleClick = React.useCallback(() => {

View File

@@ -5,7 +5,7 @@ import { useTranslations } from "next-intl";
import { LightButton } from "@/components/ui/buttons";
import { PlayButtonProps } from "../../types/player";
export default function PlayButton({ isPlaying, onToggle, disabled, className }: PlayButtonProps) {
export function PlayButton({ isPlaying, onToggle, disabled, className }: PlayButtonProps) {
const t = useTranslations("srt_player");
return (

View File

@@ -3,7 +3,7 @@
import React from "react";
import { SeekBarProps } from "../../types/player";
export default function SeekBar({ value, max, onChange, disabled, className }: SeekBarProps) {
export function SeekBar({ value, max, onChange, disabled, className }: SeekBarProps) {
const handleChange = React.useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
const newValue = parseInt(event.target.value);
onChange(newValue);

View File

@@ -5,7 +5,7 @@ import { LightButton } from "@/components/ui/buttons";
import { SpeedControlProps } from "../../types/player";
import { getPlaybackRateOptions, getPlaybackRateLabel } from "../../utils/timeUtils";
export default function SpeedControl({ playbackRate, onPlaybackRateChange, disabled, className }: SpeedControlProps) {
export function SpeedControl({ playbackRate, onPlaybackRateChange, disabled, className }: SpeedControlProps) {
const speedOptions = getPlaybackRateOptions();
const handleSpeedChange = React.useCallback(() => {

View File

@@ -3,7 +3,7 @@
import React from "react";
import { SubtitleTextProps } from "../../types/subtitle";
export default function SubtitleText({ text, onWordClick, style, className }: SubtitleTextProps) {
export function SubtitleText({ text, onWordClick, style, className }: SubtitleTextProps) {
const handleWordClick = React.useCallback((word: string) => {
onWordClick?.(word);
}, [onWordClick]);

View File

@@ -46,4 +46,4 @@ const VideoElement = forwardRef<HTMLVideoElement, VideoElementProps>(
VideoElement.displayName = "VideoElement";
export default VideoElement;
export { VideoElement };

View File

@@ -5,10 +5,10 @@ import { useTranslations } from "next-intl";
import { ChevronLeft, ChevronRight, RotateCcw, Pause } from "lucide-react";
import { LightButton } from "@/components/ui/buttons";
import { ControlBarProps } from "../../types/controls";
import PlayButton from "../atoms/PlayButton";
import SpeedControl from "../atoms/SpeedControl";
import { PlayButton } from "../atoms/PlayButton";
import { SpeedControl } from "../atoms/SpeedControl";
export default function ControlBar({
export function ControlBar({
isPlaying,
onPlayPause,
onPrevious,

View File

@@ -2,9 +2,9 @@
import React from "react";
import { SubtitleDisplayProps } from "../../types/subtitle";
import SubtitleText from "../atoms/SubtitleText";
import { SubtitleText } from "../atoms/SubtitleText";
export default function SubtitleArea({ subtitle, onWordClick, settings, className }: SubtitleDisplayProps) {
export function SubtitleArea({ subtitle, onWordClick, settings, className }: SubtitleDisplayProps) {
const handleWordClick = React.useCallback((word: string) => {
// 打开有道词典页面查询单词
window.open(

View File

@@ -8,7 +8,7 @@ import { LightButton } from "@/components/ui/buttons";
import { FileUploadProps } from "../../types/controls";
import { useFileUpload } from "../../hooks/useFileUpload";
export default function UploadZone({ onVideoUpload, onSubtitleUpload, className }: FileUploadProps) {
export function UploadZone({ onVideoUpload, onSubtitleUpload, className }: FileUploadProps) {
const t = useTranslations("srt_player");
const { uploadVideo, uploadSubtitle } = useFileUpload();

View File

@@ -2,7 +2,7 @@
import React, { forwardRef } from "react";
import { VideoElementProps } from "../../types/player";
import VideoElement from "../atoms/VideoElement";
import { VideoElement } from "../atoms/VideoElement";
interface VideoPlayerComponentProps extends VideoElementProps {
children?: React.ReactNode;
@@ -38,4 +38,4 @@ const VideoPlayer = forwardRef<HTMLVideoElement, VideoPlayerComponentProps>(
VideoPlayer.displayName = "VideoPlayer";
export default VideoPlayer;
export { VideoPlayer };

View File

@@ -9,11 +9,11 @@ import { useSubtitleSync } from "./hooks/useSubtitleSync";
import { useKeyboardShortcuts, createSrtPlayerShortcuts } from "./hooks/useKeyboardShortcuts";
import { useFileUpload } from "./hooks/useFileUpload";
import { loadSubtitle } from "./utils/subtitleParser";
import VideoPlayer from "./components/compounds/VideoPlayer";
import SubtitleArea from "./components/compounds/SubtitleArea";
import ControlBar from "./components/compounds/ControlBar";
import UploadZone from "./components/compounds/UploadZone";
import SeekBar from "./components/atoms/SeekBar";
import { VideoPlayer } from "./components/compounds/VideoPlayer";
import { SubtitleArea } from "./components/compounds/SubtitleArea";
import { ControlBar } from "./components/compounds/ControlBar";
import { UploadZone } from "./components/compounds/UploadZone";
import { SeekBar } from "./components/atoms/SeekBar";
import { LightButton } from "@/components/ui/buttons";
export default function SrtPlayerPage() {

View File

@@ -7,7 +7,7 @@ import {
TextSpeakerItemSchema,
} from "@/lib/interfaces";
import { IconClick } from "@/components/ui/buttons";
import IMAGES from "@/config/images";
import { IMAGES } from "@/config/images";
import { useTranslations } from "next-intl";
import { getLocalStorageOperator } from "@/lib/browser/localStorageOperators";
@@ -50,7 +50,7 @@ interface SaveListProps {
show?: boolean;
handleUse: (item: z.infer<typeof TextSpeakerItemSchema>) => void;
}
export default function SaveList({ show = false, handleUse }: SaveListProps) {
export function SaveList({ show = false, handleUse }: SaveListProps) {
const t = useTranslations("text_speaker");
const { get: getFromLocalStorage, set: setIntoLocalStorage } =
getLocalStorageOperator<typeof TextSpeakerArraySchema>(

View File

@@ -2,7 +2,7 @@
import { LightButton } from "@/components/ui/buttons";
import { IconClick } from "@/components/ui/buttons";
import IMAGES from "@/config/images";
import { IMAGES } from "@/config/images";
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
import {
TextSpeakerArraySchema,
@@ -10,13 +10,13 @@ import {
} from "@/lib/interfaces";
import { ChangeEvent, useEffect, useRef, useState } from "react";
import z from "zod";
import SaveList from "./SaveList";
import { SaveList } from "./SaveList";
import { useTranslations } from "next-intl";
import { getLocalStorageOperator } from "@/lib/browser/localStorageOperators";
import { genIPA, genLanguage } from "@/modules/translator/translator-action";
import { logger } from "@/lib/logger";
import PageLayout from "@/components/ui/PageLayout";
import { PageLayout } from "@/components/ui/PageLayout";
import { getTTSUrl, TTS_SUPPORTED_LANGUAGES } from "@/lib/bigmodel/tts";
export default function TextSpeakerPage() {

View File

@@ -2,14 +2,14 @@
import { LightButton } from "@/components/ui/buttons";
import { IconClick } from "@/components/ui/buttons";
import IMAGES from "@/config/images";
import { IMAGES } from "@/config/images";
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
import { useTranslations } from "next-intl";
import { useRef, useState } from "react";
import { actionTranslateText } from "@/modules/translator";
import { actionTranslateText } from "@/modules/translator/translator-action";
import { toast } from "sonner";
import { getTTSUrl, TTS_SUPPORTED_LANGUAGES } from "@/lib/bigmodel/tts";
import { TSharedTranslationResult } from "@/shared";
import { TSharedTranslationResult } from "@/shared/translator-type";
export default function TranslatorPage() {
const t = useTranslations("translator");

View File

@@ -2,17 +2,17 @@
import { useState, useActionState, startTransition } from "react";
import { useTranslations } from "next-intl";
import Container from "@/components/ui/Container";
import Input from "@/components/ui/Input";
import { Container } from "@/components/ui/Container";
import { Input } from "@/components/ui/Input";
import { LightButton } from "@/components/ui/buttons";
import { authClient } from "@/lib/auth-client";
import { signInAction, signUpAction, SignUpState } from "@/modules/auth";
import { signInAction, signUpAction, SignUpState } from "@/modules/auth/auth-action";
interface AuthFormProps {
redirectTo?: string;
}
export default function AuthForm({ redirectTo }: AuthFormProps) {
export function AuthForm({ redirectTo }: AuthFormProps) {
const t = useTranslations("auth");
const [mode, setMode] = useState<'signin' | 'signup'>('signin');
const [clearSignIn, setClearSignIn] = useState(false);

View File

@@ -1,7 +1,7 @@
import { auth } from "@/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
import AuthForm from "./AuthForm";
import { AuthForm } from "./AuthForm";
export default async function AuthPage(
props: {

View File

@@ -11,10 +11,10 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { toast } from "sonner";
import PageLayout from "@/components/ui/PageLayout";
import PageHeader from "@/components/ui/PageHeader";
import CardList from "@/components/ui/CardList";
import { actionCreateFolder, actionDeleteFolderById, actionGetFoldersWithTotalPairsByUserId, actionRenameFolderById } from "@/modules/folder";
import { PageLayout } from "@/components/ui/PageLayout";
import { PageHeader } from "@/components/ui/PageHeader";
import { CardList } from "@/components/ui/CardList";
import { actionCreateFolder, actionDeleteFolderById, actionGetFoldersWithTotalPairsByUserId, actionRenameFolderById } from "@/modules/folder/folder-aciton";
import { TSharedFolderWithTotalPairs } from "@/shared/folder-type";
interface FolderProps {
@@ -97,7 +97,7 @@ const FolderCard = ({ folder, refresh }: FolderProps) => {
);
};
export default function FoldersClient({ userId }: { userId: string; }) {
export function FoldersClient({ userId }: { userId: string; }) {
const t = useTranslations("folders");
const [folders, setFolders] = useState<TSharedFolderWithTotalPairs[]>(
[],

View File

@@ -1,5 +1,5 @@
import { LightButton } from "@/components/ui/buttons";
import Input from "@/components/ui/Input";
import { Input } from "@/components/ui/Input";
import { LocaleSelector } from "@/components/ui/LocaleSelector";
import { X } from "lucide-react";
import { useRef, useState } from "react";
@@ -16,7 +16,7 @@ interface AddTextPairModalProps {
) => void;
}
export default function AddTextPairModal({
export function AddTextPairModal({
isOpen,
onClose,
onAdd,

View File

@@ -3,19 +3,19 @@
import { ArrowLeft, Plus } from "lucide-react";
import { useEffect, useState } from "react";
import { redirect, useRouter } from "next/navigation";
import AddTextPairModal from "./AddTextPairModal";
import TextPairCard from "./TextPairCard";
import { AddTextPairModal } from "./AddTextPairModal";
import { TextPairCard } from "./TextPairCard";
import { useTranslations } from "next-intl";
import PageLayout from "@/components/ui/PageLayout";
import { PageLayout } from "@/components/ui/PageLayout";
import { GreenButton } from "@/components/ui/buttons";
import { IconButton } from "@/components/ui/buttons";
import CardList from "@/components/ui/CardList";
import { actionCreatePair, actionDeletePairById, actionGetPairsByFolderId } from "@/modules/folder";
import { CardList } from "@/components/ui/CardList";
import { actionCreatePair, actionDeletePairById, actionGetPairsByFolderId } from "@/modules/folder/folder-aciton";
import { TSharedPair } from "@/shared/folder-type";
import { toast } from "sonner";
export default function InFolder({ folderId }: { folderId: number; }) {
export function InFolder({ folderId }: { folderId: number; }) {
const [textPairs, setTextPairs] = useState<TSharedPair[]>([]);
const [loading, setLoading] = useState(true);
const [openAddModal, setAddModal] = useState(false);

View File

@@ -1,9 +1,10 @@
import { Edit, Trash2 } from "lucide-react";
import { useState } from "react";
import UpdateTextPairModal from "./UpdateTextPairModal";
import { UpdateTextPairModal } from "./UpdateTextPairModal";
import { useTranslations } from "next-intl";
import { TSharedPair } from "@/shared/folder-type";
import { actionUpdatePairById, ActionInputUpdatePairById } from "@/modules/folder";
import { actionUpdatePairById } from "@/modules/folder/folder-aciton";
import { ActionInputUpdatePairById } from "@/modules/folder/folder-action-dto";
import { toast } from "sonner";
interface TextPairCardProps {
@@ -12,7 +13,7 @@ interface TextPairCardProps {
refreshTextPairs: () => void;
}
export default function TextPairCard({
export function TextPairCard({
textPair,
onDel,
refreshTextPairs,

View File

@@ -1,11 +1,11 @@
import { LightButton } from "@/components/ui/buttons";
import Input from "@/components/ui/Input";
import { Input } from "@/components/ui/Input";
import { LocaleSelector } from "@/components/ui/LocaleSelector";
import { X } from "lucide-react";
import { useRef, useState } from "react";
import { useTranslations } from "next-intl";
import { TSharedPair } from "@/shared/folder-type";
import { ActionInputUpdatePairById } from "@/modules/folder";
import { ActionInputUpdatePairById } from "@/modules/folder/folder-action-dto";
interface UpdateTextPairModalProps {
isOpen: boolean;
@@ -14,7 +14,7 @@ interface UpdateTextPairModalProps {
onUpdate: (id: number, tp: ActionInputUpdatePairById) => void;
}
export default function UpdateTextPairModal({
export function UpdateTextPairModal({
isOpen,
onClose,
onUpdate,

View File

@@ -1,9 +1,9 @@
import { redirect } from "next/navigation";
import { getTranslations } from "next-intl/server";
import InFolder from "./InFolder";
import { InFolder } from "./InFolder";
import { auth } from "@/auth";
import { headers } from "next/headers";
import { actionGetUserIdByFolderId } from "@/modules/folder";
import { actionGetUserIdByFolderId } from "@/modules/folder/folder-aciton";
export default async function FoldersPage({
params,
}: {

View File

@@ -1,5 +1,5 @@
import { auth } from "@/auth";
import FoldersClient from "./FoldersClient";
import { FoldersClient } from "./FoldersClient";
import { redirect } from "next/navigation";
import { headers } from "next/headers";

View File

@@ -5,7 +5,7 @@ import { authClient } from "@/lib/auth-client";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
export default function LogoutButton() {
export function LogoutButton() {
const t = useTranslations("profile");
const router = useRouter();
return <LightButton onClick={async () => {

View File

@@ -1,11 +1,11 @@
import Image from "next/image";
import PageLayout from "@/components/ui/PageLayout";
import PageHeader from "@/components/ui/PageHeader";
import { PageLayout } from "@/components/ui/PageLayout";
import { PageHeader } from "@/components/ui/PageHeader";
import { auth } from "@/auth";
import { getTranslations } from "next-intl/server";
import { redirect } from "next/navigation";
import { headers } from "next/headers";
import LogoutButton from "./LogoutButton";
import { LogoutButton } from "./LogoutButton";
export default async function ProfilePage() {
const t = await getTranslations("profile");

View File

@@ -1,7 +1,7 @@
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { nextCookies } from "better-auth/next-js";
import prisma from "./lib/db";
import { prisma } from "./lib/db";
export const auth = betterAuth({
database: prismaAdapter(prisma, {

View File

@@ -1,10 +1,10 @@
"use client";
import IMAGES from "@/config/images";
import { IMAGES } from "@/config/images";
import { IconClick, GhostButton } from "./ui/buttons";
import { useState } from "react";
export default function LanguageSettings() {
export function LanguageSettings() {
const [showLanguageMenu, setShowLanguageMenu] = useState(false);
const handleLanguageClick = () => {
setShowLanguageMenu((prev) => !prev);

View File

@@ -1,7 +1,7 @@
import Image from "next/image";
import IMAGES from "@/config/images";
import { IMAGES } from "@/config/images";
import { Folder, Home, User } from "lucide-react";
import LanguageSettings from "../LanguageSettings";
import { LanguageSettings } from "../LanguageSettings";
import { auth } from "@/auth";
import { headers } from "next/headers";
import { getTranslations } from "next-intl/server";

View File

@@ -34,7 +34,7 @@ export interface ButtonProps {
href?: string;
}
export default function Button({
export function Button({
variant = "secondary",
size = "md",
selected = false,

View File

@@ -21,7 +21,7 @@ interface CardListProps {
className?: string;
}
export default function CardList({ children, className = "" }: CardListProps) {
export function CardList({ children, className = "" }: CardListProps) {
return (
<div className={`max-h-96 overflow-y-auto rounded-xl border border-gray-200 overflow-hidden ${className}`}>
{children}

View File

@@ -3,7 +3,7 @@ interface ContainerProps {
className?: string;
}
export default function Container({ children, className }: ContainerProps) {
export function Container({ children, className }: ContainerProps) {
return (
<div
className={`w-full max-w-2xl mx-auto bg-white border border-gray-200 rounded-2xl ${className}`}

View File

@@ -7,7 +7,7 @@ interface Props {
defaultValue?: string;
}
export default function Input({
export function Input({
ref,
placeholder = "",
type = "text",

View File

@@ -15,7 +15,7 @@ interface PageHeaderProps {
subtitle?: string;
}
export default function PageHeader({ title, subtitle }: PageHeaderProps) {
export function PageHeader({ title, subtitle }: PageHeaderProps) {
return (
<div className="mb-6">
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 mb-2">

View File

@@ -20,7 +20,7 @@ interface PageLayoutProps {
className?: string;
}
export default function PageLayout({ children, className = "" }: PageLayoutProps) {
export function PageLayout({ children, className = "" }: PageLayoutProps) {
return (
<div className={`min-h-[calc(100vh-64px)] bg-[#35786f] flex items-center justify-center px-4 py-8 ${className}`}>
<div className="w-full max-w-2xl">

View File

@@ -1,7 +1,7 @@
// 向后兼容的按钮组件包装器
// 这些组件将新 Button 组件包装,以保持向后兼容
import Button from "../Button";
import { Button } from "../Button";
// LightButton: 次要按钮,支持 selected 状态
export const LightButton = (props: any) => <Button variant="secondary" {...props} />;

View File

@@ -21,4 +21,4 @@ const IMAGES = {
github_mark_white: "/images/github-mark/github-mark-white.svg",
};
export default IMAGES;
export { IMAGES };

View File

@@ -1,6 +1,6 @@
import { useRef } from "react";
export default function useFileUpload(callback: (file: File) => void) {
export function useFileUpload(callback: (file: File) => void) {
const inputRef = useRef<HTMLInputElement>(null);
const upload = (type: string = "*") => {
const input = inputRef.current;

View File

@@ -1,18 +0,0 @@
/**
* 词典查询模块 - 多阶段 LLM 调用架构
*
* 将词典查询拆分为 4 个独立的 LLM 调用阶段,每个阶段都有代码层面的数据验证
* 只要有一环失败,直接返回错误
*/
// 导出主编排器
export { executeDictionaryLookup } from "./orchestrator";
// 导出各阶段的独立函数(可选,用于调试或单独使用)
export { analyzeInput } from "./stage1-inputAnalysis";
export { determineSemanticMapping } from "./stage2-semanticMapping";
export { generateStandardForm } from "./stage3-standardForm";
export { generateEntries } from "./stage4-entriesGeneration";
// 导出类型定义
export * from "./types";

View File

@@ -1,2 +0,0 @@
export { executeTranslation } from "./orchestrator";
export * from "./types";

View File

@@ -7,4 +7,4 @@ const adapter = new PrismaPg({
const prisma = new PrismaClient({
adapter: adapter,
});
export default prisma;
export { prisma };

View File

@@ -1 +0,0 @@
export * from './auth-action';

View File

@@ -1,4 +1,4 @@
import { TSharedItem } from "@/shared";
import { TSharedItem } from "@/shared/dictionary-type";
import { LENGTH_MAX_DICTIONARY_TEXT, LENGTH_MAX_LANGUAGE, LENGTH_MIN_DICTIONARY_TEXT, LENGTH_MIN_LANGUAGE } from "@/shared/constant";
import { generateValidator } from "@/utils/validate";
import z from "zod";

View File

@@ -1,4 +1,4 @@
import { TSharedItem } from "@/shared";
import { TSharedItem } from "@/shared/dictionary-type";
export type RepoInputCreateDictionaryLookUp = {
userId?: string;

View File

@@ -7,7 +7,7 @@ import {
RepoInputSelectLastLookUpResult,
RepoOutputSelectLastLookUpResult,
} from "./dictionary-repository-dto";
import prisma from "@/lib/db";
import { prisma } from "@/lib/db";
export async function repoSelectLastLookUpResult(dto: RepoInputSelectLastLookUpResult): Promise<RepoOutputSelectLastLookUpResult> {
const result = await prisma.dictionaryLookUp.findFirst({

View File

@@ -1,4 +1,4 @@
import { TSharedItem } from "@/shared";
import { TSharedItem } from "@/shared/dictionary-type";
export type ServiceInputLookUp = {
text: string,

View File

@@ -1,4 +1,4 @@
import { executeDictionaryLookup } from "@/lib/bigmodel/dictionary";
import { executeDictionaryLookup } from "@/lib/bigmodel/dictionary/orchestrator";
import { repoCreateLookUp, repoCreateLookUpWithItemAndEntries, repoSelectLastLookUpResult } from "./dictionary-repository";
import { ServiceInputLookUp } from "./dictionary-service-dto";

View File

@@ -1,2 +0,0 @@
export * from "./dictionary-action";
export * from "./dictionary-action-dto";

View File

@@ -1,4 +1,4 @@
import prisma from "@/lib/db";
import { prisma } from "@/lib/db";
import { RepoInputCreateFolder, RepoInputCreatePair, RepoInputUpdatePair } from "./folder-repository-dto";
export async function repoCreatePair(data: RepoInputCreatePair) {

View File

@@ -1,2 +0,0 @@
export * from './folder-aciton';
export * from './folder-action-dto';

View File

@@ -1,2 +0,0 @@
export * from './translator-action';
export * from './translator-action-dto';

View File

@@ -1,4 +1,4 @@
import { TSharedTranslationResult } from "@/shared";
import { TSharedTranslationResult } from "@/shared/translator-type";
import {
LENGTH_MAX_LANGUAGE,
LENGTH_MIN_LANGUAGE,

View File

@@ -3,7 +3,7 @@ import {
RepoInputSelectLatestTranslation,
RepoOutputSelectLatestTranslation,
} from "./translator-repository-dto";
import prisma from "@/lib/db";
import { prisma } from "@/lib/db";
export async function repoSelectLatestTranslation(
dto: RepoInputSelectLatestTranslation

View File

@@ -1,4 +1,4 @@
import { TSharedTranslationResult } from "@/shared";
import { TSharedTranslationResult } from "@/shared/translator-type";
export type ServiceInputTranslateText = {
sourceText: string;

View File

@@ -1,4 +1,4 @@
import { executeTranslation } from "@/lib/bigmodel/translator";
import { executeTranslation } from "@/lib/bigmodel/translator/orchestrator";
import { repoCreateTranslationHistory, repoSelectLatestTranslation } from "./translator-repository";
import { ServiceInputTranslateText, ServiceOutputTranslateText } from "./translator-service-dto";

View File

@@ -1,2 +0,0 @@
export * from './dictionary-type';
export * from './translator-type';