This commit is contained in:
2026-06-17 23:02:35 +08:00
parent ca3a109c41
commit f9da920e6b
5 changed files with 160 additions and 69 deletions

View File

@@ -420,10 +420,10 @@ class GetAdminRolesView(APIView):
page = int(request.data.get('page', 1))
page_size = int(request.data.get('pageSize', 20))
# 基础查询:user_type='kefu'存在客服扩展表
users = User.query.filter(user_type='kefu', kefu_profile__isnull=False).select_related('kefu_profile')
# 基础查询:存在客服扩展表
users = User.query.filter(kefu_profile__isnull=False).select_related('kefu_profile')
if phone:
users = users.filter(phone__icontains=phone)
users = users.filter(Phone__icontains=phone)
if nicheng:
users = users.filter(kefu_profile__nicheng__icontains=nicheng)
if role_code:
@@ -488,7 +488,7 @@ class ModifyAdminUserView(APIView):
return Response({'code': 400, 'msg': '缺少目标用户账号'})
try:
target_user = User.query.get(phone=target_phone, user_type='kefu')
target_user = User.query.get(Phone=target_phone)
target_kefu = target_user.kefu_profile
except User.DoesNotExist:
return Response({'code': 404, 'msg': '用户不存在'})
@@ -574,8 +574,8 @@ class AddAdminUserView(APIView):
if len(password) < 6 or len(erjimima) < 6:
return Response({'code': 400, 'msg': '密码和二级密码至少6位'})
# 校验手机号是否已被占用(且 user_type='kefu'
if User.query.filter(phone=phone, user_type='kefu').exists():
# 校验手机号是否已被客服占用
if User.query.filter(Phone=phone, kefu_profile__isnull=False).exists():
return Response({'code': 400, 'msg': '该账号已存在'})
# 生成唯一的 yonghuid7位数字
@@ -588,17 +588,17 @@ class AddAdminUserView(APIView):
timestamp = str(int(time.time() * 1000))
random_suffix = ''.join(random.choices(string.ascii_lowercase + string.digits, k=6))
openid = f"admin_{timestamp}_{random_suffix}"
while User.query.filter(openid=openid).exists():
while User.query.filter(OpenID=openid).exists():
random_suffix = ''.join(random.choices(string.ascii_lowercase + string.digits, k=6))
openid = f"admin_{timestamp}_{random_suffix}"
with transaction.atomic():
user_main = User.query.create(
yonghuid=yonghuid,
openid=openid,
phone=phone,
password=password,
user_type='kefu'
UserUID=yonghuid,
UserName=openid,
OpenID=openid,
Phone=phone,
UserPassword=password,
)
# 创建客服扩展表(后台用户扩展)
UserKefu.query.create(
@@ -607,6 +607,16 @@ class AddAdminUserView(APIView):
erjimima=erjimima,
zhuangtai=1
)
# 分配客服角色
from gvsdsdk.models import UserRole, Role
kefu_role = Role.objects.filter(RoleName='客服').first()
if kefu_role:
UserRole.objects.create(
UserRoleUUID=uuid.uuid4().bytes,
UserUUID=user_main.UserUUID,
RoleUUID=kefu_role.RoleUUID,
CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
)
# 分配角色
for rc in role_codes:
try:

View File

@@ -397,6 +397,74 @@ class User(QModel):
def shoujihao_renzheng(self, value):
self.PhoneVerified = bool(value)
# ── 旧字段兼容属性UserMain → gvsdsdk.User 映射)──
@property
def avatar(self):
return self.Avatar
@avatar.setter
def avatar(self, value):
self.Avatar = value
@property
def phone(self):
return self.Phone
@phone.setter
def phone(self, value):
self.Phone = value
@property
def ip(self):
return self.IP
@ip.setter
def ip(self, value):
self.IP = value
@property
def last_login_time(self):
return self.UserLastLoginDate
@last_login_time.setter
def last_login_time(self, value):
self.UserLastLoginDate = value
@property
def zhifu(self):
"""兼容旧代码 — 收款码图片(存于 UserSensitiveData"""
try:
return self.sensitive_data.zhifu
except Exception:
return ''
@zhifu.setter
def zhifu(self, value):
try:
sd = self.sensitive_data
sd.zhifu = value
sd.save(update_fields=['zhifu'])
except Exception:
pass
@property
def skzhanghao(self):
"""兼容旧代码 — 收款账号(存于 UserSensitiveData"""
try:
return self.sensitive_data.skzhanghao
except Exception:
return ''
@skzhanghao.setter
def skzhanghao(self, value):
try:
sd = self.sensitive_data
sd.skzhanghao = value
sd.save(update_fields=['skzhanghao'])
except Exception:
pass
def set_password(self, raw_password):
self.SetPassword(raw_password)

View File

@@ -390,8 +390,8 @@ class ShangdianLoginView(APIView):
token = str(refresh.access_token)
# 9. 更新最后登录时间
user_main.last_login_time = timezone.now()
user_main.save(update_fields=['last_login_time'])
user_main.UserLastLoginDate = timezone.now()
user_main.save(update_fields=['UserLastLoginDate'])
# 10. 构造返回数据
data = {

View File

@@ -204,21 +204,30 @@ class WechatMiniProgramLoginView(APIView):
with transaction.atomic():
# 创建或获取用户
user_main, created = User.objects.select_for_update().get_or_create(
openid=openid,
defaults={'yonghuid': self.shengchengYonghuID(), 'user_type': 'normal'}
OpenID=openid,
defaults={'UserUID': self.shengchengYonghuID(), 'UserName': openid}
)
# 🆕【新增】保存unionid
if unionid and unionid != user_main.unionid:
user_main.unionid = unionid
# 保存unionid
if unionid and unionid != user_main.UnionID:
user_main.UnionID = unionid
cunchu_ip = kehuduan_ip
user_main.ip = cunchu_ip
user_main.last_login_time = timezone.now()
user_main.IP = kehuduan_ip
user_main.UserLastLoginDate = timezone.now()
user_main.save()
if created:
UserBoss.query.create(user=user_main, nickname='板板大人')
# 新用户默认分配消费者角色
from gvsdsdk.models import UserRole, Role
normal_role = Role.objects.filter(RoleName='消费者').first()
if normal_role:
UserRole.objects.create(
UserRoleUUID=uuid.uuid4().bytes,
UserUUID=user_main.UserUUID,
RoleUUID=normal_role.RoleUUID,
CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
)
# 检查扩展表
dashou_status = 0
@@ -270,7 +279,7 @@ class WechatMiniProgramLoginView(APIView):
token = str(refresh.access_token)
# 计算订单数量
order_counts = self.jisuanDingdanShuliang(user_main.yonghuid)
order_counts = self.jisuanDingdanShuliang(user_main.UserUID)
# 获取群配置
group_info = self.huoquQunPeizhi()
@@ -279,8 +288,8 @@ class WechatMiniProgramLoginView(APIView):
response_data = {
'token': token,
'nicheng': boss_nickname,
'uid': user_main.yonghuid,
'touxiang': user_main.avatar or '',
'uid': user_main.UserUID,
'touxiang': user_main.Avatar or '',
'shangjiastatus': shangjia_status,
'dashoustatus': dashou_status,
'guanshistatus': guanshi_status,
@@ -1694,7 +1703,7 @@ class ShoukuanXinxiShangchuanView(APIView):
# 5. 保存所有信息到数据库
with transaction.atomic():
user_main.phone = txdianhua
user_main.Phone = txdianhua
user_main.skzhanghao = txzh if txzh else ''
# 只有上传了图片才更新zhifu字段
@@ -5317,10 +5326,10 @@ class WechatLoginAndDashouRegisterView(APIView):
with transaction.atomic():
# 4.1 创建或获取用户(登录逻辑)
user_main, created = User.objects.select_for_update().get_or_create(
openid=openid,
OpenID=openid,
defaults={
'yonghuid': self.shengchengYonghuID(),
'user_type': 'normal',
'UserUID': self.shengchengYonghuID(),
'UserName': openid,
}
)
@@ -6785,9 +6794,9 @@ class KefuLoginView(APIView):
}, status=status.HTTP_400_BAD_REQUEST)
# 5. 更新IP和最后登录时间
target_user.ip = client_ip
target_user.last_login_time = timezone.now()
target_user.save(update_fields=['ip', 'last_login_time'])
target_user.IP = client_ip
target_user.UserLastLoginDate = timezone.now()
target_user.save(update_fields=['IP', 'UserLastLoginDate'])
# 6. 生成JWT token
refresh = RefreshToken.for_user(target_user)
@@ -8617,7 +8626,7 @@ class KefuUpdateDashouView(APIView):
# 3. 查询打手是否存在
try:
dashou_user = User.query.get(UserUID=dashou_id, user_type='dashou')
dashou_user = User.query.get(UserUID=dashou_id)
dashou_profile = dashou_user.dashou_profile
except User.DoesNotExist:
return Response({'code': 404, 'msg': '打手不存在'})
@@ -10320,7 +10329,7 @@ class AdKftjView(APIView):
return Response({'code': 401, 'message': '身份验证失败'}, status=status.HTTP_401_UNAUTHORIZED)
# 3. 检查手机号是否已被使用
if User.query.filter(phone=phone).exists():
if User.query.filter(Phone=phone).exists():
return Response({'code': 400, 'message': '该手机号已被注册'})
# 4. 生成唯一 yonghuid
@@ -10336,11 +10345,11 @@ class AdKftjView(APIView):
with transaction.atomic():
# 创建主表用户
user = User.query.create(
yonghuid=generate_yonghuid(),
phone=phone,
password=password,
user_type='kefu',
openid=f'kefu_{phone}' # 临时openid
UserUID=generate_yonghuid(),
UserName=f'kefu_{phone}',
Phone=phone,
UserPassword=password,
OpenID=f'kefu_{phone}' # 临时openid
)
# 创建客服扩展表
kefu = UserKefu.query.create(
@@ -10467,7 +10476,7 @@ class AdKfxgView(APIView):
# 查询客服
try:
user = User.query.get(phone=uid)
user = User.query.get(Phone=uid)
kefu = user.kefu_profile
except (User.DoesNotExist, UserKefu.DoesNotExist):
return Response({'code': 404, 'message': '客服不存在'})
@@ -10477,7 +10486,7 @@ class AdKfxgView(APIView):
# 更新主表字段
if 'phone' in request.data:
new_phone = request.data.get('phone').strip()
if new_phone and User.query.filter(phone=new_phone).exclude(phone=uid).exists():
if new_phone and User.query.filter(Phone=new_phone).exclude(phone=uid).exists():
return Response({'code': 400, 'message': '手机号已被使用'})
user.phone = new_phone
if 'password' in request.data:
@@ -10540,14 +10549,14 @@ class WechatLoginAndGuanshiRegisterView(APIView):
with transaction.atomic():
user_main, created = User.objects.select_for_update().get_or_create(
openid=openid,
OpenID=openid,
defaults={
'yonghuid': self._shengcheng_yonghu_id(),
'user_type': 'normal',
'UserUID': self._shengcheng_yonghu_id(),
'UserName': openid,
}
)
user_main.ip = kehuduan_ip
user_main.last_login_time = timezone.now()
user_main.IP = kehuduan_ip
user_main.UserLastLoginDate = timezone.now()
user_main.save()
if created:

View File

@@ -8,42 +8,46 @@ from rest_framework_simplejwt.authentication import JWTAuthentication
from unittest.mock import Mock
u = User.objects.filter(UserName__isnull=False).first()
print(f'测试用户: {u.UserName}, UserUID: {u.UserUID}')
print(f'用户: {u.UserName}, UserUID: {u.UserUID}')
# 1. JWT 认证
refresh = RefreshToken.for_user(u)
access = refresh.access_token
print('1. JWT Token 生成成功')
auth = JWTAuthentication()
request = Mock()
request.META = {'HTTP_AUTHORIZATION': f'Bearer {access}'}
request._request = request
validated_user, _ = auth.authenticate(request)
print(f' JWT 验证成功: {validated_user.UserName}')
print(f'1. JWT: {validated_user.UserName}')
# 2. yonghuid 兼容属性
# 2. 兼容属性
print(f'2. yonghuid: {u.yonghuid}')
print(f' phone: {u.phone}')
print(f' avatar: {u.avatar}')
print(f' ip: {u.ip}')
print(f' last_login_time: {u.last_login_time}')
print(f' shoujihao_renzheng: {u.shoujihao_renzheng}')
print(f' zhifu: {u.zhifu}')
print(f' skzhanghao: {u.skzhanghao}')
# 3. dashou_profile
dp = u.dashou_profile
print(f'3. dashou_profile: {dp}')
# 4. shoujihao_renzheng
print(f'4. shoujihao_renzheng: {u.shoujihao_renzheng}')
# 5. user_type
print(f'5. user_type: {u.user_type}')
# 6. User.query.get(UserUID=...)
# 3. ORM 查询
u2 = User.query.get(UserUID=u.UserUID)
print(f'6. User.query.get(UserUID=...) OK: {u2.UserName}')
print(f'3. User.query.get(UserUID=): {u2.UserName}')
# 7. user.id
print(f'7. user.id: {u.id}, bool: {bool(u.id)}')
u3 = User.query.filter(OpenID=u.OpenID).first()
print(f' User.query.filter(OpenID=): {u3.UserName}')
# 8. has_role
print(f'8. has_role(dashou): {u.has_role("dashou")}')
u4 = User.query.filter(Phone=u.Phone).first() if u.Phone else None
print(f' User.query.filter(Phone=): {u4.UserName if u4 else "N/A"}')
print()
print('所有兼容性测试通过!')
# 4. user_type
print(f'4. user_type: {u.user_type}')
# 5. has_role
print(f'5. has_role(dashou): {u.has_role("dashou")}')
# 6. dashou_profile
dp = u.dashou_profile
print(f'6. dashou_profile: {dp}')
print('\n所有测试通过!')