refactor: optimize component rendering with memoization and improve state management

- Added memoization to ChatHistoryPanel, ChatMessageList, and TaskBoard components to prevent unnecessary re-renders.
- Refactored HomePage to utilize useMemo for derived state calculations, enhancing performance.
- Updated main.tsx to conditionally render React.StrictMode based on the environment.
- Improved chat and channel store hooks to allow for selector functions, enhancing flexibility in state selection.
- Enhanced streaming message handling in chat store to manage pending deltas more effectively.
- Refactored LoginPage to include animated decorations for improved user experience.
- Implemented lazy loading for routes in the router to optimize initial load time.
This commit is contained in:
duanshuwen
2026-04-18 11:05:49 +08:00
parent 85d92b937f
commit dfa4388087
12 changed files with 533 additions and 189 deletions

View File

@@ -43,6 +43,7 @@ export default function LoginPage() {
const [form, setForm] = useState<LoginFormValues>(INITIAL_FORM);
const [errors, setErrors] = useState<FormErrors>({});
const [submitting, setSubmitting] = useState(false);
const [showDecorations, setShowDecorations] = useState(false);
const captchaUrl = useMemo(
() => (form.randomStr ? getCaptchaImageUrl(form.randomStr) : ''),
@@ -50,7 +51,14 @@ export default function LoginPage() {
);
useEffect(() => {
setForm((current) => ({ ...current, ...createCaptchaState() }));
const frameId = window.requestAnimationFrame(() => {
setShowDecorations(true);
setForm((current) => ({ ...current, ...createCaptchaState() }));
});
return () => {
window.cancelAnimationFrame(frameId);
};
}, []);
function refreshCaptcha(clearSubmitError = true): void {
@@ -123,20 +131,25 @@ export default function LoginPage() {
return (
<div
className="flex h-screen flex-col"
style={{
backgroundImage: `url(${loginBackground})`,
backgroundSize: '100% 100%',
backgroundPosition: '0 0',
backgroundRepeat: 'no-repeat',
}}
className="relative flex h-screen flex-col overflow-hidden bg-[linear-gradient(135deg,#eef5ff_0%,#f8fbff_42%,#ffffff_100%)] dark:bg-[#111214]"
>
{showDecorations ? (
<img
aria-hidden="true"
alt=""
className="pointer-events-none absolute inset-0 h-full w-full object-cover"
decoding="async"
fetchPriority="low"
src={loginBackground}
/>
) : null}
<TitleBar variant="light" />
<main
className={['box-border flex flex-auto pl-2 pr-2 pb-2', platform !== 'linux' ? 'pt-2' : 'pt-11'].join(' ')}
className={['relative z-10 box-border flex flex-auto pl-2 pr-2 pb-2', platform !== 'linux' ? 'pt-2' : 'pt-11'].join(' ')}
>
<div className="box-border w-[836px] rounded-2xl border border-black/5 bg-white p-8 shadow-[0_18px_50px_rgba(15,23,42,0.12)] dark:border-[#2a2a2d] dark:bg-[#1b1b1d]">
<div className="box-border w-[836px] rounded-2xl border border-black/5 bg-white/95 p-8 shadow-[0_18px_50px_rgba(15,23,42,0.12)] backdrop-blur-sm dark:border-[#2a2a2d] dark:bg-[#1b1b1d]/95">
<div className="flex items-center">
<img className="h-12 w-12" src={blueLogo} alt="zn-ai" />
</div>
@@ -241,7 +254,17 @@ export default function LoginPage() {
</form>
</div>
<img className="ml-2 w-[540px] max-w-[48vw] self-center object-contain" src={loginIllustration} alt="" />
{showDecorations ? (
<img
aria-hidden="true"
alt=""
className="ml-2 w-[540px] max-w-[48vw] self-center object-contain"
decoding="async"
fetchPriority="low"
loading="eager"
src={loginIllustration}
/>
) : null}
</main>
</div>
);