统一记录后台敏感操作到 xiugaijilu,并提供管理员操作日志查询接口。

覆盖商家/管事/组长资金与封禁、冻结解冻、后台账号变更;列表接口权限 000001。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-17 01:41:35 +08:00
parent 83ccdff0f5
commit d3f6ff34bb
7 changed files with 545 additions and 10 deletions

View File

@@ -0,0 +1,37 @@
# Generated manually for Xiugaijilu zuzhang fields + indexes
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('yonghu', '0025_tixianshenhejilu_dakuan_mch_id'),
]
operations = [
migrations.AddField(
model_name='xiugaijilu',
name='zuzhangyue',
field=models.DecimalField(
decimal_places=2, default=0.00, max_digits=12,
verbose_name='修改后的组长可提现金额',
),
),
migrations.AddField(
model_name='xiugaijilu',
name='zuzhangyueq',
field=models.DecimalField(
decimal_places=2, default=0.00, max_digits=12,
verbose_name='修改前的组长可提现金额',
),
),
migrations.AddIndex(
model_name='xiugaijilu',
index=models.Index(fields=['xiugaiid', '-create_time'], name='idx_xiugai_op_time'),
),
migrations.AddIndex(
model_name='xiugaijilu',
index=models.Index(fields=['yonghuid', '-create_time'], name='idx_xiugai_target_time'),
),
]

View File

@@ -623,6 +623,10 @@ class Xiugaijilu(models.Model):
guanshiyue = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='修改后的管事余额')
guanshiyueq = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='修改前的管事余额')
# 组长可提现余额
zuzhangyue = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='修改后的组长可提现金额')
zuzhangyueq = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='修改前的组长可提现金额')
# 会员相关
huiyuants = models.IntegerField(default=0, verbose_name='添加会员天数')
huiyuan_id = models.CharField(max_length=6, null=True, blank=True, verbose_name='会员ID')
@@ -636,6 +640,10 @@ class Xiugaijilu(models.Model):
db_table = 'xiugaijilu'
verbose_name = '修改记录表'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['xiugaiid', '-create_time'], name='idx_xiugai_op_time'),
models.Index(fields=['yonghuid', '-create_time'], name='idx_xiugai_target_time'),
]
def __str__(self):
return f"修改记录-用户{self.yonghuid}"

102
yonghu/xiugai_log.py Normal file
View File

@@ -0,0 +1,102 @@
"""
后台敏感操作统一写入 xiugaijilu修改/操作日志)。
leixing 约定:
0=系统配置, 2=打手, 3=管事, 4=商家, 5=组长, 9=后台账号
"""
from __future__ import annotations
from decimal import Decimal
from typing import Any, Optional
from .models import Xiugaijilu
LEIXING_SYSTEM = 0
LEIXING_DASHOU = 2
LEIXING_GUANSHI = 3
LEIXING_SHANGJIA = 4
LEIXING_ZUZHANG = 5
LEIXING_KEFU = 9
LEIXING_NAME = {
LEIXING_SYSTEM: '系统配置',
LEIXING_DASHOU: '打手',
LEIXING_GUANSHI: '管事',
LEIXING_SHANGJIA: '商家',
LEIXING_ZUZHANG: '组长',
LEIXING_KEFU: '后台账号',
}
# 冻结提现类型 → 操作日志用户类型
FREEZE_TO_XIUGAI_LEIXING = {
1: LEIXING_DASHOU, # 打手佣金
2: LEIXING_GUANSHI, # 管事
5: LEIXING_DASHOU, # 打手押金
6: LEIXING_SHANGJIA, # 商家
}
FREEZE_LEIXING_NAME = {
1: '打手佣金',
2: '管事分红',
5: '打手押金',
6: '商家余额',
}
def _d(v: Any) -> Decimal:
if v is None:
return Decimal('0.00')
if isinstance(v, Decimal):
return v
return Decimal(str(v))
def write_xiugai_log(
*,
yonghuid: str,
operator_phone: str,
leixing: int,
qitashuoming: str = '',
dashou_yue_before=None,
dashou_yue_after=None,
jifen_before=None,
jifen_after=None,
yajin_before=None,
yajin_after=None,
shangjia_yue_before=None,
shangjia_yue_after=None,
guanshi_yue_before=None,
guanshi_yue_after=None,
zuzhang_yue_before=None,
zuzhang_yue_after=None,
huiyuants: int = 0,
huiyuan_id: Optional[str] = None,
) -> Xiugaijilu:
"""写入一条操作日志;金额类字段仅在传入时覆盖默认 0。"""
kwargs = {
'yonghuid': str(yonghuid or '')[:7],
'xiugaiid': str(operator_phone or '')[:30],
'leixing': int(leixing),
'qitashuoming': (qitashuoming or '')[:2000] or None,
'huiyuants': int(huiyuants or 0),
'huiyuan_id': (str(huiyuan_id)[:6] if huiyuan_id else None),
}
if dashou_yue_before is not None or dashou_yue_after is not None:
kwargs['xiugaitijiaoq'] = _d(dashou_yue_before)
kwargs['xiugaitijiao'] = _d(dashou_yue_after)
if jifen_before is not None or jifen_after is not None:
kwargs['yjifen'] = int(jifen_before or 0)
kwargs['jifen'] = int(jifen_after or 0)
if yajin_before is not None or yajin_after is not None:
kwargs['yyajin'] = _d(yajin_before)
kwargs['yajin'] = _d(yajin_after)
if shangjia_yue_before is not None or shangjia_yue_after is not None:
kwargs['shangjiayueq'] = _d(shangjia_yue_before)
kwargs['shangjiayue'] = _d(shangjia_yue_after)
if guanshi_yue_before is not None or guanshi_yue_after is not None:
kwargs['guanshiyueq'] = _d(guanshi_yue_before)
kwargs['guanshiyue'] = _d(guanshi_yue_after)
if zuzhang_yue_before is not None or zuzhang_yue_after is not None:
kwargs['zuzhangyueq'] = _d(zuzhang_yue_before)
kwargs['zuzhangyue'] = _d(zuzhang_yue_after)
return Xiugaijilu.objects.create(**kwargs)