mirror of
https://github.com/ccmjga/zhilu-admin
synced 2026-03-25 12:53:43 +08:00
重构角色和权限相关DTO,替换RoleDto为RoleRespDto,并更新相关服务和控制器逻辑
This commit is contained in:
@@ -289,7 +289,7 @@
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RoleDto"
|
||||
"$ref": "#/components/schemas/RoleRespDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1031,7 +1031,7 @@
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/PageResponseDtoListRoleDto"
|
||||
"$ref": "#/components/schemas/PageResponseDtoListRoleRespDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1718,6 +1718,12 @@
|
||||
}
|
||||
},
|
||||
"PermissionRespDto": {
|
||||
"required": [
|
||||
"code",
|
||||
"id",
|
||||
"isBound",
|
||||
"name"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -1735,7 +1741,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"RoleDto": {
|
||||
"RoleRespDto": {
|
||||
"required": [
|
||||
"code",
|
||||
"id",
|
||||
"isBound",
|
||||
"name"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -1760,6 +1772,12 @@
|
||||
}
|
||||
},
|
||||
"UserRolePermissionDto": {
|
||||
"required": [
|
||||
"createTime",
|
||||
"enable",
|
||||
"id",
|
||||
"username"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -1782,7 +1800,7 @@
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/RoleDto"
|
||||
"$ref": "#/components/schemas/RoleRespDto"
|
||||
}
|
||||
},
|
||||
"createTime": {
|
||||
@@ -1832,7 +1850,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"PageResponseDtoListRoleDto": {
|
||||
"PageResponseDtoListRoleRespDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": {
|
||||
@@ -1842,7 +1860,7 @@
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/RoleDto"
|
||||
"$ref": "#/components/schemas/RoleRespDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
frontend/src/api/types/schema.d.ts
vendored
36
frontend/src/api/types/schema.d.ts
vendored
@@ -779,29 +779,29 @@ export interface components {
|
||||
};
|
||||
PermissionRespDto: {
|
||||
/** Format: int64 */
|
||||
id?: number;
|
||||
code?: string;
|
||||
name?: string;
|
||||
isBound?: boolean;
|
||||
id: number;
|
||||
code: string;
|
||||
name: string;
|
||||
isBound: boolean;
|
||||
};
|
||||
RoleDto: {
|
||||
RoleRespDto: {
|
||||
/** Format: int64 */
|
||||
id?: number;
|
||||
code?: string;
|
||||
name?: string;
|
||||
isBound?: boolean;
|
||||
id: number;
|
||||
code: string;
|
||||
name: string;
|
||||
isBound: boolean;
|
||||
permissions?: components["schemas"]["PermissionRespDto"][];
|
||||
};
|
||||
UserRolePermissionDto: {
|
||||
/** Format: int64 */
|
||||
id?: number;
|
||||
username?: string;
|
||||
id: number;
|
||||
username: string;
|
||||
password?: string;
|
||||
avatar?: string;
|
||||
enable?: boolean;
|
||||
roles?: components["schemas"]["RoleDto"][];
|
||||
enable: boolean;
|
||||
roles?: components["schemas"]["RoleRespDto"][];
|
||||
/** Format: date-time */
|
||||
createTime?: string;
|
||||
createTime: string;
|
||||
permissions?: components["schemas"]["PermissionRespDto"][];
|
||||
};
|
||||
RoleQueryDto: {
|
||||
@@ -815,10 +815,10 @@ export interface components {
|
||||
/** @enum {string} */
|
||||
bindState?: "BIND" | "UNBIND" | "ALL";
|
||||
};
|
||||
PageResponseDtoListRoleDto: {
|
||||
PageResponseDtoListRoleRespDto: {
|
||||
/** Format: int64 */
|
||||
total?: number;
|
||||
data?: components["schemas"]["RoleDto"][];
|
||||
data?: components["schemas"]["RoleRespDto"][];
|
||||
};
|
||||
PermissionQueryDto: {
|
||||
/** Format: int64 */
|
||||
@@ -1113,7 +1113,7 @@ export interface operations {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": components["schemas"]["RoleDto"];
|
||||
"*/*": components["schemas"]["RoleRespDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1750,7 +1750,7 @@ export interface operations {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": components["schemas"]["PageResponseDtoListRoleDto"];
|
||||
"*/*": components["schemas"]["PageResponseDtoListRoleRespDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
import { getUserAvatarUrl } from "@/utils/avatarUtil";
|
||||
import { computed } from "vue";
|
||||
|
||||
const {
|
||||
src = "",
|
||||
alt = "用户头像",
|
||||
size = "md"
|
||||
const {
|
||||
src = "",
|
||||
alt = "用户头像",
|
||||
size = "md",
|
||||
} = defineProps<{
|
||||
src?: string;
|
||||
alt?: string;
|
||||
@@ -37,7 +37,7 @@ const processedSrc = computed(() => {
|
||||
}
|
||||
if (src === "/trump.jpg") {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
return getUserAvatarUrl(src);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<nav class="flex mb-4" aria-label="Breadcrumb">
|
||||
<ol class="inline-flex items-center space-x-1 sm:space-x-2 text-sm">
|
||||
<li class="inline-flex items-center">
|
||||
<RouterLink :to="{ name: RouteName.HOME }"
|
||||
<RouterLink :to="Routes.HOME.fullPath()"
|
||||
class="inline-flex items-center font-medium text-gray-500 hover:text-blue-600">
|
||||
<svg class="w-3.5 h-3.5 mr-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
|
||||
viewBox="0 0 20 20">
|
||||
@@ -30,7 +30,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { RouteName } from "@/router/constants";
|
||||
import { Routes } from "@/router/constants";
|
||||
import { computed } from "vue";
|
||||
import type { RouteLocationRaw } from "vue-router";
|
||||
|
||||
|
||||
@@ -53,14 +53,14 @@
|
||||
<li>
|
||||
<button @click="() => {
|
||||
userDropDownMenu?.toggle()
|
||||
router.push(`${RoutePath.DASHBOARD}/${RoutePath.SETTINGS}`)
|
||||
router.push(Routes.SETTINGS.fullPath())
|
||||
}" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 "
|
||||
role="menuitem">Settings</button>
|
||||
</li>
|
||||
<li>
|
||||
<button @click="() => {
|
||||
userDropDownMenu?.toggle()
|
||||
router.push(RouteName.USERVIEW)
|
||||
router.push(Routes.USERVIEW.withParams({}))
|
||||
}" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 "
|
||||
role="menuitem">Dashboard</button>
|
||||
</li>
|
||||
@@ -93,7 +93,7 @@ import { Dropdown, type DropdownInterface, initFlowbite } from "flowbite";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import useUserAuth from "../composables/auth/useUserAuth";
|
||||
import { RouteName, RoutePath } from "../router/constants";
|
||||
import { Routes } from "../router/constants";
|
||||
import Avatar from "./Avatar.vue";
|
||||
import AiChatIcon from "./icons/AiChatIcon.vue";
|
||||
|
||||
@@ -113,7 +113,7 @@ const { signOut } = useUserAuth();
|
||||
const router = useRouter();
|
||||
const handleLogoutClick = () => {
|
||||
signOut();
|
||||
router.push(RoutePath.LOGIN);
|
||||
router.push(Routes.LOGIN.path);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -52,7 +52,7 @@ import type { components } from "../api/types/schema";
|
||||
const alertStore = useAlertStore();
|
||||
|
||||
const { role, onSubmit } = defineProps<{
|
||||
role?: components["schemas"]["RoleDto"];
|
||||
role?: components["schemas"]["RoleRespDto"];
|
||||
closeModal: () => void;
|
||||
onSubmit: (data: RoleUpsertModel) => Promise<void>;
|
||||
}>();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { RoutePath } from "@/router/constants";
|
||||
import { Routes } from "@/router/constants";
|
||||
import { initFlowbite } from "flowbite";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { RouterLink, useRoute } from "vue-router";
|
||||
@@ -73,42 +73,42 @@ defineExpose({
|
||||
const menuItems = [
|
||||
{
|
||||
title: "用户管理",
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.USERVIEW}`,
|
||||
path: Routes.USERVIEW.fullPath(),
|
||||
icon: UsersIcon,
|
||||
},
|
||||
{
|
||||
title: "角色管理",
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.ROLEVIEW}`,
|
||||
path: Routes.ROLEVIEW.fullPath(),
|
||||
icon: RoleIcon,
|
||||
},
|
||||
{
|
||||
title: "权限管理",
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.PERMISSIONVIEW}`,
|
||||
path: Routes.PERMISSIONVIEW.fullPath(),
|
||||
icon: PermissionIcon,
|
||||
},
|
||||
{
|
||||
title: "部门管理",
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.DEPARTMENTVIEW}`,
|
||||
path: Routes.DEPARTMENTVIEW.fullPath(),
|
||||
icon: DepartmentIcon,
|
||||
},
|
||||
{
|
||||
title: "岗位管理",
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.POSITIONVIEW}`,
|
||||
path: Routes.POSITIONVIEW.fullPath(),
|
||||
icon: PositionIcon,
|
||||
},
|
||||
{
|
||||
title: "个人中心",
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.SETTINGS}`,
|
||||
path: Routes.SETTINGS.fullPath(),
|
||||
icon: SettingsIcon,
|
||||
},
|
||||
{
|
||||
title: "定时任务",
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.SCHEDULERVIEW}`,
|
||||
path: Routes.SCHEDULERVIEW.fullPath(),
|
||||
icon: SchedulerIcon,
|
||||
},
|
||||
{
|
||||
title: "大模型管理",
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.LLMCONFIGVIEW}`,
|
||||
path: Routes.LLMCONFIGVIEW.fullPath(),
|
||||
icon: LlmConfigIcon,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -4,8 +4,8 @@ import type { components } from "../../api/types/schema";
|
||||
|
||||
export const useRolesQuery = () => {
|
||||
const total = ref<number>(0);
|
||||
const roles = ref<components["schemas"]["RoleDto"][]>();
|
||||
const roleWithDetail = ref<components["schemas"]["RoleDto"]>();
|
||||
const roles = ref<components["schemas"]["RoleRespDto"][]>();
|
||||
const roleWithDetail = ref<components["schemas"]["RoleRespDto"]>();
|
||||
|
||||
const getRoleWithDetail = async (roleId: number) => {
|
||||
const { data } = await client.GET("/iam/role", {
|
||||
|
||||
@@ -1,56 +1,156 @@
|
||||
export enum RoutePath {
|
||||
HOME = "/",
|
||||
LOGIN = "/login",
|
||||
DASHBOARD = "/dashboard",
|
||||
GLOBAL_NOTFOUND = "/:pathMatch(.*)*",
|
||||
NOTFOUND = ":pathMatch(.*)*",
|
||||
OVERVIEW = "overview",
|
||||
USERVIEW = "users",
|
||||
ROLEVIEW = "roles",
|
||||
BINDROLEVIEW = "bind-roles/:userId",
|
||||
BINDPERMISSIONVIEW = "bind-permissions/:roleId",
|
||||
BINDDEPARTMENTVIEW = "bind-departments/:userId",
|
||||
BINDPOSITIONVIEW = "bind-positions/:userId",
|
||||
PERMISSIONVIEW = "permissions",
|
||||
DEPARTMENTVIEW = "departments",
|
||||
POSITIONVIEW = "positions",
|
||||
CREATEUSERVIEW = "create-user",
|
||||
LLMCONFIGVIEW = "llm/config",
|
||||
SCHEDULERVIEW = "scheduler",
|
||||
UPSERTUSERVIEW = "upsert-user",
|
||||
UPSERTROLEVIEW = "upsert-role",
|
||||
UPSERTPERMISSIONVIEW = "upsert-permission",
|
||||
UPSERTDEPARTMENTVIEW = "upsert-department",
|
||||
UPSERTPOSITIONVIEW = "upsert-position",
|
||||
SETTINGS = "settings",
|
||||
}
|
||||
import type { RouteLocationRaw } from "vue-router";
|
||||
|
||||
export enum RouteName {
|
||||
HOME = "home",
|
||||
LOGIN = "login",
|
||||
DASHBOARD = "dashboard",
|
||||
OVERVIEW = "overview",
|
||||
USERVIEW = "users",
|
||||
ROLEVIEW = "roles",
|
||||
BINDROLEVIEW = "bind-roles",
|
||||
BINDPERMISSIONVIEW = "bind-permissions",
|
||||
BINDDEPARTMENTVIEW = "bind-departments",
|
||||
BINDPOSITIONVIEW = "bind-positions",
|
||||
PERMISSIONVIEW = "permissions",
|
||||
DEPARTMENTVIEW = "departments",
|
||||
POSITIONVIEW = "positions",
|
||||
CREATEUSERVIEW = "create-user",
|
||||
LLMCONFIGVIEW = "llm/config",
|
||||
SCHEDULERVIEW = "scheduler",
|
||||
UPSERTUSERVIEW = "upsert-user",
|
||||
UPSERTROLEVIEW = "upsert-role",
|
||||
UPSERTPERMISSIONVIEW = "upsert-permission",
|
||||
UPSERTDEPARTMENTVIEW = "upsert-department",
|
||||
UPSERTPOSITIONVIEW = "upsert-position",
|
||||
SETTINGS = "settings",
|
||||
NOTFOUND = "notfound",
|
||||
GLOBAL_NOTFOUND = "global-notfound",
|
||||
}
|
||||
export type RouteConfig = {
|
||||
path: string;
|
||||
name: string;
|
||||
fullPath: () => string;
|
||||
withParams: <T extends Record<string, string | number>>(
|
||||
params: T,
|
||||
) => RouteLocationRaw;
|
||||
};
|
||||
|
||||
// 基础路由
|
||||
export const BaseRoutes = {
|
||||
HOME: {
|
||||
path: "/",
|
||||
name: "home",
|
||||
fullPath: () => "/",
|
||||
withParams: () => ({ name: "home" }),
|
||||
},
|
||||
LOGIN: {
|
||||
path: "/login",
|
||||
name: "login",
|
||||
fullPath: () => "/login",
|
||||
withParams: () => ({ name: "login" }),
|
||||
},
|
||||
DASHBOARD: {
|
||||
path: "/dashboard",
|
||||
name: "dashboard",
|
||||
fullPath: () => "/dashboard",
|
||||
withParams: () => ({ name: "dashboard" }),
|
||||
},
|
||||
NOTFOUND: {
|
||||
path: ":pathMatch(.*)*",
|
||||
name: "notfound",
|
||||
fullPath: () => "/dashboard/:pathMatch(.*)*",
|
||||
withParams: () => ({ name: "notfound" }),
|
||||
},
|
||||
GLOBAL_NOTFOUND: {
|
||||
path: "/:pathMatch(.*)*",
|
||||
name: "global-notfound",
|
||||
fullPath: () => "/:pathMatch(.*)*",
|
||||
withParams: () => ({ name: "global-notfound" }),
|
||||
},
|
||||
} as const;
|
||||
|
||||
// 仪表盘子路由
|
||||
export const DashboardRoutes = {
|
||||
OVERVIEW: {
|
||||
path: "overview",
|
||||
name: "overview",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/overview`,
|
||||
withParams: () => ({ name: "overview" }),
|
||||
},
|
||||
SETTINGS: {
|
||||
path: "settings",
|
||||
name: "settings",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/settings`,
|
||||
withParams: () => ({ name: "settings" }),
|
||||
},
|
||||
} as const;
|
||||
|
||||
// 用户管理相关路由
|
||||
export const UserRoutes = {
|
||||
USERVIEW: {
|
||||
path: "users",
|
||||
name: "users",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/users`,
|
||||
withParams: () => ({ name: "users" }),
|
||||
},
|
||||
ROLEVIEW: {
|
||||
path: "roles",
|
||||
name: "roles",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/roles`,
|
||||
withParams: () => ({ name: "roles" }),
|
||||
},
|
||||
BINDROLEVIEW: {
|
||||
path: "bind-roles/:userId",
|
||||
name: "bind-roles",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/bind-roles/:userId`,
|
||||
withParams: <T extends { userId: string | number }>(params: T) => ({
|
||||
name: "bind-roles",
|
||||
params: { userId: params.userId.toString() },
|
||||
}),
|
||||
},
|
||||
BINDPERMISSIONVIEW: {
|
||||
path: "bind-permissions/:roleId",
|
||||
name: "bind-permissions",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/bind-permissions/:roleId`,
|
||||
withParams: <T extends { roleId: string | number }>(params: T) => ({
|
||||
name: "bind-permissions",
|
||||
params: { roleId: params.roleId.toString() },
|
||||
}),
|
||||
},
|
||||
BINDDEPARTMENTVIEW: {
|
||||
path: "bind-departments/:userId",
|
||||
name: "bind-departments",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/bind-departments/:userId`,
|
||||
withParams: <T extends { userId: string | number }>(params: T) => ({
|
||||
name: "bind-departments",
|
||||
params: { userId: params.userId.toString() },
|
||||
}),
|
||||
},
|
||||
BINDPOSITIONVIEW: {
|
||||
path: "bind-positions/:userId",
|
||||
name: "bind-positions",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/bind-positions/:userId`,
|
||||
withParams: <T extends { userId: string | number }>(params: T) => ({
|
||||
name: "bind-positions",
|
||||
params: { userId: params.userId.toString() },
|
||||
}),
|
||||
},
|
||||
PERMISSIONVIEW: {
|
||||
path: "permissions",
|
||||
name: "permissions",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/permissions`,
|
||||
withParams: () => ({ name: "permissions" }),
|
||||
},
|
||||
DEPARTMENTVIEW: {
|
||||
path: "departments",
|
||||
name: "departments",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/departments`,
|
||||
withParams: () => ({ name: "departments" }),
|
||||
},
|
||||
POSITIONVIEW: {
|
||||
path: "positions",
|
||||
name: "positions",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/positions`,
|
||||
withParams: () => ({ name: "positions" }),
|
||||
},
|
||||
} as const;
|
||||
|
||||
// AI相关路由
|
||||
export const AiRoutes = {
|
||||
LLMCONFIGVIEW: {
|
||||
path: "llm/config",
|
||||
name: "llm/config",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/llm/config`,
|
||||
withParams: () => ({ name: "llm/config" }),
|
||||
},
|
||||
SCHEDULERVIEW: {
|
||||
path: "scheduler",
|
||||
name: "scheduler",
|
||||
fullPath: () => `${BaseRoutes.DASHBOARD.path}/scheduler`,
|
||||
withParams: () => ({ name: "scheduler" }),
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const Routes = {
|
||||
...BaseRoutes,
|
||||
...DashboardRoutes,
|
||||
...UserRoutes,
|
||||
...AiRoutes,
|
||||
} as const;
|
||||
|
||||
export enum ERole {
|
||||
ADMIN = "ADMIN",
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import useAlertStore from "@/composables/store/useAlertStore";
|
||||
import useUserStore from "@/composables/store/useUserStore";
|
||||
import type { NavigationGuard, Router } from "vue-router";
|
||||
import type { RouteMeta } from "../types/router";
|
||||
import { RoutePath } from "./constants";
|
||||
import useAlertStore from "@/composables/store/useAlertStore";
|
||||
import { Routes } from "./constants";
|
||||
|
||||
export const authGuard: NavigationGuard = (to) => {
|
||||
const userStore = useUserStore();
|
||||
if (to.meta.requiresAuth && !userStore.user) {
|
||||
return {
|
||||
path: RoutePath.LOGIN,
|
||||
path: Routes.LOGIN.path,
|
||||
query: { redirect: to.fullPath },
|
||||
};
|
||||
}
|
||||
if (to.path === RoutePath.LOGIN && userStore.user) {
|
||||
return { path: `${RoutePath.DASHBOARD}/${RoutePath.USERVIEW}` };
|
||||
if (to.path === Routes.LOGIN.path && userStore.user) {
|
||||
return { path: `${Routes.DASHBOARD.path}/${Routes.USERVIEW.path}` };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,20 +2,20 @@ import { createRouter, createWebHistory } from "vue-router";
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import { setupGuards } from "./guards";
|
||||
|
||||
import { Routes } from "./constants";
|
||||
import authRoutes from "./modules/auth";
|
||||
import dashboardRoutes from "./modules/dashboard";
|
||||
import errorRoutes from "./modules/error";
|
||||
import { RouteName, RoutePath } from "./constants";
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
dashboardRoutes,
|
||||
...authRoutes,
|
||||
...errorRoutes,
|
||||
{
|
||||
path: RoutePath.HOME,
|
||||
name: RouteName.HOME,
|
||||
path: Routes.HOME.path,
|
||||
name: Routes.HOME.name,
|
||||
redirect: {
|
||||
path: `${RoutePath.DASHBOARD}/${RoutePath.USERVIEW}`,
|
||||
path: `${Routes.DASHBOARD.path}/${Routes.USERVIEW.path}`,
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -27,7 +27,7 @@ const router = createRouter({
|
||||
|
||||
router.onError((err) => {
|
||||
console.error("router err:", err);
|
||||
router.push(RouteName.USERVIEW);
|
||||
router.push(Routes.USERVIEW.name);
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import { EPermission, RouteName, RoutePath } from "../constants";
|
||||
import { EPermission, Routes } from "../constants";
|
||||
|
||||
const aiRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: RoutePath.LLMCONFIGVIEW,
|
||||
name: RouteName.LLMCONFIGVIEW,
|
||||
path: Routes.LLMCONFIGVIEW.path,
|
||||
name: Routes.LLMCONFIGVIEW.name,
|
||||
component: () => import("@/views/LlmConfigView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import { RouteName, RoutePath } from "../constants";
|
||||
import { Routes } from "../constants";
|
||||
|
||||
const authRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: RoutePath.HOME,
|
||||
name: RouteName.HOME,
|
||||
path: Routes.HOME.path,
|
||||
name: Routes.HOME.name,
|
||||
redirect: {
|
||||
name: RouteName.LOGIN,
|
||||
name: Routes.LOGIN.name,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.LOGIN,
|
||||
name: RouteName.LOGIN,
|
||||
path: Routes.LOGIN.path,
|
||||
name: Routes.LOGIN.name,
|
||||
component: () => import("../../views/LoginView.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import Dashboard from "../../components/Dashboard.vue";
|
||||
import { EPermission, ERole, RouteName, RoutePath } from "../constants";
|
||||
import userManagementRoutes from "./user";
|
||||
import { EPermission, ERole, Routes } from "../constants";
|
||||
import aiRoutes from "./ai";
|
||||
import userManagementRoutes from "./user";
|
||||
|
||||
const dashboardRoutes: RouteRecordRaw = {
|
||||
path: RoutePath.DASHBOARD,
|
||||
name: RouteName.DASHBOARD,
|
||||
path: Routes.DASHBOARD.path,
|
||||
name: Routes.DASHBOARD.name,
|
||||
component: Dashboard,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: RoutePath.OVERVIEW,
|
||||
name: RouteName.OVERVIEW,
|
||||
path: Routes.OVERVIEW.path,
|
||||
name: Routes.OVERVIEW.name,
|
||||
component: () => import("@/views/OverView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.SETTINGS,
|
||||
name: RouteName.SETTINGS,
|
||||
path: Routes.SETTINGS.path,
|
||||
name: Routes.SETTINGS.name,
|
||||
component: () => import("@/views/SettingsView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -31,13 +31,13 @@ const dashboardRoutes: RouteRecordRaw = {
|
||||
...userManagementRoutes,
|
||||
...aiRoutes,
|
||||
{
|
||||
path: RoutePath.NOTFOUND,
|
||||
name: RouteName.NOTFOUND,
|
||||
path: Routes.NOTFOUND.path,
|
||||
name: Routes.NOTFOUND.name,
|
||||
component: () => import("@/views/NotFound.vue"),
|
||||
},
|
||||
{
|
||||
path: RoutePath.SCHEDULERVIEW,
|
||||
name: RouteName.SCHEDULERVIEW,
|
||||
path: Routes.SCHEDULERVIEW.path,
|
||||
name: Routes.SCHEDULERVIEW.name,
|
||||
component: () => import("@/views/SchedulerView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -45,8 +45,8 @@ const dashboardRoutes: RouteRecordRaw = {
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.DEPARTMENTVIEW,
|
||||
name: RouteName.DEPARTMENTVIEW,
|
||||
path: Routes.DEPARTMENTVIEW.path,
|
||||
name: Routes.DEPARTMENTVIEW.name,
|
||||
component: () => import("@/views/DepartmentView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -54,8 +54,8 @@ const dashboardRoutes: RouteRecordRaw = {
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.POSITIONVIEW,
|
||||
name: RouteName.POSITIONVIEW,
|
||||
path: Routes.POSITIONVIEW.path,
|
||||
name: Routes.POSITIONVIEW.name,
|
||||
component: () => import("@/views/PositionView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import { RouteName, RoutePath } from "../constants";
|
||||
import { Routes } from "../constants";
|
||||
|
||||
const errorRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: RoutePath.GLOBAL_NOTFOUND,
|
||||
name: RouteName.GLOBAL_NOTFOUND,
|
||||
path: Routes.GLOBAL_NOTFOUND.path,
|
||||
name: Routes.GLOBAL_NOTFOUND.name,
|
||||
component: () => import("../../views/NotFound.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import { EPermission, RouteName, RoutePath } from "../constants";
|
||||
import { EPermission, Routes } from "../constants";
|
||||
|
||||
const userManagementRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: RoutePath.USERVIEW,
|
||||
name: RouteName.USERVIEW,
|
||||
path: Routes.USERVIEW.path,
|
||||
name: Routes.USERVIEW.name,
|
||||
component: () => import("@/views/UserView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -12,8 +12,8 @@ const userManagementRoutes: RouteRecordRaw[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.ROLEVIEW,
|
||||
name: RouteName.ROLEVIEW,
|
||||
path: Routes.ROLEVIEW.path,
|
||||
name: Routes.ROLEVIEW.name,
|
||||
component: () => import("@/views/RoleView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -21,8 +21,8 @@ const userManagementRoutes: RouteRecordRaw[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.BINDROLEVIEW,
|
||||
name: RouteName.BINDROLEVIEW,
|
||||
path: Routes.BINDROLEVIEW.path,
|
||||
name: Routes.BINDROLEVIEW.name,
|
||||
component: () => import("@/views/BindRoleView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -30,8 +30,8 @@ const userManagementRoutes: RouteRecordRaw[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.BINDDEPARTMENTVIEW,
|
||||
name: RouteName.BINDDEPARTMENTVIEW,
|
||||
path: Routes.BINDDEPARTMENTVIEW.path,
|
||||
name: Routes.BINDDEPARTMENTVIEW.name,
|
||||
component: () => import("@/views/BindDepartmentView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -39,8 +39,8 @@ const userManagementRoutes: RouteRecordRaw[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.BINDPERMISSIONVIEW,
|
||||
name: RouteName.BINDPERMISSIONVIEW,
|
||||
path: Routes.BINDPERMISSIONVIEW.path,
|
||||
name: Routes.BINDPERMISSIONVIEW.name,
|
||||
component: () => import("@/views/BindPermissionView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -48,8 +48,8 @@ const userManagementRoutes: RouteRecordRaw[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.PERMISSIONVIEW,
|
||||
name: RouteName.PERMISSIONVIEW,
|
||||
path: Routes.PERMISSIONVIEW.path,
|
||||
name: Routes.PERMISSIONVIEW.name,
|
||||
component: () => import("@/views/PermissionView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
@@ -57,8 +57,8 @@ const userManagementRoutes: RouteRecordRaw[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: RoutePath.BINDPOSITIONVIEW,
|
||||
name: RouteName.BINDPOSITIONVIEW,
|
||||
path: Routes.BINDPOSITIONVIEW.path,
|
||||
name: Routes.BINDPOSITIONVIEW.name,
|
||||
component: () => import("@/views/BindPositionView.vue"),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { ComponentPublicInstance } from "vue";
|
||||
import type { Router } from "vue-router";
|
||||
import { RoutePath } from "../router/constants";
|
||||
import {
|
||||
ForbiddenError,
|
||||
InternalServerError,
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
UnAuthError,
|
||||
} from "../types/error";
|
||||
import { z } from "zod";
|
||||
import { Routes } from "../router/constants";
|
||||
|
||||
const makeErrorHandler =
|
||||
(
|
||||
@@ -31,7 +31,7 @@ const makeErrorHandler =
|
||||
});
|
||||
} else if (err instanceof UnAuthError) {
|
||||
signOut();
|
||||
router.push(RoutePath.LOGIN);
|
||||
router.push(Routes.LOGIN.path);
|
||||
showAlert({
|
||||
level: "error",
|
||||
content: err.message,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
||||
<div class="mb-4 sm:mb-6 col-span-full">
|
||||
<Breadcrumbs :names="['用户管理', '绑定部门']" :routes="[{ name: RouteName.USERVIEW }]" />
|
||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定部门</h1>
|
||||
</div>
|
||||
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
||||
<div class="mb-4 sm:mb-6 col-span-full">
|
||||
<Breadcrumbs :names="['用户管理', '绑定部门']" :routes="[Routes.USERVIEW.fullPath()]" />
|
||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定部门</h1>
|
||||
</div>
|
||||
|
||||
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||
@update:values="updateFilterValues">
|
||||
<template #actions>
|
||||
<div class="flex gap-x-2">
|
||||
<TableButton variant="primary" @click="() => {
|
||||
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||
@update:values="updateFilterValues">
|
||||
<template #actions>
|
||||
<div class="flex gap-x-2">
|
||||
<TableButton variant="primary" @click="() => {
|
||||
if (checkedDepartmentIds.length === 0) {
|
||||
alertStore.showAlert({
|
||||
content: '没有选择部门',
|
||||
@@ -19,9 +19,9 @@
|
||||
departmentBindModal?.show();
|
||||
}
|
||||
}">
|
||||
绑定
|
||||
</TableButton>
|
||||
<TableButton variant="danger" @click="() => {
|
||||
绑定
|
||||
</TableButton>
|
||||
<TableButton variant="danger" @click="() => {
|
||||
if (checkedDepartmentIds.length === 0) {
|
||||
alertStore.showAlert({
|
||||
content: '没有选择部门',
|
||||
@@ -31,59 +31,59 @@
|
||||
departmentUnbindModal?.show();
|
||||
}
|
||||
}">
|
||||
解绑
|
||||
</TableButton>
|
||||
</div>
|
||||
</template>
|
||||
</TableFilterForm>
|
||||
解绑
|
||||
</TableButton>
|
||||
</div>
|
||||
</template>
|
||||
</TableFilterForm>
|
||||
|
||||
<!-- 移动端卡片布局 -->
|
||||
<div class="md:hidden space-y-4">
|
||||
<MobileCardListWithCheckbox :items="departments || []" v-model="checkedDepartmentIds">
|
||||
<template #title="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #status="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
<span class="text-sm">{{ item.isBound === true ? "已绑定" : "未绑定" }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #content="{ item }">
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-600">上级部门</p>
|
||||
<p class="text-sm text-gray-900 mt-0.5">{{ !item.parentName ? '无' : item.parentName }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</MobileCardListWithCheckbox>
|
||||
</div>
|
||||
<!-- 移动端卡片布局 -->
|
||||
<div class="md:hidden space-y-4">
|
||||
<MobileCardListWithCheckbox :items="departments || []" v-model="checkedDepartmentIds">
|
||||
<template #title="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #status="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
<span class="text-sm">{{ item.isBound === true ? "已绑定" : "未绑定" }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #content="{ item }">
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-600">上级部门</p>
|
||||
<p class="text-sm text-gray-900 mt-0.5">{{ !item.parentName ? '无' : item.parentName }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</MobileCardListWithCheckbox>
|
||||
</div>
|
||||
|
||||
<!-- PC端表格布局 -->
|
||||
<div class="hidden md:block">
|
||||
<TableFormLayout :items="departments || []" :columns="columns" :hasCheckbox="true" v-model="checkedDepartmentIds"
|
||||
@all-checked-change="allChecked = $event">
|
||||
<template #parentName="{ item }">
|
||||
{{ !item.parentName ? '无' : item.parentName }}
|
||||
</template>
|
||||
<template #name="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #bindState="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
{{ item.isBound === true ? "已绑定" : "未绑定" }}
|
||||
</div>
|
||||
</template>
|
||||
</TableFormLayout>
|
||||
</div>
|
||||
<TablePagination :pageChange="handlePageChange" :total="total" />
|
||||
<BindModal :id="'department-bind-modal'" :closeModal="() => {
|
||||
<!-- PC端表格布局 -->
|
||||
<div class="hidden md:block">
|
||||
<TableFormLayout :items="departments || []" :columns="columns" :hasCheckbox="true" v-model="checkedDepartmentIds"
|
||||
@all-checked-change="allChecked = $event">
|
||||
<template #parentName="{ item }">
|
||||
{{ !item.parentName ? '无' : item.parentName }}
|
||||
</template>
|
||||
<template #name="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #bindState="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
{{ item.isBound === true ? "已绑定" : "未绑定" }}
|
||||
</div>
|
||||
</template>
|
||||
</TableFormLayout>
|
||||
</div>
|
||||
<TablePagination :pageChange="handlePageChange" :total="total" />
|
||||
<BindModal :id="'department-bind-modal'" :closeModal="() => {
|
||||
departmentBindModal!.hide();
|
||||
}" :onSubmit="handleBindDepartmentSubmit" title="绑定选中的部门吗"></BindModal>
|
||||
<UnModal :id="'department-unbind-modal'" :closeModal="() => {
|
||||
<UnModal :id="'department-unbind-modal'" :closeModal="() => {
|
||||
departmentUnbindModal!.hide();
|
||||
}" :onSubmit="handleUnbindDepartmentSubmit" title="解绑选中的部门吗"></UnModal>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@@ -99,7 +99,7 @@ import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||
import TablePagination from "@/components/TablePagination.vue";
|
||||
import { useDepartmentQuery } from "@/composables/department/useDepartmentQuery";
|
||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||
import { RouteName } from "@/router/constants";
|
||||
import { Routes } from "@/router/constants";
|
||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||
import { onMounted, reactive, ref, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
||||
<div class="mb-4 sm:mb-6 col-span-full">
|
||||
<Breadcrumbs :names="['角色管理', '绑定权限']" :routes="[{ name: RouteName.ROLEVIEW }]" />
|
||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定权限</h1>
|
||||
</div>
|
||||
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
||||
<div class="mb-4 sm:mb-6 col-span-full">
|
||||
<Breadcrumbs :names="['角色管理', '绑定权限']" :routes="[Routes.ROLEVIEW.fullPath()]" />
|
||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定权限</h1>
|
||||
</div>
|
||||
|
||||
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||
@update:values="updateFilterValues">
|
||||
<template #actions>
|
||||
<div class="flex gap-x-2">
|
||||
<TableButton variant="primary" @click="() => {
|
||||
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||
@update:values="updateFilterValues">
|
||||
<template #actions>
|
||||
<div class="flex gap-x-2">
|
||||
<TableButton variant="primary" @click="() => {
|
||||
if (checkedPermissionIds.length === 0) {
|
||||
alertStore.showAlert({
|
||||
content: '没有选择权限',
|
||||
@@ -19,9 +19,9 @@
|
||||
permissionBindModal?.show();
|
||||
}
|
||||
}">
|
||||
绑定
|
||||
</TableButton>
|
||||
<TableButton variant="danger" @click="() => {
|
||||
绑定
|
||||
</TableButton>
|
||||
<TableButton variant="danger" @click="() => {
|
||||
if (checkedPermissionIds.length === 0) {
|
||||
alertStore.showAlert({
|
||||
content: '没有选择权限',
|
||||
@@ -31,59 +31,59 @@
|
||||
permissionUnbindModal?.show();
|
||||
}
|
||||
}">
|
||||
解绑
|
||||
</TableButton>
|
||||
</div>
|
||||
</template>
|
||||
</TableFilterForm>
|
||||
解绑
|
||||
</TableButton>
|
||||
</div>
|
||||
</template>
|
||||
</TableFilterForm>
|
||||
|
||||
<!-- 移动端卡片布局 -->
|
||||
<div class="md:hidden space-y-4">
|
||||
<MobileCardListWithCheckbox :items="permissions || []" v-model="checkedPermissionIds">
|
||||
<template #title="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #status="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
<span class="text-sm">{{ item.isBound === true ? "已绑定" : "未绑定" }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #content="{ item }">
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-600">权限编码</p>
|
||||
<p class="text-sm text-gray-900 mt-0.5">{{ item.code }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</MobileCardListWithCheckbox>
|
||||
</div>
|
||||
<!-- 移动端卡片布局 -->
|
||||
<div class="md:hidden space-y-4">
|
||||
<MobileCardListWithCheckbox :items="permissions || []" v-model="checkedPermissionIds">
|
||||
<template #title="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #status="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
<span class="text-sm">{{ item.isBound === true ? "已绑定" : "未绑定" }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #content="{ item }">
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-600">权限编码</p>
|
||||
<p class="text-sm text-gray-900 mt-0.5">{{ item.code }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</MobileCardListWithCheckbox>
|
||||
</div>
|
||||
|
||||
<!-- PC端表格布局 -->
|
||||
<div class="hidden md:block">
|
||||
<TableFormLayout :items="permissions || []" :columns="columns" :hasCheckbox="true" v-model="checkedPermissionIds"
|
||||
@all-checked-change="allChecked = $event">
|
||||
<template #code="{ item }">
|
||||
{{ item.code }}
|
||||
</template>
|
||||
<template #name="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #bindState="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
{{ item.isBound === true ? "已绑定" : "未绑定" }}
|
||||
</div>
|
||||
</template>
|
||||
</TableFormLayout>
|
||||
</div>
|
||||
<!-- PC端表格布局 -->
|
||||
<div class="hidden md:block">
|
||||
<TableFormLayout :items="permissions || []" :columns="columns" :hasCheckbox="true" v-model="checkedPermissionIds"
|
||||
@all-checked-change="allChecked = $event">
|
||||
<template #code="{ item }">
|
||||
{{ item.code }}
|
||||
</template>
|
||||
<template #name="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #bindState="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
{{ item.isBound === true ? "已绑定" : "未绑定" }}
|
||||
</div>
|
||||
</template>
|
||||
</TableFormLayout>
|
||||
</div>
|
||||
|
||||
<TablePagination :pageChange="handlePageChange" :total="total" />
|
||||
</div>
|
||||
<TablePagination :pageChange="handlePageChange" :total="total" />
|
||||
</div>
|
||||
|
||||
<BindModal :id="'permission-bind-modal'" :closeModal="() => {
|
||||
<BindModal :id="'permission-bind-modal'" :closeModal="() => {
|
||||
permissionBindModal!.hide();
|
||||
}" :onSubmit="handleBindPermissionSubmit" title="确定绑定选中的权限吗"></BindModal>
|
||||
<UnModal :id="'permission-unbind-modal'" :closeModal="() => {
|
||||
<UnModal :id="'permission-unbind-modal'" :closeModal="() => {
|
||||
permissionUnbindModal!.hide();
|
||||
}" :onSubmit="handleUnbindPermissionSubmit" title="确定解绑选中的权限吗"></UnModal>
|
||||
</template>
|
||||
@@ -99,7 +99,7 @@ import type { FilterItem } from "@/components/TableFilterForm.vue";
|
||||
import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||
import TablePagination from "@/components/TablePagination.vue";
|
||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||
import { RouteName } from "@/router/constants";
|
||||
import { Routes } from "@/router/constants";
|
||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||
import { onMounted, reactive, ref, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
||||
<div class="mb-4 sm:mb-6 col-span-full">
|
||||
<Breadcrumbs :names="['用户管理', '绑定岗位']" :routes="[{ name: RouteName.USERVIEW }]" />
|
||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定岗位</h1>
|
||||
</div>
|
||||
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
||||
<div class="mb-4 sm:mb-6 col-span-full">
|
||||
<Breadcrumbs :names="['用户管理', '绑定岗位']" :routes="[Routes.USERVIEW.fullPath()]" />
|
||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">绑定岗位</h1>
|
||||
</div>
|
||||
|
||||
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||
@update:values="updateFilterValues">
|
||||
<template #actions>
|
||||
<div class="flex gap-x-2">
|
||||
<TableButton variant="primary" @click="() => {
|
||||
<TableFilterForm :filters="filterConfig" :initialValues="filterValues" @search="handleSearch"
|
||||
@update:values="updateFilterValues">
|
||||
<template #actions>
|
||||
<div class="flex gap-x-2">
|
||||
<TableButton variant="primary" @click="() => {
|
||||
if (checkedPositionIds.length === 0) {
|
||||
alertStore.showAlert({
|
||||
content: '没有选择岗位',
|
||||
@@ -19,9 +19,9 @@
|
||||
positionBindModal?.show();
|
||||
}
|
||||
}">
|
||||
绑定
|
||||
</TableButton>
|
||||
<TableButton variant="danger" @click="() => {
|
||||
绑定
|
||||
</TableButton>
|
||||
<TableButton variant="danger" @click="() => {
|
||||
if (checkedPositionIds.length === 0) {
|
||||
alertStore.showAlert({
|
||||
content: '没有选择岗位',
|
||||
@@ -31,50 +31,50 @@
|
||||
positionUnbindModal?.show();
|
||||
}
|
||||
}">
|
||||
解绑
|
||||
</TableButton>
|
||||
</div>
|
||||
</template>
|
||||
</TableFilterForm>
|
||||
解绑
|
||||
</TableButton>
|
||||
</div>
|
||||
</template>
|
||||
</TableFilterForm>
|
||||
|
||||
<!-- 移动端卡片布局 -->
|
||||
<div class="md:hidden space-y-4">
|
||||
<MobileCardListWithCheckbox :items="positions || []" v-model="checkedPositionIds">
|
||||
<template #title="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #status="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
<span class="text-sm">{{ item.isBound === true ? "已绑定" : "未绑定" }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</MobileCardListWithCheckbox>
|
||||
</div>
|
||||
<!-- 移动端卡片布局 -->
|
||||
<div class="md:hidden space-y-4">
|
||||
<MobileCardListWithCheckbox :items="positions || []" v-model="checkedPositionIds">
|
||||
<template #title="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #status="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
<span class="text-sm">{{ item.isBound === true ? "已绑定" : "未绑定" }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</MobileCardListWithCheckbox>
|
||||
</div>
|
||||
|
||||
<!-- PC端表格布局 -->
|
||||
<div class="hidden md:block">
|
||||
<TableFormLayout :items="positions || []" :columns="columns" :hasCheckbox="true" v-model="checkedPositionIds"
|
||||
@all-checked-change="allChecked = $event">
|
||||
<template #name="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #bindState="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
{{ item.isBound === true ? "已绑定" : "未绑定" }}
|
||||
</div>
|
||||
</template>
|
||||
</TableFormLayout>
|
||||
</div>
|
||||
<!-- PC端表格布局 -->
|
||||
<div class="hidden md:block">
|
||||
<TableFormLayout :items="positions || []" :columns="columns" :hasCheckbox="true" v-model="checkedPositionIds"
|
||||
@all-checked-change="allChecked = $event">
|
||||
<template #name="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
<template #bindState="{ item }">
|
||||
<div class="flex items-center">
|
||||
<div class="h-2.5 w-2.5 rounded-full me-2" :class="item.isBound ? 'bg-green-500' : 'bg-red-500'"></div>
|
||||
{{ item.isBound === true ? "已绑定" : "未绑定" }}
|
||||
</div>
|
||||
</template>
|
||||
</TableFormLayout>
|
||||
</div>
|
||||
|
||||
<TablePagination :pageChange="handlePageChange" :total="total" />
|
||||
</div>
|
||||
<TablePagination :pageChange="handlePageChange" :total="total" />
|
||||
</div>
|
||||
|
||||
<BindModal :id="'position-bind-modal'" :closeModal="() => {
|
||||
<BindModal :id="'position-bind-modal'" :closeModal="() => {
|
||||
positionBindModal!.hide();
|
||||
}" :onSubmit="handleBindPositionSubmit" title="绑定选中的岗位吗"></BindModal>
|
||||
<UnModal :id="'position-unbind-modal'" :closeModal="() => {
|
||||
<UnModal :id="'position-unbind-modal'" :closeModal="() => {
|
||||
positionUnbindModal!.hide();
|
||||
}" :onSubmit="handleUnbindPositionSubmit" title="解绑选中的岗位吗"></UnModal>
|
||||
</template>
|
||||
@@ -93,7 +93,7 @@ import { usePositionBind } from "@/composables/position/usePositionBind";
|
||||
import { usePositionQuery } from "@/composables/position/usePositionQuery";
|
||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||
import { useMobileStyles } from "@/composables/useMobileStyles";
|
||||
import { RouteName } from "@/router/constants";
|
||||
import { Routes } from "@/router/constants";
|
||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||
import { onMounted, reactive, ref, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
|
||||
<div class="mb-4 sm:mb-6 col-span-full">
|
||||
<Breadcrumbs :names="['用户管理', '角色分配']" :routes="[{ name: RouteName.USERVIEW }]" />
|
||||
<Breadcrumbs :names="['用户管理', '角色分配']" :routes="[Routes.USERVIEW.fullPath()]" />
|
||||
<h1 class="text-xl sm:text-2xl mb-4 sm:mb-6 font-semibold text-gray-900">角色分配</h1>
|
||||
</div>
|
||||
|
||||
@@ -101,7 +101,7 @@ import TableFormLayout from "@/components/TableFormLayout.vue";
|
||||
import TablePagination from "@/components/TablePagination.vue";
|
||||
import { useRolesQuery } from "@/composables/role/useRolesQuery";
|
||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||
import { RouteName } from "@/router/constants";
|
||||
import { Routes } from "@/router/constants";
|
||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
@@ -33,7 +33,7 @@ import { useRoute, useRouter } from "vue-router";
|
||||
import { z } from "zod";
|
||||
import useUserAuth from "../composables/auth/useUserAuth";
|
||||
import useAlertStore from "../composables/store/useAlertStore";
|
||||
import { RoutePath } from "../router/constants";
|
||||
import { Routes } from "../router/constants";
|
||||
|
||||
const username = ref("admin");
|
||||
const password = ref("admin");
|
||||
@@ -58,8 +58,7 @@ const handleLogin = async () => {
|
||||
content: "登录成功",
|
||||
});
|
||||
const redirectPath =
|
||||
(route.query.redirect as string) ||
|
||||
`${RoutePath.DASHBOARD}/${RoutePath.USERVIEW}`;
|
||||
(route.query.redirect as string) || Routes.USERVIEW.fullPath();
|
||||
router.push(redirectPath);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { RoutePath } from "../router/constants";
|
||||
import { Routes } from "../router/constants";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -10,7 +10,7 @@ import { RoutePath } from "../router/constants";
|
||||
found</h1>
|
||||
<p class="mt-6 text-base sm:text-lg font-medium text-pretty text-gray-500">您访问的资源未找到,请点击浏览器后退按钮返回</p>
|
||||
<div class="mt-10 flex items-center justify-center gap-x-6">
|
||||
<RouterLink :to="`${RoutePath.DASHBOARD}/${RoutePath.OVERVIEW}`"
|
||||
<RouterLink :to="Routes.OVERVIEW.fullPath()"
|
||||
class="rounded-md px-3.5 py-2.5 text-sm font-semibold bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 text-white shadow-xs focus-visible:outline-2 focus-visible:outline-offset-2">
|
||||
回到主页</RouterLink>
|
||||
<a href="#" class="text-sm font-semibold text-gray-900">联系我们<span aria-hidden="true">→</span></a>
|
||||
|
||||
@@ -135,7 +135,7 @@ import PlusIcon from "@/components/icons/PlusIcon.vue";
|
||||
import useRoleDelete from "@/composables/role/useRoleDelete";
|
||||
import { useRolesQuery } from "@/composables/role/useRolesQuery";
|
||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||
import { RouteName } from "@/router/constants";
|
||||
import { Routes } from "@/router/constants";
|
||||
import type { RoleUpsertModel } from "@/types/role";
|
||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||
@@ -169,7 +169,7 @@ const updateFilterValues = (
|
||||
}
|
||||
};
|
||||
|
||||
const selectedRole = ref<components["schemas"]["RoleDto"]>();
|
||||
const selectedRole = ref<components["schemas"]["RoleRespDto"]>();
|
||||
const roleUpsertModal = ref<ModalInterface>();
|
||||
const roleDeleteModal = ref<ModalInterface>();
|
||||
const actionExcStore = useActionExcStore();
|
||||
@@ -223,7 +223,7 @@ const handleUpsertModalSubmit = async (data: RoleUpsertModel) => {
|
||||
};
|
||||
|
||||
const handleUpsertRoleClick = async (
|
||||
role?: components["schemas"]["RoleDto"],
|
||||
role?: components["schemas"]["RoleRespDto"],
|
||||
) => {
|
||||
selectedRole.value = role;
|
||||
await nextTick(() => {
|
||||
@@ -232,14 +232,13 @@ const handleUpsertRoleClick = async (
|
||||
};
|
||||
|
||||
const handleBindPermissionClick = async (
|
||||
role: components["schemas"]["RoleDto"],
|
||||
role: components["schemas"]["RoleRespDto"],
|
||||
) => {
|
||||
router.push({
|
||||
name: RouteName.BINDPERMISSIONVIEW,
|
||||
params: {
|
||||
roleId: role.id,
|
||||
},
|
||||
});
|
||||
router.push(
|
||||
Routes.BINDPERMISSIONVIEW.withParams({
|
||||
roleId: role.id!,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleDeletedModalSubmit = async () => {
|
||||
@@ -256,7 +255,7 @@ const handleDeletedModalSubmit = async () => {
|
||||
};
|
||||
|
||||
const handleDeleteRoleClick = async (
|
||||
role: components["schemas"]["RoleDto"],
|
||||
role: components["schemas"]["RoleRespDto"],
|
||||
) => {
|
||||
selectedRole.value = role;
|
||||
await nextTick(() => {
|
||||
|
||||
@@ -52,14 +52,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
||||
import useUserAuth from "@/composables/auth/useUserAuth";
|
||||
import useUserStore from "@/composables/store/useUserStore";
|
||||
import { initFlowbite } from "flowbite";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { z } from "zod";
|
||||
import useAlertStore from "../composables/store/useAlertStore";
|
||||
import { RouteName } from "../router/constants";
|
||||
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
||||
import { Routes } from "../router/constants";
|
||||
|
||||
const { user } = useUserStore();
|
||||
const { upsertCurrentUser } = useUserAuth();
|
||||
|
||||
@@ -174,7 +174,7 @@ import { useSort } from "@/composables/sort";
|
||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||
import useUserDelete from "@/composables/user/useUserDelete";
|
||||
import { useUserQuery } from "@/composables/user/useUserQuery";
|
||||
import { RouteName } from "@/router/constants";
|
||||
import { Routes } from "@/router/constants";
|
||||
import type { UserUpsertSubmitModel } from "@/types/user";
|
||||
import { dayjs, formatDate } from "@/utils/dateUtil";
|
||||
import { Modal, type ModalInterface, initFlowbite } from "flowbite";
|
||||
@@ -289,34 +289,31 @@ const handleUpsertUserClick = async (
|
||||
const handleBindRoleClick = async (
|
||||
user: components["schemas"]["UserRolePermissionDto"],
|
||||
) => {
|
||||
router.push({
|
||||
name: RouteName.BINDROLEVIEW,
|
||||
params: {
|
||||
userId: user.id,
|
||||
},
|
||||
});
|
||||
router.push(
|
||||
Routes.BINDROLEVIEW.withParams({
|
||||
userId: user.id!,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleBindDepartmentClick = async (
|
||||
user: components["schemas"]["UserRolePermissionDto"],
|
||||
) => {
|
||||
router.push({
|
||||
name: RouteName.BINDDEPARTMENTVIEW,
|
||||
params: {
|
||||
userId: user.id,
|
||||
},
|
||||
});
|
||||
router.push(
|
||||
Routes.BINDDEPARTMENTVIEW.withParams({
|
||||
userId: user.id!,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleBindPositionClick = async (
|
||||
user: components["schemas"]["UserRolePermissionDto"],
|
||||
) => {
|
||||
router.push({
|
||||
name: RouteName.BINDPOSITIONVIEW,
|
||||
params: {
|
||||
userId: user.id,
|
||||
},
|
||||
});
|
||||
router.push(
|
||||
Routes.BINDPOSITIONVIEW.withParams({
|
||||
userId: user.id!,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleSortClick = async (field: string) => {
|
||||
|
||||
Reference in New Issue
Block a user