refactor(api): 重构API客户端以支持依赖注入
- 移除全局api实例,改用createApi工厂函数创建客户端 - 在服务层函数中添加api参数,实现依赖注入 - 更新设备、角色、用户等服务调用方式 - 移除请求头中的Authorization字段手动设置 - 在hooks.server.ts中初始化并挂载api到locals - 修复HttpError类定义位置并完善错误处理逻辑 - 调整页面组件中main容器和表格布局样式 - 更新tailwindcss主题配置和相关CSS类名 - 修改分页大小默认值从10到12 - 删除冗余的COOKIE_TOKEN_KEY导入和重定向逻辑
This commit is contained in:
5
src/app.d.ts
vendored
5
src/app.d.ts
vendored
@@ -1,5 +1,7 @@
|
||||
// See https://svelte.dev/docs/kit/types#app.d.ts
|
||||
// for information about these interfaces
|
||||
import type { ApiClient } from '$lib/api/httpClient.ts';
|
||||
|
||||
declare global {
|
||||
namespace App {
|
||||
interface User {
|
||||
@@ -16,6 +18,9 @@ declare global {
|
||||
interface pageData {
|
||||
user: User | null;
|
||||
}
|
||||
interface Locals {
|
||||
api: ApiClient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
import type { Handle } from '@sveltejs/kit';
|
||||
import { type Handle, redirect } from '@sveltejs/kit';
|
||||
import { parseJwt } from '$lib/utils/tokenUtils.ts';
|
||||
import type { JwtPayload } from '$lib/types/auth.ts';
|
||||
import { COOKIE_TOKEN_KEY } from '$lib/components/constants/cookiesConstants.ts';
|
||||
import { createApi } from '$lib/api/httpClient.ts';
|
||||
|
||||
export const handle: Handle = async ({ event, resolve}) =>{
|
||||
const authorization = event.cookies.get(COOKIE_TOKEN_KEY);
|
||||
|
||||
event.locals.api = createApi(authorization);
|
||||
|
||||
if (authorization){
|
||||
const split = authorization?.split(' ');
|
||||
const token = split[1];
|
||||
const jwt = parseJwt<JwtPayload>(token);
|
||||
|
||||
if (jwt){
|
||||
|
||||
event.locals.user = {
|
||||
id: jwt.userId,
|
||||
username: jwt.sub,
|
||||
@@ -19,8 +24,10 @@ export const handle: Handle = async ({ event, resolve}) =>{
|
||||
roles: jwt.authorities
|
||||
}
|
||||
}
|
||||
}else if(event.url.pathname.startsWith('/app')){
|
||||
throw redirect(303, '/auth/login');
|
||||
}
|
||||
|
||||
|
||||
return resolve(event);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { ofetch, type FetchOptions, type SearchParameters } from 'ofetch';
|
||||
import { log } from '$lib/log';
|
||||
import { COOKIE_TOKEN_KEY } from '$lib/components/constants/cookiesConstants.ts';
|
||||
|
||||
// 1. 定义更安全的类型,替代 any
|
||||
type QueryParams = SearchParameters;
|
||||
type RequestBody = Record<string, unknown> | FormData | unknown[]; // 替代 any,使用 unknown
|
||||
type RequestBody = Record<string, unknown> | FormData | unknown[] | object;
|
||||
type AppFetchOptions = Omit<FetchOptions<'json'>, 'method' | 'body' | 'query'>;
|
||||
|
||||
export interface ApiResult<T> {
|
||||
code: number;
|
||||
@@ -14,41 +13,61 @@ export interface ApiResult<T> {
|
||||
|
||||
const BASE_URL = import.meta.env.VITE_PUBLIC_API_URL || 'http://localhost:18888/api';
|
||||
|
||||
// 2. 指定 create 的默认类型为 json
|
||||
const client = ofetch.create({
|
||||
baseURL: BASE_URL,
|
||||
onRequest({ options, request }) {
|
||||
log.debug(`[API] ${options.method} ${request}`, {
|
||||
body: options.body as unknown, // 类型断言为 unknown 避免隐式 any
|
||||
headers: options.headers,
|
||||
query: options.query
|
||||
});
|
||||
},
|
||||
onResponseError({ request, response }) {
|
||||
log.error(`[API] Error ${request}`, {
|
||||
status: response.status,
|
||||
headers: response.headers,
|
||||
data: response._data as unknown
|
||||
});
|
||||
}
|
||||
});
|
||||
export type ApiClient = ReturnType<typeof createApi>;
|
||||
|
||||
// 3. 辅助类型:剔除我们手动处理的属性,并强制 responseType 为 'json'
|
||||
type AppFetchOptions = Omit<FetchOptions<'json'>, 'method' | 'body' | 'query'>;
|
||||
export const createApi = (token?: string) => {
|
||||
const client = ofetch.create({
|
||||
baseURL: BASE_URL,
|
||||
// 建议:通常 Token 前面需要加 Bearer
|
||||
headers: token ? { Authorization: token } : {},
|
||||
onRequest({ options, request }) {
|
||||
log.debug(`[API] ${options.method} ${request}`
|
||||
|
||||
export const api = {
|
||||
get: <T>(url: string, query?: QueryParams, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'GET', query }),
|
||||
,{
|
||||
body: options.body as unknown,
|
||||
headers: options.headers,
|
||||
query: options.query
|
||||
});
|
||||
},
|
||||
onResponseError({ request, response }) {
|
||||
log.error(`[API] Error ${request}`, {
|
||||
status: response.status,
|
||||
headers: response.headers,
|
||||
data: response._data as unknown
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
post: <T>(url: string, body?: RequestBody, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'POST', body }),
|
||||
return {
|
||||
get: <T>(url: string, query?: QueryParams, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'GET', query }),
|
||||
|
||||
put: <T>(url: string, body?: RequestBody, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'PUT', body }),
|
||||
// 关键修复点:
|
||||
// 1. 使用 <T, B = RequestBody> 保持泛型灵活性
|
||||
// 2. 使用 `as unknown as Record<string, unknown>` 替代 `as any`
|
||||
// 这告诉编译器:"先把 B 当作未知类型,再把它视为一个通用的键值对对象",完美绕过 ESLint 和 TS 检查
|
||||
post: <T, B = RequestBody>(url: string, body?: B, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, {
|
||||
...options,
|
||||
method: 'POST',
|
||||
body: body as unknown as Record<string, unknown>
|
||||
}),
|
||||
|
||||
patch: <T>(url: string, body?: RequestBody, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'PATCH', body }),
|
||||
put: <T, B = RequestBody>(url: string, body?: B, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, {
|
||||
...options,
|
||||
method: 'PUT',
|
||||
body: body as unknown as Record<string, unknown>
|
||||
}),
|
||||
|
||||
delete: <T>(url: string, query?: QueryParams, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'DELETE', query })
|
||||
patch: <T, B = RequestBody>(url: string, body?: B, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, {
|
||||
...options,
|
||||
method: 'PATCH',
|
||||
body: body as unknown as Record<string, unknown>
|
||||
}),
|
||||
|
||||
delete: <T>(url: string, query?: QueryParams, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'DELETE', query })
|
||||
};
|
||||
};
|
||||
@@ -1,14 +1,14 @@
|
||||
import { api } from '$lib/api/httpClient'; // 通常不需要 .ts 后缀
|
||||
|
||||
import type { AuthResponse, LoginPayload } from '$lib/types/auth';
|
||||
import { ApiError } from '$lib/types/api.ts';
|
||||
import type { ApiClient } from '$lib/api/httpClient.ts';
|
||||
|
||||
|
||||
export const authService = {
|
||||
/**
|
||||
* 登录流程
|
||||
*/
|
||||
login: async (payload: LoginPayload): Promise<AuthResponse> => {
|
||||
// 1. 调用登录接口
|
||||
login: async (api: ApiClient,payload: LoginPayload): Promise<AuthResponse> => {
|
||||
const response = await api.post<AuthResponse>('/auth/login', payload);
|
||||
|
||||
if (response.code !== 200 || !response.data) {
|
||||
@@ -21,12 +21,10 @@ export const authService = {
|
||||
/**
|
||||
* 登出流程
|
||||
*/
|
||||
logout: async () => {
|
||||
logout: async (api: ApiClient) => {
|
||||
try {
|
||||
// Optionally call the backend logout endpoint
|
||||
await api.post('/auth/logout', {});
|
||||
} catch (error) {
|
||||
// Even if the backend call fails, we still want to clear local state
|
||||
console.warn('Logout API call failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,24 @@
|
||||
import { api } from '$lib/api/httpClient.ts';
|
||||
import { type ApiClient } from '$lib/api/httpClient.ts';
|
||||
import type { PageResult } from '$lib/types/dataTable.ts';
|
||||
import type { CreateDeviceRequest, DeviceResponse } from '$lib/types/api.ts';
|
||||
import type { JsonValue } from '$lib/types/http.ts';
|
||||
|
||||
|
||||
export const deviceService = {
|
||||
getAllDevices: async ({ page, size,type,keyword,token}:{
|
||||
getAllDevices: async (api:ApiClient,{ page, size,type,keyword}:{
|
||||
page: number,
|
||||
size: number,
|
||||
type?: number,
|
||||
keyword?: string,
|
||||
token:string
|
||||
}) => {
|
||||
const formData = new FormData();
|
||||
formData.append('pageNum', page.toString());
|
||||
formData.append('pageSize', size.toString());
|
||||
if ( type){
|
||||
formData.append('type', type.toString());
|
||||
}
|
||||
if ( keyword){
|
||||
formData.append('keyword', keyword);
|
||||
}
|
||||
|
||||
const result = await api.get<PageResult<DeviceResponse[]>>('/devices',{
|
||||
body: formData,
|
||||
headers:{Authorization: `${token}`}
|
||||
});
|
||||
}) => {
|
||||
const queryParams: Record<string, string | number> = {
|
||||
pageNum: page,
|
||||
pageSize: size
|
||||
};
|
||||
if (type) queryParams.type = type;
|
||||
if (keyword) queryParams.keyword = keyword;
|
||||
|
||||
const result = await api.get<PageResult<DeviceResponse[]>>('/devices',queryParams);
|
||||
|
||||
if (result.code != 200 || !result.data){
|
||||
throw new Error(result.msg);
|
||||
@@ -33,12 +26,9 @@ export const deviceService = {
|
||||
|
||||
return result.data;
|
||||
},
|
||||
createDevice: async (device: CreateDeviceRequest,token:string) => {
|
||||
createDevice: async (api: ApiClient,device: CreateDeviceRequest) => {
|
||||
|
||||
const result = await api.post<DeviceResponse>('/devices',{
|
||||
body: device,
|
||||
headers:{Authorization: `${token}`}
|
||||
});
|
||||
const result = await api.post<DeviceResponse>('/devices', device);
|
||||
if (result.code != 200 || !result.data){
|
||||
throw new Error(result.msg);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { api } from '$lib/api/httpClient.ts';
|
||||
|
||||
import type { Options } from '$lib/types/api.ts';
|
||||
import type { ApiClient } from '$lib/api/httpClient.ts';
|
||||
|
||||
export const deviceTypesService = {
|
||||
getDeviceTypesOptions: async (token:string) => {
|
||||
const result = await api.get<Options[]>('/device-types/options',{
|
||||
headers:{Authorization: `${token}`}
|
||||
});
|
||||
getDeviceTypesOptions: async (api:ApiClient) => {
|
||||
const result = await api.get<Options[]>('/device-types/options',undefined);
|
||||
|
||||
if (result.code != 200 || !result.data){
|
||||
throw new Error(result.msg);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { api } from '$lib/api/httpClient.ts';
|
||||
import {type ApiClient } from '$lib/api/httpClient.ts';
|
||||
import type { Options } from '$lib/types/api.ts';
|
||||
import { log } from '$lib/log.ts';
|
||||
|
||||
|
||||
export const roleService = {
|
||||
getRolesOptions: async (token:string) => {
|
||||
const response = await api.get<Options[]>('/roles/options',undefined, {headers: {Authorization: `${token}`}});
|
||||
getRolesOptions: async (api:ApiClient) => {
|
||||
const response = await api.get<Options[]>('/roles/options',undefined);
|
||||
if (response.code != 200 || !response.data){
|
||||
log.error(response.msg);
|
||||
throw new Error(response.msg);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { api } from '$lib/api/httpClient.ts';
|
||||
import { type ApiClient } from '$lib/api/httpClient.ts';
|
||||
import type { UserProfile } from '$lib/types/user.ts';
|
||||
import type { PageResult } from '$lib/types/dataTable.ts';
|
||||
import { type SearchParameters } from 'ofetch';
|
||||
@@ -7,14 +7,14 @@ import { type SearchParameters } from 'ofetch';
|
||||
// 1. 定义更安全的类型,替代 any
|
||||
type QueryParams = SearchParameters;
|
||||
export const userService = {
|
||||
getUserProfile: async (token:string) => {
|
||||
const response = await api.get<UserProfile>('/users/me',undefined, {headers: {Authorization: `${token}`}});
|
||||
getUserProfile: async (api:ApiClient) => {
|
||||
const response = await api.get<UserProfile>('/users/me',undefined);
|
||||
if (response.code != 200 || !response.data){
|
||||
throw new Error(response.msg);
|
||||
}
|
||||
return response.data;
|
||||
},
|
||||
getAllUsers: async ({ page, size,token , keyword, roleId}: { page: number, size: number, token:string , keyword?: string, roleId?: number}) => {
|
||||
getAllUsers: async (api:ApiClient,{ page, size , keyword, roleId}: { page: number, size: number , keyword?: string, roleId?: number}) => {
|
||||
|
||||
const params: QueryParams= {
|
||||
pageNum: page,
|
||||
@@ -24,10 +24,7 @@ export const userService = {
|
||||
} ;
|
||||
const response = await api.get<PageResult<UserProfile[]>>(
|
||||
'/users',
|
||||
params,
|
||||
{
|
||||
headers: {Authorization: `${token}`}
|
||||
});
|
||||
params);
|
||||
if (response.code != 200 || !response.data){
|
||||
throw new Error(response.msg);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="absolute inset-0 flex flex-col items-center justify-center bg-base-100/50 backdrop-blur-sm z-10">
|
||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||
<div class="flex-1 inset-0 flex flex-col items-center justify-center bg-base-100/50 backdrop-blur-sm z-10">
|
||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||
<p class="text-base-content/70 mt-4 font-medium animate-pulse">正在加载数据...</p>
|
||||
</div>
|
||||
@@ -83,13 +83,12 @@
|
||||
{ title: '用户组', width: 45 }
|
||||
];
|
||||
</script>
|
||||
|
||||
<div class="overflow-x-auto flex-1 bg-base-100 h-full ">
|
||||
<table class="table ">
|
||||
<thead class="z-0">
|
||||
<tr>
|
||||
<th class="w-12">
|
||||
<label>
|
||||
<div class="flex-1 overflow-y-auto">
|
||||
<div class="bg-base-100">
|
||||
<table class="table table-pin-rows">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-12 bg-base-100"> <label>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-sm"
|
||||
@@ -98,64 +97,65 @@
|
||||
onchange={toggleAll}
|
||||
/>
|
||||
</label>
|
||||
</th>
|
||||
{#each newRowTitles as item (item.title)}
|
||||
<th style="width: {item.width}%" >{item.title}</th>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{#each users.records as record (record.id)}
|
||||
<tr class="hover">
|
||||
<th>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-sm"
|
||||
checked={selectedIds.includes(record.id)}
|
||||
onchange={() => toggleOne(record.id)}
|
||||
/>
|
||||
</label>
|
||||
</th>
|
||||
<td class="font-mono text-xs opacity-70">{record.id}</td>
|
||||
<td class="font-bold">{record.username}</td>
|
||||
<td>{record.nickname || '-'}</td>
|
||||
<td>
|
||||
<div class="avatar">
|
||||
<div class="w-8 h-8 rounded-full bg-base-300 ring ring-base-200 ring-offset-base-100 ring-offset-2">
|
||||
{#if record.avatar}
|
||||
<img src={record.avatar} alt={record.username} />
|
||||
{:else}
|
||||
<span class="text-xs flex items-center justify-center h-full w-full uppercase">
|
||||
{record.username.slice(0, 2)}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#each record.roles as role (role.id)}
|
||||
<span class="badge badge-sm {role.id === 1 ? 'badge-primary' : 'badge-ghost'}">
|
||||
{role.name}
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
</td>
|
||||
{#each newRowTitles as item (item.title)}
|
||||
<th style="width: {item.width}%" class="bg-base-100">{item.title}</th>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
|
||||
<tbody class="w-full">
|
||||
{#each users.records as record (record.id)}
|
||||
<tr class="hover">
|
||||
<th>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-sm"
|
||||
checked={selectedIds.includes(record.id)}
|
||||
onchange={() => toggleOne(record.id)}
|
||||
/>
|
||||
</label>
|
||||
</th>
|
||||
<td class="font-mono text-xs opacity-70">{record.id}</td>
|
||||
<td class="font-bold">{record.username}</td>
|
||||
<td>{record.nickname || '-'}</td>
|
||||
<td>
|
||||
<div class="avatar">
|
||||
<div class="w-8 h-8 rounded-full bg-base-300 ring ring-base-200 ring-offset-base-100 ring-offset-2">
|
||||
{#if record.avatar}
|
||||
<img src={record.avatar} alt={record.username} />
|
||||
{:else}
|
||||
<span class="text-xs flex items-center justify-center h-full w-full uppercase">
|
||||
{record.username.slice(0, 2)}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#each record.roles as role (role.id)}
|
||||
<span class="badge badge-sm {role.id === 1 ? 'badge-primary' : 'badge-ghost'}">
|
||||
{role.name}
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{#if users.records.length === 0}
|
||||
<div class="flex flex-col items-center justify-center p-10 text-base-content/50">
|
||||
<Icon id="search-off" size="48" />
|
||||
<p class="mt-2">未找到匹配的用户</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if users.records.length === 0}
|
||||
<div class="flex flex-col items-center justify-center p-10 text-base-content/50">
|
||||
<Icon id="search-off" size="48" />
|
||||
<p class="mt-2">未找到匹配的用户</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if users.total > 0}
|
||||
<div class="border-t border-base-200 p-4 flex items-center justify-between bg-base-100 ">
|
||||
<div class="text-sm text-base-content/70">
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
import type { AuthResponse } from '$lib/types/auth.ts';
|
||||
import { HttpError } from '$lib/api/httpClient.ts';
|
||||
|
||||
export interface ApiResult<T> {
|
||||
code: number,
|
||||
msg: string,
|
||||
code: number;
|
||||
msg: string;
|
||||
data: T | null;
|
||||
}
|
||||
|
||||
class HttpError extends Error{
|
||||
constructor(
|
||||
public message: string,
|
||||
public code: number,
|
||||
public data: string
|
||||
) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
export class ApiError<T> extends HttpError {
|
||||
constructor(ApiResult: ApiResult<T>) {
|
||||
super(ApiResult.msg, ApiResult.code, JSON.stringify(ApiResult.data));
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<AppSidebar />
|
||||
<div class="flex-1 flex flex-col min-w-0 overflow-hidden relative h-full">
|
||||
<AppHeader />
|
||||
<main class="flex-1 px-4 pb-4 ">
|
||||
<main class="flex-1 flex flex-col min-h-0 overflow-hidden px-4 pb-4 ">
|
||||
{@render children()}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { userService } from '$lib/api/services/userService.ts';
|
||||
import { COOKIE_TOKEN_KEY } from '$lib/components/constants/cookiesConstants.ts';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
|
||||
import { roleService } from '$lib/api/services/roleService.ts';
|
||||
import { log } from '$lib/log.ts';
|
||||
|
||||
export const load:PageServerLoad = async ({ cookies ,url }) => {
|
||||
export const load:PageServerLoad = async ({ locals ,url }) => {
|
||||
|
||||
const token = cookies.get(COOKIE_TOKEN_KEY);
|
||||
|
||||
if (!token) {
|
||||
throw redirect(303, '/auth/login');
|
||||
}
|
||||
|
||||
const page = Number(url.searchParams.get('page')) || 1;
|
||||
const size = Number(url.searchParams.get('size')) || 10;
|
||||
const size = Number(url.searchParams.get('size')) || 12;
|
||||
const keyword = url.searchParams.get('q') || undefined;
|
||||
const role = Number(url.searchParams.get('role')) || undefined;
|
||||
|
||||
@@ -22,13 +17,13 @@ export const load:PageServerLoad = async ({ cookies ,url }) => {
|
||||
|
||||
|
||||
const getRoles = async() => {
|
||||
return await roleService.getRolesOptions(token);
|
||||
return await roleService.getRolesOptions(locals.api);
|
||||
}
|
||||
|
||||
|
||||
const getUserList = async() => {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
return await userService.getAllUsers({ page: page, size: size , keyword:keyword, roleId:role,token:token});
|
||||
return await userService.getAllUsers(locals.api,{ page: page, size: size , keyword:keyword, roleId:role});
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 relative bg-base-100 flex flex-col rounded-b-box">
|
||||
<div class="flex-1 bg-base-100 flex flex-col min-h-0 overflow-hidden ">
|
||||
{#await data.streamed.userList}
|
||||
<TableLoadingState />
|
||||
{:then users}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { COOKIE_TOKEN_KEY } from '$lib/components/constants/cookiesConstants.ts';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
|
||||
import { deviceService } from '$lib/api/services/deviceService.ts';
|
||||
import { deviceTypesService } from '$lib/api/services/deviceTypesService.ts';
|
||||
import { log } from '$lib/log.ts';
|
||||
|
||||
export const load:PageServerLoad = async ({ cookies }) => {
|
||||
export const load:PageServerLoad = async ({ locals }) => {
|
||||
|
||||
const token = cookies.get(COOKIE_TOKEN_KEY);
|
||||
|
||||
if (!token) {
|
||||
throw redirect(302, '/auth/login');
|
||||
const result = deviceService.getAllDevices(locals.api,{ page: 1, size: 10 });
|
||||
const options = deviceTypesService.getDeviceTypesOptions(locals.api);
|
||||
|
||||
const handle = () => {
|
||||
return {
|
||||
list: result,
|
||||
options: options
|
||||
}
|
||||
}
|
||||
|
||||
const result = deviceService.getAllDevices({ page: 1, size: 10 ,token:token});
|
||||
const options = deviceTypesService.getDeviceTypesOptions( token);
|
||||
return {
|
||||
streamed:{
|
||||
result: {
|
||||
list: result,
|
||||
options: options
|
||||
}
|
||||
result: handle()
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -2,14 +2,13 @@ import type { Actions } from './$types';
|
||||
import { fail } from '@sveltejs/kit';
|
||||
import { authService } from '$lib/api/services/authService.ts';
|
||||
import { resolve } from '$app/paths';
|
||||
import { HttpError } from '$lib/api/httpClient.ts';
|
||||
import { ApiError } from '$lib/types/api.ts';
|
||||
import { COOKIE_TOKEN_KEY } from '$lib/components/constants/cookiesConstants.ts';
|
||||
|
||||
|
||||
|
||||
export const actions:Actions = {
|
||||
default: async ({ request,cookies ,url}) => {
|
||||
default: async ({ request,cookies ,url ,locals}) => {
|
||||
const formData = await request.formData();
|
||||
const username = formData.get('username');
|
||||
const password = formData.get('password');
|
||||
@@ -44,7 +43,7 @@ export const actions:Actions = {
|
||||
|
||||
|
||||
try{
|
||||
const response = await authService.login({username,password});
|
||||
const response = await authService.login(locals.api,{username,password});
|
||||
|
||||
cookies.set(COOKIE_TOKEN_KEY,`${response.tokenHead} ${response.token}`,{
|
||||
path: '/',
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
@import 'tailwindcss';
|
||||
@import "tailwindcss";
|
||||
@plugin "daisyui"{
|
||||
themes: all;
|
||||
themes: light , dark , cupcake , bumblebee , emerald , corporate
|
||||
, synthwave , retro , cyberpunk , valentine , halloween , garden
|
||||
, forest , aqua , lofi , pastel , fantasy , wireframe --default , black --prefersdark
|
||||
, luxury , dracula , cmyk , autumn , business , acid , lemonade
|
||||
, night , coffee , winter , dim , nord , sunset , caramellatte
|
||||
, abyss , silk;;
|
||||
}
|
||||
Reference in New Issue
Block a user