Refactor UUID generation, remove unused logger and encryption utilities, and clean up request handling

- Updated `generateUUID` function for improved readability and performance.
- Deleted `logger.ts`, `other.ts`, `request.ts`, `storage.ts`, `tansParams.ts`, and `validate.ts` as they were no longer needed.
- Simplified TypeScript configuration by removing unnecessary paths and aliases.
- Enhanced Vite configuration for better project structure and maintainability.
This commit is contained in:
DEV_DSW
2026-04-17 15:38:08 +08:00
parent b1dea9a5c2
commit 79bea4f107
360 changed files with 14495 additions and 30856 deletions

View File

@@ -0,0 +1,125 @@
import { useRef } from 'react';
import type { AttachedFileMeta } from '../../shared/chat-model';
type ChatComposerProps = {
value: string;
isSending: boolean;
attachments: AttachedFileMeta[];
error?: string | null;
onChange: (value: string) => void;
onSend: () => void;
onStop: () => void;
onAttach: (files: File[]) => void | Promise<void>;
onRemoveAttachment: (index: number) => void;
onDismissError?: () => void;
};
export default function ChatComposer({
value,
isSending,
attachments,
error,
onChange,
onSend,
onStop,
onAttach,
onRemoveAttachment,
onDismissError,
}: ChatComposerProps) {
const fileInputRef = useRef<HTMLInputElement | null>(null);
return (
<div className="border-t border-[#edf2f7] px-6 py-4 dark:border-[#2a2a2d]">
<div className="rounded-[18px] border border-[#dfeaf6] bg-white p-4 shadow-[0_10px_30px_rgba(15,23,42,0.04)] dark:border-[#2a2a2d] dark:bg-[#1f1f22]">
<div className="flex items-start gap-3">
<div className="mt-1 flex h-9 w-9 flex-none items-center justify-center rounded-full bg-[#eff6ff] text-xs font-bold text-[#2B7FFF] dark:bg-[#222225]">
AI
</div>
<div className="min-w-0 flex-1">
{error ? (
<div className="mb-3 flex items-center justify-between gap-3 rounded-[14px] border border-[#fecaca] bg-[#fff1f2] px-4 py-3 text-sm text-[#b91c1c] dark:border-[#7f1d1d] dark:bg-[#2d1618] dark:text-[#fca5a5]">
<span className="min-w-0 flex-1">{error}</span>
{onDismissError ? (
<button type="button" className="text-xs transition-colors hover:text-[#7f1d1d]" onClick={onDismissError}>
</button>
) : null}
</div>
) : null}
<textarea
className="min-h-[120px] w-full resize-none rounded-[14px] border border-[#BEDBFF] bg-[#f8fbff] px-4 py-3 text-sm text-[#171717] outline-none transition-colors placeholder:text-[#99A0AE] focus:border-[#2B7FFF] dark:border-[#2a2a2d] dark:bg-[#232327] dark:text-gray-100 dark:placeholder:text-gray-500"
placeholder="输入消息,按 Enter 发送Shift + Enter 换行"
value={value}
onChange={(event) => onChange(event.target.value)}
onKeyDown={(event) => {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
if (isSending) {
onStop();
return;
}
onSend();
}
}}
/>
{attachments.length > 0 ? (
<div className="mt-3 flex flex-wrap gap-2">
{attachments.map((attachment, index) => (
<div
key={attachment.filePath || `${attachment.fileName}-${index}`}
className="flex items-center gap-2 rounded-full border border-[#E5E8EE] bg-white px-3 py-1.5 text-xs text-[#525866] dark:border-[#2a2a2d] dark:bg-[#232327] dark:text-gray-300"
>
<span className="max-w-[180px] truncate">{attachment.fileName}</span>
<button
type="button"
className="text-[#99A0AE] transition-colors hover:text-[#ef4444]"
onClick={() => onRemoveAttachment(index)}
>
x
</button>
</div>
))}
</div>
) : null}
<div className="mt-3 flex flex-wrap gap-2">
<input
ref={fileInputRef}
hidden
multiple
type="file"
onChange={(event) => {
const files = Array.from(event.target.files || []);
if (files.length > 0) {
void onAttach(files);
}
event.currentTarget.value = '';
}}
/>
<button
type="button"
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
onClick={() => fileInputRef.current?.click()}
>
</button>
<button
type="button"
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
onClick={isSending ? onStop : onSend}
>
{isSending ? '停止生成' : '发送消息'}
</button>
<button
type="button"
className="rounded-full border border-[#E5E8EE] px-3 py-1.5 text-xs text-[#525866] transition-colors hover:border-[#2B7FFF] hover:text-[#2B7FFF] dark:border-[#2a2a2d] dark:text-gray-300"
onClick={() => onChange('')}
>
</button>
</div>
</div>
</div>
</div>
</div>
);
}