diff --git a/backend/app/api/v1/services/system/dept_service.py b/backend/app/api/v1/services/system/dept_service.py index d8748c7d..03a781e4 100644 --- a/backend/app/api/v1/services/system/dept_service.py +++ b/backend/app/api/v1/services/system/dept_service.py @@ -10,6 +10,7 @@ from app.api.v1.schemas.system.dept_schema import ( DeptOutSchema ) from app.core.base_schema import BatchSetAvailable +from app.core.exceptions import CustomException from app.utils.common_util import ( get_parent_id_map, get_parent_recursion, @@ -59,6 +60,9 @@ class DeptService: :param data: 部门创建对象 :return: 新创建的部门对象 """ + dept = await DeptCRUD(auth).get(name=data.name) + if dept: + raise CustomException(msg='创建失败,该部门已存在') dept = await DeptCRUD(auth).create(data=data) return DeptOutSchema.model_validate(dept).model_dump() @@ -71,6 +75,12 @@ class DeptService: :param data: 部门更新对象 :return: 更新后的部门对象 """ + dept = await DeptCRUD(auth).get_dept_by_id(id=data.id) + if not dept: + raise CustomException(msg='更新失败,该部门不存在') + exist_dept = await DeptCRUD(auth).get(name=data.name) + if exist_dept and exist_dept.id != data.id: + raise CustomException(msg='更新失败,部门名称重复') dept = await DeptCRUD(auth).update(id=data.id, data=data) if data.available: await cls.batch_set_available_services(auth=auth, data=BatchSetAvailable(ids=[data.id], available=True)) @@ -86,6 +96,9 @@ class DeptService: :param auth: 认证对象 :param id: 部门ID """ + dept = await DeptCRUD(auth).get_dept_by_id(id=id) + if not dept: + raise CustomException(msg='删除失败,该部门不存在') await DeptCRUD(auth).delete(ids=[id]) @classmethod diff --git a/backend/app/api/v1/services/system/menu_service.py b/backend/app/api/v1/services/system/menu_service.py index a5c33134..a3f189b8 100644 --- a/backend/app/api/v1/services/system/menu_service.py +++ b/backend/app/api/v1/services/system/menu_service.py @@ -10,6 +10,7 @@ from app.api.v1.schemas.system.menu_schema import ( MenuOutSchema ) from app.core.base_schema import BatchSetAvailable +from app.core.exceptions import CustomException from app.utils.common_util import ( get_parent_id_map, get_parent_recursion, @@ -39,6 +40,9 @@ class MenuService: @classmethod async def create_menu(cls, auth: AuthSchema, data: MenuCreateSchema) -> Dict: + menu = await MenuCRUD(auth).get(name=data.name) + if menu: + raise CustomException(msg='创建失败,该菜单已存在') if data.parent_id: parent_menu = await MenuCRUD(auth).get_menu_by_id(id=data.parent_id) data.parent_name = parent_menu.name @@ -48,6 +52,13 @@ class MenuService: @classmethod async def update_menu(cls, auth: AuthSchema, data: MenuUpdateSchema) -> Dict: + menu = await MenuCRUD(auth).get_menu_by_id(id=data.id) + if not menu: + raise CustomException(msg='更新失败,该菜单不存在') + exist_menu = await MenuCRUD(auth).get(name=data.name) + if exist_menu and exist_menu.id != data.id: + raise CustomException(msg='更新失败,菜单名称重复') + if data.parent_id: parent_menu = await MenuCRUD(auth).get_menu_by_id(id=data.parent_id) data.parent_name = parent_menu.name @@ -60,6 +71,9 @@ class MenuService: @classmethod async def delete_menu(cls, auth: AuthSchema, id: int) -> None: + menu = await MenuCRUD(auth).get_menu_by_id(id=id) + if not menu: + raise CustomException(msg='删除失败,该菜单不存在') await MenuCRUD(auth).delete(ids=[id]) @classmethod diff --git a/backend/app/api/v1/services/system/notice_service.py b/backend/app/api/v1/services/system/notice_service.py index 35bcb824..90d8bc7f 100644 --- a/backend/app/api/v1/services/system/notice_service.py +++ b/backend/app/api/v1/services/system/notice_service.py @@ -7,6 +7,7 @@ from app.api.v1.schemas.system.notice_schema import NoticeCreateSchema, NoticeUp from app.core.base_schema import BatchSetAvailable from app.api.v1.params.system.notice_param import NoticeQueryParams from app.api.v1.cruds.system.notice_crud import NoticeCRUD +from app.core.exceptions import CustomException from app.utils.excel_util import ExcelUtil @@ -27,16 +28,28 @@ class NoticeService: @classmethod async def create_notice_services(cls, auth: AuthSchema, data: NoticeCreateSchema) -> Dict: + config = await NoticeCRUD(auth).get(notice_title=data.notice_title) + if config: + raise CustomException(msg='创建失败,该公告通知已存在') config_obj = await NoticeCRUD(auth).create_notice(data=data) return NoticeOutSchema.model_validate(config_obj).model_dump() @classmethod async def update_notice_services(cls, auth: AuthSchema, data: NoticeUpdateSchema) -> Dict: + config = await NoticeCRUD(auth).get_notice_by_id(id=data.id) + if not config: + raise CustomException(msg='更新失败,该公告通知不存在') + exist_config = await NoticeCRUD(auth).get(notice_title=data.notice_title) + if exist_config and exist_config.id != data.id: + raise CustomException(msg='更新失败,公告通知标题重复') config_obj = await NoticeCRUD(auth).update_notice(id=data.id, data=data) return NoticeOutSchema.model_validate(config_obj).model_dump() @classmethod async def delete_notice_services(cls, auth: AuthSchema, id: int) -> None: + config = await NoticeCRUD(auth).get_notice_by_id(id=id) + if not config: + raise CustomException(msg='删除失败,该公告通知不存在') await NoticeCRUD(auth).delete_notice(ids=[id]) @classmethod diff --git a/backend/app/api/v1/services/system/position_service.py b/backend/app/api/v1/services/system/position_service.py index bcbeb095..07b5080e 100644 --- a/backend/app/api/v1/services/system/position_service.py +++ b/backend/app/api/v1/services/system/position_service.py @@ -10,6 +10,7 @@ from app.api.v1.schemas.system.position_schema import ( PositionOutSchema, ) from app.core.base_schema import BatchSetAvailable +from app.core.exceptions import CustomException from app.utils.excel_util import ExcelUtil from app.api.v1.params.system.position_param import PositionQueryParams @@ -32,18 +33,30 @@ class PositionService: @classmethod async def create_position(cls, auth: AuthSchema, data: PositionCreateSchema) -> Dict: """创建岗位""" + position = await PositionCRUD(auth).get(name=data.name) + if position: + raise CustomException(msg='创建失败,该岗位已存在') new_position = await PositionCRUD(auth).create(data=data) return PositionOutSchema.model_validate(new_position).model_dump() @classmethod async def update_position(cls, auth: AuthSchema, data: PositionUpdateSchema) -> Dict: """更新岗位""" + position = await PositionCRUD(auth).get_position_by_id(id=data.id) + if not position: + raise CustomException(msg='更新失败,该岗位不存在') + exist_position = await PositionCRUD(auth).get(name=data.name) + if exist_position and exist_position.id != data.id: + raise CustomException(msg='更新失败,岗位名称重复') updated_position = await PositionCRUD(auth).update(id=data.id, data=data) return PositionOutSchema.model_validate(updated_position).model_dump() @classmethod async def delete_position(cls, auth: AuthSchema, id: int) -> None: """删除岗位""" + position = await PositionCRUD(auth).get_position_by_id(id=id) + if not position: + raise CustomException(msg='删除失败,该岗位不存在') await PositionCRUD(auth).delete(ids=[id]) @classmethod diff --git a/backend/app/api/v1/services/system/role_service.py b/backend/app/api/v1/services/system/role_service.py index 8f9edfb2..0ca94322 100644 --- a/backend/app/api/v1/services/system/role_service.py +++ b/backend/app/api/v1/services/system/role_service.py @@ -4,6 +4,7 @@ from typing import Dict, List from app.api.v1.cruds.system.dept_crud import DeptCRUD from app.core.base_schema import BatchSetAvailable +from app.core.exceptions import CustomException from app.utils.common_util import get_child_id_map, get_child_recursion, get_parent_id_map, get_parent_recursion from app.api.v1.cruds.system.role_crud import RoleCRUD, MenuCRUD from app.api.v1.schemas.system.auth_schema import AuthSchema @@ -36,18 +37,30 @@ class RoleService: @classmethod async def create_role(cls, auth: AuthSchema, data: RoleCreateSchema) -> Dict: """创建角色""" + role = await RoleCRUD(auth).get(name=data.name) + if role: + raise CustomException(msg='创建失败,该角色已存在') new_role = await RoleCRUD(auth).create(data=data) return RoleOutSchema.model_validate(new_role).model_dump() @classmethod async def update_role(cls, auth: AuthSchema, data: RoleUpdateSchema) -> Dict: """更新角色""" + role = await RoleCRUD(auth).get_role_by_id(id=data.id) + if not role: + raise CustomException(msg='更新失败,该角色不存在') + exist_role = await RoleCRUD(auth).get(name=data.name) + if exist_role and exist_role.id != data.id: + raise CustomException(msg='更新失败,角色名称重复') updated_role = await RoleCRUD(auth).update(id=data.id, data=data) return RoleOutSchema.model_validate(updated_role).model_dump() @classmethod async def delete_role(cls, auth: AuthSchema, id: int) -> None: """删除角色""" + role = await RoleCRUD(auth).get_role_by_id(id=id) + if not role: + raise CustomException(msg='删除失败,该角色不存在') await RoleCRUD(auth).delete(ids=[id]) @classmethod diff --git a/backend/app/api/v1/services/system/user_service.py b/backend/app/api/v1/services/system/user_service.py index 7eba2ffe..2fa298c3 100644 --- a/backend/app/api/v1/services/system/user_service.py +++ b/backend/app/api/v1/services/system/user_service.py @@ -244,7 +244,7 @@ class UserService: # 检查用户名是否存在 user = await UserCRUD(auth).get_user_by_username(username=data.username) if user: - raise CustomException(msg='用户名已存在') + raise CustomException(msg='注册失败,用户名已存在') data.password = PwdUtil.set_password_hash(password=data.password) dict_data = data.model_dump(exclude_unset=True) diff --git a/backend/dev_sql.db b/backend/dev_sql.db index 78e8051b..40c2ba14 100644 Binary files a/backend/dev_sql.db and b/backend/dev_sql.db differ diff --git a/frontend/src/utils/request.js b/frontend/src/utils/request.js index d5d23a2c..aba73065 100644 --- a/frontend/src/utils/request.js +++ b/frontend/src/utils/request.js @@ -4,6 +4,7 @@ import router from "@/router"; import { getNewToken } from "@/api/system/auth"; import { save_token } from "@/utils/util"; import notification from "ant-design-vue/es/notification"; +import { message } from 'ant-design-vue'; // 创建 axios 实例 const request = axios.create({ @@ -13,7 +14,7 @@ const request = axios.create({ // 异常拦截处理器 const errorHandler = async (error) => { - console.log(error); + // console.error(error); if (!error.response) { return Promise.reject(error); @@ -27,20 +28,14 @@ const errorHandler = async (error) => { storage.remove("Access-Token"); storage.remove("Refresh-Token"); - notification.error({ - message: "错误", - description: data.msg, - }); + message.error(data.msg); router.push("/login"); return Promise.reject(error); } if (data.status_code === 401) { if (!access_token) { - notification.error({ - message: "错误", - description: data.msg, - }); + message.error(data.msg); router.push("/login"); return Promise.reject(error); } @@ -60,26 +55,16 @@ const errorHandler = async (error) => { ); return request(error.response.config).then((response) => response); } - - notification.error({ - message: "错误", - description: result.msg, - }); + message.error(result.msg); router.push("/login"); return Promise.reject(error); }) .catch((error) => { - notification.error({ - message: "错误", - description: data.msg, - }); + message.error(data.msg); return Promise.reject(error); }); } else { - notification.error({ - message: "错误", - description: data.msg, - }); + message.error(data.msg); return Promise.reject(error); } }; @@ -98,18 +83,16 @@ request.interceptors.request.use((config) => { // 响应拦截器 request.interceptors.response.use((response) => { // 打印全局响应 - console.log(response); + console.log(response.data); // 如果是文件下载类型的响应,直接返回 if (response.config.responseType === 'blob') { return response; } if (response.data.status_code !== 200) { - notification.error({ - message: "错误", - description: response.data.msg, - }); + message.error(response.data.msg); return Promise.reject(response); } + // message.success(response.data.msg); return response; }, errorHandler); diff --git a/frontend/src/views/system/dept/index.vue b/frontend/src/views/system/dept/index.vue index 0e9f12e6..eaef7ea0 100644 --- a/frontend/src/views/system/dept/index.vue +++ b/frontend/src/views/system/dept/index.vue @@ -435,11 +435,30 @@ const handleMoreClick: MenuProps['onClick'] = e => { }); }; + // 弹窗关键字处理 const modalHandle = (modalType: string, record?: tableDataType) => { modalTitle.value = modalType; openModal.value = true; + // 重新创建 createState 和 updateState 以重置为初始状态 + Object.assign(createState, { + name: '', + order: 1, + available: true, + parent_id: undefined, + description: '' + }); + + Object.assign(updateState, { + id: undefined, + name: '', + order: 1, + available: true, + parent_id: undefined, + description: '' + }); + if (modalType === 'view' && record !== undefined) { detailStateLoading.value = true; detailState.value = record @@ -478,6 +497,7 @@ const handleModalSumbit = () => { loadingData(); }).catch(error => { console.error(error); + modalSubmitLoading.value = false; }); }).catch(error => { modalSubmitLoading.value = false; diff --git a/frontend/src/views/system/menu/index.vue b/frontend/src/views/system/menu/index.vue index 6fd26350..acfe6a58 100644 --- a/frontend/src/views/system/menu/index.vue +++ b/frontend/src/views/system/menu/index.vue @@ -550,6 +550,42 @@ const modalHandle = (modalType: string, record?: tableDataType) => { modalTitle.value = modalType; openModal.value = true; + // 重新创建 createState 和 updateState 以重置为初始状态 + Object.assign(createState, { + name: '', + type: 1, + icon: '', + order: 1, + permission: '', + route_name: '', + route_path: '', + component_path: '', + redirect: '', + parent_id: undefined, + cache: true, + hidden: false, + available: true, + description: '' + }); + + Object.assign(updateState, { + id: undefined, + name: '', + type: 1, + icon: '', + order: 1, + permission: '', + route_name: '', + route_path: '', + component_path: '', + redirect: '', + parent_id: undefined, + cache: true, + hidden: false, + available: true, + description: '' + }); + if (modalType === 'view' && record !== undefined) { detailStateLoading.value = true; detailState.value = record; diff --git a/frontend/src/views/system/notice/index.vue b/frontend/src/views/system/notice/index.vue index 45a6848b..557b5ecb 100644 --- a/frontend/src/views/system/notice/index.vue +++ b/frontend/src/views/system/notice/index.vue @@ -380,6 +380,24 @@ const modalHandle = (modalType: string, index?: number) => { modalTitle.value = modalType; openModal.value = true; + // 重新创建 createState 和 updateState 以重置为初始状态 + Object.assign(createState, { + notice_title: '', + notice_type: 1, + notice_content: '', + available: true, + description: '' + }); + + Object.assign(updateState, { + id: undefined, + notice_title: '', + notice_type: 1, + notice_content: '', + available: true, + description: '' + }); + if (modalType === 'view' && index !== undefined) { detailStateLoading.value = true; diff --git a/frontend/src/views/system/position/index.vue b/frontend/src/views/system/position/index.vue index f8da6c8e..1a78aa4f 100644 --- a/frontend/src/views/system/position/index.vue +++ b/frontend/src/views/system/position/index.vue @@ -348,6 +348,22 @@ const modalHandle = (modalType: string, index?: number) => { modalTitle.value = modalType; openModal.value = true; + // 重新创建 createState 和 updateState 以重置为初始状态 + Object.assign(createState, { + name: '', + order: 1, + available: true, + description: '' + }); + + Object.assign(updateState, { + id: undefined, + name: '', + order: 1, + available: true, + description: '' + }); + if (modalType === 'view' && index !== undefined) { detailStateLoading.value = true; diff --git a/frontend/src/views/system/role/index.vue b/frontend/src/views/system/role/index.vue index af6ca7f3..e85a1f71 100644 --- a/frontend/src/views/system/role/index.vue +++ b/frontend/src/views/system/role/index.vue @@ -408,6 +408,22 @@ const modalHandle = (modalType: string, index?: number) => { modalTitle.value = modalType; openModal.value = true; + // 重新创建 createState 和 updateState 以重置为初始状态 + Object.assign(createState, { + name: '', + order: 1, + available: true, + description: '' + }); + + Object.assign(updateState, { + id: undefined, + name: '', + order: 1, + available: true, + description: '' + }); + if (modalType === 'view' && index !== undefined) { detailStateLoading.value = true; diff --git a/frontend/src/views/system/user/index.vue b/frontend/src/views/system/user/index.vue index 191f6a24..e6adfd6a 100644 --- a/frontend/src/views/system/user/index.vue +++ b/frontend/src/views/system/user/index.vue @@ -639,6 +639,44 @@ const modalHandle = (modalType: string, index?: number) => { modalTitle.value = modalType; openModal.value = true; + // 重新创建 createState 和 updateState 以重置为初始状态 + Object.assign(createState, { + username: '', + name: '', + dept_id: undefined, + dept_name: '', + role_ids: undefined, + roleNames: undefined, + position_ids: undefined, + positionNames: undefined, + password: '', + gender: undefined, + email: '', + mobile: '', + is_superuser: false, + available: true, + description: '' + }); + + Object.assign(updateState, { + id: undefined, + username: '', + name: '', + dept_id: undefined, + dept_name: '', + role_ids: [], + roleNames: undefined, + position_ids: [], + positionNames: undefined, + password: '', + gender: undefined, + email: '', + mobile: '', + is_superuser: false, + available: true, + description: '', + }); + if (modalType === 'view' && index !== undefined) { detailStateLoading.value = true;