feat: add user search support

Signed-off-by: Ryan Wang <i@ryanc.cc>
pull/3445/head
Ryan Wang 2022-09-28 18:27:21 +08:00
parent fe72b5ee28
commit a71a04cbf3
1 changed files with 23 additions and 4 deletions

View File

@ -19,12 +19,13 @@ import {
import UserEditingModal from "./components/UserEditingModal.vue"; import UserEditingModal from "./components/UserEditingModal.vue";
import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue"; import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue";
import GrantPermissionModal from "./components/GrantPermissionModal.vue"; import GrantPermissionModal from "./components/GrantPermissionModal.vue";
import { inject, onMounted, ref, watch } from "vue"; import { computed, inject, onMounted, ref, watch } from "vue";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
import type { User, UserList } from "@halo-dev/api-client"; import type { User, UserList } from "@halo-dev/api-client";
import { rbacAnnotations } from "@/constants/annotations"; import { rbacAnnotations } from "@/constants/annotations";
import { formatDatetime } from "@/utils/date"; import { formatDatetime } from "@/utils/date";
import { useRouteQuery } from "@vueuse/router"; import { useRouteQuery } from "@vueuse/router";
import Fuse from "fuse.js";
const dialog = useDialog(); const dialog = useDialog();
@ -47,6 +48,8 @@ const selectedUserNames = ref<string[]>([]);
const selectedUser = ref<User>(); const selectedUser = ref<User>();
const currentUser = inject<User>("currentUser"); const currentUser = inject<User>("currentUser");
let fuse: Fuse<User> | undefined = undefined;
const handleFetchUsers = async () => { const handleFetchUsers = async () => {
try { try {
const { data } = await apiClient.extension.user.listv1alpha1User({ const { data } = await apiClient.extension.user.listv1alpha1User({
@ -54,13 +57,28 @@ const handleFetchUsers = async () => {
size: users.value.size, size: users.value.size,
}); });
users.value = data; users.value = data;
fuse = new Fuse(data.items, {
keys: ["spec.displayName", "metadata.name", "spec.email"],
useExtendedSearch: true,
});
} catch (e) { } catch (e) {
console.error(e); console.error("Failed to fetch users", e);
} finally { } finally {
selectedUser.value = undefined; selectedUser.value = undefined;
} }
}; };
const keyword = ref("");
const searchResults = computed(() => {
if (!fuse || !keyword.value) {
return users.value.items;
}
return fuse?.search(keyword.value).map((item) => item.item);
});
const handlePaginationChange = async ({ const handlePaginationChange = async ({
page, page,
size, size,
@ -248,6 +266,7 @@ onMounted(() => {
<div class="flex w-full flex-1 sm:w-auto"> <div class="flex w-full flex-1 sm:w-auto">
<FormKit <FormKit
v-if="!selectedUserNames.length" v-if="!selectedUserNames.length"
v-model="keyword"
placeholder="输入关键词搜索" placeholder="输入关键词搜索"
type="text" type="text"
></FormKit> ></FormKit>
@ -257,7 +276,7 @@ onMounted(() => {
</VButton> </VButton>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <div v-if="false" class="mt-4 flex sm:mt-0">
<VSpace spacing="lg"> <VSpace spacing="lg">
<FloatingDropdown> <FloatingDropdown>
<div <div
@ -361,7 +380,7 @@ onMounted(() => {
</div> </div>
</template> </template>
<ul class="box-border h-full w-full divide-y divide-gray-100" role="list"> <ul class="box-border h-full w-full divide-y divide-gray-100" role="list">
<li v-for="(user, index) in users.items" :key="index"> <li v-for="(user, index) in searchResults" :key="index">
<VEntity :is-selected="checkSelection(user)"> <VEntity :is-selected="checkSelection(user)">
<template #checkbox> <template #checkbox>
<input <input