# 单兵终端APP + 声源分析模块 问题清单

> 评估范围：仅评估你们组负责的两个模块  
> 评估时间：2026-05-23

---

## 一、单兵终端APP 问题清单

### 🔴 严重问题（演示前必须修复）

| # | 问题 | 位置 | 影响 | 修复方式 |
|---|------|------|------|----------|
| 1 | **HTML 语法错误** — `</nav>1` 多余字符 | `index.html:471` | DOM 解析异常，底部导航栏下方出现无意义文本 | 删除 `</nav>` 后的 `1` |
| 2 | **调用不存在函数** — `toggleTheme`、`showChangePasswordModal`、`selectDropPointFromMap` | `index.html:237,426,436` | 用户点击直接抛出 `TypeError`，APP 崩溃 | 方案A：在 `app.js` 中补齐这 3 个函数<br>方案B：从 `index.html` 中移除这 3 处 `onclick` 绑定 |
| 3 | **数量验证逻辑漏洞** — `"abc" < 1` 为 `false` | `js/app.js:287` | 输入非数字（如"abc"）绕过验证，`parseInt` 生成 `NaN` 发送到后端导致 500 | ```javascript
const num = parseInt(qty, 10);
if (isNaN(num) || num < 1) { showToast('请输入有效数量'); return; }
``` |
| 4 | **高德地图 API Key 硬编码泄露** | `js/location.js:22,66` | Key 被盗用产生额外费用 | 从代码中删除硬编码 Key，改为从配置文件读取 |
| 5 | **DOM 操作空值保护缺失** — `loadDroneStatus` | `js/app.js:547-557` | 元素不存在时抛出 `TypeError` | 统一添加 `if (el) el.textContent = ...` |
| 6 | **敏感凭证明文存储** — `auth_token` 存 `localStorage` | `js/app.js:196`, `js/api.js:8` | XSS 攻击可直接窃取 Token | 改为 `sessionStorage`，或实现 Token 自动刷新 |
| 7 | **路由栈无限增长** — `pageStack` 只有 push | `js/app.js:75-123` | 内存泄漏，长时间使用后卡顿 | 登录成功用 `replace` 而非 `push`；限制栈深度 |
| 8 | **后台轮询未暂停** | `js/app.js:715`, `js/location.js:509` | 耗电、流量浪费 | 监听 `visibilitychange`，隐藏时 `clearInterval` |
| 9 | **请求超时过短** — 统一 5 秒 | `js/api.js:17` | 弱网环境下频繁超时 | 关键接口改为 10 秒，非关键保持 5 秒 |

### 🟡 一般问题（建议修复）

| # | 问题 | 位置 | 影响 |
|---|------|------|------|
| 10 | **重复嵌套目录** — `js/js/`、`www/js/js/` | 全项目 | 构建脚本路径配置错误，APK 体积增大 |
| 11 | **登录后未清空密码** | `js/app.js:181-213` | 密码在内存中持续存在 |
| 12 | **Mock 数据字段缺失** — `getMockDropPoints` 无 `lat`/`lng` | `js/api.js:177-183` | 地图定位到 `(0, 0)` |
| 13 | **`setInterval` async 未防并发** | `js/location.js:514` | 网络阻塞时请求堆积 |
| 14 | **位置上报失败静默吞掉** | `js/location.js:520-528` | 用户不知位置是否同步成功 |
| 15 | **网络/电量为静态假数据** | `index.html:99-100` | UI 永远显示 `--` |
| 16 | **偏移距离使用随机数** | `js/app.js:636-637` | `Math.random() * 100` 误导用户 |

### 🟢 建议（优化项）

| # | 建议 | 说明 |
|---|------|------|
| 17 | 删除 `rememberMe` 复选框 | 代码完全未实现，纯摆设 |
| 18 | 统一错误码体系 | 区分网络超时/500/认证失效/业务错误 |
| 19 | 地图实例缓存 | 避免每次进入页面销毁重建地图 |

---

## 二、声源分析模块（acoustic）问题清单

### 🔴 严重问题（演示前必须修复）

| # | 问题 | 位置 | 影响 | 修复方式 |
|---|------|------|------|----------|
| 1 | **`AudioBuffer` 除零崩溃** — `capacity_frames_ = 0` 时 `% 0` | `src/core/audio_buffer.cpp:24` | 构造传入 0 时程序崩溃 | 构造函数加 `assert(capacity_samples > 0)` |
| 2 | **`AudioBuffer` 假线程安全** — 头文件声明线程安全但实现无同步 | `include/acoustic_analyzer/core/audio_buffer.h:14` | 多线程调用时数据竞争、内存损坏 | 将 `head_`/`tail_`/`size_` 改为 `std::atomic` 或加 `std::mutex` |
| 3 | **GCC-PHAT 整数溢出** — `int nfft` 左移可能溢出为负数 | `src/core/gcc_phat_localizer.cpp:88-133` | 大输入时死循环或分配负尺寸数组 | 循环索引统一用 `std::size_t`；对 `nfft` 加上限检查 |
| 4 | **YAML 路径不展开** — `$(find pkg)` 语法原样传入 | `config/acoustic_params.yaml:49-50`<br>`src/ros/acoustic_node.cpp:77-78` | 模型加载失败，检测流水线静默失效，永远输出 "unknown" | ```cpp
std::string pkg_path = ros::package::getPath("acoustic_analyzer");
params_.model_path = pkg_path + "/models/gunshot_classifier.onnx";
``` |
| 5 | **UDP 接收队列无界** — `buffer_` 无限增长 | `src/io/mobile_phone_source.cpp:69-95` | 消费慢时内存耗尽 | 设置队列上限，超限时丢弃最旧数据 |
| 6 | **C++ 多模态融合未订阅声学话题** ❗ | `src/多模态融合/cpp/src/main.cpp` | 声学节点发布的 `/acoustic/threats` 无人消费，声源数据无法参与融合避障 | 在融合节点的 `setup_ros()` 中增加：<br>```cpp
ros::Subscriber acoustic_sub_ = nh.subscribe("/acoustic/threats", 5,
    &ThreatFusionNode::acoustic_threats_cb, this);
``` |

### 🟡 一般问题（建议修复）

| # | 问题 | 位置 | 影响 |
|---|------|------|------|
| 7 | **ONNX 节点名硬编码** — `"input"`/`"output"` | `src/core/gunshot_classifier.cpp:170-172` | 模型节点名不同时 `session->Run` 失败 |
| 8 | **Mel 滤波器组路径硬编码** — 相对路径 `"models/..."` | `src/core/feature_extractor.cpp:33` | 工作目录不同时找不到文件 |
| 9 | **魔法数字 `63`** — 目标帧数与模型强耦合 | `src/core/feature_extractor.cpp:124` | 更换模型需重新编译 |
| 10 | **分类器与定位器输入来源不一致** | `src/core/pipeline.cpp:130-149` | 分类器看 0.5s，定位器看 2s，精度下降 |
| 11 | **`Predict` 对空矩阵无校验** | `src/core/gunshot_classifier.cpp:155` | 传入空矩阵时行为未定义 |
| 12 | **demo 参数解析无异常保护** | `tests/demo_offline.cpp:200` | 输入非数字时崩溃 |
| 13 | **WAV 头解析依赖未打包结构体** | `src/io/wav_file_source.cpp:48-50` | 编译器插入填充时解析失败 |
| 14 | **缺少启动自检** — 模型加载失败不退出 | `src/ros/acoustic_node.cpp:63-85` | 节点启动后永远输出假数据 |
| 15 | **`CMakeLists.txt` 缺少 onnxruntime 目录** | `CMakeLists.txt:75` | 首次克隆构建失败 |
| 16 | **`package.xml` 未声明 yaml-cpp 依赖** | `package.xml` | `rosdep` 安装时遗漏 |

### 🟢 建议（优化项）

| # | 建议 | 说明 |
|---|------|------|
| 17 | 统一 ROS 话题命名空间 | 声学节点应支持 UAV 命名空间前缀，如 `/uav1/acoustic/threats` |
| 18 | 增加诊断心跳 | 发布 `DiagnosticArray`，报告模型加载状态、推理耗时 |
| 19 | 将 VAD 门限等参数移入配置 | `-60.0f dB`、`zcr_rate` 等不应写死在代码中 |
| 20 | 声速 `343.0f` 作为配置参数 | 不同温度/海拔下声速变化 |

---

## 三、两个模块之间的关联问题

### 问题 1：后端与声源模块零集成 ❌

- **现状**：后端 `app.py` 没有任何与声源分析模块的接口
- **影响**：单兵APP无法接收声源威胁告警
- **建议**：如需 APP 接收声源告警，后端应订阅 ROS `/acoustic/threats` 话题，通过 WebSocket 推送或轮询接口发送到 APP

### 问题 2：后端无人机状态是演示数据 ⚠️

- **现状**：`_drone_status` 和 `_drone_logs` 是内存变量，非真实无人机数据
- **影响**：单兵APP看到的无人机状态是静态假数据
- **说明**：这是整体架构设计（电脑端前端直连 rosbridge），不属你们模块的责任范围，但需在演示时明确说明

---

## 四、优先修复清单（演示前）

### 单兵终端（Top 5）
1. 删除 `index.html:471` 的 `1`
2. 补齐/移除不存在的函数调用
3. 修复数量验证逻辑
4. 移除硬编码高德 Key
5. 为 DOM 操作加空值保护

### 声源分析（Top 5）
1. 修复 `AudioBuffer` 除零和线程安全
2. 修复 YAML 路径 `$(find)` 不展开问题
3. **在 C++ 多模态融合节点中订阅 `/acoustic/threats`**
4. 修复 GCC-PHAT 整数溢出
5. 为 UDP 接收队列加容量上限

---

## 五、演示注意事项

| 场景 | 预期表现 | 风险点 |
|------|----------|--------|
| 士兵登录APP | 正常 | Token 过期需重新登录 |
| 上报物资需求 | 正常 | 数量输入非数字可能崩溃 |
| 查看无人机状态 | 显示静态演示数据 | 需提前说明这是演示数据 |
| 声源检测 → 融合避障 | **可能无法工作** | 融合节点未订阅声学话题 |
| SOS求救 | 正常 | 会自动标记危险区域 |

**特别提醒**：声源分析模块虽然在离线 demo 中能正常运行，但在完整系统链路中**无法将声源数据送入多模态融合**，这是你们组需要与其他组协调修复的关键集成点。

---

*报告生成时间：2026-05-23*
