diff --git a/src/modules/cms/link/models.py b/src/modules/cms/link/models.py index 7356cf2..4f5e301 100644 --- a/src/modules/cms/link/models.py +++ b/src/modules/cms/link/models.py @@ -50,7 +50,6 @@ from src.common.base_db import BaseDB from src.common.base_model import BaseModel from config import DB_PREFIX from src.core.database import db -from src.common.utils.case_converter import convert_camel_to_snake # ============================================================ diff --git a/src/modules/cms/link/repository.py b/src/modules/cms/link/repository.py new file mode 100644 index 0000000..86b602f --- /dev/null +++ b/src/modules/cms/link/repository.py @@ -0,0 +1,15 @@ +""" +Link 仓储模块 +============================================================= + +数据访问层,继承 BaseRepository 获得通用 CRUD 能力。 +""" + +from src.common.base_repository import BaseRepository +from src.modules.cms.link.models import Link + + +class LinkRepository(BaseRepository): + """Link 仓储""" + + model = Link diff --git a/src/modules/cms/link/router.py b/src/modules/cms/link/router.py index e2ce6ac..d21bacb 100644 --- a/src/modules/cms/link/router.py +++ b/src/modules/cms/link/router.py @@ -55,22 +55,24 @@ application.middleware.check_permission - 权限校验中间件 """ -from flask import Blueprint +from flask import Blueprint, request from application.middleware.check_demo import check_demo from application.middleware.check_permission import check_permission from src.modules.cms.link import service as link -from src.common.utils.request import parse_batch_ids -link_blue = Blueprint('link', __name__, url_prefix='/link') +from src.common.utils.request import parse_batch_ids, parse_request_body from src.core import response as R +link_blue = Blueprint("link", __name__, url_prefix="/link") + # ============================================================ # 友链分页查询 # ============================================================ -@link_blue.route('/page', methods=["GET"]) + +@link_blue.route("/page", methods=["GET"]) @check_permission("sys:link:page") def page(): """ @@ -82,15 +84,15 @@ def page(): Returns: JSON: 友链分页数据,包含 records(数据列表)、total(总记录数)等 """ - result = link.get_link_page() - return result + return R.ok(data=link.get_link_page(request.args)) # ============================================================ # 友链详情查询 # ============================================================ -@link_blue.route('/detail/', methods=["GET"]) + +@link_blue.route("/detail/", methods=["GET"]) @check_permission("sys:link:detail") def detail(id): """ @@ -110,7 +112,8 @@ def detail(id): # 友链添加 # ============================================================ -@link_blue.route('/add', methods=["POST"]) + +@link_blue.route("/add", methods=["POST"]) @check_permission("sys:link:add") @check_demo def add(): @@ -123,15 +126,19 @@ def add(): Returns: JSON: 操作结果 """ - result = link.add_link() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + link.add_link(json_data) + return R.ok(msg="添加成功") # ============================================================ # 友链更新 # ============================================================ -@link_blue.route('/update', methods=["PUT"]) + +@link_blue.route("/update", methods=["PUT"]) @check_permission("sys:link:update") @check_demo def update(): @@ -144,15 +151,19 @@ def update(): Returns: JSON: 操作结果 """ - result = link.update_link() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + link.update_link(json_data) + return R.ok(msg="更新成功") # ============================================================ # 友链删除 # ============================================================ -@link_blue.route('/delete/', methods=["DELETE"]) + +@link_blue.route("/delete/", methods=["DELETE"]) @check_permission("sys:link:delete") @check_demo def delete(id): @@ -165,15 +176,16 @@ def delete(id): Returns: JSON: 操作结果 """ - result = link.delete_links(id) - return result + count = link.delete_links(id) + return R.ok(msg=f"本次共删除{count}条数据") # ============================================================ # 友链批量删除 # ============================================================ -@link_blue.route('/batchDelete', methods=["DELETE"]) + +@link_blue.route("/batchDelete", methods=["DELETE"]) @check_permission("sys:link:batch_delete") @check_demo def batch_delete(): @@ -199,7 +211,8 @@ def batch_delete(): # 友链状态设置 # ============================================================ -@link_blue.route('/status', methods=["PUT"]) + +@link_blue.route("/status", methods=["PUT"]) @check_permission("sys:link:status") @check_demo def status(): @@ -212,5 +225,8 @@ def status(): Returns: JSON: 操作结果 """ - result = link.update_link_status() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + link.update_link_status(json_data) + return R.ok(msg="更新成功") diff --git a/src/modules/cms/link/service.py b/src/modules/cms/link/service.py index 20d97ea..f9b46c4 100644 --- a/src/modules/cms/link/service.py +++ b/src/modules/cms/link/service.py @@ -65,19 +65,17 @@ import logging from datetime import datetime, timezone -from flask import request -from sqlalchemy import and_ from src.common.constants.common import PAGE_SIZE from src.common.constants.dictionary_constants import LINK_TYPE_LIST, LINK_FORM_LIST from src.modules.cms.link.schema import LinkForm, LinkStatusForm from src.modules.cms.link.models import Link -from src.core.database import db -from src.core import response as R +from src.modules.cms.link.repository import LinkRepository +from src.core.exceptions import BizError from src.common.utils import regular from src.common.utils.case_converter import convert_camel_to_snake -from src.common.utils.model_utils import models_to_list, model_to_dict -from src.common.utils.request import parse_request_body, parse_id_list, like_contains +from src.common.utils.model_utils import model_to_dict +from src.common.utils.request import parse_id_list, like_contains from src.common.utils.rich_text import get_file_url, save_file from src.core.security import get_username @@ -89,7 +87,8 @@ logger = logging.getLogger(__name__) # 友链分页查询 # ============================================================ -def get_link_page(): + +def get_link_page(params: dict) -> dict: """ 查询友链分页数据 @@ -112,31 +111,26 @@ def get_link_page(): "pages": 总页数 } """ - try: - # 获取分页参数 - page_no = int(request.args.get('pageNo', 1)) - page_size = int(request.args.get('pageSize', PAGE_SIZE)) + # 获取分页参数 + page_no = int(params.get("pageNo", 1)) + page_size = int(params.get("pageSize", PAGE_SIZE)) - # 应用筛选条件 - query = _apply_filters() + # 应用筛选条件 + query = _apply_filters(params) - # 记录总数 - total = query.count() - # 计算总页数 - pages = (total + page_size - 1) // page_size if total > 0 else 0 + # 记录总数 + total = query.count() + # 计算总页数 + pages = (total + page_size - 1) // page_size if total > 0 else 0 - # 分页查询 - link_list = query.limit(page_size).offset((page_no - 1) * page_size).all() - # 构建返回数据 - page_data = _build_page_data(link_list, total, page_size, page_no, pages) - return R.ok(data=page_data) - - except Exception as e: - logger.error(f"查询友链分页数据异常: {str(e)}") - return R.failed(msg="查询失败,请稍后重试") + # 分页查询 + link_list = query.limit(page_size).offset((page_no - 1) * page_size).all() + # 构建返回数据 + page_data = _build_page_data(link_list, total, page_size, page_no, pages) + return page_data -def _apply_filters(): +def _apply_filters(params: dict): """ 应用查询筛选条件 @@ -156,22 +150,22 @@ def _apply_filters(): query = Link.query.filter(Link.is_delete == 0) # 友链名称模糊筛选 - name = request.args.get('name') + name = params.get("name") if name: - query = query.filter(Link.name.like(like_contains(name), escape='\\')) + query = query.filter(Link.name.like(like_contains(name), escape="\\")) # 友链类型精确筛选 - link_type = request.args.get('type') + link_type = params.get("type") if link_type: query = query.filter(Link.type == link_type) # 友链形式精确筛选 - form = request.args.get('form') + form = params.get("form") if form: query = query.filter(Link.form == form) # 友链状态精确筛选 - status = request.args.get('status') + status = params.get("status") if status: query = query.filter(Link.status == status) @@ -198,27 +192,22 @@ def _build_page_data(link_list, total, page_size, page_no, pages): for item in link_list: data = model_to_dict(item) # 添加友链类型描述 - data['typeName'] = LINK_TYPE_LIST.get(item.type) + data["typeName"] = LINK_TYPE_LIST.get(item.type) # 添加友链形式描述 - data['formName'] = LINK_FORM_LIST.get(item.form) + data["formName"] = LINK_FORM_LIST.get(item.form) # 友链图片URL if item.image: - data['image'] = get_file_url(item.image) + data["image"] = get_file_url(item.image) records.append(data) - return { - 'records': records, - 'total': total, - 'size': page_size, - 'current': page_no, - 'pages': pages - } + return {"records": records, "total": total, "size": page_size, "current": page_no, "pages": pages} # ============================================================ # 友链详情查询 # ============================================================ + def get_link_detail(link_id): """ 根据ID查询友链详情(返回字典格式) @@ -241,7 +230,7 @@ def get_link_detail(link_id): data = model_to_dict(link) # 友链图片URL if link.image: - data['image'] = get_file_url(link.image) + data["image"] = get_file_url(link.image) return data except Exception as e: @@ -253,6 +242,7 @@ def get_link_detail(link_id): # 友链信息查询(根据ID)- 核心查询方法 # ============================================================ + def get_info(link_id: int): """ 根据ID查询友链信息(返回模型对象) @@ -278,26 +268,10 @@ def get_info(link_id: int): if link: print(link.name) """ - # 参数有效性验证 - if not link_id or link_id <= 0: - return None - - try: - # 查询未删除的友链 - link = Link.query.filter( - and_(Link.id == link_id, Link.is_delete == 0) - ).first() - return link - except Exception as e: - logger.error(f"查询友链信息异常,ID: {link_id}, 错误: {str(e)}") - return None + return LinkRepository.get_by_id(link_id) -# ============================================================ -# 友链添加 -# ============================================================ - -def add_link(): +def add_link(data: dict) -> None: """ 添加友链 @@ -310,40 +284,29 @@ def add_link(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = LinkForm(data=json_data) - if not form.validate(): - err_msg = regular.get_err(form) - return R.failed(msg=err_msg) + # 表单验证 + form = LinkForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - # 处理友链图片 - image = form.data.get('image') - if image: - form.image.data = save_file(image, "link") + # 处理友链图片 + image = form.data.get("image") + if image: + form.image.data = save_file(image, "link") - # 创建友链 - link = Link(**form.data) - link.create_user = get_username() - link.save() - - return R.ok(msg="添加成功") - - except Exception as e: - logger.error(f"添加友链异常: {str(e)}") - return R.failed(msg="添加失败,请稍后重试") + # 创建友链 + link = Link(**form.data) + link.create_user = get_username() + link.save() # ============================================================ # 友链更新 # ============================================================ -def update_link(): + +def update_link(data: dict) -> None: """ 更新友链 @@ -357,57 +320,47 @@ def update_link(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = LinkForm(data=json_data) - if not form.validate(): - return R.failed(msg=regular.get_err(form)) + # 表单验证 + form = LinkForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - # 获取友链ID - link_id = form.data.get('id') - if not link_id or int(link_id) <= 0: - return R.failed("友链ID无效") - link_id = int(link_id) + # 获取友链ID + link_id = form.data.get("id") + if not link_id or int(link_id) <= 0: + raise BizError("友链ID无效") + link_id = int(link_id) - # 复用 get_info 方法验证友链是否存在 - link = get_info(link_id) - if not link: - return R.failed("友链不存在") + # 复用 get_info 方法验证友链是否存在 + link = get_info(link_id) + if not link: + raise BizError("友链不存在") - # 处理友链图片 - image = form.data.get('image') - if image: - form.image.data = save_file(image, "link") + # 处理友链图片 + image = form.data.get("image") + if image: + form.image.data = save_file(image, "link") - # 更新友链信息(移除ID,避免更新主键) - form_data = convert_camel_to_snake(form.data.copy()) - form_data.pop('id', None) + # 更新友链信息(移除ID,避免更新主键) + form_data = convert_camel_to_snake(form.data.copy()) + form_data.pop("id", None) - form_data['update_time'] = datetime.now(tz=timezone.utc) - form_data['update_user'] = get_username() + form_data["update_time"] = datetime.now(tz=timezone.utc) + form_data["update_user"] = get_username() - result = Link.query.filter_by(id=link_id).update(form_data) + result = Link.query.filter_by(id=link_id).update(form_data) - if not result: - return R.failed("更新失败") - - return R.ok(msg="更新成功") - - except Exception as e: - logger.error(f"更新友链异常: {str(e)}") - return R.failed(msg="更新友链失败,请稍后重试") + if not result: + raise BizError("更新失败") # ============================================================ # 友链删除 # ============================================================ -def delete_links(link_ids): + +def delete_links(link_ids: str) -> int: """ 删除友链(批量删除) @@ -420,14 +373,18 @@ def delete_links(link_ids): Returns: R: 操作结果 """ - return Link.batch_delete_r(link_ids) + link_ids_list = parse_id_list(link_ids) + if not link_ids_list: + raise BizError("无效的记录ID") + return Link.batch_delete(link_ids_list) # ============================================================ # 友链状态设置 # ============================================================ -def update_link_status(): + +def update_link_status(data: dict) -> None: """ 设置友链状态 @@ -436,35 +393,23 @@ def update_link_status(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = LinkStatusForm(data=json_data) - if not form.validate(): - err_msg = regular.get_err(form) - return R.failed(msg=err_msg) + # 表单验证 + form = LinkStatusForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - link_id = int(form.data['id']) - status = int(form.data['status']) + link_id = int(form.data["id"]) + status = int(form.data["status"]) - # 复用 get_info 方法验证友链是否存在 - link = get_info(link_id) - if not link: - return R.failed("友链不存在") + # 复用 get_info 方法验证友链是否存在 + link = get_info(link_id) + if not link: + raise BizError("友链不存在") - # 更新状态 - update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()} - result = Link.query.filter_by(id=link_id).update(update_data) + # 更新状态 + update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()} + result = Link.query.filter_by(id=link_id).update(update_data) - if not result: - return R.failed("设置失败") - - return R.ok(msg="设置成功") - - except Exception as e: - logger.error(f"设置友链状态异常: {str(e)}") - return R.failed(msg="设置友链状态失败,请稍后重试") + if not result: + raise BizError("设置失败") diff --git a/src/modules/notice/models.py b/src/modules/notice/models.py index f3025a7..473a01b 100644 --- a/src/modules/notice/models.py +++ b/src/modules/notice/models.py @@ -50,7 +50,6 @@ from src.common.base_db import BaseDB from src.common.base_model import BaseModel from config import DB_PREFIX from src.core.database import db -from src.common.utils.case_converter import convert_camel_to_snake # ============================================================ diff --git a/src/modules/notice/repository.py b/src/modules/notice/repository.py new file mode 100644 index 0000000..24476a8 --- /dev/null +++ b/src/modules/notice/repository.py @@ -0,0 +1,15 @@ +""" +Notice 仓储模块 +============================================================= + +数据访问层,继承 BaseRepository 获得通用 CRUD 能力。 +""" + +from src.common.base_repository import BaseRepository +from src.modules.notice.models import Notice + + +class NoticeRepository(BaseRepository): + """Notice 仓储""" + + model = Notice diff --git a/src/modules/notice/router.py b/src/modules/notice/router.py index 3a19796..105e11d 100644 --- a/src/modules/notice/router.py +++ b/src/modules/notice/router.py @@ -53,22 +53,24 @@ 依赖模块: application.services.notice - 通知业务逻辑层 application.middleware.check_permission - 权限校验中间件 """ -from flask import Blueprint +from flask import Blueprint, request from application.middleware.check_demo import check_demo from application.middleware.check_permission import check_permission from src.modules.notice import service as notice -from src.common.utils.request import parse_batch_ids -notice_blue = Blueprint('notice', __name__, url_prefix='/notice') +from src.common.utils.request import parse_batch_ids, parse_request_body from src.core import response as R +notice_blue = Blueprint("notice", __name__, url_prefix="/notice") + # ============================================================ # 通知分页查询 # ============================================================ -@notice_blue.route('/page', methods=["GET"]) + +@notice_blue.route("/page", methods=["GET"]) @check_permission("sys:notice:page") def page(): """ @@ -80,15 +82,15 @@ def page(): Returns: JSON: 通知分页数据,包含 records(数据列表)、total(总记录数)等 """ - result = notice.get_notice_page() - return result + return R.ok(data=notice.get_notice_page(request.args)) # ============================================================ # 通知详情查询 # ============================================================ -@notice_blue.route('/detail/', methods=["GET"]) + +@notice_blue.route("/detail/", methods=["GET"]) @check_permission("sys:notice:detail") def detail(id): """ @@ -108,7 +110,8 @@ def detail(id): # 通知添加 # ============================================================ -@notice_blue.route('/add', methods=["POST"]) + +@notice_blue.route("/add", methods=["POST"]) @check_permission("sys:notice:add") @check_demo def add(): @@ -121,15 +124,19 @@ def add(): Returns: JSON: 操作结果 """ - result = notice.add_notice() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + notice.add_notice(json_data) + return R.ok(msg="添加成功") # ============================================================ # 通知更新 # ============================================================ -@notice_blue.route('/update', methods=["PUT"]) + +@notice_blue.route("/update", methods=["PUT"]) @check_permission("sys:notice:update") @check_demo def update(): @@ -142,15 +149,19 @@ def update(): Returns: JSON: 操作结果 """ - result = notice.update_notice() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + notice.update_notice(json_data) + return R.ok(msg="更新成功") # ============================================================ # 通知删除 # ============================================================ -@notice_blue.route('/delete/', methods=["DELETE"]) + +@notice_blue.route("/delete/", methods=["DELETE"]) @check_permission("sys:notice:delete") @check_demo def delete(id): @@ -163,15 +174,16 @@ def delete(id): Returns: JSON: 操作结果 """ - result = notice.delete_notices(id) - return result + count = notice.delete_notices(id) + return R.ok(msg=f"本次共删除{count}条数据") # ============================================================ # 通知公告批量删除 # ============================================================ -@notice_blue.route('/batchDelete', methods=["DELETE"]) + +@notice_blue.route("/batchDelete", methods=["DELETE"]) @check_permission("sys:notice:batch_delete") @check_demo def batch_delete(): diff --git a/src/modules/notice/service.py b/src/modules/notice/service.py index 5407a45..e980869 100644 --- a/src/modules/notice/service.py +++ b/src/modules/notice/service.py @@ -63,20 +63,18 @@ import logging from datetime import datetime, timezone -from flask import request -from sqlalchemy import and_ from src.common.constants.common import PAGE_SIZE from src.common.constants.dictionary_constants import NOTICE_TYPE_LIST from src.modules.notice.schema import NoticeForm from src.modules.notice.models import Notice +from src.modules.notice.repository import NoticeRepository +from src.core.exceptions import BizError from config import FLASK_FILE_URL -from src.core.database import db -from src.core import response as R from src.common.utils import regular from src.common.utils.case_converter import convert_camel_to_snake from src.common.utils.model_utils import model_to_dict -from src.common.utils.request import parse_request_body, parse_id_list, like_contains +from src.common.utils.request import parse_id_list, like_contains from src.common.utils.rich_text import save_content, save_file from src.core.security import get_username @@ -88,7 +86,8 @@ logger = logging.getLogger(__name__) # 通知公告分页查询 # ============================================================ -def get_notice_page(): + +def get_notice_page(params: dict) -> dict: """ 查询通知公告分页数据 @@ -110,31 +109,26 @@ def get_notice_page(): "pages": 总页数 } """ - try: - # 获取分页参数 - page_no = int(request.args.get('pageNo', 1)) - page_size = int(request.args.get('pageSize', PAGE_SIZE)) + # 获取分页参数 + page_no = int(params.get("pageNo", 1)) + page_size = int(params.get("pageSize", PAGE_SIZE)) - # 应用筛选条件 - query = _apply_filters() + # 应用筛选条件 + query = _apply_filters(params) - # 记录总数 - total = query.count() - # 计算总页数 - pages = (total + page_size - 1) // page_size if total > 0 else 0 + # 记录总数 + total = query.count() + # 计算总页数 + pages = (total + page_size - 1) // page_size if total > 0 else 0 - # 分页查询 - notice_list = query.limit(page_size).offset((page_no - 1) * page_size).all() - # 构建返回数据 - page_data = _build_page_data(notice_list, total, page_size, page_no, pages) - return R.ok(data=page_data) - - except Exception as e: - logger.error(f"查询通知公告分页数据异常: {str(e)}") - return R.failed(msg="查询失败,请稍后重试") + # 分页查询 + notice_list = query.limit(page_size).offset((page_no - 1) * page_size).all() + # 构建返回数据 + page_data = _build_page_data(notice_list, total, page_size, page_no, pages) + return page_data -def _apply_filters(): +def _apply_filters(params: dict): """ 应用查询筛选条件 @@ -152,17 +146,17 @@ def _apply_filters(): query = Notice.query.filter(Notice.is_delete == 0) # 通知公告标题模糊筛选 - title = request.args.get('title') + title = params.get("title") if title: - query = query.filter(Notice.title.like(like_contains(title), escape='\\')) + query = query.filter(Notice.title.like(like_contains(title), escape="\\")) # 通知类型精确筛选 - type = request.args.get('type') + type = params.get("type") if type: query = query.filter(Notice.type == type) # 通知状态精确筛选 - status = request.args.get('status') + status = params.get("status") if status: query = query.filter(Notice.status == status) @@ -189,22 +183,17 @@ def _build_page_data(notice_list, total, page_size, page_no, pages): for notice in notice_list: data = model_to_dict(notice) # 添加通知来源描述 - data['typeText'] = NOTICE_TYPE_LIST.get(notice.type) + data["typeText"] = NOTICE_TYPE_LIST.get(notice.type) records.append(data) - return { - 'records': records, - 'total': total, - 'size': page_size, - 'current': page_no, - 'pages': pages - } + return {"records": records, "total": total, "size": page_size, "current": page_no, "pages": pages} # ============================================================ # 通知公告详情查询 # ============================================================ + def get_notice_detail(notice_id): """ 根据ID查询通知公告详情(返回字典格式) @@ -227,9 +216,9 @@ def get_notice_detail(notice_id): data = model_to_dict(notice) # 富文本内容处理:替换图片URL占位符 content = notice.content.replace("[IMG_URL]", FLASK_FILE_URL) if notice.content else "" - data['content'] = content + data["content"] = content # 通知来源描述 - data['typeText'] = NOTICE_TYPE_LIST.get(notice.type) + data["typeText"] = NOTICE_TYPE_LIST.get(notice.type) return data except Exception as e: @@ -241,6 +230,7 @@ def get_notice_detail(notice_id): # 通知公告信息查询(根据ID)- 核心查询方法 # ============================================================ + def get_info(notice_id: int): """ 根据ID查询通知公告信息(返回模型对象) @@ -265,26 +255,10 @@ def get_info(notice_id: int): if notice: print(notice.title) """ - # 参数有效性验证 - if not notice_id or notice_id <= 0: - return None - - try: - # 查询未删除的通知公告 - notice = Notice.query.filter( - and_(Notice.id == notice_id, Notice.is_delete == 0) - ).first() - return notice - except Exception as e: - logger.error(f"查询通知公告信息异常,ID: {notice_id}, 错误: {str(e)}") - return None + return NoticeRepository.get_by_id(notice_id) -# ============================================================ -# 通知公告添加 -# ============================================================ - -def add_notice(): +def add_notice(data: dict) -> None: """ 添加通知公告 @@ -297,46 +271,35 @@ def add_notice(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = NoticeForm(data=json_data) - if not form.validate(): - err_msg = regular.get_err(form) - return R.failed(msg=err_msg) + # 表单验证 + form = NoticeForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - # 通知封面处理 - cover = form.data.get('cover') - if cover: - cover = save_file(cover, "notice") - form.cover.data = cover - # 处理富文本内容 - title = form.data.get('title', '') - content = form.data.get('content', '') - if content: - form.content.data = save_content(content, title, "notice") + # 通知封面处理 + cover = form.data.get("cover") + if cover: + cover = save_file(cover, "notice") + form.cover.data = cover + # 处理富文本内容 + title = form.data.get("title", "") + content = form.data.get("content", "") + if content: + form.content.data = save_content(content, title, "notice") - # 创建通知公告 - notice = Notice(**form.data) - notice.create_user = get_username() - notice.save() - - return R.ok(msg="添加成功") - - except Exception as e: - logger.error(f"添加通知公告异常: {str(e)}") - return R.failed(msg="添加失败,请稍后重试") + # 创建通知公告 + notice = Notice(**form.data) + notice.create_user = get_username() + notice.save() # ============================================================ # 通知公告更新 # ============================================================ -def update_notice(): + +def update_notice(data: dict) -> None: """ 更新通知公告 @@ -350,63 +313,53 @@ def update_notice(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = NoticeForm(data=json_data) - if not form.validate(): - return R.failed(msg=regular.get_err(form)) + # 表单验证 + form = NoticeForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - # 获取通知公告ID - notice_id = form.data.get('id') - if not notice_id or int(notice_id) <= 0: - return R.failed("通知公告ID无效") - notice_id = int(notice_id) + # 获取通知公告ID + notice_id = form.data.get("id") + if not notice_id or int(notice_id) <= 0: + raise BizError("通知公告ID无效") + notice_id = int(notice_id) - # 复用 get_info 方法验证通知公告是否存在 - notice = get_info(notice_id) - if not notice: - return R.failed("通知公告不存在") + # 复用 get_info 方法验证通知公告是否存在 + notice = get_info(notice_id) + if not notice: + raise BizError("通知公告不存在") - # 通知封面处理 - cover = form.data.get('cover') - if cover: - cover = save_file(cover, "notice") - form.cover.data = cover - # 处理富文本内容 - title = form.data.get('title', '') - content = form.data.get('content', '') - if content: - form.content.data = save_content(content, title, "notice") + # 通知封面处理 + cover = form.data.get("cover") + if cover: + cover = save_file(cover, "notice") + form.cover.data = cover + # 处理富文本内容 + title = form.data.get("title", "") + content = form.data.get("content", "") + if content: + form.content.data = save_content(content, title, "notice") - # 更新通知公告信息(移除ID,避免更新主键) - form_data = convert_camel_to_snake(form.data.copy()) - form_data.pop('id', None) + # 更新通知公告信息(移除ID,避免更新主键) + form_data = convert_camel_to_snake(form.data.copy()) + form_data.pop("id", None) - form_data['update_time'] = datetime.now(tz=timezone.utc) - form_data['update_user'] = get_username() + form_data["update_time"] = datetime.now(tz=timezone.utc) + form_data["update_user"] = get_username() - result = Notice.query.filter_by(id=notice_id).update(form_data) + result = Notice.query.filter_by(id=notice_id).update(form_data) - if not result: - return R.failed("更新失败") - - return R.ok(msg="更新成功") - - except Exception as e: - logger.error(f"更新通知公告异常: {str(e)}") - return R.failed(msg="更新通知公告失败,请稍后重试") + if not result: + raise BizError("更新失败") # ============================================================ # 通知公告删除 # ============================================================ -def delete_notices(notice_ids): + +def delete_notices(notice_ids: str) -> int: """ 删除通知公告(批量删除) @@ -419,4 +372,7 @@ def delete_notices(notice_ids): Returns: R: 操作结果 """ - return Notice.batch_delete_r(notice_ids) + notice_ids_list = parse_id_list(notice_ids) + if not notice_ids_list: + raise BizError("无效的记录ID") + return Notice.batch_delete(notice_ids_list) diff --git a/src/modules/param/models.py b/src/modules/param/models.py index 583bce0..ec5beae 100644 --- a/src/modules/param/models.py +++ b/src/modules/param/models.py @@ -9,7 +9,6 @@ from src.common.base_db import BaseDB from src.common.base_model import BaseModel from config import DB_PREFIX from src.core.database import db -from src.common.utils.case_converter import convert_camel_to_snake # ============================================================ diff --git a/src/modules/param/repository.py b/src/modules/param/repository.py new file mode 100644 index 0000000..065e4ef --- /dev/null +++ b/src/modules/param/repository.py @@ -0,0 +1,15 @@ +""" +Param 仓储模块 +============================================================= + +数据访问层,继承 BaseRepository 获得通用 CRUD 能力。 +""" + +from src.common.base_repository import BaseRepository +from src.modules.param.models import Param + + +class ParamRepository(BaseRepository): + """Param 仓储""" + + model = Param diff --git a/src/modules/param/router.py b/src/modules/param/router.py index fbea281..b2ccbf8 100644 --- a/src/modules/param/router.py +++ b/src/modules/param/router.py @@ -57,22 +57,24 @@ 依赖模块: application.services.param - 参数业务逻辑层 application.middleware.check_permission - 权限校验中间件 """ -from flask import Blueprint +from flask import Blueprint, request from application.middleware.check_demo import check_demo from application.middleware.check_permission import check_permission from src.modules.param import service as param -from src.common.utils.request import parse_batch_ids -param_blue = Blueprint('param', __name__, url_prefix='/param') +from src.common.utils.request import parse_batch_ids, parse_request_body from src.core import response as R +param_blue = Blueprint("param", __name__, url_prefix="/param") + # ============================================================ # 参数分页查询 # ============================================================ -@param_blue.route('/page', methods=["GET"]) + +@param_blue.route("/page", methods=["GET"]) @check_permission("sys:param:page") def page(): """ @@ -84,15 +86,15 @@ def page(): Returns: JSON: 参数分页数据,包含 records(数据列表)、total(总记录数)等 """ - result = param.get_param_page() - return result + return R.ok(data=param.get_param_page(request.args)) # ============================================================ # 参数详情查询 # ============================================================ -@param_blue.route('/detail/', methods=["GET"]) + +@param_blue.route("/detail/", methods=["GET"]) @check_permission("sys:param:detail") def detail(id): """ @@ -112,7 +114,8 @@ def detail(id): # 参数添加 # ============================================================ -@param_blue.route('/add', methods=["POST"]) + +@param_blue.route("/add", methods=["POST"]) @check_permission("sys:param:add") @check_demo def add(): @@ -125,15 +128,19 @@ def add(): Returns: JSON: 操作结果 """ - result = param.add_param() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + param.add_param(json_data) + return R.ok(msg="添加成功") # ============================================================ # 参数更新 # ============================================================ -@param_blue.route('/update', methods=["PUT"]) + +@param_blue.route("/update", methods=["PUT"]) @check_permission("sys:param:update") @check_demo def update(): @@ -146,15 +153,19 @@ def update(): Returns: JSON: 操作结果 """ - result = param.update_param() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + param.update_param(json_data) + return R.ok(msg="更新成功") # ============================================================ # 参数删除 # ============================================================ -@param_blue.route('/delete/', methods=["DELETE"]) + +@param_blue.route("/delete/", methods=["DELETE"]) @check_permission("sys:param:delete") @check_demo def delete(id): @@ -167,15 +178,16 @@ def delete(id): Returns: JSON: 操作结果 """ - result = param.delete_params(id) - return result + count = param.delete_params(id) + return R.ok(msg=f"本次共删除{count}条数据") # ============================================================ # 参数批量删除 # ============================================================ -@param_blue.route('/batchDelete', methods=["DELETE"]) + +@param_blue.route("/batchDelete", methods=["DELETE"]) @check_permission("sys:param:batch_delete") @check_demo def batch_delete(): @@ -201,7 +213,8 @@ def batch_delete(): # 参数状态设置 # ============================================================ -@param_blue.route('/status', methods=["PUT"]) + +@param_blue.route("/status", methods=["PUT"]) @check_permission("sys:param:status") @check_demo def status(): @@ -214,5 +227,8 @@ def status(): Returns: JSON: 操作结果 """ - result = param.update_param_status() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + param.update_param_status(json_data) + return R.ok(msg="更新成功") diff --git a/src/modules/param/service.py b/src/modules/param/service.py index 33db374..1033740 100644 --- a/src/modules/param/service.py +++ b/src/modules/param/service.py @@ -26,17 +26,15 @@ import logging from datetime import datetime, timezone -from flask import request -from sqlalchemy import and_ from src.common.constants.common import PAGE_SIZE from src.modules.param.schema import ParamForm, ParamStatusForm from src.modules.param.models import Param -from src.core.database import db -from src.core import response as R +from src.modules.param.repository import ParamRepository +from src.core.exceptions import BizError from src.common.utils import regular from src.common.utils.model_utils import models_to_list, model_to_dict -from src.common.utils.request import parse_request_body, parse_id_list, like_contains +from src.common.utils.request import parse_id_list, like_contains from src.core.security import get_username # 获取日志记录器 @@ -47,7 +45,8 @@ logger = logging.getLogger(__name__) # 参数分页查询 # ============================================================ -def get_param_page(): + +def get_param_page(params: dict) -> dict: """ 查询参数分页数据 @@ -70,31 +69,26 @@ def get_param_page(): "pages": 总页数 } """ - try: - # 获取分页参数 - page_no = int(request.args.get('pageNo', 1)) - page_size = int(request.args.get('pageSize', PAGE_SIZE)) + # 获取分页参数 + page_no = int(params.get("pageNo", 1)) + page_size = int(params.get("pageSize", PAGE_SIZE)) - # 应用筛选条件 - query = _apply_filters() + # 应用筛选条件 + query = _apply_filters(params) - # 记录总数 - total = query.count() - # 计算总页数 - pages = (total + page_size - 1) // page_size if total > 0 else 0 + # 记录总数 + total = query.count() + # 计算总页数 + pages = (total + page_size - 1) // page_size if total > 0 else 0 - # 分页查询 - param_list = query.limit(page_size).offset((page_no - 1) * page_size).all() - # 构建返回数据 - page_data = _build_page_data(param_list, total, page_size, page_no, pages) - return R.ok(data=page_data) - - except Exception as e: - logger.error(f"查询参数分页数据异常: {str(e)}") - return R.failed(msg="查询失败,请稍后重试") + # 分页查询 + param_list = query.limit(page_size).offset((page_no - 1) * page_size).all() + # 构建返回数据 + page_data = _build_page_data(param_list, total, page_size, page_no, pages) + return page_data -def _apply_filters(): +def _apply_filters(params: dict): """ 应用查询筛选条件 @@ -113,22 +107,22 @@ def _apply_filters(): query = Param.query.filter(Param.is_delete == 0) # 参数名称模糊筛选 - name = request.args.get('name') + name = params.get("name") if name: - query = query.filter(Param.name.like(like_contains(name), escape='\\')) + query = query.filter(Param.name.like(like_contains(name), escape="\\")) # 参数编码模糊筛选 - code = request.args.get('code') + code = params.get("code") if code: - query = query.filter(Param.code.like(like_contains(code), escape='\\')) + query = query.filter(Param.code.like(like_contains(code), escape="\\")) # 参数类型精确筛选 - param_type = request.args.get('type') + param_type = params.get("type") if param_type: query = query.filter(Param.type == param_type) # 参数状态精确筛选 - status = request.args.get('status') + status = params.get("status") if status: query = query.filter(Param.status == status) @@ -153,19 +147,14 @@ def _build_page_data(param_list, total, page_size, page_no, pages): # 将模型对象列表转换为字典列表 records = models_to_list(param_list) - return { - 'records': records, - 'total': total, - 'size': page_size, - 'current': page_no, - 'pages': pages - } + return {"records": records, "total": total, "size": page_size, "current": page_no, "pages": pages} # ============================================================ # 参数详情查询 # ============================================================ + def get_param_detail(param_id): """ 根据ID查询参数详情(返回字典格式) @@ -196,6 +185,7 @@ def get_param_detail(param_id): # 参数信息查询(根据ID)- 核心查询方法 # ============================================================ + def get_info(param_id: int): """ 根据ID查询参数信息(返回模型对象) @@ -221,26 +211,10 @@ def get_info(param_id: int): if param: print(param.name) """ - # 参数有效性验证 - if not param_id or param_id <= 0: - return None - - try: - # 查询未删除的参数 - param = Param.query.filter( - and_(Param.id == param_id, Param.is_delete == 0) - ).first() - return param - except Exception as e: - logger.error(f"查询参数信息异常,ID: {param_id}, 错误: {str(e)}") - return None + return ParamRepository.get_by_id(param_id) -# ============================================================ -# 参数添加 -# ============================================================ - -def add_param(): +def add_param(data: dict) -> None: """ 添加参数 @@ -252,35 +226,24 @@ def add_param(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = ParamForm(data=json_data) - if not form.validate(): - err_msg = regular.get_err(form) - return R.failed(msg=err_msg) + # 表单验证 + form = ParamForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - # 创建参数 - param = Param(**form.data) - param.create_user = get_username() - param.save() - - return R.ok(msg="添加成功") - - except Exception as e: - logger.error(f"添加参数异常: {str(e)}") - return R.failed(msg="添加参数失败,请稍后重试") + # 创建参数 + param = Param(**form.data) + param.create_user = get_username() + param.save() # ============================================================ # 参数更新 # ============================================================ -def update_param(): + +def update_param(data: dict) -> None: """ 更新参数 @@ -293,52 +256,42 @@ def update_param(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = ParamForm(data=json_data) - if not form.validate(): - return R.failed(msg=regular.get_err(form)) + # 表单验证 + form = ParamForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - # 获取参数ID - param_id = form.data.get('id') - if not param_id or int(param_id) <= 0: - return R.failed("参数ID无效") - param_id = int(param_id) + # 获取参数ID + param_id = form.data.get("id") + if not param_id or int(param_id) <= 0: + raise BizError("参数ID无效") + param_id = int(param_id) - # 复用 get_info 方法验证参数是否存在 - param = get_info(param_id) - if not param: - return R.failed("参数不存在") + # 复用 get_info 方法验证参数是否存在 + param = get_info(param_id) + if not param: + raise BizError("参数不存在") - # 更新参数信息(移除ID,避免更新主键) - form_data = form.data.copy() - form_data.pop('id', None) + # 更新参数信息(移除ID,避免更新主键) + form_data = form.data.copy() + form_data.pop("id", None) - form_data['update_time'] = datetime.now(tz=timezone.utc) - form_data['update_user'] = get_username() + form_data["update_time"] = datetime.now(tz=timezone.utc) + form_data["update_user"] = get_username() - result = Param.query.filter_by(id=param_id).update(form_data) + result = Param.query.filter_by(id=param_id).update(form_data) - if not result: - return R.failed("更新失败") - - return R.ok(msg="更新成功") - - except Exception as e: - logger.error(f"更新参数异常: {str(e)}") - return R.failed(msg="更新参数失败,请稍后重试") + if not result: + raise BizError("更新失败") # ============================================================ # 参数删除 # ============================================================ -def delete_params(param_ids): + +def delete_params(param_ids: str) -> int: """ 删除参数(批量删除) @@ -351,14 +304,18 @@ def delete_params(param_ids): Returns: R: 操作结果 """ - return Param.batch_delete_r(param_ids) + param_ids_list = parse_id_list(param_ids) + if not param_ids_list: + raise BizError("无效的记录ID") + return Param.batch_delete(param_ids_list) # ============================================================ # 参数状态设置 # ============================================================ -def update_param_status(): + +def update_param_status(data: dict) -> None: """ 设置参数状态 @@ -367,35 +324,23 @@ def update_param_status(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = ParamStatusForm(data=json_data) - if not form.validate(): - err_msg = regular.get_err(form) - return R.failed(msg=err_msg) + # 表单验证 + form = ParamStatusForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - param_id = int(form.data['id']) - status = int(form.data['status']) + param_id = int(form.data["id"]) + status = int(form.data["status"]) - # 复用 get_info 方法验证参数是否存在 - param = get_info(param_id) - if not param: - return R.failed("参数不存在") + # 复用 get_info 方法验证参数是否存在 + param = get_info(param_id) + if not param: + raise BizError("参数不存在") - # 更新状态 - update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()} - result = Param.query.filter_by(id=param_id).update(update_data) + # 更新状态 + update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()} + result = Param.query.filter_by(id=param_id).update(update_data) - if not result: - return R.failed("设置失败") - - return R.ok(msg="设置成功") - - except Exception as e: - logger.error(f"设置参数状态异常: {str(e)}") - return R.failed(msg="设置参数状态失败,请稍后重试") + if not result: + raise BizError("设置失败") diff --git a/src/modules/system/level/models.py b/src/modules/system/level/models.py index 9e21e7a..9e5bd65 100644 --- a/src/modules/system/level/models.py +++ b/src/modules/system/level/models.py @@ -50,7 +50,6 @@ from src.common.base_db import BaseDB from src.common.base_model import BaseModel from config import DB_PREFIX from src.core.database import db -from src.common.utils.case_converter import convert_camel_to_snake # ============================================================ diff --git a/src/modules/system/level/repository.py b/src/modules/system/level/repository.py new file mode 100644 index 0000000..f7e58e7 --- /dev/null +++ b/src/modules/system/level/repository.py @@ -0,0 +1,15 @@ +""" +Level 仓储模块 +============================================================= + +数据访问层,继承 BaseRepository 获得通用 CRUD 能力。 +""" + +from src.common.base_repository import BaseRepository +from src.modules.system.level.models import Level + + +class LevelRepository(BaseRepository): + """Level 仓储""" + + model = Level diff --git a/src/modules/system/level/router.py b/src/modules/system/level/router.py index 9f49d0a..9725e0c 100644 --- a/src/modules/system/level/router.py +++ b/src/modules/system/level/router.py @@ -56,22 +56,24 @@ 依赖模块: application.services.level - 职级业务逻辑层 application.middleware.check_permission - 权限校验中间件 """ -from flask import Blueprint +from flask import Blueprint, request from application.middleware.check_demo import check_demo from application.middleware.check_permission import check_permission from src.modules.system.level import service as level -from src.common.utils.request import parse_batch_ids -level_blue = Blueprint('level', __name__, url_prefix='/level') +from src.common.utils.request import parse_batch_ids, parse_request_body from src.core import response as R +level_blue = Blueprint("level", __name__, url_prefix="/level") + # ============================================================ # 职级分页查询 # ============================================================ -@level_blue.route('/page', methods=["GET"]) + +@level_blue.route("/page", methods=["GET"]) @check_permission("sys:level:page") def page(): """ @@ -83,15 +85,15 @@ def page(): Returns: JSON: 职级分页数据,包含 records(数据列表)、total(总记录数)等 """ - result = level.get_level_page() - return result + return R.ok(data=level.get_level_page(request.args)) # ============================================================ # 职级详情查询 # ============================================================ -@level_blue.route('/detail/', methods=["GET"]) + +@level_blue.route("/detail/", methods=["GET"]) @check_permission("sys:level:detail") def detail(id): """ @@ -111,7 +113,8 @@ def detail(id): # 职级添加 # ============================================================ -@level_blue.route('/add', methods=["POST"]) + +@level_blue.route("/add", methods=["POST"]) @check_permission("sys:level:add") @check_demo def add(): @@ -124,15 +127,19 @@ def add(): Returns: JSON: 操作结果 """ - result = level.add_level() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + level.add_level(json_data) + return R.ok(msg="添加成功") # ============================================================ # 职级更新 # ============================================================ -@level_blue.route('/update', methods=["PUT"]) + +@level_blue.route("/update", methods=["PUT"]) @check_permission("sys:level:update") @check_demo def update(): @@ -145,15 +152,19 @@ def update(): Returns: JSON: 操作结果 """ - result = level.update_level() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + level.update_level(json_data) + return R.ok(msg="更新成功") # ============================================================ # 职级删除 # ============================================================ -@level_blue.route('/delete/', methods=["DELETE"]) + +@level_blue.route("/delete/", methods=["DELETE"]) @check_permission("sys:level:delete") @check_demo def delete(id): @@ -166,15 +177,16 @@ def delete(id): Returns: JSON: 操作结果 """ - result = level.delete_levels(id) - return result + count = level.delete_levels(id) + return R.ok(msg=f"本次共删除{count}条数据") # ============================================================ # 职级批量删除 # ============================================================ -@level_blue.route('/batchDelete', methods=["DELETE"]) + +@level_blue.route("/batchDelete", methods=["DELETE"]) @check_permission("sys:level:batch_delete") @check_demo def batch_delete(): @@ -200,7 +212,8 @@ def batch_delete(): # 职级状态设置 # ============================================================ -@level_blue.route('/status', methods=["PUT"]) + +@level_blue.route("/status", methods=["PUT"]) @check_permission("sys:level:status") @check_demo def status(): @@ -213,15 +226,19 @@ def status(): Returns: JSON: 操作结果 """ - result = level.update_level_status() - return result + json_data, err = parse_request_body() + if err: + return R.failed(msg=err) + level.update_level_status(json_data) + return R.ok(msg="更新成功") # ============================================================ # Excel导入 # ============================================================ -@level_blue.route('/import', methods=["POST"]) + +@level_blue.route("/import", methods=["POST"]) @check_permission("sys:level:import") @check_demo def imports(): @@ -242,7 +259,8 @@ def imports(): # Excel导出 # ============================================================ -@level_blue.route('/export', methods=["POST"]) + +@level_blue.route("/export", methods=["POST"]) @check_permission("sys:level:export") @check_demo def export(): @@ -263,7 +281,8 @@ def export(): # 职级列表获取(无分页) # ============================================================ -@level_blue.route('/list', methods=["GET"]) + +@level_blue.route("/list", methods=["GET"]) def get_level_list(): """ 获取职级数据列表(无分页) diff --git a/src/modules/system/level/service.py b/src/modules/system/level/service.py index 56144f4..e873389 100644 --- a/src/modules/system/level/service.py +++ b/src/modules/system/level/service.py @@ -71,24 +71,25 @@ import time import logging from datetime import datetime, timezone -from flask import request +from sqlalchemy import and_ from openpyxl.reader.excel import load_workbook from openpyxl.workbook import Workbook -from sqlalchemy import and_ import utils from src.common.constants.common import PAGE_SIZE from src.modules.system.level.schema import LevelForm, LevelStatusForm from src.modules.system.level.models import Level +from src.modules.system.level.repository import LevelRepository +from src.core import response as R +from src.core.database import db +from src.core.exceptions import BizError from src.modules.upload import service as upload from config import FLASK_TEMP_PATH, FLASK_UPLOAD_DIR -from src.core.database import db -from src.core import response as R from src.common.utils import regular from src.common.utils.case_converter import convert_camel_to_snake from src.common.utils.model_utils import models_to_list, model_to_dict -from src.common.utils.request import parse_request_body, parse_id_list, like_contains +from src.common.utils.request import parse_id_list, like_contains from src.common.utils.rich_text import get_file_url from src.common.utils.file import mkdir from src.core.security import get_username @@ -101,7 +102,8 @@ logger = logging.getLogger(__name__) # 职级分页查询 # ============================================================ -def get_level_page(): + +def get_level_page(params: dict) -> dict: """ 查询职级分页数据 @@ -122,31 +124,26 @@ def get_level_page(): "pages": 总页数 } """ - try: - # 获取分页参数 - page_no = int(request.args.get('pageNo', 1)) - page_size = int(request.args.get('pageSize', PAGE_SIZE)) + # 获取分页参数 + page_no = int(params.get("pageNo", 1)) + page_size = int(params.get("pageSize", PAGE_SIZE)) - # 应用筛选条件 - query = _apply_filters() + # 应用筛选条件 + query = _apply_filters(params) - # 记录总数 - total = query.count() - # 计算总页数 - pages = (total + page_size - 1) // page_size if total > 0 else 0 + # 记录总数 + total = query.count() + # 计算总页数 + pages = (total + page_size - 1) // page_size if total > 0 else 0 - # 分页查询 - level_list = query.limit(page_size).offset((page_no - 1) * page_size).all() - # 构建返回数据 - page_data = _build_page_data(level_list, total, page_size, page_no, pages) - return R.ok(data=page_data) - - except Exception as e: - logger.error(f"查询职级分页数据异常: {str(e)}") - return R.failed(msg="查询失败,请稍后重试") + # 分页查询 + level_list = query.limit(page_size).offset((page_no - 1) * page_size).all() + # 构建返回数据 + page_data = _build_page_data(level_list, total, page_size, page_no, pages) + return page_data -def _apply_filters(): +def _apply_filters(params: dict): """ 应用查询筛选条件 @@ -163,12 +160,12 @@ def _apply_filters(): query = Level.query.filter(Level.is_delete == 0) # 职级名称模糊筛选 - name = request.args.get('name') + name = params.get("name") if name: - query = query.filter(Level.name.like(like_contains(name), escape='\\')) + query = query.filter(Level.name.like(like_contains(name), escape="\\")) # 职级状态精确筛选 - status = request.args.get('status') + status = params.get("status") if status: query = query.filter(Level.status == status) @@ -193,19 +190,14 @@ def _build_page_data(level_list, total, page_size, page_no, pages): # 将模型对象列表转换为字典列表 records = models_to_list(level_list) - return { - 'records': records, - 'total': total, - 'size': page_size, - 'current': page_no, - 'pages': pages - } + return {"records": records, "total": total, "size": page_size, "current": page_no, "pages": pages} # ============================================================ # 职级详情查询 # ============================================================ + def get_level_detail(level_id): """ 根据ID查询职级详情(返回字典格式) @@ -236,6 +228,7 @@ def get_level_detail(level_id): # 职级信息查询(根据ID)- 核心查询方法 # ============================================================ + def get_info(level_id: int): """ 根据ID查询职级信息(返回模型对象) @@ -261,26 +254,10 @@ def get_info(level_id: int): if level: print(level.name) """ - # 参数有效性验证 - if not level_id or level_id <= 0: - return None - - try: - # 查询未删除的职级 - level = Level.query.filter( - and_(Level.id == level_id, Level.is_delete == 0) - ).first() - return level - except Exception as e: - logger.error(f"查询职级信息异常,ID: {level_id}, 错误: {str(e)}") - return None + return LevelRepository.get_by_id(level_id) -# ============================================================ -# 职级添加 -# ============================================================ - -def add_level(): +def add_level(data: dict) -> None: """ 添加职级 @@ -292,35 +269,24 @@ def add_level(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = LevelForm(data=json_data) - if not form.validate(): - err_msg = regular.get_err(form) - return R.failed(msg=err_msg) + # 表单验证 + form = LevelForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - # 创建职级 - level = Level(**form.data) - level.create_user = get_username() - level.save() - - return R.ok(msg="添加成功") - - except Exception as e: - logger.error(f"添加职级异常: {str(e)}") - return R.failed(msg="添加失败,请稍后重试") + # 创建职级 + level = Level(**form.data) + level.create_user = get_username() + level.save() # ============================================================ # 职级更新 # ============================================================ -def update_level(): + +def update_level(data: dict) -> None: """ 更新职级 @@ -333,52 +299,42 @@ def update_level(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = LevelForm(data=json_data) - if not form.validate(): - return R.failed(msg=regular.get_err(form)) + # 表单验证 + form = LevelForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - # 获取职级ID - level_id = form.data.get('id') - if not level_id or int(level_id) <= 0: - return R.failed("职级ID无效") - level_id = int(level_id) + # 获取职级ID + level_id = form.data.get("id") + if not level_id or int(level_id) <= 0: + raise BizError("职级ID无效") + level_id = int(level_id) - # 复用 get_info 方法验证职级是否存在 - level = get_info(level_id) - if not level: - return R.failed("职级不存在") + # 复用 get_info 方法验证职级是否存在 + level = get_info(level_id) + if not level: + raise BizError("职级不存在") - # 更新职级信息(移除ID,避免更新主键) - form_data = convert_camel_to_snake(form.data.copy()) - form_data.pop('id', None) + # 更新职级信息(移除ID,避免更新主键) + form_data = convert_camel_to_snake(form.data.copy()) + form_data.pop("id", None) - form_data['update_time'] = datetime.now(tz=timezone.utc) - form_data['update_user'] = get_username() + form_data["update_time"] = datetime.now(tz=timezone.utc) + form_data["update_user"] = get_username() - result = Level.query.filter_by(id=level_id).update(form_data) + result = Level.query.filter_by(id=level_id).update(form_data) - if not result: - return R.failed("更新失败") - - return R.ok(msg="更新成功") - - except Exception as e: - logger.error(f"更新职级异常: {str(e)}") - return R.failed(msg="更新职级失败,请稍后重试") + if not result: + raise BizError("更新失败") # ============================================================ # 职级删除 # ============================================================ -def delete_levels(level_ids): + +def delete_levels(level_ids: str) -> int: """ 删除职级(批量删除) @@ -391,14 +347,18 @@ def delete_levels(level_ids): Returns: R: 操作结果 """ - return Level.batch_delete_r(level_ids) + level_ids_list = parse_id_list(level_ids) + if not level_ids_list: + raise BizError("无效的记录ID") + return Level.batch_delete(level_ids_list) # ============================================================ # 职级状态设置 # ============================================================ -def update_level_status(): + +def update_level_status(data: dict) -> None: """ 设置职级状态 @@ -407,44 +367,33 @@ def update_level_status(): Returns: R: 操作结果 """ - try: - # 获取参数 - json_data, error = parse_request_body() - if error: - return R.failed(msg=error) - # 表单验证 - form = LevelStatusForm(data=json_data) - if not form.validate(): - err_msg = regular.get_err(form) - return R.failed(msg=err_msg) + # 表单验证 + form = LevelStatusForm(data=data) + if not form.validate(): + raise BizError(regular.get_err(form)) - level_id = int(form.data['id']) - status = int(form.data['status']) + level_id = int(form.data["id"]) + status = int(form.data["status"]) - # 复用 get_info 方法验证职级是否存在 - level = get_info(level_id) - if not level: - return R.failed("职级不存在") + # 复用 get_info 方法验证职级是否存在 + level = get_info(level_id) + if not level: + raise BizError("职级不存在") - # 更新状态 - update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()} - result = Level.query.filter_by(id=level_id).update(update_data) + # 更新状态 + update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()} + result = Level.query.filter_by(id=level_id).update(update_data) - if not result: - return R.failed("设置失败") - - return R.ok(msg="设置成功") - - except Exception as e: - logger.error(f"设置职级状态异常: {str(e)}") - return R.failed(msg="设置职级状态失败,请稍后重试") + if not result: + raise BizError("设置失败") # ============================================================ # Excel导入 # ============================================================ + def import_levels(): """ 导入Excel文件批量导入职级 @@ -462,7 +411,7 @@ def import_levels(): try: # 上传并读取Excel文件 file = upload.upload_file(".xls|.xlsx") - path = file['filePath'] + path = file["filePath"] wb = load_workbook(path) ws = wb.worksheets[0] @@ -502,8 +451,8 @@ def import_levels(): finally: # 清理导入产生的临时Excel文件 try: - if 'path' in dir() and path: - abs_path = os.path.join(FLASK_UPLOAD_DIR, path.lstrip('/')) + if "path" in dir() and path: + abs_path = os.path.join(FLASK_UPLOAD_DIR, path.lstrip("/")) if os.path.isfile(abs_path): os.remove(abs_path) except Exception: @@ -514,6 +463,7 @@ def import_levels(): # Excel导出 # ============================================================ + def export_levels(): """ 导出职级数据到Excel文件 @@ -533,17 +483,17 @@ def export_levels(): wb = Workbook() ws = wb.worksheets[0] # 写入表头 - ws.append(['职级ID', '职级名称', '职级排序', '职级状态', '创建时间', '更新时间']) + ws.append(["职级ID", "职级名称", "职级排序", "职级状态", "创建时间", "更新时间"]) # 写入数据 for data in level_list: ws.append(list(data.values())) # 保存文件 - save_path = FLASK_TEMP_PATH + "/" + time.strftime('%Y%m%d') + save_path = FLASK_TEMP_PATH + "/" + time.strftime("%Y%m%d") mkdir(save_path) - file_name = time.strftime('%Y%m%d%H%M%S') + '%05d' % random.randint(0, 100) + ".xlsx" + file_name = time.strftime("%Y%m%d%H%M%S") + "%05d" % random.randint(0, 100) + ".xlsx" file_path = save_path + "/" + file_name wb.save(file_path) @@ -562,6 +512,7 @@ def export_levels(): # 职级列表获取(无分页) # ============================================================ + def get_level_list(): """ 获取所有启用的职级列表(无分页) @@ -574,9 +525,7 @@ def get_level_list(): """ try: # 查询所有启用的职级 - level_list = Level.query.filter( - and_(Level.is_delete == 0, Level.status == 1) - ).order_by(Level.sort.asc()).all() + level_list = Level.query.filter(and_(Level.is_delete == 0, Level.status == 1)).order_by(Level.sort.asc()).all() # 转换为字典列表 result = [] diff --git a/重构方案-v2.md b/重构方案-v2.md index cef680d..5b6cfc4 100644 --- a/重构方案-v2.md +++ b/重构方案-v2.md @@ -354,7 +354,7 @@ from src.core.database import db # 统一 db 单例 | **P1 工具链** | pyproject.toml / requirements-dev.txt / .flake8 / .pre-commit / Makefile / pytest 骨架 | 现有代码 `flake8` 通过(或登记存量告警);`pytest` 空跑通过。**已登记存量告警:154 条(F401×111 / E402×36 / 其余 7);pytest 5 passed** | 低 | | **P2 core+common** | 建 `src/core/` `src/common/`;extensions/utils 打 shim;模型聚合器建 `src/models_registry.py` | 已验收:22 模型表全量识别且 DB 全部存在;src/ flake8 零告警;pytest 5 passed;应用启动;/login 表单校验与 /user/page 鉴权拦截冒烟正常。**基线修复**:application/models + middleware 原被嵌套 `.gitignore`(`*`)误排除,已补入。**登记既有缺陷**:① `flask db` CLI 因 .env 的 FLASK_VERSION 与 --version 冲突报错(Makefile 已加 FLASK_SKIP_DOTENV 规避);② 本机 Redis 未设密码但 REDIS_AUTH=True,/captcha 报 AUTH 错误(环境问题,非重构) | 高(依赖面最大,已完成) | | **P3 模块搬迁** | 按 §2.5 顺序逐组迁移 23 个模块(models→forms→services→views),每批打 shim + 验证 | 已验收:22 模型→19 模块 models.py;23 表单→schema.py;29 服务→service.py(含 executor/scheduler_service/mail_service/sms_service);26 视图→router.py(login+index 合并入 auth)。应用启动、25 蓝图无重复注册(views/__init__.py 已加去重)、pytest 5 passed、接口冒烟(登录校验/鉴权 401)正常 | 中(已完成) | -| **P4 服务层改造** | 26 个服务文件改「入参数据/出参数据」;router 取参包 R;引入 base_service/base_repository + BizError | **P4a 地基已完成**:BizError/base_repository/base_service + 全局处理器接入。**P4b 标杆(position)已完成**:服务函数入参数据/出参数据、raise BizError、repository 层、7 个单测(无需 DB 可测)。**待铺开**:其余 ~25 个服务按 position 范式批量改造 + 单测 | 高(P4a/P4b 已完成,铺开中) | +| **P4 服务层改造** | 26 个服务文件改「入参数据/出参数据」;router 取参包 R;引入 base_service/base_repository + BizError | **P4a 地基 ✓**(BizError/base_repository/base_service)。**P4b 标杆 position ✓**(含单测)。**P4c 批次1 ✓**(notice/param/link/level 服务+router 改造,flake8 零告警,服务运行时验证通过)。**待铺开**:其余 ~20 个服务。注:level 的 Excel import/export 仍返回 R(暂保留 R 导入,后续统一改造) | 高(地基+标杆+批次1 完成,铺开中) | | **P5 DI 注入** | core/permission.py + op_log 接口化;app 工厂注入 menu 服务 | `grep -r "from application" src/core/` 为空;权限/日志行为与现状一致 | 中 | | **P6 API v1** | routes/v1.py + `/api/v1`;白名单/内部调用/前端前缀同步 | 全部接口路径 `curl /api/v1/...` 通过;`/login` 白名单放行 | 中 | | **P7 切尾** | 删除 application/extensions/utils;`src/wsgi.py`;gunicorn.conf 指向 src.wsgi;更新 CLAUDE.md | `gunicorn -c gunicorn.conf.py src.wsgi:app` 启动;全量回归 | 高 |