fix: 修复多个关键问题

- 修复前端路由守卫:未登录时不显示提示,直接跳转登录页
- 修复API拦截器:401错误不显示提示,直接跳转
- 增强验证码显示:图片尺寸从120x40增加到200x80
- 增大验证码字体:从28号增加到48号
- 优化验证码字符:排除易混淆的0和1
- 减少干扰线:从5条减少到3条,添加背景色优化
- 增强登录API日志:添加详细的调试日志
- 增强验证码生成和验证日志
- 优化异常处理和错误追踪

影响文件:
- src/router/index.ts
- src/api/request.ts
- app/services/auth_service.py
- app/api/v1/auth.py
- app/schemas/user.py

测试状态:
- 前端构建通过
- 后端语法检查通过
- 验证码显示效果优化完成

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-01-25 00:26:21 +08:00
commit e71181f0a3
150 changed files with 39549 additions and 0 deletions

97
app/utils/asset_code.py Normal file
View File

@@ -0,0 +1,97 @@
"""
资产编码生成工具
使用PostgreSQL Advisory Lock保证并发安全
"""
from datetime import datetime
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.config import settings
async def generate_asset_code(db: AsyncSession) -> str:
"""
生成资产编码
格式: AS + YYYYMMDD + 流水号(4位)
示例: AS202501240001
使用PostgreSQL Advisory Lock保证并发安全
Args:
db: 数据库会话
Returns:
资产编码
"""
# 获取当前日期字符串
date_str = datetime.now().strftime("%Y%m%d")
prefix = f"AS{date_str}"
# 使用Advisory Lock保证并发安全
# 使用日期作为锁ID避免不同日期的锁冲突
lock_id = int(date_str)
try:
# 获取锁
await db.execute(text(f"SELECT pg_advisory_lock({lock_id})"))
# 查询今天最大的序号
result = await db.execute(
text("""
SELECT CAST(SUBSTRING(asset_code FROM 13 FOR 4) AS INTEGER) as max_seq
FROM assets
WHERE asset_code LIKE :prefix
AND deleted_at IS NULL
ORDER BY asset_code DESC
LIMIT 1
"""),
{"prefix": f"{prefix}%"}
)
row = result.fetchone()
max_seq = row[0] if row and row[0] else 0
# 生成新序号
new_seq = max_seq + 1
seq_str = f"{new_seq:04d}" # 补零到4位
# 组合编码
asset_code = f"{prefix}{seq_str}"
return asset_code
finally:
# 释放锁
await db.execute(text(f"SELECT pg_advisory_unlock({lock_id})"))
def validate_asset_code(asset_code: str) -> bool:
"""
验证资产编码格式
Args:
asset_code: 资产编码
Returns:
是否有效
"""
if not asset_code or len(asset_code) != 14:
return False
# 检查前缀
if not asset_code.startswith("AS"):
return False
# 检查日期部分
date_str = asset_code[2:10]
try:
datetime.strptime(date_str, "%Y%m%d")
except ValueError:
return False
# 检查序号部分
seq_str = asset_code[10:]
if not seq_str.isdigit():
return False
return True