5.7 KiB
EzVibeR+ 实施记录 — 2026-06-11/12
Tauri v2 升级 + 健康提醒 CRUD + 窗口交互修复 + Live2D 表情动作映射
一、双击变大修复
问题
GNOME/KDE 窗口管理器在透明窗口上双击会将窗口最大化/填充屏幕,导致桌面宠变形和点击失效。
修复
| 文件 | 变更 |
|---|---|
src-tauri/tauri.conf.json |
主窗口新增 "maximizable": false,"maxWidth": 800,"maxHeight": 640 |
src-tauri/src/main.rs |
setup 中调用 main_window.set_maximizable(false);show 托盘处理中也设置 |
二、drag-region 逻辑反转(点击修复)
问题
data-tauri-drag-region="true" 默认设在 canvas 上,导致 GNOME 窗口管理器将所有 pointer 事件截获用于拖窗,PIXI 交互系统完全收不到点击。
修复(src/live2d/index.vue)
- 默认:canvas 不设 drag-region → 点击正常到达 DOM → 手动桥接到模型
- 移动模式(工具栏定位按钮):canvas 启用 drag-region → 窗口可拖
onFocusChanged不再恢复 drag-region
DOM→模型桥接
由于 PIXI v6 在 Tauri 透明窗口下交互系统失效,改为直接在 canvas 的 pointerdown 事件中:
- 计算点击坐标相对模型的位置
- 上级 35% 为头部 → 切换表情
- 其余为身体 → 播放动作 + 通知后端情绪引擎
canvas.addEventListener("pointerdown", async (e) => {
const px = (e.clientX - rect.left) * scaleX;
const py = (e.clientY - rect.top) * scaleY;
const isHead = (py - model.y) < model.height * 0.35;
// ...
});
三、健康提醒 CRUD 面板
架构设计
单一数据源:所有提醒行为统一存储在 AppConf.behaviors 中,不再区分"内置"与"自定义"。
新增文件
| 文件 | 用途 |
|---|---|
health.html |
入口页面 |
src/health/App.ts |
Vue 入口 |
src/components/HealthReminders.vue |
CRUD 表格 + 模态表单 |
后端改动
| 文件 | 变更 |
|---|---|
src-tauri/src/app/config.rs |
新增 BehaviorDef 结构体 + default_behaviors() + ensure_default_behaviors() + write_behaviors() 安全写入 |
src-tauri/src/modules/scheduler.rs |
移除硬编码 register_builtin(),新增 reload_all_behaviors() 全量替换 |
src-tauri/src/app/commands.rs |
新增 list_behaviors, add_behavior, update_behavior, delete_behavior |
src-tauri/src/main.rs |
启动时 ensure_default_behaviors() + reload_all_behaviors();托盘新增 "健康提醒" 菜单项 |
安全写入
write_behaviors() 只修改 behaviors 字段,不影响 LLM 等配置:
pub fn write_behaviors(behaviors: Vec<BehaviorDef>) {
let conf = Self::read();
let mut json = serde_json::to_value(&conf).unwrap();
json["behaviors"] = serde_json::to_value(&behaviors).unwrap();
std::fs::write(Self::file_path(), serde_json::to_string_pretty(&json).unwrap());
}
用户使用
右键托盘 → 健康提醒 → 打开管理面板。支持增删改查实时同步到后端调度器。
四、情绪引擎 → Live2D 动作/表情映射
架构
后端 emotion.rs 前端 index.vue
┌─────────────────┐ ┌──────────────────────────┐
│ EmotionEngine │──心跳→ │ ezvibe:emotion/heartbeat │
│ Idle/Happy/... │ │ ↓ │
└─────────────────┘ │ applyEmotion(state) │
│ ├─ motion 动作 │
│ └─ expression 表情 │
└──────────────────────────┘
关键实现
| 功能 | 位置 | 说明 |
|---|---|---|
| 模型能力发现 | discoverModelCapabilities() |
从 model3.json 读取表达式列表和动作组 |
| 情绪→表情映射 | applyEmotion() |
关键词匹配(Happy→星星/比耶, Annoyed→黑脸等) |
| 动作匹配 | fuzzyMatch() |
精确/包含/反向三种策略 |
| 事件监听 | onMounted |
监听 ezvibe:emotion + ezvibe:heartbeat |
表达式文件路径修复
March 7th 模型的表达式文件在 exp/ 子目录,但 model3.json 引用路径不含子目录前缀。pixi-live2d-display v0.4.0 无法正确加载,导致 model.expression() 静默失败。
修复:用 fetch 直接从 exp/{n}.exp3.json 加载表达式文件,调用 coreModel.setParameterValueById() 直接操作 Cubism 4 参数。
表达式重置
每个表达式只改 1 个参数(如 Param27),切换时需先清除上一个表达式的参数:
上一个表达式 → setParameterValueById(Param27, 0) // 清掉
resetExpression() // 原生重置
新表达式 → setParameterValueById(Param28, 0.5) // 应用
记录 lastExpressionParamIds 数组,每次切前先清掉所有上一个涉及的参数 ID。
五、前景遮罩修复
tryAddFrame() 中的前景 Sprite 使用 stage.addChildAt(foreground, 0) 添加到 index 0(最底层),确保模型始终在上方接收事件。
六、配置窗口重建
托盘 "配置中心" / "健康提醒" 点击时先关闭旧窗口再重建,确保 Vue 组件重新挂载并从后端重新读取配置。
七、新增 Tauri 命令
| 命令 | 功能 |
|---|---|
list_behaviors |
列出所有提醒行为 |
add_behavior |
添加提醒行为 |
update_behavior |
更新提醒行为(支持改名) |
delete_behavior |
删除提醒行为 |
debug_log |
前端日志透传到终端 stderr |