refactor: P4c 批次1 服务层改造(notice/param/link/level)
【服务层新范式批量铺开】4 个 uniform 模块: - service:get_x_page(params)->dict、add/update/status(data)->None、 delete(ids)->int、get_info 委托 Repository(新建 repository.py) - 业务失败 raise BizError;router 取参包 R - level 的 Excel import/export 暂保留 R 返回(后续统一改造) 【工具】codemod 函数级转换(try/except 退格移除、R.failed→BizError、 R.ok→return data)+ black 格式化 + 未用导入清理 【教训】清理脚本 startswith 前缀误删含多名字的 import 行(models_to_list, model_to_dict 同行)导致 F821,已按 F821 精确补回 【验收】应用启动;4 服务分页查询运行时正常;12 passed;flake8 零告警 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
63afa4e629
commit
3f55f62f0d
@@ -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
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -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
|
||||
@@ -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/<int:id>', methods=["GET"])
|
||||
|
||||
@link_blue.route("/detail/<int:id>", 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/<string:id>', methods=["DELETE"])
|
||||
|
||||
@link_blue.route("/delete/<string:id>", 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="更新成功")
|
||||
|
||||
+97
-152
@@ -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("设置失败")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -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
|
||||
@@ -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/<int:id>', methods=["GET"])
|
||||
|
||||
@notice_blue.route("/detail/<int:id>", 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/<string:id>', methods=["DELETE"])
|
||||
|
||||
@notice_blue.route("/delete/<string:id>", 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():
|
||||
|
||||
+89
-133
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -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
|
||||
+36
-20
@@ -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/<int:id>', methods=["GET"])
|
||||
|
||||
@param_blue.route("/detail/<int:id>", 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/<string:id>', methods=["DELETE"])
|
||||
|
||||
@param_blue.route("/delete/<string:id>", 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="更新成功")
|
||||
|
||||
+85
-140
@@ -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("设置失败")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -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
|
||||
@@ -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/<int:id>', methods=["GET"])
|
||||
|
||||
@level_blue.route("/detail/<int:id>", 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/<string:id>', methods=["DELETE"])
|
||||
|
||||
@level_blue.route("/delete/<string:id>", 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():
|
||||
"""
|
||||
获取职级数据列表(无分页)
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
+1
-1
@@ -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` 启动;全量回归 | 高 |
|
||||
|
||||
Reference in New Issue
Block a user