refactor(layout): 重构应用布局结构

- 将原有布局中的侧边栏和头部组件拆分为独立的 AppSidebar 和 AppHeader 组件
- 移除内联的导航逻辑和样式,交由专用组件管理
- 更新图标库,优化部分图标的显示效果
- 简化认证存储逻辑,增强状态持久化与安全性
- 优化侧边栏状态管理机制,提高响应式体验
- 改进登录流程错误处理,增加网络异常提示
- 调整路由组件结构,提升代码可维护性
This commit is contained in:
Chaos
2025-11-25 07:33:58 +08:00
parent 877a47807c
commit 8f3f2d63a0
2 changed files with 53 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
import type { Actions } from './$types'; import type { Actions } from './$types';
import { fail } from '@sveltejs/kit'; import { fail, redirect } from '@sveltejs/kit';
import { authService } from '$lib/api/services/authService.ts'; import { authService } from '$lib/api/services/authService.ts';
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import { HttpError } from '$lib/api/httpClient.ts'; import { HttpError } from '$lib/api/httpClient.ts';
@@ -25,6 +25,22 @@ export const actions:Actions = {
}) })
} }
const regexp = /^[a-zA-Z0-9_-]{5,16}$/
if (!regexp.test(username)){
return fail(400,{
username: username.toString(),
message: '用户名格式错误请输入5-16位字符只能包含字母、数字、下划线、减号'
})
}
if (password.length<8 || password.length>16){
return fail(400,{
message: '密码格式错误请输入8-16位字符'
})
}
try{ try{
const response = await authService.login({username,password}); const response = await authService.login({username,password});

View File

@@ -2,10 +2,10 @@
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import Icon from '$lib/components/icon/Icon.svelte'; import Icon from '$lib/components/icon/Icon.svelte';
import { toast } from '$lib/stores/toastStore.ts'; import { toast } from '$lib/stores/toastStore.ts';
import { enhance } from '$app/forms'; import { enhance } from '$app/forms';
import type { EnhanceResult, LoginFailure } from '$lib/types/api.ts'; import { goto } from '$app/navigation';
let loading = false;
</script> </script>
@@ -24,13 +24,25 @@
<form method="post" <form method="post"
use:enhance={() => { use:enhance={() => {
loading = true;
return async ({ result , update }) => { return async ({ result , update }) => {
const res = result as EnhanceResult<LoginFailure>; loading = false;
if (res.status === 200) { if (result.type === 'failure') {
toast.success('登录成功');
update(); if (typeof result.data?.message === 'string' ){
} else { toast.error(result.data?.message)
toast.error(res.data.message); }
await update();
}else if (result.type === 'success') {
if (typeof result.data?.message === 'string' ){
toast.success(result.data?.message || '登录成功')
}
if (result.data?.redirectTo && typeof result.data?.redirectTo === 'string') {
await goto(resolve(result.data.redirectTo));
}
} }
}; };
}} }}
@@ -38,7 +50,7 @@
<div class="form-control"> <div class="form-control">
<label class="label" for="username"> <label class="label" for="username">
<span class="label-text" >用户名</span> <span class="label-text">用户名</span>
</label> </label>
<div class="relative"> <div class="relative">
<input <input
@@ -49,7 +61,9 @@
required required
/> />
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-base-content/50"> <span class="absolute left-3 top-1/2 -translate-y-1/2 text-base-content/50">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70"><path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002 0 0 0-11.215 0c-.22.578.254 1.139.872 1.139h9.47Z" /></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor"
class="w-4 h-4 opacity-70"><path
d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002 0 0 0-11.215 0c-.22.578.254 1.139.872 1.139h9.47Z" /></svg>
</span> </span>
</div> </div>
</div> </div>
@@ -67,7 +81,10 @@
required required
/> />
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-base-content/50"> <span class="absolute left-3 top-1/2 -translate-y-1/2 text-base-content/50">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70"><path fill-rule="evenodd" d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2.293a.5.5 0 0 1 .146-.353l3.955-3.955A4 4 0 1 1 14 6Zm-4-2a.75.75 0 0 0 0 1.5.5.5 0 0 1 .5.5.75.75 0 0 0 1.5 0 2 2 0 0 0-2-2Z" clip-rule="evenodd" /></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor"
class="w-4 h-4 opacity-70"><path fill-rule="evenodd"
d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2.293a.5.5 0 0 1 .146-.353l3.955-3.955A4 4 0 1 1 14 6Zm-4-2a.75.75 0 0 0 0 1.5.5.5 0 0 1 .5.5.75.75 0 0 0 1.5 0 2 2 0 0 0-2-2Z"
clip-rule="evenodd" /></svg>
</span> </span>
</div> </div>
@@ -75,19 +92,20 @@
<div class="form-control mt-6 flex justify-between"> <div class="form-control mt-6 flex justify-between">
<label class="label cursor-pointer justify-start gap-2"> <label class="label cursor-pointer justify-start gap-2">
<input type="checkbox" class="checkbox checkbox-sm checkbox-primary" /> <input type="checkbox" class="checkbox checkbox-sm checkbox-primary" />
<span class="label-text">记住我</span> <span class="label-text">记住我</span>
</label> </label>
<div class="label" > <div class="label">
<a href={resolve('/auth/forgetPassword')} class="label-text-alt link link-hover">忘记密码?</a> <a href={resolve('/auth/forgetPassword')} class="label-text-alt link link-hover">忘记密码?</a>
</div> </div>
</div> </div>
<div class="form-control mt-2"> <div class="form-control mt-2">
<button class="btn btn-primary w-full" > <button class="btn btn-primary w-full {loading?'btn-disabled ':''}" >
{#if loading}
登录 <span class="loading loading-spinner"></span>
{/if}
<span>登录</span>
</button> </button>
</div> </div>