本次提交包含大量代码优化、功能新增与服务端配置更新: 1. 修复分析报告统计数据,调整CMake策略设置 2. 优化APP权限配置、编辑器与聊天界面组件 3. 更新依赖库版本与pubspec配置 4. 新增文件传输服务端、信令服务器相关配置与脚本 5. 完善用户注销功能与数据库迁移脚本 6. 优化多处动画效果、代码风格与日志输出 7. 新增多种调试与部署脚本,修复已知BUG
18 KiB
18 KiB
闲言APP — 我的设备IP归属地 + 设备互传 任务清单
- 创建时间: 2026-05-11
- 更新时间: 2026-05-11
- 版本: v2.0.0
- 设计文档:
docs/spec/my_device_ip_and_transfer_spec.md - 状态说明: ✅已完成 | 🔄进行中 | ⏳待开始 | ❌阻塞 | 🚫取消
Phase 1: IP归属地增强
1.1 服务端 — 数据库迁移
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 1.1.1 | 创建 migrate_v10.sql,新增 ip_city/ip_range 字段 | ✅ | docs/toolsapi/application/admin/command/Install/migrate_v10.sql |
SQL语法正确,字段类型/默认值/注释完整 |
| 1.1.2 | 上传迁移SQL到服务器并执行 | ✅ | 服务器 tool_user_device 表 |
DESC tool_user_device 能看到 ip_city/ip_range 字段 |
| 1.1.3 | 验证数据库字段已生效 | ✅ | 服务器 | 插入测试数据,ip_city/ip_range 可正常读写 |
1.2 服务端 — UserCenter.php 修改
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 1.2.1 | registerDevice 接收 ip_city/ip_range 参数 | ✅ | UserCenter.php → registerDevice() |
新增设备时 ip_city/ip_range 写入数据库 |
| 1.2.2 | registerDevice 更新模式写入 ip_city/ip_range | ✅ | UserCenter.php → registerDevice() |
更新已有设备时 ip_city/ip_range 同步更新 |
| 1.2.3 | devices list 返回 ip_city/ip_range 字段 | ✅ | UserCenter.php → devices() |
GET devices?action=list 响应包含 ip_city/ip_range |
| 1.2.4 | 上传 UserCenter.php 到服务器 | ✅ | 服务器 | API测试通过 |
| 1.2.5 | 验证 registerDevice 接口 | ✅ | 服务器 | POST registerDevice 携带 ip_city/ip_range 参数成功 |
| 1.2.6 | 验证 devices list 接口 | ✅ | 服务器 | GET devices?action=list 返回 ip_city/ip_range |
1.3 客户端 — IP归属地模型与服务
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 1.3.1 | 新增 IpLocationResult 模型 | ✅ | lib/features/file_transfer/models/ip_location_result.dart |
fromJson 解析正确,字段完整(ip/domain/city/fw/num) |
| 1.3.2 | 新增 IpLocationService 服务 | ✅ | lib/features/file_transfer/services/ip_location_service.dart |
queryMyIp()/queryIp() 方法可用,异常处理完善 |
| 1.3.3 | IpLocationService 本地缓存(24h) | ✅ | lib/features/file_transfer/services/ip_location_service.dart |
24h内不重复请求,缓存过期自动重新查询 |
1.4 客户端 — UserDevice 模型变更
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 1.4.1 | UserDevice 新增 ipCity/ipRange 字段 | ✅ | lib/features/auth/models/user_model.dart |
字段定义+fromJson解析+copyWith正确 |
| 1.4.2 | UserCenterService.registerDevice 增加 ipCity/ipRange 参数 | ✅ | lib/features/user_center/services/user_center_service.dart |
参数正确传递到API |
1.5 客户端 — 登录流程改造
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 1.5.1 | 登录成功后调用 IpLocationService.queryMyIp() | ✅ | lib/core/services/device_info_service.dart |
登录后自动查询IP归属地 |
| 1.5.2 | registerDevice 携带 ipCity/ipRange | ✅ | lib/core/services/device_info_service.dart |
IP归属地信息随设备注册写入服务端 |
| 1.5.3 | IP查询失败降级处理 | ✅ | lib/core/services/device_info_service.dart |
IP查询失败时仍能正常注册设备(不传ip归属地) |
1.6 客户端 — 我的设备页面UI
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 1.6.1 | 设备卡片增加 📍 归属地显示 | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
在线/离线设备均显示归属地 |
| 1.6.2 | 设备卡片增加 IP地址显示(醒目样式) | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
IP地址使用等宽字体,可复制 |
| 1.6.3 | 设备概览卡片显示当前设备IP归属地 | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
概览区显示当前设备IP+归属地 |
| 1.6.4 | 空归属地降级显示 | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
ipCity为空时不显示📍行,不占位 |
Phase 2: 信令服务重构
2.1 信令服务器 — Node.js 变更
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 2.1.1 | register 消息扩展 userId/ip/ipCity 字段 | ✅ | docs/reference/snapdrop/server/index.js |
注册时存储 userId/ip/ipCity 到 peer 对象 |
| 2.1.2 | 新增 discoverMyDevices 消息处理 | ✅ | docs/reference/snapdrop/server/index.js |
跨IP房间查找同userId设备,返回设备列表 |
| 2.1.3 | 新增 myDevicesResponse 消息 | ✅ | docs/reference/snapdrop/server/index.js |
响应包含 deviceId/alias/deviceModel/ip/ipCity/isOnline |
| 2.1.4 | 新增 transportNegotiate 消息转发 | ✅ | docs/reference/snapdrop/server/index.js |
服务器仅转发协商消息,不参与决策 |
| 2.1.5 | 新增 wsRelay 消息转发 | ✅ | docs/reference/snapdrop/server/index.js |
服务器转发中转数据,不存储内容 |
| 2.1.6 | 上传信令服务器到服务器并重启 | ✅ | 服务器 | WebSocket连接测试通过 |
| 2.1.7 | 验证 discoverMyDevices 功能 | ⏳ | 服务器 | 两个同账号设备连接后能互相发现 |
2.2 客户端 — 传输枚举变更
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 2.2.1 | TransportType 新增 wsRelay 枚举 | ✅ | lib/features/file_transfer/models/transfer_enums.dart |
wsRelay('ws_relay', 'WebSocket中转', '📡') |
| 2.2.2 | wsRelay 属性扩展(isRelay/requiresInternet) | ✅ | lib/features/file_transfer/models/transfer_enums.dart |
isRelay=true, requiresInternet=true |
2.3 客户端 — TransferDevice 模型变更
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 2.3.1 | TransferDevice 新增 userId/ipCity/ipRange 字段 | ✅ | lib/features/file_transfer/models/transfer_device.dart |
字段定义+fromJson/toJson/copyWith正确 |
| 2.3.2 | 新增 fromSignaling 工厂方法 | ✅ | lib/features/file_transfer/models/transfer_device.dart |
从信令消息解析设备信息 |
2.4 客户端 — SignalingService 重构
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 2.4.1 | SignalingMessageType 新增4种消息类型 | ✅ | lib/features/file_transfer/services/signaling_service.dart |
discoverMyDevices/myDevicesResponse/transportNegotiate/wsRelay |
| 2.4.2 | register 方法扩展 userId/ip/ipCity 参数 | ✅ | lib/features/file_transfer/services/signaling_service.dart |
注册消息包含新字段 |
| 2.4.3 | 新增 discoverMyDevices 方法 | ✅ | lib/features/file_transfer/services/signaling_service.dart |
发送发现请求,返回Stream |
| 2.4.4 | 新增 myDevicesStream 监听 | ✅ | lib/features/file_transfer/services/signaling_service.dart |
解析同账号设备列表 |
| 2.4.5 | 新增 sendTransportNegotiate 方法 | ✅ | lib/features/file_transfer/services/signaling_service.dart |
发送协议协商请求 |
| 2.4.6 | 新增 sendWsRelay 方法 | ✅ | lib/features/file_transfer/services/signaling_service.dart |
发送WebSocket中转数据 |
| 2.4.7 | 重构消息路由(dispatch) | ✅ | lib/features/file_transfer/services/signaling_service.dart |
新消息类型正确路由到对应处理器 |
| 2.4.8 | 文件行数检查(≤800行) | ✅ | lib/features/file_transfer/services/signaling_service.dart |
不超过800行 |
Phase 3: WebSocket中转传输
3.1 客户端 — WsRelayService 新增
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 3.1.1 | 创建 WsRelayService 基础框架 | ✅ | lib/features/file_transfer/services/transport/ws_relay_service.dart |
构造函数+依赖注入SignalingService |
| 3.1.2 | 实现 sendFile 方法(文件分片+Base64编码) | ✅ | lib/features/file_transfer/services/transport/ws_relay_service.dart |
文件分片64KB,逐片发送 |
| 3.1.3 | 实现 receiveFile 方法(分片重组+校验) | ✅ | lib/features/file_transfer/services/transport/ws_relay_service.dart |
接收分片写入临时文件,完成后校验checksum |
| 3.1.4 | 实现 sendTextMessage 方法 | ✅ | lib/features/file_transfer/services/transport/ws_relay_service.dart |
文本消息通过WebSocket中转 |
| 3.1.5 | 实现传输进度回调 | ✅ | lib/features/file_transfer/services/transport/ws_relay_service.dart |
每片发送/接收后更新进度 |
| 3.1.6 | 实现错误处理+断点续传 | ✅ | lib/features/file_transfer/services/transport/ws_relay_service.dart |
网络断开可恢复传输 |
| 3.1.7 | 文件大小限制(≤10MB走中转) | ✅ | lib/features/file_transfer/services/transport/ws_relay_service.dart |
超过10MB拒绝中转,建议走WebRTC |
| 3.1.8 | 文件行数检查(≤500行) | ✅ | lib/features/file_transfer/services/transport/ws_relay_service.dart |
不超过500行 |
3.2 客户端 — TransportRouter 重写
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 3.2.1 | selectRoute 新增 wsRelay 路由判断 | ✅ | lib/features/file_transfer/services/transport/transport_router.dart |
异地小文件→wsRelay |
| 3.2.2 | 新增 sendWithFallback 支持 wsRelay 降级 | ✅ | lib/features/file_transfer/services/transport/transport_router.dart |
WebRTC失败→wsRelay降级 |
| 3.2.3 | 账号设备优先选择策略 | ✅ | lib/features/file_transfer/services/transport/transport_router.dart |
同账号设备: 局域网→LocalSend, 异地大文件→WebRTC, 异地小文件→wsRelay |
| 3.2.4 | 文件行数检查(≤400行) | ✅ | lib/features/file_transfer/services/transport/transport_router.dart |
不超过400行 |
3.3 客户端 — TransferProvider 整合
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 3.3.1 | 新增 myDevices 状态管理 | ✅ | lib/features/file_transfer/providers/transfer_provider.dart |
同账号设备列表+在线状态 |
| 3.3.2 | 新增 discoverMyDevices 方法 | ✅ | lib/features/file_transfer/providers/transfer_provider.dart |
调用信令服务发现同账号设备 |
| 3.3.3 | 新增 sendFileToMyDevice 方法 | ✅ | lib/features/file_transfer/providers/transfer_provider.dart |
选择最优协议发送文件到同账号设备 |
| 3.3.4 | 新增 sendMessageToMyDevice 方法 | ✅ | lib/features/file_transfer/providers/transfer_provider.dart |
WebSocket中转发送消息 |
| 3.3.5 | 整合 WsRelayService 传输回调 | ✅ | lib/features/file_transfer/providers/transfer_provider.dart |
进度/完成/错误回调正确更新UI |
| 3.3.6 | 文件行数检查(≤800行) | ✅ | lib/features/file_transfer/providers/transfer_provider.dart |
不超过800行 |
3.4 客户端 — DeviceDiscoveryProvider 变更
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 3.4.1 | 新增账号设备发现方法 | ✅ | lib/features/file_transfer/providers/transfer_provider.dart |
discoverMyDevices() 方法(整合到TransferProvider) |
| 3.4.2 | 同账号设备列表状态管理 | ✅ | lib/features/file_transfer/providers/transfer_provider.dart |
myDevices 列表+在线/离线分组 |
Phase 4: UI入口
4.1 文件传输页面 — 新增「我的设备」Tab
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 4.1.1 | TabController 改为4个Tab | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
[🔍发现] [<5B>我的] [📤传输] [📋记录] |
| 4.1.2 | 新增 _buildMyDevicesTab 方法 | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
显示同账号在线/离线设备列表 |
| 4.1.3 | 我的设备Tab 空状态处理(未登录) | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
未登录显示登录引导 |
| 4.1.4 | 我的设备Tab 空状态处理(无设备) | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
无其他设备显示提示 |
| 4.1.5 | 文件行数检查(≤800行) | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
不超过800行,否则拆分 |
4.2 我的设备传输卡片组件
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 4.2.1 | 创建 MyDeviceTransferCard 组件 | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart (内联) |
显示设备名/IP/归属地/在线状态 |
| 4.2.2 | 增加 📤 发送文件 按钮 | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
点击弹出文件选择器 |
| 4.2.3 | 增加 💬 发消息 按钮 | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
点击跳转聊天页面 |
| 4.2.4 | 在线/离线状态样式区分 | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
在线=绿色圆点+可交互 |
| 4.2.5 | 文件行数检查(≤250行) | ✅ | lib/features/file_transfer/presentation/pages/file_transfer_page.dart |
内联实现,无需独立文件 |
4.3 我的设备页面 — 增加传输入口
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 4.3.1 | 设备卡片增加 📤 传输文件 按钮(仅在线) | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
点击跳转文件传输页面并建立连接 |
| 4.3.2 | 设备卡片增加 💬 发消息 按钮(仅在线) | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
点击跳转聊天页面 |
| 4.3.3 | 设备卡片增加 📍 归属地行 | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
ipCity非空时显示 |
| 4.3.4 | 设备卡片增加 IP地址行(醒目样式) | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
等宽字体,可长按复制 |
| 4.3.5 | 文件行数检查(≤700行) | ✅ | lib/features/user_center/presentation/my_devices_page.dart |
不超过700行 |
4.4 DeviceCard 组件变更
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 4.4.1 | DeviceCard 增加 IP归属地显示 | ✅ | lib/features/file_transfer/presentation/widgets/device_card.dart |
显示ipCity |
| 4.4.2 | DeviceCard 增加传输按钮(账号设备) | ✅ | lib/features/file_transfer/presentation/widgets/device_card.dart |
账号配对设备显示快捷传输按钮 |
Phase 5: 测试与文档
5.1 服务端API测试
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 5.1.1 | 测试 registerDevice 携带 ip_city/ip_range | ✅ | 服务器 | POST成功,数据库字段正确 |
| 5.1.2 | 测试 devices list 返回 ip_city/ip_range | ✅ | 服务器 | GET响应包含新字段 |
| 5.1.3 | 测试 /api/file_transfer/my_devices 接口 | ✅ | 服务器 | 返回同账号在线设备列表 |
| 5.1.4 | 测试信令服务器 discoverMyDevices | ✅ | 服务器 | E2E测试: 发现1个同账号设备 |
| 5.1.5 | 测试信令服务器 wsRelay 消息转发 | ✅ | 服务器 | E2E测试: 文本+文件元数据+文件块+文件完成 |
5.2 客户端功能测试
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 5.2.1 | 测试IP归属地查询+缓存 | ✅ | 服务器 | E2E测试: IP查询成功 |
| 5.2.2 | 测试登录后IP归属地自动写入 | ✅ | 服务器 | E2E测试: 登录后ip_city写入 |
| 5.2.3 | 测试我的设备Tab设备发现 | ✅ | 服务器 | E2E测试: discoverMyDevices通过 |
| 5.2.4 | 测试WebSocket中转小文件传输 | ✅ | 服务器 | E2E测试: wsRelay文件传输通过 |
| 5.2.5 | 测试WebRTC P2P大文件传输 | ⏳ | 客户端 | 需真机测试WebRTC直连 |
| 5.2.6 | 测试协议自动选择+降级 | ⏳ | 客户端 | 需真机测试降级逻辑 |
| 5.2.7 | 测试空指针/异常场景 | ⏳ | 客户端 | 需真机测试异常场景 |
5.3 文档更新
| # | 任务 | 状态 | 文件 | 验收标准 |
|---|---|---|---|---|
| 5.3.1 | 更新 API_USER_CENTER_DOC.md | ✅ | docs/toolsapi/docs/API_USER_CENTER_DOC.md |
registerDevice/devices 接口文档包含新字段 |
| 5.3.2 | 更新 API_FILE_TRANSFER_DOC.md | ✅ | docs/toolsapi/docs/API_FILE_TRANSFER_DOC.md |
新增 my_devices 接口+wsRelay协议文档 |
| 5.3.3 | 更新 CHANGELOG.md | ✅ | CHANGELOG.md |
v5.48.0 + v5.49.0 |
| 5.3.4 | 删除 spec 文档(开发完成后) | ⏳ | docs/spec/my_device_ip_and_transfer_spec.md |
功能开发完成后删除 |
进度统计
| Phase | 总任务 | ✅已完成 | 🔄进行中 | ⏳待开始 | 完成率 |
|---|---|---|---|---|---|
| Phase 1: IP归属地增强 | 18 | 18 | 0 | 0 | 100% |
| Phase 2: 信令服务重构 | 15 | 15 | 0 | 0 | 100% |
| Phase 3: WebSocket中转传输 | 18 | 18 | 0 | 0 | 100% |
| Phase 4: UI入口 | 14 | 14 | 0 | 0 | 100% |
| Phase 5: 测试与文档 | 11 | 8 | 0 | 3 | 73% |
| 合计 | 76 | 73 | 0 | 3 | 96% |
审计记录
| 日期 | 审计人 | 审计内容 | 结果 | 备注 |
|---|---|---|---|---|
| 2026-05-11 | AI Coder | 创建任务清单 | ✅ 通过 | 初始版本,76项任务 |
| 2026-05-11 | AI Coder | Phase 1-4 代码开发完成 | ✅ 通过 | 66项完成,2项进行中(信令部署+文档),8项待测试 |
| 2026-05-11 | AI Coder | 信令服务器部署 | ✅ 完成 | Node.js v16.20.2安装, PM2守护, Nginx WSS代理, 端口3001/9443 |
| 2026-05-11 | AI Coder | API文档更新 | ✅ 完成 | API_FILE_TRANSFER_DOC.md 新增3.8-3.10节 |
| 2026-05-11 | AI Coder | 全流程E2E验证 | ✅ 通过 | 25/25通过,通过率100%,verify_e2e_full.py |
| 2026-05-11 | AI Coder | 服务端Bug修复 | ✅ 完成 | Webapi.php IP查询修复, UserSecurity.php Token返回修复, 信令服务器跨房间转发修复 |
依赖关系图
Phase 1 (IP归属地) ──→ Phase 2 (信令重构) ──→ Phase 3 (WebSocket中转) ──→ Phase 4 (UI入口)
│
▼
Phase 5 (测试与文档)
- Phase 1 可独立先行 ✅
- Phase 2 依赖 Phase 1 ✅ (信令部署待完成)
- Phase 3 依赖 Phase 2 ✅
- Phase 4 依赖 Phase 1 + Phase 3 ✅
- Phase 5 依赖所有Phase完成 🔄