feat(users): implement role filtering and pagination in user management
- Add role filtering functionality with radio buttons for each role - Implement pagination controls at the bottom of the user table - Update user table to show loading state without text - Improve avatar display logic with conditional rendering - Adjust styling for better UI consistency and responsiveness - Remove unused sidebar state imports and commented-out code - Add console logs for debugging data flow and role changes - Modify search button size from sm to xs for better fit - Enhance role badge styling with margin adjustments - Refactor sidebar overlay and positioning classes
This commit is contained in:
13
package-lock.json
generated
13
package-lock.json
generated
@@ -1473,6 +1473,7 @@
|
||||
"integrity": "sha512-/rnwfSWS3qwUSzvHynUTORF9xSJi7PCR9yXkxUOnRrNqyKmCmh3FPHH+E9BbgqxXfTevGXBqgnlh9kMb+9T5XA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"@sveltejs/acorn-typescript": "^1.0.5",
|
||||
@@ -1512,6 +1513,7 @@
|
||||
"integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
|
||||
"debug": "^4.4.1",
|
||||
@@ -1844,6 +1846,7 @@
|
||||
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
@@ -1894,6 +1897,7 @@
|
||||
"integrity": "sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.47.0",
|
||||
"@typescript-eslint/types": "8.47.0",
|
||||
@@ -2112,6 +2116,7 @@
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -2488,6 +2493,7 @@
|
||||
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -3608,6 +3614,7 @@
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -3635,6 +3642,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -3768,6 +3776,7 @@
|
||||
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
@@ -3784,6 +3793,7 @@
|
||||
"integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"prettier": "^3.0.0",
|
||||
"svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
|
||||
@@ -4510,6 +4520,7 @@
|
||||
"integrity": "sha512-d1R+3pFa39LXoHCsxHmV//D2pSFZlEMlnxCVQ54TlrQv+4o5pewJO0/Pc5MUp+j71PJrOrPJHTvREZJHn+ymDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/remapping": "^2.3.4",
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||
@@ -4707,6 +4718,7 @@
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -4776,6 +4788,7 @@
|
||||
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
<script lang="ts">
|
||||
|
||||
import { resolve } from '$app/paths';
|
||||
|
||||
import { page } from '$app/state';
|
||||
|
||||
import { fly, fade } from 'svelte/transition';
|
||||
|
||||
import Icon from '$lib/components/icon/Icon.svelte';
|
||||
|
||||
import type { NavItem, ProcessedNavItem } from '$lib/types/layout';
|
||||
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
import { resolve } from '$app/paths';
|
||||
import { fade, fly } from 'svelte/transition';
|
||||
import Icon from '$lib/components/icon/Icon.svelte';
|
||||
import type { NavItem, ProcessedNavItem } from '$lib/types/layout';
|
||||
import { TOAST_KEY, type ToastState } from '$lib/stores/toast.svelte.ts';
|
||||
|
||||
// import { SIDEBAR_KEY, SidebarState } from '$lib/stores/sidebar.svelte.ts';
|
||||
import { enhance } from '$app/forms';
|
||||
|
||||
import { SIDEBAR_KEY, SidebarState } from '$lib/stores/sidebar.svelte.ts';
|
||||
|
||||
const sidebarState = getContext<SidebarState>(SIDEBAR_KEY);
|
||||
// const sidebarState = getContext<SidebarState>(SIDEBAR_KEY);
|
||||
|
||||
|
||||
// 1. 模拟数据:包含三层结构
|
||||
@@ -312,12 +303,12 @@
|
||||
|
||||
<div
|
||||
|
||||
class="fixed inset-0 z-20 cursor-pointer bg-black/50 backdrop-blur-sm md:hidden"
|
||||
|
||||
role="button"
|
||||
|
||||
tabindex="0"
|
||||
|
||||
class="fixed inset-0 z-20 cursor-pointer bg-black/50 backdrop-blur-sm md:hidden"
|
||||
|
||||
|
||||
transition:fade={{ duration: 200 }}
|
||||
|
||||
@@ -326,25 +317,25 @@
|
||||
|
||||
<aside
|
||||
|
||||
class="bg-base-200 border-base-100/70 fixed z-30 flex h-full w-64 flex-shrink-0 flex-col border-r md:relative"
|
||||
|
||||
in:fly={{ duration: 200, x: -100 }}
|
||||
|
||||
out:fly={{ duration: 200, x: -100 }}
|
||||
|
||||
class="bg-base-200 border-base-100/70 fixed z-30 flex h-full w-64 flex-shrink-0 flex-col border-r md:relative"
|
||||
|
||||
>
|
||||
|
||||
<div class="h-18 flex flex-shrink-0 items-center p-4">
|
||||
|
||||
<a
|
||||
|
||||
href={resolve('/app/dashboard')}
|
||||
|
||||
class="flex items-center gap-3"
|
||||
|
||||
href={resolve('/app/dashboard')}
|
||||
|
||||
>
|
||||
|
||||
<Icon id="logo" size="32" className="flex-shrink-0 rounded-box" />
|
||||
<Icon className="flex-shrink-0 rounded-box" id="logo" size="32" />
|
||||
|
||||
<p class="truncate font-serif text-lg font-bold">IT DTMS</p>
|
||||
|
||||
@@ -366,12 +357,12 @@
|
||||
{/each}
|
||||
|
||||
</ul>
|
||||
<!-- 状态: {sidebarState.isSidebarExpanded ? '展开' : '收起'}-->
|
||||
<!-- <button-->
|
||||
<!-- onclick="{sidebarState.toggleSidebar}"-->
|
||||
<!-- class="btn btn-square btn-ghost">-->
|
||||
<!-- 123-->
|
||||
<!-- </button>-->
|
||||
<!-- 状态: {sidebarState.isSidebarExpanded ? '展开' : '收起'}-->
|
||||
<!-- <button-->
|
||||
<!-- onclick="{sidebarState.toggleSidebar}"-->
|
||||
<!-- class="btn btn-square btn-ghost">-->
|
||||
<!-- 123-->
|
||||
<!-- </button>-->
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
const { data } = $props();
|
||||
|
||||
console.log("data", data);
|
||||
const newRowTitles = [
|
||||
{ title: 'ID', width: 5}
|
||||
, { title: '用户名', width: 15 }
|
||||
@@ -11,12 +12,19 @@
|
||||
, { title: '头像', width: 10 }
|
||||
, { title: '用户组', width: 45 }
|
||||
];
|
||||
|
||||
let x ;
|
||||
|
||||
const handleRoleChange = (e) => {
|
||||
console.log(e.target.value);
|
||||
x = e.target.value;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class=" ">
|
||||
|
||||
<div class="flex justify-between items-center ">
|
||||
<p class="">用户管理</p>
|
||||
<p class="font-bold">用户管理</p>
|
||||
<div class="breadcrumbs ">
|
||||
<ul>
|
||||
<li><a href={resolve('/app/dashboard')}>仪表盘</a></li>
|
||||
@@ -46,23 +54,16 @@
|
||||
</g>
|
||||
</svg>
|
||||
<input type="search" required placeholder="Search" />
|
||||
<button class="btn btn-sm btn-primary">搜索</button>
|
||||
<button class="btn btn-xs btn-primary">搜索</button>
|
||||
</label>
|
||||
{#await data.streamed.roles}
|
||||
<div></div>
|
||||
{:then roles }
|
||||
<div class=" ">
|
||||
<select class="select w-36" aria-label="Category">
|
||||
<option disabled selected>用户组别</option>
|
||||
|
||||
<div class="filter w-64">
|
||||
<input class="btn filter-reset " type="radio" value='' name="metaframeworks" aria-label="All" onchange={handleRoleChange} />
|
||||
{#each roles as role(role.id)}
|
||||
<option value="{role.id}">{role.name}</option>
|
||||
<input class="btn " type="radio" name="metaframeworks" aria-label="{role.name}" value={role.id} onchange={handleRoleChange} />
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
{:catch error}
|
||||
<div>
|
||||
|
||||
</div>
|
||||
{/await}
|
||||
</div>
|
||||
@@ -101,7 +102,7 @@
|
||||
<tr>
|
||||
<td colspan={newRowTitles.length + 1} class="text-center py-4 ">
|
||||
<div class="min-h-96 flex items-center justify-center">
|
||||
<div class="loading text-base-content">Loading...</div>
|
||||
<div class="loading text-base-content"></div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
@@ -119,18 +120,45 @@
|
||||
<td>{record.id}</td>
|
||||
<td>{record.username}</td>
|
||||
<td>{record.nickname}</td>
|
||||
<td><img class="w-8 h-8 rounded-box bg-primary-content/10 border-0" src="{record.avatar}" alt=" "></td>
|
||||
<td class="flex gap-2">
|
||||
{#each record.roles as role(role.id)}
|
||||
|
||||
<span class="badge {role.id === 1 ? 'badge-primary' : 'badge-secondary'}">{role.name}</span>
|
||||
|
||||
<td>
|
||||
<div class="w-8 h-8 rounded-box bg-primary-content/10 border-0">
|
||||
{#if record.avatar}
|
||||
<img class="w-8 h-8 rounded-box bg-primary-content/10 border-0" src="{record.avatar}" alt=" ">
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
<td class="">
|
||||
{#each record.roles as role (role.id)}
|
||||
<span class="badge mr-2 last:mr-0 {role.id === 1 ? 'badge-primary' : 'badge-secondary'}">{role.name}</span>
|
||||
{/each}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan={newRowTitles.length + 1} class="text-center py-4 ">
|
||||
<div class=" flex items-center justify-between">
|
||||
<div>
|
||||
page {userList.current} of {userList.pages}
|
||||
</div>
|
||||
|
||||
<div class="join">
|
||||
<button class="join-item btn">1</button>
|
||||
<button class="join-item btn">2</button>
|
||||
<button class="join-item btn btn-disabled">...</button>
|
||||
<button class="join-item btn">99</button>
|
||||
<button class="join-item btn">100</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-primary">下一页</button>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
{:catch error}
|
||||
|
||||
<tbody>
|
||||
@@ -144,6 +172,7 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
{/await}
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user