mirror of
https://github.com/ccmjga/zhilu-admin
synced 2026-04-05 11:47:32 +00:00
fix table filter
This commit is contained in:
@@ -4,60 +4,39 @@
|
|||||||
<Breadcrumbs :names="['用户管理', '绑定部门']" :routes="[{ name: RouteName.USERVIEW }]" />
|
<Breadcrumbs :names="['用户管理', '绑定部门']" :routes="[{ name: RouteName.USERVIEW }]" />
|
||||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定部门</h1>
|
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定部门</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 gap-y-3 sm:gap-y-0">
|
|
||||||
<form class="w-full sm:w-auto flex flex-col xs:flex-row gap-2 xs:gap-3 items-stretch xs:items-center">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<div class="flex-grow">
|
@update:values="updateFilterValues">
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
<template #actions>
|
||||||
<div class="relative">
|
<div class="flex gap-x-2">
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
<TableButton variant="primary" @click="() => {
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
if (checkedDepartmentIds.length === 0) {
|
||||||
viewBox="0 0 20 20">
|
alertStore.showAlert({
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
content: '没有选择部门',
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
level: 'error',
|
||||||
</svg>
|
});
|
||||||
</div>
|
} else {
|
||||||
<input type="search" id="default-search" v-model="departmentName"
|
departmentBindModal?.show();
|
||||||
class="block w-full p-2.5 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
}
|
||||||
placeholder="部门名" required />
|
}">
|
||||||
</div>
|
绑定
|
||||||
|
</TableButton>
|
||||||
|
<TableButton variant="danger" @click="() => {
|
||||||
|
if (checkedDepartmentIds.length === 0) {
|
||||||
|
alertStore.showAlert({
|
||||||
|
content: '没有选择部门',
|
||||||
|
level: 'error',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
departmentUnbindModal?.show();
|
||||||
|
}
|
||||||
|
}">
|
||||||
|
解绑
|
||||||
|
</TableButton>
|
||||||
</div>
|
</div>
|
||||||
<select id="bind-state" v-model="bindState"
|
</template>
|
||||||
class="w-full xs:w-auto bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5">
|
</TableFilterForm>
|
||||||
<option value="BIND">已绑定</option>
|
|
||||||
<option value="UNBIND">未绑定</option>
|
|
||||||
<option value="ALL">全部</option>
|
|
||||||
</select>
|
|
||||||
<button type="submit"
|
|
||||||
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2.5"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</form>
|
|
||||||
<div class="flex gap-x-2">
|
|
||||||
<TableButton variant="primary" @click="() => {
|
|
||||||
if (checkedDepartmentIds.length === 0) {
|
|
||||||
alertStore.showAlert({
|
|
||||||
content: '没有选择部门',
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
departmentBindModal?.show();
|
|
||||||
}
|
|
||||||
}">
|
|
||||||
绑定
|
|
||||||
</TableButton>
|
|
||||||
<TableButton variant="danger" @click="() => {
|
|
||||||
if (checkedDepartmentIds.length === 0) {
|
|
||||||
alertStore.showAlert({
|
|
||||||
content: '没有选择部门',
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
departmentUnbindModal?.show();
|
|
||||||
}
|
|
||||||
}">
|
|
||||||
解绑
|
|
||||||
</TableButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden space-y-4">
|
<div class="md:hidden space-y-4">
|
||||||
<MobileCardListWithCheckbox :items="departments || []" v-model="checkedDepartmentIds">
|
<MobileCardListWithCheckbox :items="departments || []" v-model="checkedDepartmentIds">
|
||||||
@@ -114,24 +93,63 @@ import MobileCardListWithCheckbox from "@/components/MobileCardListWithCheckbox.
|
|||||||
import BindModal from "@/components/PopupModal.vue";
|
import BindModal from "@/components/PopupModal.vue";
|
||||||
import UnModal from "@/components/PopupModal.vue";
|
import UnModal from "@/components/PopupModal.vue";
|
||||||
import TableButton from "@/components/TableButton.vue";
|
import TableButton from "@/components/TableButton.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
import { useDepartmentQuery } from "@/composables/department/useDepartmentQuery";
|
import { useDepartmentQuery } from "@/composables/department/useDepartmentQuery";
|
||||||
|
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||||
import { RouteName } from "@/router/constants";
|
import { RouteName } from "@/router/constants";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { onMounted, ref, watch } from "vue";
|
import { onMounted, reactive, ref, watch } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { useDepartmentBind } from "../composables/department/useDepartmentBind";
|
import { useDepartmentBind } from "../composables/department/useDepartmentBind";
|
||||||
import useAlertStore from "../composables/store/useAlertStore";
|
import useAlertStore from "../composables/store/useAlertStore";
|
||||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
|
||||||
|
|
||||||
const departmentName = ref<string>("");
|
// 定义筛选配置
|
||||||
|
const filterConfig: FilterItem[] = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "departmentName",
|
||||||
|
placeholder: "部门名",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
name: "bindState",
|
||||||
|
options: [
|
||||||
|
{ value: "BIND", label: "已绑定" },
|
||||||
|
{ value: "UNBIND", label: "未绑定" },
|
||||||
|
{ value: "ALL", label: "全部" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
departmentName: string;
|
||||||
|
bindState: "BIND" | "ALL" | "UNBIND";
|
||||||
|
}>({
|
||||||
|
departmentName: "",
|
||||||
|
bindState: "ALL",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.departmentName !== undefined) {
|
||||||
|
filterValues.departmentName = values.departmentName as string;
|
||||||
|
}
|
||||||
|
if (values.bindState !== undefined) {
|
||||||
|
filterValues.bindState = values.bindState as "BIND" | "ALL" | "UNBIND";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const checkedDepartmentIds = ref<number[]>([]);
|
const checkedDepartmentIds = ref<number[]>([]);
|
||||||
const departmentBindModal = ref<ModalInterface>();
|
const departmentBindModal = ref<ModalInterface>();
|
||||||
const departmentUnbindModal = ref<ModalInterface>();
|
const departmentUnbindModal = ref<ModalInterface>();
|
||||||
const allChecked = ref<boolean>(false);
|
const allChecked = ref<boolean>(false);
|
||||||
const $route = useRoute();
|
const $route = useRoute();
|
||||||
const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL");
|
|
||||||
|
|
||||||
const alertStore = useAlertStore();
|
const alertStore = useAlertStore();
|
||||||
const actionExcStore = useActionExcStore();
|
const actionExcStore = useActionExcStore();
|
||||||
@@ -159,9 +177,9 @@ const handleBindDepartmentSubmit = async () => {
|
|||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
await fetchDepartmentWith({
|
await fetchDepartmentWith({
|
||||||
name: departmentName.value,
|
name: filterValues.departmentName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -178,17 +196,17 @@ const handleUnbindDepartmentSubmit = async () => {
|
|||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
await fetchDepartmentWith({
|
await fetchDepartmentWith({
|
||||||
name: departmentName.value,
|
name: filterValues.departmentName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchDepartmentWith({
|
await fetchDepartmentWith({
|
||||||
name: departmentName.value,
|
name: filterValues.departmentName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $bindModalElement: HTMLElement | null = document.querySelector(
|
const $bindModalElement: HTMLElement | null = document.querySelector(
|
||||||
@@ -210,18 +228,18 @@ onMounted(async () => {
|
|||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchDepartmentWith({
|
await fetchDepartmentWith({
|
||||||
name: departmentName.value,
|
name: filterValues.departmentName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, pageSize: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchDepartmentWith(
|
await fetchDepartmentWith(
|
||||||
{
|
{
|
||||||
name: departmentName.value,
|
name: filterValues.departmentName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
},
|
},
|
||||||
page,
|
page,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
|||||||
@@ -4,60 +4,38 @@
|
|||||||
<Breadcrumbs :names="['角色管理', '绑定权限']" :routes="[{ name: RouteName.ROLEVIEW }]" />
|
<Breadcrumbs :names="['角色管理', '绑定权限']" :routes="[{ name: RouteName.ROLEVIEW }]" />
|
||||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定权限</h1>
|
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定权限</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 gap-y-3 sm:gap-y-0">
|
|
||||||
<form class="w-full sm:w-auto flex flex-col xs:flex-row gap-2 xs:gap-3 items-stretch xs:items-center">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<div class="flex-grow">
|
@update:values="updateFilterValues">
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
<template #actions>
|
||||||
<div class="relative">
|
<div class="flex gap-x-2">
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
<TableButton variant="primary" @click="() => {
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
if (checkedPermissionIds.length === 0) {
|
||||||
viewBox="0 0 20 20">
|
alertStore.showAlert({
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
content: '没有选择权限',
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
level: 'error',
|
||||||
</svg>
|
});
|
||||||
</div>
|
} else {
|
||||||
<input type="search" id="default-search" v-model="permissionName"
|
permissionBindModal?.show();
|
||||||
class="block w-full p-2.5 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
}
|
||||||
placeholder="权限名" required />
|
}">
|
||||||
</div>
|
绑定
|
||||||
|
</TableButton>
|
||||||
|
<TableButton variant="danger" @click="() => {
|
||||||
|
if (checkedPermissionIds.length === 0) {
|
||||||
|
alertStore.showAlert({
|
||||||
|
content: '没有选择权限',
|
||||||
|
level: 'error',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
permissionUnbindModal?.show();
|
||||||
|
}
|
||||||
|
}">
|
||||||
|
解绑
|
||||||
|
</TableButton>
|
||||||
</div>
|
</div>
|
||||||
<select id="bind-state" v-model="bindState"
|
</template>
|
||||||
class="w-full xs:w-auto bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5">
|
</TableFilterForm>
|
||||||
<option value="BIND">已绑定</option>
|
|
||||||
<option value="UNBIND">未绑定</option>
|
|
||||||
<option value="ALL">全部</option>
|
|
||||||
</select>
|
|
||||||
<button type="submit"
|
|
||||||
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2.5"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</form>
|
|
||||||
<div class="flex gap-x-2">
|
|
||||||
<TableButton variant="primary" @click="() => {
|
|
||||||
if (checkedPermissionIds.length === 0) {
|
|
||||||
alertStore.showAlert({
|
|
||||||
content: '没有选择权限',
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
permissionBindModal?.show();
|
|
||||||
}
|
|
||||||
}">
|
|
||||||
绑定
|
|
||||||
</TableButton>
|
|
||||||
<TableButton variant="danger" @click="() => {
|
|
||||||
if (checkedPermissionIds.length === 0) {
|
|
||||||
alertStore.showAlert({
|
|
||||||
content: '没有选择权限',
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
permissionUnbindModal?.show();
|
|
||||||
}
|
|
||||||
}">
|
|
||||||
解绑
|
|
||||||
</TableButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden space-y-4">
|
<div class="md:hidden space-y-4">
|
||||||
@@ -116,24 +94,63 @@ import MobileCardListWithCheckbox from "@/components/MobileCardListWithCheckbox.
|
|||||||
import BindModal from "@/components/PopupModal.vue";
|
import BindModal from "@/components/PopupModal.vue";
|
||||||
import UnModal from "@/components/PopupModal.vue";
|
import UnModal from "@/components/PopupModal.vue";
|
||||||
import TableButton from "@/components/TableButton.vue";
|
import TableButton from "@/components/TableButton.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
|
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||||
import { RouteName } from "@/router/constants";
|
import { RouteName } from "@/router/constants";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { onMounted, ref, watch } from "vue";
|
import { onMounted, reactive, ref, watch } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { usePermissionBind } from "../composables/permission/usePermissionBind";
|
import { usePermissionBind } from "../composables/permission/usePermissionBind";
|
||||||
import usePermissionsQuery from "../composables/permission/usePermissionQuery";
|
import usePermissionsQuery from "../composables/permission/usePermissionQuery";
|
||||||
import useAlertStore from "../composables/store/useAlertStore";
|
import useAlertStore from "../composables/store/useAlertStore";
|
||||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
|
||||||
|
|
||||||
const permissionName = ref<string>("");
|
// 定义筛选配置
|
||||||
|
const filterConfig: FilterItem[] = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "permissionName",
|
||||||
|
placeholder: "权限名",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
name: "bindState",
|
||||||
|
options: [
|
||||||
|
{ value: "BIND", label: "已绑定" },
|
||||||
|
{ value: "UNBIND", label: "未绑定" },
|
||||||
|
{ value: "ALL", label: "全部" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
permissionName: string;
|
||||||
|
bindState: "BIND" | "ALL" | "UNBIND";
|
||||||
|
}>({
|
||||||
|
permissionName: "",
|
||||||
|
bindState: "ALL",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.permissionName !== undefined) {
|
||||||
|
filterValues.permissionName = values.permissionName as string;
|
||||||
|
}
|
||||||
|
if (values.bindState !== undefined) {
|
||||||
|
filterValues.bindState = values.bindState as "BIND" | "ALL" | "UNBIND";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const checkedPermissionIds = ref<number[]>([]);
|
const checkedPermissionIds = ref<number[]>([]);
|
||||||
const permissionBindModal = ref<ModalInterface>();
|
const permissionBindModal = ref<ModalInterface>();
|
||||||
const permissionUnbindModal = ref<ModalInterface>();
|
const permissionUnbindModal = ref<ModalInterface>();
|
||||||
const allChecked = ref<boolean>(false);
|
const allChecked = ref<boolean>(false);
|
||||||
const $route = useRoute();
|
const $route = useRoute();
|
||||||
const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL");
|
|
||||||
|
|
||||||
const alertStore = useAlertStore();
|
const alertStore = useAlertStore();
|
||||||
const actionExcStore = useActionExcStore();
|
const actionExcStore = useActionExcStore();
|
||||||
@@ -160,9 +177,9 @@ const handleBindPermissionSubmit = async () => {
|
|||||||
clearCheckedRoleIds();
|
clearCheckedRoleIds();
|
||||||
allChecked.value = false;
|
allChecked.value = false;
|
||||||
await fetchPermissionsWith({
|
await fetchPermissionsWith({
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
roleId: Number($route.params.roleId),
|
roleId: Number($route.params.roleId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -179,17 +196,17 @@ const handleUnbindPermissionSubmit = async () => {
|
|||||||
clearCheckedRoleIds();
|
clearCheckedRoleIds();
|
||||||
allChecked.value = false;
|
allChecked.value = false;
|
||||||
await fetchPermissionsWith({
|
await fetchPermissionsWith({
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
roleId: Number($route.params.roleId),
|
roleId: Number($route.params.roleId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchPermissionsWith({
|
await fetchPermissionsWith({
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
roleId: Number($route.params.roleId),
|
roleId: Number($route.params.roleId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $bindModalElement: HTMLElement | null = document.querySelector(
|
const $bindModalElement: HTMLElement | null = document.querySelector(
|
||||||
@@ -215,18 +232,18 @@ onMounted(async () => {
|
|||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchPermissionsWith({
|
await fetchPermissionsWith({
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
roleId: Number($route.params.roleId),
|
roleId: Number($route.params.roleId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, pageSize: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchPermissionsWith(
|
await fetchPermissionsWith(
|
||||||
{
|
{
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
roleId: Number($route.params.roleId),
|
roleId: Number($route.params.roleId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
},
|
},
|
||||||
page,
|
page,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
|||||||
@@ -4,60 +4,38 @@
|
|||||||
<Breadcrumbs :names="['用户管理', '绑定岗位']" :routes="[{ name: RouteName.USERVIEW }]" />
|
<Breadcrumbs :names="['用户管理', '绑定岗位']" :routes="[{ name: RouteName.USERVIEW }]" />
|
||||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定岗位</h1>
|
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定岗位</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 gap-y-3 sm:gap-y-0">
|
|
||||||
<form class="w-full sm:w-auto flex flex-col xs:flex-row gap-2 xs:gap-3 items-stretch xs:items-center">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<div class="flex-grow">
|
@update:values="updateFilterValues">
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
<template #actions>
|
||||||
<div class="relative">
|
<div class="flex gap-x-2">
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
<TableButton variant="primary" @click="() => {
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
if (checkedPositionIds.length === 0) {
|
||||||
viewBox="0 0 20 20">
|
alertStore.showAlert({
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
content: '没有选择岗位',
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
level: 'error',
|
||||||
</svg>
|
});
|
||||||
</div>
|
} else {
|
||||||
<input type="search" id="default-search" v-model="positionName"
|
positionBindModal?.show();
|
||||||
class="block w-full p-2.5 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
}
|
||||||
placeholder="岗位名" required />
|
}">
|
||||||
</div>
|
绑定
|
||||||
|
</TableButton>
|
||||||
|
<TableButton variant="danger" @click="() => {
|
||||||
|
if (checkedPositionIds.length === 0) {
|
||||||
|
alertStore.showAlert({
|
||||||
|
content: '没有选择岗位',
|
||||||
|
level: 'error',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
positionUnbindModal?.show();
|
||||||
|
}
|
||||||
|
}">
|
||||||
|
解绑
|
||||||
|
</TableButton>
|
||||||
</div>
|
</div>
|
||||||
<select id="bind-state" v-model="bindState"
|
</template>
|
||||||
class="w-full xs:w-auto bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5">
|
</TableFilterForm>
|
||||||
<option value="BIND">已绑定</option>
|
|
||||||
<option value="UNBIND">未绑定</option>
|
|
||||||
<option value="ALL">全部</option>
|
|
||||||
</select>
|
|
||||||
<button type="submit"
|
|
||||||
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2.5"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</form>
|
|
||||||
<div class="flex gap-x-2">
|
|
||||||
<TableButton variant="primary" @click="() => {
|
|
||||||
if (checkedPositionIds.length === 0) {
|
|
||||||
alertStore.showAlert({
|
|
||||||
content: '没有选择岗位',
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
positionBindModal?.show();
|
|
||||||
}
|
|
||||||
}">
|
|
||||||
绑定
|
|
||||||
</TableButton>
|
|
||||||
<TableButton variant="danger" @click="() => {
|
|
||||||
if (checkedPositionIds.length === 0) {
|
|
||||||
alertStore.showAlert({
|
|
||||||
content: '没有选择岗位',
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
positionUnbindModal?.show();
|
|
||||||
}
|
|
||||||
}">
|
|
||||||
解绑
|
|
||||||
</TableButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden space-y-4">
|
<div class="md:hidden space-y-4">
|
||||||
@@ -107,25 +85,64 @@ import MobileCardListWithCheckbox from "@/components/MobileCardListWithCheckbox.
|
|||||||
import BindModal from "@/components/PopupModal.vue";
|
import BindModal from "@/components/PopupModal.vue";
|
||||||
import UnModal from "@/components/PopupModal.vue";
|
import UnModal from "@/components/PopupModal.vue";
|
||||||
import TableButton from "@/components/TableButton.vue";
|
import TableButton from "@/components/TableButton.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
import { usePositionBind } from "@/composables/position/usePositionBind";
|
import { usePositionBind } from "@/composables/position/usePositionBind";
|
||||||
import { usePositionQuery } from "@/composables/position/usePositionQuery";
|
import { usePositionQuery } from "@/composables/position/usePositionQuery";
|
||||||
|
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||||
import { useMobileStyles } from "@/composables/useMobileStyles";
|
import { useMobileStyles } from "@/composables/useMobileStyles";
|
||||||
import { RouteName } from "@/router/constants";
|
import { RouteName } from "@/router/constants";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { onMounted, ref, watch } from "vue";
|
import { onMounted, reactive, ref, watch } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import useAlertStore from "../composables/store/useAlertStore";
|
import useAlertStore from "../composables/store/useAlertStore";
|
||||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
|
||||||
|
|
||||||
const positionName = ref<string>("");
|
// 定义筛选配置
|
||||||
|
const filterConfig: FilterItem[] = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "positionName",
|
||||||
|
placeholder: "岗位名",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
name: "bindState",
|
||||||
|
options: [
|
||||||
|
{ value: "BIND", label: "已绑定" },
|
||||||
|
{ value: "UNBIND", label: "未绑定" },
|
||||||
|
{ value: "ALL", label: "全部" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
positionName: string;
|
||||||
|
bindState: "BIND" | "ALL" | "UNBIND";
|
||||||
|
}>({
|
||||||
|
positionName: "",
|
||||||
|
bindState: "ALL",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.positionName !== undefined) {
|
||||||
|
filterValues.positionName = values.positionName as string;
|
||||||
|
}
|
||||||
|
if (values.bindState !== undefined) {
|
||||||
|
filterValues.bindState = values.bindState as "BIND" | "ALL" | "UNBIND";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const checkedPositionIds = ref<number[]>([]);
|
const checkedPositionIds = ref<number[]>([]);
|
||||||
const positionBindModal = ref<ModalInterface>();
|
const positionBindModal = ref<ModalInterface>();
|
||||||
const positionUnbindModal = ref<ModalInterface>();
|
const positionUnbindModal = ref<ModalInterface>();
|
||||||
const allChecked = ref<boolean>(false);
|
const allChecked = ref<boolean>(false);
|
||||||
const $route = useRoute();
|
const $route = useRoute();
|
||||||
const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL");
|
|
||||||
|
|
||||||
const alertStore = useAlertStore();
|
const alertStore = useAlertStore();
|
||||||
const actionExcStore = useActionExcStore();
|
const actionExcStore = useActionExcStore();
|
||||||
@@ -147,9 +164,9 @@ const handleBindPositionSubmit = async () => {
|
|||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
await fetchPositionWith({
|
await fetchPositionWith({
|
||||||
name: positionName.value,
|
name: filterValues.positionName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
clearCheckedPositionIds();
|
clearCheckedPositionIds();
|
||||||
allChecked.value = false;
|
allChecked.value = false;
|
||||||
@@ -163,9 +180,9 @@ const handleUnbindPositionSubmit = async () => {
|
|||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
await fetchPositionWith({
|
await fetchPositionWith({
|
||||||
name: positionName.value,
|
name: filterValues.positionName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
clearCheckedPositionIds();
|
clearCheckedPositionIds();
|
||||||
allChecked.value = false;
|
allChecked.value = false;
|
||||||
@@ -173,9 +190,9 @@ const handleUnbindPositionSubmit = async () => {
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchPositionWith({
|
await fetchPositionWith({
|
||||||
name: positionName.value,
|
name: filterValues.positionName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $bindModalElement: HTMLElement | null = document.querySelector(
|
const $bindModalElement: HTMLElement | null = document.querySelector(
|
||||||
@@ -201,18 +218,18 @@ onMounted(async () => {
|
|||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchPositionWith({
|
await fetchPositionWith({
|
||||||
name: positionName.value,
|
name: filterValues.positionName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, pageSize: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchPositionWith(
|
await fetchPositionWith(
|
||||||
{
|
{
|
||||||
name: positionName.value,
|
name: filterValues.positionName,
|
||||||
userId: Number($route.params.userId),
|
userId: Number($route.params.userId),
|
||||||
bindState: bindState.value,
|
bindState: filterValues.bindState,
|
||||||
},
|
},
|
||||||
page,
|
page,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
|||||||
@@ -4,35 +4,21 @@
|
|||||||
<Breadcrumbs :names="['部门管理']" />
|
<Breadcrumbs :names="['部门管理']" />
|
||||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">部门管理</h1>
|
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">部门管理</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 gap-y-3 sm:gap-y-0">
|
|
||||||
<form class="w-full sm:max-w-xs">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
@update:values="updateFilterValues">
|
||||||
<div class="relative">
|
<template #actions>
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
<Button :handleClick="() => handleUpsertDepartmentClick()" :isLoading="false" :abortable="false"
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
submitContent="新增部门" class="w-full sm:w-auto">
|
||||||
viewBox="0 0 20 20">
|
<template #icon>
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</template>
|
||||||
<input type="search" id="default-search" v-model="name"
|
</Button>
|
||||||
class="block w-full p-3 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
</template>
|
||||||
placeholder="部门名称" required />
|
</TableFilterForm>
|
||||||
<button type="submit"
|
|
||||||
class="text-white absolute end-1.5 bottom-1.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-1.5 sm:px-4 sm:py-2"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<Button :handleClick="() => handleUpsertDepartmentClick()" :isLoading="false" :abortable="false"
|
|
||||||
submitContent="新增部门" class="w-full sm:w-auto">
|
|
||||||
<template #icon>
|
|
||||||
<svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
||||||
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden">
|
<div class="md:hidden">
|
||||||
@@ -131,19 +117,45 @@ import DepartmentUpsertModal from "@/components/DepartmentUpsertModal.vue";
|
|||||||
import MobileCardList from "@/components/MobileCardList.vue";
|
import MobileCardList from "@/components/MobileCardList.vue";
|
||||||
import DepartmentDeleteModal from "@/components/PopupModal.vue";
|
import DepartmentDeleteModal from "@/components/PopupModal.vue";
|
||||||
import TableButton from "@/components/TableButton.vue";
|
import TableButton from "@/components/TableButton.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
|
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||||
import type { DepartmentUpsertModel } from "@/types/department";
|
import type { DepartmentUpsertModel } from "@/types/department";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { nextTick, onMounted, ref } from "vue";
|
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||||
import type { components } from "../api/types/schema";
|
import type { components } from "../api/types/schema";
|
||||||
import useDepartmentDelete from "../composables/department/useDepartmentDelete";
|
import useDepartmentDelete from "../composables/department/useDepartmentDelete";
|
||||||
import { useDepartmentQuery } from "../composables/department/useDepartmentQuery";
|
import { useDepartmentQuery } from "../composables/department/useDepartmentQuery";
|
||||||
import { useDepartmentUpsert } from "../composables/department/useDepartmentUpsert";
|
import { useDepartmentUpsert } from "../composables/department/useDepartmentUpsert";
|
||||||
import useAlertStore from "../composables/store/useAlertStore";
|
import useAlertStore from "../composables/store/useAlertStore";
|
||||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
|
||||||
|
|
||||||
const name = ref<string>("");
|
// 定义筛选配置
|
||||||
|
const filterConfig = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "departmentName",
|
||||||
|
placeholder: "部门名称",
|
||||||
|
},
|
||||||
|
] as FilterItem[];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
departmentName: string;
|
||||||
|
}>({
|
||||||
|
departmentName: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.departmentName !== undefined) {
|
||||||
|
filterValues.departmentName = values.departmentName as string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const selectedDepartment = ref<components["schemas"]["Department"]>();
|
const selectedDepartment = ref<components["schemas"]["Department"]>();
|
||||||
const departmentUpsertModal = ref<ModalInterface>();
|
const departmentUpsertModal = ref<ModalInterface>();
|
||||||
const departmentDeleteModal = ref<ModalInterface>();
|
const departmentDeleteModal = ref<ModalInterface>();
|
||||||
@@ -170,7 +182,7 @@ const columns = [
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchDepartmentWith({
|
await fetchDepartmentWith({
|
||||||
name: name.value,
|
name: filterValues.departmentName,
|
||||||
});
|
});
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $upsertModalElement: HTMLElement | null = document.querySelector(
|
const $upsertModalElement: HTMLElement | null = document.querySelector(
|
||||||
@@ -202,7 +214,7 @@ const handleUpsertDepartmentSubmit = async (
|
|||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
await fetchDepartmentWith({
|
await fetchDepartmentWith({
|
||||||
name: name.value,
|
name: filterValues.departmentName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -210,14 +222,14 @@ const handleUpsertDepartmentClick = async (
|
|||||||
department?: components["schemas"]["Department"],
|
department?: components["schemas"]["Department"],
|
||||||
) => {
|
) => {
|
||||||
selectedDepartment.value = department;
|
selectedDepartment.value = department;
|
||||||
await fetchAvailableDepartments(selectedDepartment.value?.id);
|
await fetchAvailableDepartments(department?.id);
|
||||||
await nextTick(() => {
|
await nextTick(() => {
|
||||||
departmentUpsertModal.value?.show();
|
departmentUpsertModal.value?.show();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteDepartmentSubmit = async () => {
|
const handleDeleteDepartmentSubmit = async () => {
|
||||||
if (!selectedDepartment?.value?.id) return;
|
if (!selectedDepartment.value?.id) return;
|
||||||
await deleteDepartment(selectedDepartment.value.id);
|
await deleteDepartment(selectedDepartment.value.id);
|
||||||
departmentDeleteModal.value?.hide();
|
departmentDeleteModal.value?.hide();
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
@@ -225,7 +237,7 @@ const handleDeleteDepartmentSubmit = async () => {
|
|||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
await fetchDepartmentWith({
|
await fetchDepartmentWith({
|
||||||
name: name.value,
|
name: filterValues.departmentName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -240,17 +252,17 @@ const handleDeleteDepartmentClick = async (
|
|||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchDepartmentWith({
|
await fetchDepartmentWith({
|
||||||
name: name.value,
|
name: filterValues.departmentName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, size: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchDepartmentWith(
|
await fetchDepartmentWith(
|
||||||
{
|
{
|
||||||
name: name.value,
|
name: filterValues.departmentName,
|
||||||
},
|
},
|
||||||
page,
|
page,
|
||||||
size,
|
pageSize,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,26 +4,10 @@
|
|||||||
<Breadcrumbs :names="['大模型管理']" />
|
<Breadcrumbs :names="['大模型管理']" />
|
||||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">大模型管理</h1>
|
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">大模型管理</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
|
||||||
<form class="w-full sm:max-w-xs">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
@update:values="updateFilterValues">
|
||||||
<div class="relative">
|
</TableFilterForm>
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
||||||
viewBox="0 0 20 20">
|
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<input type="search" id="default-search" v-model="name"
|
|
||||||
class="block w-full p-3 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
|
||||||
placeholder="模型名称" required />
|
|
||||||
<button type="submit"
|
|
||||||
class="text-white absolute end-1.5 bottom-1.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-1.5 sm:px-4 sm:py-2"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden">
|
<div class="md:hidden">
|
||||||
@@ -134,18 +118,44 @@
|
|||||||
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
||||||
import LlmUpdateModal from "@/components/LlmUpdateModal.vue";
|
import LlmUpdateModal from "@/components/LlmUpdateModal.vue";
|
||||||
import MobileCardList from "@/components/MobileCardList.vue";
|
import MobileCardList from "@/components/MobileCardList.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
import { useLlmQuery } from "@/composables/ai/useLlmQuery";
|
import { useLlmQuery } from "@/composables/ai/useLlmQuery";
|
||||||
import { useLlmUpdate } from "@/composables/ai/useLlmUpdate";
|
import { useLlmUpdate } from "@/composables/ai/useLlmUpdate";
|
||||||
import useAlertStore from "@/composables/store/useAlertStore";
|
import useAlertStore from "@/composables/store/useAlertStore";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { nextTick, onMounted, ref } from "vue";
|
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||||
import type { components } from "../api/types/schema";
|
import type { components } from "../api/types/schema";
|
||||||
|
|
||||||
|
// 定义筛选配置
|
||||||
|
const filterConfig: FilterItem[] = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "modelName",
|
||||||
|
placeholder: "模型名称",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
modelName: string;
|
||||||
|
}>({
|
||||||
|
modelName: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.modelName !== undefined) {
|
||||||
|
filterValues.modelName = values.modelName as string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const llmUpdateModal = ref<ModalInterface>();
|
const llmUpdateModal = ref<ModalInterface>();
|
||||||
const selectedLlm = ref<components["schemas"]["LlmVm"]>();
|
const selectedLlm = ref<components["schemas"]["LlmVm"]>();
|
||||||
const name = ref<string>("");
|
|
||||||
|
|
||||||
const { llms, fetchLlmConfigs, total } = useLlmQuery();
|
const { llms, fetchLlmConfigs, total } = useLlmQuery();
|
||||||
const { updateLlmConfig } = useLlmUpdate();
|
const { updateLlmConfig } = useLlmUpdate();
|
||||||
@@ -171,15 +181,15 @@ const handleUpdateModalSubmit = async (llm: components["schemas"]["LlmVm"]) => {
|
|||||||
level: "success",
|
level: "success",
|
||||||
content: "操作成功",
|
content: "操作成功",
|
||||||
});
|
});
|
||||||
await fetchLlmConfigs();
|
await fetchLlmConfigs(1, 10, filterValues.modelName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchLlmConfigs();
|
await fetchLlmConfigs(1, 10, filterValues.modelName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, pageSize: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchLlmConfigs(page, pageSize);
|
await fetchLlmConfigs(page, pageSize, filterValues.modelName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLlmUpdateClick = async (llm: components["schemas"]["LlmVm"]) => {
|
const handleLlmUpdateClick = async (llm: components["schemas"]["LlmVm"]) => {
|
||||||
@@ -190,7 +200,7 @@ const handleLlmUpdateClick = async (llm: components["schemas"]["LlmVm"]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchLlmConfigs();
|
await fetchLlmConfigs(1, 10, filterValues.modelName);
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $llmUpdateModalElement: HTMLElement | null =
|
const $llmUpdateModalElement: HTMLElement | null =
|
||||||
document.querySelector("#llm-update-modal");
|
document.querySelector("#llm-update-modal");
|
||||||
|
|||||||
@@ -4,36 +4,21 @@
|
|||||||
<Breadcrumbs :names="['权限管理']" />
|
<Breadcrumbs :names="['权限管理']" />
|
||||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">权限管理</h1>
|
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">权限管理</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 gap-y-3 sm:gap-y-0">
|
|
||||||
<form class="w-full sm:max-w-xs">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
@update:values="updateFilterValues">
|
||||||
<div class="relative">
|
<template #actions>
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
<Button :handleClick="() => handleUpsertPermissionClick(undefined)" :isLoading="false" :abortable="false"
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
submitContent="新增权限" class="w-full sm:w-auto">
|
||||||
viewBox="0 0 20 20">
|
<template #icon>
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</template>
|
||||||
<input type="search" id="default-search" v-model="permissionName"
|
</Button>
|
||||||
class="block w-full p-3 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
</template>
|
||||||
placeholder="权限名" required />
|
</TableFilterForm>
|
||||||
<button type="submit"
|
|
||||||
class="text-white absolute end-1.5 bottom-1.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-1.5 sm:px-4 sm:py-2"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<!-- Create Modal toggle -->
|
|
||||||
<Button :handleClick="() => handleUpsertPermissionClick(undefined)" :isLoading="false" :abortable="false"
|
|
||||||
submitContent="新增权限" class="w-full sm:w-auto">
|
|
||||||
<template #icon>
|
|
||||||
<svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
||||||
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden">
|
<div class="md:hidden">
|
||||||
@@ -125,26 +110,51 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Button from "@/components/Button.vue";
|
|
||||||
import PermissionUpsertModal from "@/components/PermissionUpsertModal.vue";
|
|
||||||
import PermissionDeleteModal from "@/components/PopupModal.vue";
|
|
||||||
import usePermissionDelete from "@/composables/permission/usePermissionDelete";
|
|
||||||
|
|
||||||
import type { components } from "@/api/types/schema";
|
import type { components } from "@/api/types/schema";
|
||||||
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
||||||
|
import Button from "@/components/Button.vue";
|
||||||
import MobileCardList from "@/components/MobileCardList.vue";
|
import MobileCardList from "@/components/MobileCardList.vue";
|
||||||
|
import PermissionUpsertModal from "@/components/PermissionUpsertModal.vue";
|
||||||
|
import PermissionDeleteModal from "@/components/PopupModal.vue";
|
||||||
import TableButton from "@/components/TableButton.vue";
|
import TableButton from "@/components/TableButton.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
|
import usePermissionDelete from "@/composables/permission/usePermissionDelete";
|
||||||
|
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { nextTick, onMounted, ref } from "vue";
|
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||||
import usePermissionsQuery from "../composables/permission/usePermissionQuery";
|
import usePermissionsQuery from "../composables/permission/usePermissionQuery";
|
||||||
import usePermissionUpsert from "../composables/permission/usePermissionUpsert";
|
import usePermissionUpsert from "../composables/permission/usePermissionUpsert";
|
||||||
import useAlertStore from "../composables/store/useAlertStore";
|
import useAlertStore from "../composables/store/useAlertStore";
|
||||||
import type { PermissionUpsertModel } from "../types/permission";
|
import type { PermissionUpsertModel } from "../types/permission";
|
||||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
|
||||||
|
|
||||||
const permissionName = ref<string>("");
|
// 定义筛选配置
|
||||||
|
const filterConfig = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "permissionName",
|
||||||
|
placeholder: "权限名",
|
||||||
|
},
|
||||||
|
] as FilterItem[];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
permissionName: string;
|
||||||
|
}>({
|
||||||
|
permissionName: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.permissionName !== undefined) {
|
||||||
|
filterValues.permissionName = values.permissionName as string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const selectedPermission = ref<components["schemas"]["PermissionRespDto"]>();
|
const selectedPermission = ref<components["schemas"]["PermissionRespDto"]>();
|
||||||
const permissionUpsertModal = ref<ModalInterface>();
|
const permissionUpsertModal = ref<ModalInterface>();
|
||||||
const permissionDeleteModal = ref<ModalInterface>();
|
const permissionDeleteModal = ref<ModalInterface>();
|
||||||
@@ -164,7 +174,7 @@ const columns = [
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchPermissionsWith({
|
await fetchPermissionsWith({
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
});
|
});
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $upsertModalElement: HTMLElement | null = document.querySelector(
|
const $upsertModalElement: HTMLElement | null = document.querySelector(
|
||||||
@@ -189,7 +199,7 @@ onMounted(async () => {
|
|||||||
const handleUpsertModalSubmit = async (data: PermissionUpsertModel) => {
|
const handleUpsertModalSubmit = async (data: PermissionUpsertModel) => {
|
||||||
await permissionUpsert.upsertPermission(data);
|
await permissionUpsert.upsertPermission(data);
|
||||||
await fetchPermissionsWith({
|
await fetchPermissionsWith({
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
});
|
});
|
||||||
permissionUpsertModal.value?.hide();
|
permissionUpsertModal.value?.hide();
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
@@ -208,7 +218,7 @@ const handleUpsertPermissionClick = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteModalSubmit = async () => {
|
const handleDeleteModalSubmit = async () => {
|
||||||
if (!selectedPermission?.value?.id) return;
|
if (!selectedPermission.value?.id) return;
|
||||||
await deletePermission(selectedPermission.value.id);
|
await deletePermission(selectedPermission.value.id);
|
||||||
permissionDeleteModal.value?.hide();
|
permissionDeleteModal.value?.hide();
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
@@ -216,7 +226,7 @@ const handleDeleteModalSubmit = async () => {
|
|||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
await fetchPermissionsWith({
|
await fetchPermissionsWith({
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -231,14 +241,14 @@ const handleDeletePermissionClick = async (
|
|||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchPermissionsWith({
|
await fetchPermissionsWith({
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, pageSize: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchPermissionsWith(
|
await fetchPermissionsWith(
|
||||||
{
|
{
|
||||||
name: permissionName.value,
|
name: filterValues.permissionName,
|
||||||
},
|
},
|
||||||
page,
|
page,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
|||||||
@@ -4,36 +4,21 @@
|
|||||||
<Breadcrumbs :names="['岗位管理']" />
|
<Breadcrumbs :names="['岗位管理']" />
|
||||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">岗位管理</h1>
|
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">岗位管理</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 gap-y-3 sm:gap-y-0">
|
|
||||||
<form class="w-full sm:max-w-xs">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
@update:values="updateFilterValues">
|
||||||
<div class="relative">
|
<template #actions>
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
<Button :handleClick="() => handleUpsertPositionClick()" :isLoading="false" :abortable="false"
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
submitContent="新增岗位" class="w-full sm:w-auto">
|
||||||
viewBox="0 0 20 20">
|
<template #icon>
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</template>
|
||||||
<input type="search" id="default-search" v-model="name"
|
</Button>
|
||||||
class="block w-full p-3 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
</template>
|
||||||
placeholder="岗位名称" required />
|
</TableFilterForm>
|
||||||
<button type="submit"
|
|
||||||
class="text-white absolute end-1.5 bottom-1.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-1.5 sm:px-4 sm:py-2"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<!-- Create Modal toggle -->
|
|
||||||
<Button :handleClick="() => handleUpsertPositionClick()" :isLoading="false" :abortable="false"
|
|
||||||
submitContent="新增岗位" class="w-full sm:w-auto">
|
|
||||||
<template #icon>
|
|
||||||
<svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
||||||
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden">
|
<div class="md:hidden">
|
||||||
@@ -121,18 +106,44 @@ import Button from "@/components/Button.vue";
|
|||||||
import MobileCardList from "@/components/MobileCardList.vue";
|
import MobileCardList from "@/components/MobileCardList.vue";
|
||||||
import PositionDeleteModal from "@/components/PopupModal.vue";
|
import PositionDeleteModal from "@/components/PopupModal.vue";
|
||||||
import PositionUpsertModal from "@/components/PositionUpsertModal.vue";
|
import PositionUpsertModal from "@/components/PositionUpsertModal.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
import usePositionDelete from "@/composables/position/usePositionDelete";
|
import usePositionDelete from "@/composables/position/usePositionDelete";
|
||||||
import { usePositionQuery } from "@/composables/position/usePositionQuery";
|
import { usePositionQuery } from "@/composables/position/usePositionQuery";
|
||||||
import { usePositionUpsert } from "@/composables/position/usePositionUpsert";
|
import { usePositionUpsert } from "@/composables/position/usePositionUpsert";
|
||||||
|
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { nextTick, onMounted, ref } from "vue";
|
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||||
import type { components } from "../api/types/schema";
|
import type { components } from "../api/types/schema";
|
||||||
import useAlertStore from "../composables/store/useAlertStore";
|
import useAlertStore from "../composables/store/useAlertStore";
|
||||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
|
||||||
|
|
||||||
const name = ref<string>("");
|
// 定义筛选配置
|
||||||
|
const filterConfig = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "positionName",
|
||||||
|
placeholder: "岗位名称",
|
||||||
|
},
|
||||||
|
] as FilterItem[];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
positionName: string;
|
||||||
|
}>({
|
||||||
|
positionName: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.positionName !== undefined) {
|
||||||
|
filterValues.positionName = values.positionName as string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const selectedPosition = ref<components["schemas"]["Position"]>();
|
const selectedPosition = ref<components["schemas"]["Position"]>();
|
||||||
const positionUpsertModal = ref<ModalInterface>();
|
const positionUpsertModal = ref<ModalInterface>();
|
||||||
const positionDeleteModal = ref<ModalInterface>();
|
const positionDeleteModal = ref<ModalInterface>();
|
||||||
@@ -154,7 +165,7 @@ const columns = [
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchAllPositions();
|
await fetchAllPositions();
|
||||||
await fetchPositionWith({
|
await fetchPositionWith({
|
||||||
name: name.value,
|
name: filterValues.positionName,
|
||||||
});
|
});
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $upsertModalElement: HTMLElement | null = document.querySelector(
|
const $upsertModalElement: HTMLElement | null = document.querySelector(
|
||||||
@@ -187,7 +198,7 @@ const handleUpsertPositionSubmit = async (
|
|||||||
});
|
});
|
||||||
fetchAllPositions();
|
fetchAllPositions();
|
||||||
await fetchPositionWith({
|
await fetchPositionWith({
|
||||||
name: name.value,
|
name: filterValues.positionName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -201,16 +212,15 @@ const handleUpsertPositionClick = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDeletePositionSubmit = async () => {
|
const handleDeletePositionSubmit = async () => {
|
||||||
if (!selectedPosition?.value?.id) return;
|
if (!selectedPosition.value?.id) return;
|
||||||
await deletePosition(selectedPosition.value.id);
|
await deletePosition(selectedPosition.value.id);
|
||||||
positionDeleteModal.value?.hide();
|
positionDeleteModal.value?.hide();
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
content: "删除成功",
|
content: "删除成功",
|
||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
fetchAllPositions();
|
|
||||||
await fetchPositionWith({
|
await fetchPositionWith({
|
||||||
name: name.value,
|
name: filterValues.positionName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -225,17 +235,17 @@ const handleDeletePositionClick = async (
|
|||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchPositionWith({
|
await fetchPositionWith({
|
||||||
name: name.value,
|
name: filterValues.positionName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, size: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchPositionWith(
|
await fetchPositionWith(
|
||||||
{
|
{
|
||||||
name: name.value,
|
name: filterValues.positionName,
|
||||||
},
|
},
|
||||||
page,
|
page,
|
||||||
size,
|
pageSize,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,36 +4,21 @@
|
|||||||
<Breadcrumbs :names="['角色管理']" />
|
<Breadcrumbs :names="['角色管理']" />
|
||||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">角色管理</h1>
|
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">角色管理</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 gap-y-3 sm:gap-y-0">
|
|
||||||
<form class="w-full sm:max-w-xs">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
@update:values="updateFilterValues">
|
||||||
<div class="relative">
|
<template #actions>
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
<Button :handleClick="() => handleUpsertRoleClick(undefined)" :isLoading="false" :abortable="false"
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
submitContent="新增角色" class="w-full sm:w-auto">
|
||||||
viewBox="0 0 20 20">
|
<template #icon>
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</template>
|
||||||
<input type="search" id="default-search" v-model="roleName"
|
</Button>
|
||||||
class="block w-full p-3 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
</template>
|
||||||
placeholder="角色名" required />
|
</TableFilterForm>
|
||||||
<button type="submit"
|
|
||||||
class="text-white absolute end-1.5 bottom-1.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-1.5 sm:px-4 sm:py-2"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<!-- Create Modal toggle -->
|
|
||||||
<Button :handleClick="() => handleUpsertRoleClick(undefined)" :isLoading="false" :abortable="false"
|
|
||||||
submitContent="新增角色" class="w-full sm:w-auto">
|
|
||||||
<template #icon>
|
|
||||||
<svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
||||||
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden">
|
<div class="md:hidden">
|
||||||
@@ -145,21 +130,47 @@ import Button from "@/components/Button.vue";
|
|||||||
import MobileCardList from "@/components/MobileCardList.vue";
|
import MobileCardList from "@/components/MobileCardList.vue";
|
||||||
import RoleDeleteModal from "@/components/PopupModal.vue";
|
import RoleDeleteModal from "@/components/PopupModal.vue";
|
||||||
import RoleUpsertModal from "@/components/RoleUpsertModal.vue";
|
import RoleUpsertModal from "@/components/RoleUpsertModal.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
import useRoleDelete from "@/composables/role/useRoleDelete";
|
import useRoleDelete from "@/composables/role/useRoleDelete";
|
||||||
import { useRolesQuery } from "@/composables/role/useRolesQuery";
|
import { useRolesQuery } from "@/composables/role/useRolesQuery";
|
||||||
|
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||||
import { RouteName } from "@/router/constants";
|
import { RouteName } from "@/router/constants";
|
||||||
import type { RoleUpsertModel } from "@/types/role";
|
import type { RoleUpsertModel } from "@/types/role";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { nextTick, onMounted, ref } from "vue";
|
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import type { components } from "../api/types/schema";
|
import type { components } from "../api/types/schema";
|
||||||
import { useRoleUpsert } from "../composables/role/useRoleUpsert";
|
import { useRoleUpsert } from "../composables/role/useRoleUpsert";
|
||||||
import useAlertStore from "../composables/store/useAlertStore";
|
import useAlertStore from "../composables/store/useAlertStore";
|
||||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
|
||||||
|
|
||||||
const roleName = ref<string>("");
|
// 定义筛选配置
|
||||||
|
const filterConfig = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "roleName",
|
||||||
|
placeholder: "角色名",
|
||||||
|
},
|
||||||
|
] as FilterItem[];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
roleName: string;
|
||||||
|
}>({
|
||||||
|
roleName: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.roleName !== undefined) {
|
||||||
|
filterValues.roleName = values.roleName as string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const selectedRole = ref<components["schemas"]["RoleDto"]>();
|
const selectedRole = ref<components["schemas"]["RoleDto"]>();
|
||||||
const roleUpsertModal = ref<ModalInterface>();
|
const roleUpsertModal = ref<ModalInterface>();
|
||||||
const roleDeleteModal = ref<ModalInterface>();
|
const roleDeleteModal = ref<ModalInterface>();
|
||||||
@@ -181,7 +192,7 @@ const columns = [
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchRolesWith({
|
await fetchRolesWith({
|
||||||
name: roleName.value,
|
name: filterValues.roleName,
|
||||||
});
|
});
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $upsertModalElement: HTMLElement | null =
|
const $upsertModalElement: HTMLElement | null =
|
||||||
@@ -203,14 +214,14 @@ onMounted(async () => {
|
|||||||
|
|
||||||
const handleUpsertModalSubmit = async (data: RoleUpsertModel) => {
|
const handleUpsertModalSubmit = async (data: RoleUpsertModel) => {
|
||||||
await upsertRole.upsertRole(data);
|
await upsertRole.upsertRole(data);
|
||||||
await fetchRolesWith({
|
|
||||||
name: roleName.value,
|
|
||||||
});
|
|
||||||
roleUpsertModal.value?.hide();
|
roleUpsertModal.value?.hide();
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
content: "操作成功",
|
content: "操作成功",
|
||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
|
await fetchRolesWith({
|
||||||
|
name: filterValues.roleName,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpsertRoleClick = async (
|
const handleUpsertRoleClick = async (
|
||||||
@@ -222,17 +233,28 @@ const handleUpsertRoleClick = async (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeletedModalSubmit = async () => {
|
const handleBindPermissionClick = async (
|
||||||
if (!selectedRole?.value?.id) return;
|
role: components["schemas"]["RoleDto"],
|
||||||
await deleteRole(selectedRole.value.id);
|
) => {
|
||||||
await fetchRolesWith({
|
router.push({
|
||||||
name: roleName.value,
|
name: RouteName.BINDPERMISSIONVIEW,
|
||||||
|
params: {
|
||||||
|
roleId: role.id,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeletedModalSubmit = async () => {
|
||||||
|
if (!selectedRole.value?.id) return;
|
||||||
|
await deleteRole(selectedRole.value.id);
|
||||||
roleDeleteModal.value?.hide();
|
roleDeleteModal.value?.hide();
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
content: "删除成功",
|
content: "删除成功",
|
||||||
level: "success",
|
level: "success",
|
||||||
});
|
});
|
||||||
|
await fetchRolesWith({
|
||||||
|
name: filterValues.roleName,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteRoleClick = async (
|
const handleDeleteRoleClick = async (
|
||||||
@@ -244,24 +266,16 @@ const handleDeleteRoleClick = async (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBindPermissionClick = async (
|
|
||||||
role: components["schemas"]["RoleDto"],
|
|
||||||
) => {
|
|
||||||
router.push({
|
|
||||||
name: RouteName.BINDPERMISSIONVIEW,
|
|
||||||
params: { roleId: role.id },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchRolesWith({
|
await fetchRolesWith({
|
||||||
name: roleName.value,
|
name: filterValues.roleName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, pageSize: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchRolesWith(
|
await fetchRolesWith(
|
||||||
{
|
{
|
||||||
name: roleName.value,
|
name: filterValues.roleName,
|
||||||
},
|
},
|
||||||
page,
|
page,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
|||||||
@@ -4,26 +4,10 @@
|
|||||||
<Breadcrumbs :names="['任务管理']" />
|
<Breadcrumbs :names="['任务管理']" />
|
||||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">任务管理</h1>
|
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">任务管理</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
|
||||||
<form class="w-full sm:max-w-xs">
|
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||||
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only">Search</label>
|
@update:values="updateFilterValues">
|
||||||
<div class="relative">
|
</TableFilterForm>
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
|
||||||
<svg class="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
||||||
viewBox="0 0 20 20">
|
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
||||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<input type="search" id="default-search" v-model="jobName"
|
|
||||||
class="block w-full p-3 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
|
|
||||||
placeholder="任务名称" required />
|
|
||||||
<button type="submit"
|
|
||||||
class="text-white absolute end-1.5 bottom-1.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-1.5 sm:px-4 sm:py-2"
|
|
||||||
@click.prevent="handleSearch">搜索</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 移动端卡片布局 -->
|
<!-- 移动端卡片布局 -->
|
||||||
<div class="md:hidden">
|
<div class="md:hidden">
|
||||||
@@ -167,6 +151,8 @@ import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
|||||||
import MobileCardList from "@/components/MobileCardList.vue";
|
import MobileCardList from "@/components/MobileCardList.vue";
|
||||||
import PopupModal from "@/components/PopupModal.vue";
|
import PopupModal from "@/components/PopupModal.vue";
|
||||||
import SchedulerUpdateModal from "@/components/SchedulerUpdateModal.vue";
|
import SchedulerUpdateModal from "@/components/SchedulerUpdateModal.vue";
|
||||||
|
import TableFilterForm from "@/components/TableFilterForm.vue";
|
||||||
|
import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||||
import TablePagination from "@/components/TablePagination.vue";
|
import TablePagination from "@/components/TablePagination.vue";
|
||||||
import { useJobControl } from "@/composables/job/useJobControl";
|
import { useJobControl } from "@/composables/job/useJobControl";
|
||||||
@@ -175,10 +161,34 @@ import { useJobUpdate } from "@/composables/job/useJobUpdate";
|
|||||||
import useAlertStore from "@/composables/store/useAlertStore";
|
import useAlertStore from "@/composables/store/useAlertStore";
|
||||||
import { dayjs } from "@/utils/dateUtil";
|
import { dayjs } from "@/utils/dateUtil";
|
||||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||||
import { nextTick, onMounted, ref } from "vue";
|
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||||
import type { components } from "../api/types/schema";
|
import type { components } from "../api/types/schema";
|
||||||
|
|
||||||
const jobName = ref<string>("");
|
// 定义筛选配置
|
||||||
|
const filterConfig: FilterItem[] = [
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "jobName",
|
||||||
|
placeholder: "任务名称",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 筛选值
|
||||||
|
const filterValues = reactive<{
|
||||||
|
jobName: string;
|
||||||
|
}>({
|
||||||
|
jobName: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新筛选值
|
||||||
|
const updateFilterValues = (
|
||||||
|
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||||
|
) => {
|
||||||
|
if (values.jobName !== undefined) {
|
||||||
|
filterValues.jobName = values.jobName as string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const jobResumeModal = ref<ModalInterface>();
|
const jobResumeModal = ref<ModalInterface>();
|
||||||
const jobPauseModal = ref<ModalInterface>();
|
const jobPauseModal = ref<ModalInterface>();
|
||||||
const jobUpdateModal = ref<ModalInterface>();
|
const jobUpdateModal = ref<ModalInterface>();
|
||||||
@@ -249,7 +259,7 @@ const handleResumeModalSubmit = async () => {
|
|||||||
content: "操作成功",
|
content: "操作成功",
|
||||||
});
|
});
|
||||||
await fetchJobsWith({
|
await fetchJobsWith({
|
||||||
name: jobName.value,
|
name: filterValues.jobName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -265,7 +275,7 @@ const handleUpdateModalSubmit = async (cronExpression: string) => {
|
|||||||
content: "操作成功",
|
content: "操作成功",
|
||||||
});
|
});
|
||||||
await fetchJobsWith({
|
await fetchJobsWith({
|
||||||
name: jobName.value,
|
name: filterValues.jobName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -280,20 +290,20 @@ const handlePauseModalSubmit = async () => {
|
|||||||
content: "操作成功",
|
content: "操作成功",
|
||||||
});
|
});
|
||||||
await fetchJobsWith({
|
await fetchJobsWith({
|
||||||
name: jobName.value,
|
name: filterValues.jobName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
await fetchJobsWith({
|
await fetchJobsWith({
|
||||||
name: jobName.value,
|
name: filterValues.jobName,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageChange = async (page: number, pageSize: number) => {
|
const handlePageChange = async (page: number, pageSize: number) => {
|
||||||
await fetchJobsWith(
|
await fetchJobsWith(
|
||||||
{
|
{
|
||||||
name: jobName.value,
|
name: filterValues.jobName,
|
||||||
},
|
},
|
||||||
page,
|
page,
|
||||||
pageSize,
|
pageSize,
|
||||||
@@ -302,7 +312,7 @@ const handlePageChange = async (page: number, pageSize: number) => {
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchJobsWith({
|
await fetchJobsWith({
|
||||||
name: jobName.value,
|
name: filterValues.jobName,
|
||||||
});
|
});
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
const $jobResumeModalElement: HTMLElement | null =
|
const $jobResumeModalElement: HTMLElement | null =
|
||||||
|
|||||||
Reference in New Issue
Block a user