Build lightweight AI agent admin

This commit is contained in:
Codex
2026-06-08 18:14:59 +08:00
commit e164840f43
2530 changed files with 435693 additions and 0 deletions
@@ -0,0 +1,274 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
编码生成器服务
"""
import logging
import random
import string
import uuid
from datetime import datetime
from typing import Dict, Any
from sqlalchemy import select, and_
from sqlalchemy.ext.asyncio import AsyncSession
from core.code_generator.model import CodeSequence
logger = logging.getLogger(__name__)
class CodeGeneratorService:
"""编码生成器服务"""
@staticmethod
async def generate_code(
db: AsyncSession,
prefix: str = "",
separator: str = "",
generate_mode: str = "date_seq",
date_format: str = "YYYYMMDD",
seq_length: int = 4,
seq_reset_rule: str = "daily",
random_length: int = 6,
custom_template: str = "",
business_type: str = "default"
) -> str:
"""
生成编码
Args:
db: 数据库会话
prefix: 前缀
separator: 分隔符
generate_mode: 生成模式
date_format: 日期格式
seq_length: 序号长度
seq_reset_rule: 序号重置规则
random_length: 随机字符长度
custom_template: 自定义模板
business_type: 业务类型
Returns:
生成的编码
"""
if generate_mode == "date_seq":
return await CodeGeneratorService._generate_date_seq(
db, prefix, separator, date_format, seq_length, seq_reset_rule, business_type
)
elif generate_mode == "datetime":
return CodeGeneratorService._generate_datetime(prefix, separator)
elif generate_mode == "random":
return CodeGeneratorService._generate_random(prefix, separator, random_length)
elif generate_mode == "snowflake":
return CodeGeneratorService._generate_snowflake(prefix, separator)
elif generate_mode == "uuid":
return CodeGeneratorService._generate_uuid(prefix, separator)
elif generate_mode == "custom":
return await CodeGeneratorService._generate_custom(
db, custom_template, prefix, separator, date_format, seq_length, seq_reset_rule, business_type
)
else:
raise ValueError(f"不支持的生成模式: {generate_mode}")
@staticmethod
async def _generate_date_seq(
db: AsyncSession,
prefix: str,
separator: str,
date_format: str,
seq_length: int,
seq_reset_rule: str,
business_type: str
) -> str:
"""生成日期+序号格式: PREFIX20241222-0001"""
date_str = CodeGeneratorService._format_date(date_format)
date_key = CodeGeneratorService._get_date_key(seq_reset_rule)
# 获取或创建序号记录
seq = await CodeGeneratorService._get_or_create_sequence(
db, business_type, prefix, date_key
)
# 递增序号
seq.current_seq += 1
await db.commit()
await db.refresh(seq)
# 格式化序号
seq_str = str(seq.current_seq).zfill(seq_length)
# 组装编码
parts = [prefix, date_str, seq_str] if prefix else [date_str, seq_str]
return separator.join(parts)
@staticmethod
def _generate_datetime(prefix: str, separator: str) -> str:
"""生成日期时间格式: PREFIX20241222103000"""
datetime_str = datetime.now().strftime("%Y%m%d%H%M%S")
if prefix:
return f"{prefix}{separator}{datetime_str}"
return datetime_str
@staticmethod
def _generate_random(prefix: str, separator: str, length: int) -> str:
"""生成随机字符格式: PREFIX-X7K9M2"""
chars = string.ascii_uppercase + string.digits
random_str = ''.join(random.choices(chars, k=length))
if prefix:
return f"{prefix}{separator}{random_str}"
return random_str
@staticmethod
def _generate_snowflake(prefix: str, separator: str) -> str:
"""生成雪花ID格式: PREFIX1234567890123456"""
# 简化版雪花ID:时间戳(42位) + 随机数(22位)
timestamp = int(datetime.now().timestamp() * 1000)
random_part = random.randint(0, 4194303) # 22位随机数
snowflake_id = (timestamp << 22) | random_part
if prefix:
return f"{prefix}{separator}{snowflake_id}"
return str(snowflake_id)
@staticmethod
def _generate_uuid(prefix: str, separator: str) -> str:
"""生成UUID片段格式: PREFIX-a1b2c3d4"""
uuid_str = str(uuid.uuid4()).replace('-', '')[:8]
if prefix:
return f"{prefix}{separator}{uuid_str}"
return uuid_str
@staticmethod
async def _generate_custom(
db: AsyncSession,
template: str,
prefix: str,
separator: str,
date_format: str,
seq_length: int,
seq_reset_rule: str,
business_type: str
) -> str:
"""
生成自定义模板格式
支持的占位符:
- {PREFIX}: 前缀
- {DATE}: 日期
- {SEQ}: 序号
- {RANDOM:n}: n位随机字符
- {UUID}: UUID片段
"""
if not template:
return await CodeGeneratorService._generate_date_seq(
db, prefix, separator, date_format, seq_length, seq_reset_rule, business_type
)
result = template
# 替换前缀
if "{PREFIX}" in result:
result = result.replace("{PREFIX}", prefix)
# 替换日期
if "{DATE}" in result:
date_str = CodeGeneratorService._format_date(date_format)
result = result.replace("{DATE}", date_str)
# 替换序号
if "{SEQ}" in result:
date_key = CodeGeneratorService._get_date_key(seq_reset_rule)
seq = await CodeGeneratorService._get_or_create_sequence(
db, business_type, prefix, date_key
)
seq.current_seq += 1
await db.commit()
await db.refresh(seq)
seq_str = str(seq.current_seq).zfill(seq_length)
result = result.replace("{SEQ}", seq_str)
# 替换随机字符
import re
random_pattern = r'\{RANDOM:(\d+)\}'
for match in re.finditer(random_pattern, result):
length = int(match.group(1))
chars = string.ascii_uppercase + string.digits
random_str = ''.join(random.choices(chars, k=length))
result = result.replace(match.group(0), random_str)
# 替换UUID
if "{UUID}" in result:
uuid_str = str(uuid.uuid4()).replace('-', '')[:8]
result = result.replace("{UUID}", uuid_str)
return result
@staticmethod
def _format_date(date_format: str) -> str:
"""格式化日期"""
now = datetime.now()
# 转换前端格式到Python格式(长 token 必须先替换,避免 YYYY 被 YY 截断)
replacements = [
("YYYY", "%Y"),
("YY", "%y"),
("MM", "%m"),
("DD", "%d"),
("HH", "%H"),
("mm", "%M"),
("ss", "%S"),
]
python_format = date_format
for key, value in replacements:
python_format = python_format.replace(key, value)
return now.strftime(python_format)
@staticmethod
def _get_date_key(reset_rule: str) -> str:
"""获取日期键(用于序号重置)"""
now = datetime.now()
if reset_rule == "daily":
return now.strftime("%Y%m%d")
elif reset_rule == "monthly":
return now.strftime("%Y%m")
elif reset_rule == "yearly":
return now.strftime("%Y")
else: # never
return ""
@staticmethod
async def _get_or_create_sequence(
db: AsyncSession,
business_type: str,
prefix: str,
date_key: str
) -> CodeSequence:
"""获取或创建序号记录"""
stmt = select(CodeSequence).where(
and_(
CodeSequence.business_type == business_type,
CodeSequence.prefix == prefix,
CodeSequence.date_key == date_key,
CodeSequence.is_deleted == False
)
)
result = await db.execute(stmt)
seq = result.scalar_one_or_none()
if not seq:
seq = CodeSequence(
business_type=business_type,
prefix=prefix,
date_key=date_key,
current_seq=0
)
db.add(seq)
await db.flush()
return seq