fix: 加固称号增删改接口参数校验
兼容空 leixing/中文类型名,规范化板块与称号 ID,避免误报无效类型;修正 update_feiyong 复用逻辑。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -175,6 +175,58 @@ class KhpzhqView(APIView):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_CHENGHAO_LEIXING_OK = frozenset({'dashou', 'boss', 'shangjia', 'guanshi', 'zuzhang'})
|
||||||
|
_CHENGHAO_LEIXING_ALIAS = {
|
||||||
|
'打手': 'dashou',
|
||||||
|
'老板': 'boss',
|
||||||
|
'商家': 'shangjia',
|
||||||
|
'管事': 'guanshi',
|
||||||
|
'组长': 'zuzhang',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_chenghao_leixing(raw, default='dashou'):
|
||||||
|
"""兼容 null / 中文显示名 / 首尾空格,统一为合法 leixing 代码。"""
|
||||||
|
if raw is None or raw == '':
|
||||||
|
return default
|
||||||
|
s = str(raw).strip()
|
||||||
|
if not s:
|
||||||
|
return default
|
||||||
|
if s in _CHENGHAO_LEIXING_OK:
|
||||||
|
return s
|
||||||
|
mapped = _CHENGHAO_LEIXING_ALIAS.get(s) or _CHENGHAO_LEIXING_ALIAS.get(s.lower())
|
||||||
|
if mapped:
|
||||||
|
return mapped
|
||||||
|
lower = s.lower()
|
||||||
|
if lower in _CHENGHAO_LEIXING_OK:
|
||||||
|
return lower
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_optional_bankuai_id(raw):
|
||||||
|
"""空值视为未绑定板块;非法/不存在返回 False。"""
|
||||||
|
if raw is None or raw == '':
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
bid = int(raw)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return False
|
||||||
|
if bid <= 0:
|
||||||
|
return None
|
||||||
|
if not Bankuai.query.filter(bankuai_id=bid).exists():
|
||||||
|
return False
|
||||||
|
return bid
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_chenghao_id(raw):
|
||||||
|
if raw is None or str(raw).strip() == '':
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return int(raw)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class ChzsgcView(APIView):
|
class ChzsgcView(APIView):
|
||||||
"""
|
"""
|
||||||
称号(标签)增删改查统一接口
|
称号(标签)增删改查统一接口
|
||||||
@@ -197,18 +249,21 @@ class ChzsgcView(APIView):
|
|||||||
|
|
||||||
# ========== 创建称号 ==========
|
# ========== 创建称号 ==========
|
||||||
if action == 'create':
|
if action == 'create':
|
||||||
mingcheng = request.data.get('mingcheng', '').strip()
|
mingcheng = (request.data.get('mingcheng') or '').strip()
|
||||||
leixing = request.data.get('leixing', 'dashou')
|
leixing = _normalize_chenghao_leixing(request.data.get('leixing'), default='dashou')
|
||||||
bankuai_id = request.data.get('bankuai_id')
|
bankuai_id = _parse_optional_bankuai_id(request.data.get('bankuai_id'))
|
||||||
texiao_miaoshu = request.data.get('texiao_miaoshu', '')
|
texiao_miaoshu = request.data.get('texiao_miaoshu', '') or ''
|
||||||
kaohe_guize = request.data.get('kaohe_guize', '')
|
kaohe_guize = request.data.get('kaohe_guize', '') or ''
|
||||||
kaioi_jinpai = request.data.get('kaioi_jinpai', False)
|
kaioi_jinpai = bool(request.data.get('kaioi_jinpai', False))
|
||||||
feiyong_list = request.data.get('feiyong_list', [])
|
feiyong_list = request.data.get('feiyong_list', [])
|
||||||
|
|
||||||
if not mingcheng:
|
if not mingcheng:
|
||||||
return Response({'code': 1, 'msg': '称号名称不能为空'}, status=400)
|
return Response({'code': 1, 'msg': '称号名称不能为空'}, status=400)
|
||||||
if leixing not in ['dashou','boss','shangjia','guanshi','zuzhang']:
|
if leixing is None:
|
||||||
|
logger.warning('ChzsgcView create 无效 leixing=%r', request.data.get('leixing'))
|
||||||
return Response({'code': 1, 'msg': '无效的称号类型'}, status=400)
|
return Response({'code': 1, 'msg': '无效的称号类型'}, status=400)
|
||||||
|
if bankuai_id is False:
|
||||||
|
return Response({'code': 1, 'msg': '板块不存在'}, status=400)
|
||||||
if Chenghao.query.filter(mingcheng=mingcheng).exists():
|
if Chenghao.query.filter(mingcheng=mingcheng).exists():
|
||||||
return Response({'code': 1, 'msg': '称号名称已存在'}, status=400)
|
return Response({'code': 1, 'msg': '称号名称已存在'}, status=400)
|
||||||
|
|
||||||
@@ -238,7 +293,7 @@ class ChzsgcView(APIView):
|
|||||||
|
|
||||||
# ========== 修改称号 ==========
|
# ========== 修改称号 ==========
|
||||||
elif action == 'update':
|
elif action == 'update':
|
||||||
ch_id = request.data.get('chenghao_id')
|
ch_id = _parse_chenghao_id(request.data.get('chenghao_id'))
|
||||||
if not ch_id:
|
if not ch_id:
|
||||||
return Response({'code': 1, 'msg': '缺少称号ID'}, status=400)
|
return Response({'code': 1, 'msg': '缺少称号ID'}, status=400)
|
||||||
try:
|
try:
|
||||||
@@ -246,17 +301,25 @@ class ChzsgcView(APIView):
|
|||||||
except Chenghao.DoesNotExist:
|
except Chenghao.DoesNotExist:
|
||||||
return Response({'code': 1, 'msg': '称号不存在'}, status=404)
|
return Response({'code': 1, 'msg': '称号不存在'}, status=404)
|
||||||
|
|
||||||
mingcheng = request.data.get('mingcheng', ch.mingcheng).strip()
|
mingcheng = (request.data.get('mingcheng') if request.data.get('mingcheng') is not None else ch.mingcheng) or ''
|
||||||
leixing = request.data.get('leixing', ch.leixing)
|
mingcheng = str(mingcheng).strip()
|
||||||
bankuai_id = request.data.get('bankuai_id', ch.bankuai_id)
|
raw_leixing = request.data.get('leixing', ch.leixing)
|
||||||
|
leixing = _normalize_chenghao_leixing(raw_leixing, default=ch.leixing or 'dashou')
|
||||||
|
if 'bankuai_id' in request.data:
|
||||||
|
bankuai_id = _parse_optional_bankuai_id(request.data.get('bankuai_id'))
|
||||||
|
else:
|
||||||
|
bankuai_id = ch.bankuai_id
|
||||||
texiao_miaoshu = request.data.get('texiao_miaoshu', ch.texiao_miaoshu)
|
texiao_miaoshu = request.data.get('texiao_miaoshu', ch.texiao_miaoshu)
|
||||||
kaohe_guize = request.data.get('kaohe_guize', ch.kaohe_guize)
|
kaohe_guize = request.data.get('kaohe_guize', ch.kaohe_guize)
|
||||||
kaioi_jinpai = request.data.get('kaioi_jinpai', ch.kaioi_jinpai)
|
kaioi_jinpai = request.data.get('kaioi_jinpai', ch.kaioi_jinpai)
|
||||||
|
|
||||||
if not mingcheng:
|
if not mingcheng:
|
||||||
return Response({'code': 1, 'msg': '称号名称不能为空'}, status=400)
|
return Response({'code': 1, 'msg': '称号名称不能为空'}, status=400)
|
||||||
if leixing not in ['dashou','boss','shangjia','guanshi','zuzhang']:
|
if leixing is None:
|
||||||
|
logger.warning('ChzsgcView update 无效 leixing=%r ch_id=%s', raw_leixing, ch_id)
|
||||||
return Response({'code': 1, 'msg': '无效的称号类型'}, status=400)
|
return Response({'code': 1, 'msg': '无效的称号类型'}, status=400)
|
||||||
|
if bankuai_id is False:
|
||||||
|
return Response({'code': 1, 'msg': '板块不存在'}, status=400)
|
||||||
if Chenghao.query.filter(mingcheng=mingcheng).exclude(id=ch_id).exists():
|
if Chenghao.query.filter(mingcheng=mingcheng).exclude(id=ch_id).exists():
|
||||||
return Response({'code': 1, 'msg': '称号名称已存在'}, status=400)
|
return Response({'code': 1, 'msg': '称号名称已存在'}, status=400)
|
||||||
|
|
||||||
@@ -265,7 +328,7 @@ class ChzsgcView(APIView):
|
|||||||
ch.bankuai_id = bankuai_id
|
ch.bankuai_id = bankuai_id
|
||||||
ch.texiao_miaoshu = texiao_miaoshu
|
ch.texiao_miaoshu = texiao_miaoshu
|
||||||
ch.kaohe_guize = kaohe_guize
|
ch.kaohe_guize = kaohe_guize
|
||||||
ch.kaioi_jinpai = kaioi_jinpai
|
ch.kaioi_jinpai = bool(kaioi_jinpai)
|
||||||
ch.save()
|
ch.save()
|
||||||
|
|
||||||
# 如果前端传递了 feiyong_list,则全量替换费用
|
# 如果前端传递了 feiyong_list,则全量替换费用
|
||||||
@@ -284,7 +347,7 @@ class ChzsgcView(APIView):
|
|||||||
|
|
||||||
# ========== 删除称号 ==========
|
# ========== 删除称号 ==========
|
||||||
elif action == 'delete':
|
elif action == 'delete':
|
||||||
ch_id = request.data.get('chenghao_id')
|
ch_id = _parse_chenghao_id(request.data.get('chenghao_id'))
|
||||||
if not ch_id:
|
if not ch_id:
|
||||||
return Response({'code': 1, 'msg': '缺少称号ID'}, status=400)
|
return Response({'code': 1, 'msg': '缺少称号ID'}, status=400)
|
||||||
try:
|
try:
|
||||||
@@ -295,11 +358,11 @@ class ChzsgcView(APIView):
|
|||||||
return Response({'code': 0, 'msg': '删除成功'})
|
return Response({'code': 0, 'msg': '删除成功'})
|
||||||
|
|
||||||
# ========== 添加/修改某次费用 ==========
|
# ========== 添加/修改某次费用 ==========
|
||||||
elif action == 'add_feiyong':
|
elif action in ('add_feiyong', 'update_feiyong'):
|
||||||
ch_id = request.data.get('chenghao_id')
|
ch_id = _parse_chenghao_id(request.data.get('chenghao_id'))
|
||||||
cishu = request.data.get('cishu')
|
cishu = request.data.get('cishu')
|
||||||
feiyong = request.data.get('feiyong', 0)
|
feiyong = request.data.get('feiyong', 0)
|
||||||
if not ch_id or not cishu:
|
if not ch_id or cishu is None or cishu == '':
|
||||||
return Response({'code': 1, 'msg': '缺少称号ID或次数'}, status=400)
|
return Response({'code': 1, 'msg': '缺少称号ID或次数'}, status=400)
|
||||||
try:
|
try:
|
||||||
ch = Chenghao.query.get(id=ch_id)
|
ch = Chenghao.query.get(id=ch_id)
|
||||||
@@ -308,16 +371,16 @@ class ChzsgcView(APIView):
|
|||||||
if int(cishu) < 1:
|
if int(cishu) < 1:
|
||||||
return Response({'code': 1, 'msg': '次数必须>=1'}, status=400)
|
return Response({'code': 1, 'msg': '次数必须>=1'}, status=400)
|
||||||
KaoheCishuFeiyong.query.update_or_create(
|
KaoheCishuFeiyong.query.update_or_create(
|
||||||
chenghao=ch, cishu=cishu,
|
chenghao=ch, cishu=int(cishu),
|
||||||
defaults={'feiyong': feiyong}
|
defaults={'feiyong': feiyong}
|
||||||
)
|
)
|
||||||
return Response({'code': 0, 'msg': '添加/修改费用成功'})
|
return Response({'code': 0, 'msg': '添加/修改费用成功'})
|
||||||
|
|
||||||
# ========== 删除某次费用 ==========
|
# ========== 删除某次费用 ==========
|
||||||
elif action == 'remove_feiyong':
|
elif action == 'remove_feiyong':
|
||||||
ch_id = request.data.get('chenghao_id')
|
ch_id = _parse_chenghao_id(request.data.get('chenghao_id'))
|
||||||
cishu = request.data.get('cishu')
|
cishu = request.data.get('cishu')
|
||||||
if not ch_id or not cishu:
|
if not ch_id or cishu is None or cishu == '':
|
||||||
return Response({'code': 1, 'msg': '缺少称号ID或次数'}, status=400)
|
return Response({'code': 1, 'msg': '缺少称号ID或次数'}, status=400)
|
||||||
if int(cishu) == 1:
|
if int(cishu) == 1:
|
||||||
return Response({'code': 1, 'msg': '不能删除第1次考核费用'}, status=400)
|
return Response({'code': 1, 'msg': '不能删除第1次考核费用'}, status=400)
|
||||||
@@ -325,13 +388,9 @@ class ChzsgcView(APIView):
|
|||||||
ch = Chenghao.query.get(id=ch_id)
|
ch = Chenghao.query.get(id=ch_id)
|
||||||
except Chenghao.DoesNotExist:
|
except Chenghao.DoesNotExist:
|
||||||
return Response({'code': 1, 'msg': '称号不存在'}, status=404)
|
return Response({'code': 1, 'msg': '称号不存在'}, status=404)
|
||||||
KaoheCishuFeiyong.query.filter(chenghao=ch, cishu=cishu).delete()
|
KaoheCishuFeiyong.query.filter(chenghao=ch, cishu=int(cishu)).delete()
|
||||||
return Response({'code': 0, 'msg': '删除成功'})
|
return Response({'code': 0, 'msg': '删除成功'})
|
||||||
|
|
||||||
# ========== 修改某次费用(等价于add) ==========
|
|
||||||
elif action == 'update_feiyong':
|
|
||||||
return self.add_feiyong(request) # 复用逻辑
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return Response({'code': 1, 'msg': '未知操作'}, status=400)
|
return Response({'code': 1, 'msg': '未知操作'}, status=400)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user