lty/qy_lty/CLAUDE.md
pmc 33b302c773 fix(affinity-P1): CR-001 + IN-005 修复 UserDevice 软删语义 + is_bound 改名
UserDevice.is_active 改名为 is_bound(消除与 Device.is_active 的命名冲突),
新增 ActiveUserDeviceManager(active manager),4 处控制权解析调用点
(MAC 登录、bind_status、绑定校验、RTC token、绑定 endpoint)切换到
UserDevice.active.filter(...),避免 P2 软删后旧绑定者被签发 user-token、
WS 分组路由错误、RTC 房间归属错乱等安全 / 越权风险。

base_manager_name='objects' 保证 admin 默认 queryset 不受 active 过滤影响。

详见 docs/REVIEW-affinity-P1.md CR-001 / IN-005。
2026-05-13 10:10:14 +08:00

12 KiB
Raw Blame History

CLAUDE.md

本文件为 Claude Code (claude.ai/code) 在本仓库中工作时提供指导。

沟通语言(重要 — 始终生效)

  • 在本仓库工作时,所有面向用户的回复(思考后的最终回答、状态更新、错误说明、提问、计划摘要等)统一使用中文
  • 内部思考thinking可使用任意语言以保证推理质量呈现给用户的输出必须是中文
  • 工具调用参数、Git 提交信息commit message、代码注释保持原项目约定中文为主必要的英文术语、变量名、API 名等可保留)
  • 此规则覆盖默认的英文输出倾向;只有当用户明确要求改用其他语言时才切换

项目概述

QY LTY Backend 是一个基于 Django 的综合性后端服务,提供以下功能:

  • 用户管理与认证系统
  • AI 对话能力(支持语音的单轮/多轮聊天)
  • 卡片管理系统,支持批量生成与二维码功能
  • 通过 WebSocket 实时通信进行设备交互
  • 成就系统
  • 订阅管理
  • 多种第三方集成(阿里云、火山引擎、腾讯等)

对接的客户端项目

本服务器作为统一后端,与以下客户端/管理端项目进行通讯和数据交互:

项目 路径 角色 通讯方式
LTY_App_Project_URP C:\Unity2022project\LTY_App_Project_URP 洛天依 APPUnity URP 客户端) HTTP REST API + WebSocket (/ws/device/)
LTY_Project C:\Unity2022project\LTY_Project 洛天依 Unity 项目(设备端/终端) HTTP REST API + WebSocket + RTC火山引擎
qy-lty-admin ../qy-lty-admin/C:\Users\admin\Desktop\Lila-Server\qy-lty-admin Web 管理后台Next.js 15 + React 19 HTTP REST APINEXT_PUBLIC_API_BASE_URL
  • 两个 Unity 客户端通过 device_interaction 模块共享同一套 WebSocket 通道(分组模型 device_{user_id}),设备端与 APP 端解析到同一 user_id 才能互通消息
  • 管理后台通过 /api/v1/admin/ 与各业务模块接口进行运营管理数据交互

开发命令

环境配置

# 安装依赖
pip install -r requirements.txt

# 复制环境配置文件
cp .env.bak .env

# 数据库迁移
python manage.py migrate

# 创建超级用户
python manage.py createsuperuser

运行应用

# 启动开发服务器(支持 WebSocket 的 ASGI
./run.sh

# 或直接使用 daphne
daphne -b 0.0.0.0 -p 8000 qy_lty.asgi:application

# 传统 Django 开发服务器(仅 HTTP
python manage.py runserver

数据库管理

# 创建新的迁移文件
python manage.py makemigrations
python manage.py makemigrations [app_name]

# 应用迁移
python manage.py migrate

# 数据库 shell
python manage.py dbshell

# Django shell
python manage.py shell

国际化 (i18n)

# 生成消息文件
django-admin makemessages -l en
django-admin makemessages -l zh_HAns

# 编译翻译
django-admin compilemessages

Docker 部署

# 构建并启动容器
docker-compose up -d --build

# 通过 http://localhost:12012 访问应用

架构概览

核心 Django 应用结构

  • userapp/:自定义用户模型 (ParadiseUser),包含认证、手机验证和用户管理
  • aiapp/AI 对话系统,集成 Kimi通过多个服务商提供语音合成/识别
  • card/:卡片管理系统,包含分类、批次、二维码和使用追踪
  • device_interaction/:基于 WebSocket 的实时设备通信,带有认证机制
  • achievement_app/:用户成就与进度追踪系统
  • subscription_app/:用户订阅与计费管理
  • ali_vi_app/:阿里云视觉智能集成
  • workflow_app/:多租户工作流管理(开发中)

关键技术组件

ASGI/WebSocket 配置

  • 使用 Django Channels 提供 WebSocket 支持
  • 自定义基于 token 的 WebSocket 认证(device_interaction.auth.TokenAuthMiddleware,复用 userapp.authentication.RedisTokenAuthentication
  • 基于 Redis 的通道层用于实时消息传递
  • WebSocket 路由:ws://domain/ws/device/Header 鉴权)和 ws://domain/ws/device/token/{token}/URL 鉴权)
  • 分组模型device_{user_id} —— 设备端与手机端必须解析到 同一个 user_id 才能互通消息(详见下文"设备绑定与控制权"

认证系统

  • 自定义用户模型:userapp.ParadiseUser,继承自 AbstractUser
  • 基于 token 的 API 认证token 存储在 Redis 中,普通用户 key 为 token:{token},管理员为 admin_token:{token}TTL 30 天(见 userapp/utils.py:generate_token
  • 通过短信进行手机验证(阿里云 SMS 服务)
  • 通过 django-allauth 实现社交认证(微信)
  • 设备端通过 POST /api/user/mac-login/ 用 MAC 地址换取绑定用户的 user-token

数据库配置

  • 主库PostgreSQL可通过环境变量配置
  • Redis 用于缓存和 WebSocket 通道层
  • 使用 python-decouple 进行基于环境的配置

音频/语音服务

  • 多服务商音频支持:阿里云、腾讯、火山引擎
  • 通过 AUDIO_SERVICE_PROVIDER 配置切换服务商
  • 支持语音合成与识别能力

API 文档

访问入口

  • Swagger UIhttp://localhost:8000/swagger/
  • ReDochttp://localhost:8000/redoc/

主要 API 模块

  • /api/user/ - 用户认证与管理
  • /api/ai/ - AI 对话接口
  • /api/device/ - 设备交互与 WebSocket 消息
  • /api/card/ - 卡片系统管理
  • /api/achievement/ - 成就系统
  • /api/v1/admin/ - 管理功能

WebSocket 消息类型

{
    "type": "message_type",
    "message": "content",
    "user_id": "user_id"
}

支持的类型(见 device_interaction/consumers.py:DeviceConsumer.receive

  • chat_message — 默认文本消息
  • weather — 天气信息message 为 JSON 字符串)
  • sing / dance / touch — 动作指令
  • flow_light — 流水灯开关
  • device_info — 设备上报 MAC、电量、固件、WiFi 等,会写库并刷新心跳
  • device_state — 手机端设备状态
  • conversation_status / conversation_subtitle — 火山引擎对话回调转发
  • factory_reset — 恢复出厂设置

RTC火山引擎

  • 端点 /api/device/rtc-token/get_by_mac/?mac_address=... 不需鉴权,根据 MAC 返回该设备绑定用户对应的 RTC token
  • room_id = f"room_{user_id}"、token 缓存 key 为 rtc_room:{user_id}:{task_id}
  • room_id 与 WebSocket 分组绑定的是同一个 user_id保持端到端一致

环境配置

必需的环境变量 (.env)

  • SECRET_KEY - Django 密钥
  • DEBUG - 开发模式标志
  • 数据库:POSTGRESQL_DATABASE_* 系列变量
  • RedisREDIS_LOCATIONREDIS_PASSWORD
  • Kimi AIKIMI_API_KEYKIMI_BASE_URL
  • 阿里云服务:各类 ALIYUN_* 密钥
  • 音频服务:服务商相关配置
  • 火山引擎:VOLCENGINE_ACCESS_KEYVOLCENGINE_SECRET_KEY

关键依赖

核心框架

  • Django 4.2.13 配合 Django REST Framework
  • Django Channels 提供 WebSocket 支持
  • Daphne ASGI 服务器

第三方集成

  • 阿里云SMS、OSS、NLS语音、视觉智能
  • 火山引擎字节跳动RTC 服务
  • 腾讯:音频服务
  • OpenAI 兼容 APIKimi

开发工具

  • django-debug-toolbar 用于开发环境调试
  • django-simpleui 用于增强后台管理界面
  • drf-yasg 用于生成 API 文档

代码模式与约定

模型结构

  • 自定义用户模型包含丰富的资料字段性别、MBTI、兴趣等
  • 卡片系统采用基于批次的生成方式,配合分类管理
  • 成就系统包含稀有度等级与进度追踪

API 响应格式

  • 通过 common.middleware.StandardResponseMiddleware 实现标准化响应
  • 自定义分页:common.pagination.CustomPageNumberPagination

日志

  • 集成阿里云日志服务用于生产环境日志记录
  • 为 aiapp、userapp、common 模块配置专用日志记录器

文件存储

  • 使用 OSS阿里云对象存储存储音频和媒体文件
  • 开发环境使用本地存储,路径可配置

开发说明

WebSocket 开发

  • 设备连接需要基于 token 的认证
  • 通道层使用 Redis 进行消息传递
  • 自定义消费者位于 device_interaction.consumers
  • 设备心跳:每次收消息时刷新 device:last_seen:{mac}TTL 5 分钟),断连时把 Device.status 标记为 disconnected

设备绑定与控制权(重要)

  • UserDevice 关联表的 Meta.ordering = ['-bound_at']
  • "后绑的挤掉先绑的"语义userapp/views.py 的 MAC 登录显式按 order_by('-bound_at').first() 取最新绑定者并签发 user-tokendevice_interaction/views.py 中的 bind_status / rtc-token/get_by_mac 等使用 .first() 隐式依赖该 ordering结果一致
  • 由于 WebSocket 分组是 device_{user_id}同一台设备同一时刻只有一个用户能真正控制它——即最近一次绑定的那个用户
  • 必须过滤 is_bound=True(硬规则)P1-08 引入 UserDevice.is_bound(原名 is_activeP1 收尾因与 Device.is_active 命名冲突已改名)作为软删除标记。所有控制权解析的查询MAC 登录、WS 分组、RTC 房间路由、绑定校验、bind_status)必须使用 UserDevice.active.filter(...)activeActiveUserDeviceManager,自动过滤 is_bound=True)。直接 UserDevice.objects.filter(...) 仅供管理后台 / 审计 / 数据迁移等需要历史记录的场景
  • 旧的 UserDevice 记录软删而非硬删:解绑置 is_bound=False,重绑时可读取历史好感度值;硬删仅在运维清理场景下手工执行
  • is_primary 是"用户视角的主设备"(每个用户最多一个),不是"设备视角的主控用户"——同一台设备可能出现多条 is_primary=True 的记录
  • 测试 MAC AA:BB:CC:DD:EE:FFdevice_interaction/serializers.pyviews.py 中被硬编码跳过"设备已被其他用户绑定"校验,仅供测试用

音频服务集成

  • 通过 aiapp.audio.AudioService 提供与服务商无关的接口
  • 支持语音转文本与文本转语音能力
  • 集成文件存储用于音频资源管理

卡片系统功能

  • 批量生成,支持配置数量与格式
  • 二维码生成与扫描
  • 使用追踪与数据分析
  • 基于分类的组织管理,支持属性配置

后台管理界面

  • 深度定制 SimpleUI 主题
  • 支持多语言(中文/英文)
  • 为不同模块配置自定义图标与组织结构

项目修改记录规则(重要 — 自动执行)

每次对本仓库代码做出改动后,必须在同一会话内把变更追加到 docs/修改记录.md 顶部(最新在最前),不要等用户提醒。条目格式遵循该文件头部"修改格式说明"约定:

### [日期] 修改简述

- **文件路径**: 相对于项目根目录的文件路径
- **修改类型**: 新增 / 修改 / 删除 / 重构 / 修复Bug
- **修改内容**: 具体修改了什么
- **修改原因**: 为什么要做这个修改

qy_ltyqy-lty-admin 是独立项目,各自维护

  • qy_lty/docs/修改记录.md记录服务端(本仓库)改动
  • qy-lty-admin/docs/修改记录.md记录管理后台前端改动;如该文件不存在则新建(基于 qy_lty 同名文件的格式骨架)

跨项目联动(例如新增服务端接口 + 管理后台调用):两端各写一条,相互引用对方的修改记录条目,不要把两端混进同一条记录里。

适用范围

  • 业务代码、配置、迁移文件、CI / k8s / Dockerfile、文档结构性改动 → 必须记录
  • 单纯的 typo 修复、注释微调 → 可省略
  • 临时调试脚本、.gitignore 中文件、本地实验文件 → 不记录