Files
JE-Skin/frontend_prompt.md
lennlouisgeek eec9927ae6 first commit
2026-03-30 02:59:56 +08:00

255 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# premise
这是我在展会看到的友商上位机 UI`assets/paxini.jpg`)的风格参考,希望做一份相近气质的前端界面。前端由你负责实现与迭代。
## 约束(长期有效)
- 使用 `Svelte + TypeScript`
- 页面拆分成 `HudPanel``CenterStage``SignalChart`
- 不引入大型 UI 库
- 主色调:近黑背景 + 青蓝 / 荧光绿 / 橙红
- 主界面整体是“一整块 board”通过渐变过渡不做强分块
- 不做明显流光/扫光动画(可有静态纹理层次)
- 样式集中在组件内或 `theme` 文件
- 布局优先 `grid/flex`,仅在必要位置使用绝对定位
- 后续对接 Tauri组件层不要把数据源写死
---
# 当前实现基线(已完成)
## Step1主背景
- 已完成近黑全屏背景、弱渐变、暗角和轻噪声层
- `:root/html/body` 背景已与主界面统一,避免拖动窗口出现黑边断层
## Step2TitleBar + ControlBar + 主布局
- 已完成窗口按钮(最小化 / 最大化切换 / 关闭)
- 已完成 ControlBar
- 配置菜单组(打开/关闭/校准/参数)
- 连接状态卡片
- 串口下拉框
- 中英文切换
- 设备信息行(设备/采样率/通道)
- 页面主结构已固定为:`TitleBar + ControlBar + WebGL2 Area`
## Step2-1Tauri 交互与窗口体验
- TitleBar 已支持拖动(`data-tauri-drag-region`
- 默认窗口大小自动尝试调整到屏幕约 `3/4`
- 已连接 Tauri window commands
```ts
invoke("win_minimize");
invoke("win_toggle_maximize");
invoke("win_close");
```
## Step3HUD 面板与数据演示
- 左右两侧悬浮曲线面板已完成
- 有数据时入场并渲染,无数据时退场(当前 demo5s 开/关周期)
- 折线、渐变填充、边框与深色半透明底已完成
- 底部量程条已完成
---
# 当前前端结构(请按此扩展)
## 1) `src/routes/+page.svelte`
- 页面编排与状态管理
- 维护 `signalPanels`、语言、连接状态、串口、配置菜单选中态
- 将左右面板分流后传给 `CenterStage`
- 处理 Tauri invoke窗口控制
## 2) `src/lib/components/HudPanel.svelte`
- 只负责顶部控制区 UI 与交互事件分发
- 通过事件向外抛出:
- `windowcontrol`
- `localechange`
- `configlink`
- `portchange`
## 3) `src/lib/components/CenterStage.svelte`
- 承载 WebGL2 主区域和左右悬浮 rail
- 接收 `leftPanels/rightPanels` 并在 rail 内渲染 `SignalChart`
- 通过 `ResizeObserver` 动态计算:
- `panel-zone` 顶部起始位置
- 左右 rail 缩放比例(低高度窗口可自适应)
- 侧边定位策略:贴边但保留 `edge inset` 安全距离
## 4) `src/lib/components/SignalChart.svelte`
- 单个曲线面板渲染组件
- 仅消费结构化数据,不关心数据来源
- 支持 `side`left/right`active`(入场/退场)状态
---
# 关键布局规则(避免回归)
- WebGL2 区域占据下半主容器
- HUD 曲线面板浮在 WebGL2 上方,但贴近左右边缘,不遮挡中间核心区域
- 左右面板必须挂在 `CenterStage` 的 rail 容器内
- 不再使用命名 slot 传曲线面板(曾导致面板落到错误容器)
- 调试用彩色边框已移除,保持正式视觉
---
# 数据接入约定(统一结构)
```ts
type SignalTone = "cyan" | "lime" | "orange";
type SignalPanelSide = "left" | "right";
interface HudSignalSeries {
id: string;
tone: SignalTone;
points: number[];
}
interface HudSignalIcon {
id: string;
label: string;
tone: SignalTone;
}
interface HudSignalPanel {
id: string;
code: string;
title: string;
side: SignalPanelSide;
active: boolean;
series: HudSignalSeries[];
icons: HudSignalIcon[];
}
interface HudPacket {
ts: number;
panels: HudSignalPanel[];
}
```
统一入口:
```ts
let signalPanels: HudSignalPanel[] = [];
function applyPacket(packet: HudPacket) {
signalPanels = packet.panels;
}
```
---
# Step3 数据源 Demo可替换
## Demo A本地 Mock
```ts
function startMockFeed(push: (packet: HudPacket) => void): () => void {
let hasData = false;
const cycle = setInterval(() => {
hasData = !hasData;
push({
ts: Date.now(),
panels: hasData ? buildRandomPanels() : buildInactivePanels()
});
}, 5000);
const tick = setInterval(() => {
if (hasData) {
push({
ts: Date.now(),
panels: evolvePanels()
});
}
}, 1200);
return () => {
clearInterval(cycle);
clearInterval(tick);
};
}
```
## Demo BTauri invoke 轮询
```ts
import { invoke } from "@tauri-apps/api/core";
async function fetchHudPacket(): Promise<HudPacket> {
return await invoke<HudPacket>("hud_get_packet");
}
```
## Demo CTauri 事件推送
```ts
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
async function startTauriStream(push: (packet: HudPacket) => void): Promise<() => void> {
const unlisten: UnlistenFn = await listen<HudPacket>("hud_stream", (event) => {
push(event.payload);
});
return () => unlisten();
}
```
## Demo DWebSocket
```ts
function startWebSocket(push: (packet: HudPacket) => void): () => void {
const ws = new WebSocket("ws://127.0.0.1:9001/hud");
ws.onmessage = (e) => push(JSON.parse(e.data) as HudPacket);
return () => ws.close();
}
```
---
# 其他接口建议(主控区联动)
```ts
invoke("sensor_connect", { port: "COM3" });
invoke("sensor_disconnect");
invoke("sensor_set_sample_rate", { hz: 120 });
invoke("sensor_set_channels", { channels: [1, 2, 3, 4] });
invoke("sensor_start_stream");
invoke("sensor_stop_stream");
invoke("sensor_get_status");
```
---
# step3 前端细节调整
1. 添加对串口连接失败的提醒
2. 连接成功后,连接按钮变成断开按钮点击就断开连接
# step 4 webgl2
1. 黑色背景,科技感 UI 容器
2. 一个 64x64 的压力矩阵
3. 用 InstancedMesh 渲染 4096 个小圆柱或小圆环
4. 每个实例根据 value 更新位置、缩放、颜色
5. 支持 OrbitControls 旋转缩放
6. 内置一个假数据生成器,能模拟脚印从无到有再消失
7. 数据更新用平滑插值,不要跳变
8. 左侧显示总压力、最大值、平均值
9. 支持 2D/3D 模式切换,但第一版 2D 可以只是俯视正交投影
# step4 config panel
我需要一个panel来进行参数配置有以下配置后面会加
1. 点阵数量目前默认是64*64我希望可以自定义
2. range上下限我希望可以自定义max和min来映射颜色