-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
236 lines (219 loc) · 24.7 KB
/
Copy pathindex.html
File metadata and controls
236 lines (219 loc) · 24.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0d1113" />
<title>VibeCoding Controller Hub</title>
<link rel="stylesheet" href="./styles.css?v=10" />
</head>
<body>
<div class="app-shell">
<header class="topbar">
<div class="brand-lockup">
<div class="brand-mark" aria-hidden="true"><span></span><span></span><span></span></div>
<div><p class="eyebrow">DUALSENSE DESKTOP CONTROL</p><h1>VIBECODING HUB</h1></div>
</div>
<div class="header-actions">
<div class="connection-pill"><span id="connectionDot" class="status-dot"></span><span id="connectionLabel">正在查找手柄</span></div>
<label class="master-switch">
<span>映射</span>
<input id="mappingToggle" type="checkbox" />
<span class="switch-track" aria-hidden="true"><i></i></span>
<strong id="mappingToggleLabel">已停用</strong>
</label>
</div>
</header>
<div class="hub-layout">
<aside class="sidebar">
<nav class="hub-nav" aria-label="功能导航">
<button class="nav-item is-active" type="button" data-view="mapping"><span class="nav-icon">⌘</span><span>按键映射</span></button>
<button class="nav-item" type="button" data-view="touchpad"><span class="nav-icon">↔</span><span>触摸板</span></button>
<button class="nav-item" type="button" data-view="lighting"><span class="nav-icon">◉</span><span>状态灯</span></button>
<button class="nav-item" type="button" data-view="triggers"><span class="nav-icon">⌁</span><span>自适应扳机</span></button>
</nav>
<section class="device-card" aria-label="设备状态">
<div class="device-card-head"><span class="mini-controller">DS</span><div><strong id="deviceName">DualSense</strong><small id="deviceId">054C / ----</small></div></div>
<dl class="device-stats">
<div><dt>连接</dt><dd id="transportValue">USB / 等待</dd></div>
<div><dt>输入报告</dt><dd id="reportCount">0</dd></div>
<div><dt>快捷键派发</dt><dd id="dispatchCount">0</dd></div>
<div><dt>延迟</dt><dd id="reportAge">-- ms</dd></div>
</dl>
<button id="reconnectButton" class="button button-quiet" type="button">重新检测</button>
</section>
<div class="sidebar-footer"><span class="service-dot" id="serviceDot"></span><span id="serviceState">本地服务离线</span><small>127.0.0.1:37845</small></div>
</aside>
<main class="main-stage">
<section id="mappingView" class="view is-active">
<div class="view-header">
<div><p class="eyebrow">01 / INPUT MAPPING</p><h2>按键映射</h2></div>
<div class="profile-controls">
<label for="profileSelect">配置</label>
<select id="profileSelect">
<option value="vibe">Vibe Coding</option>
<option value="navigation">桌面导航</option>
<option value="blank">空白配置</option>
</select>
<button id="resetProfileButton" class="icon-button" type="button" title="恢复当前预设" aria-label="恢复当前预设">↺</button>
</div>
</div>
<div class="mapping-workspace">
<section class="controller-monitor" aria-label="手柄实时输入">
<div class="section-heading"><div><span class="section-kicker">LIVE INPUT</span><h3>手柄监视器</h3></div><span id="inputBadge" class="badge">等待输入</span></div>
<div class="controller-visual" id="controllerVisual">
<img class="controller-wireframe" src="./assets/dualsense-wireframe.png" alt="DualSense 正面线框图" />
<button class="twin-node twin-shoulder" type="button" data-button="l2" style="--x:31%;--y:9%"><span>L2</span><kbd data-map-for="l2"></kbd></button>
<button class="twin-node twin-shoulder" type="button" data-button="r2" style="--x:69%;--y:9%"><span>R2</span><kbd data-map-for="r2"></kbd></button>
<button class="twin-node twin-shoulder" type="button" data-button="l1" style="--x:38%;--y:12%"><span>L1</span><kbd data-map-for="l1"></kbd></button>
<button class="twin-node twin-shoulder" type="button" data-button="r1" style="--x:62%;--y:12%"><span>R1</span><kbd data-map-for="r1"></kbd></button>
<button class="twin-node twin-system callout-left" type="button" data-button="create" style="--x:31.5%;--y:17%"><span>CR</span><kbd data-map-for="create"></kbd></button>
<button class="twin-node twin-touchpad" type="button" data-button="touchpad" style="--x:50%;--y:24%"><span>触摸板</span><kbd data-map-for="touchpad"></kbd></button>
<button class="twin-node twin-system callout-left" type="button" data-button="options" style="--x:71.5%;--y:17%"><span>OP</span><kbd data-map-for="options"></kbd></button>
<button class="twin-node twin-dpad callout-top" type="button" data-button="dpad_up" style="--x:24.7%;--y:24.6%"><span>▲</span><kbd data-map-for="dpad_up"></kbd></button>
<button class="twin-node twin-dpad callout-right" type="button" data-button="dpad_right" style="--x:30.6%;--y:31%"><span>▶</span><kbd data-map-for="dpad_right"></kbd></button>
<button class="twin-node twin-dpad callout-bottom" type="button" data-button="dpad_down" style="--x:24.7%;--y:38.8%"><span>▼</span><kbd data-map-for="dpad_down"></kbd></button>
<button class="twin-node twin-dpad callout-left" type="button" data-button="dpad_left" style="--x:18.6%;--y:31%"><span>◀</span><kbd data-map-for="dpad_left"></kbd></button>
<button class="twin-node twin-face callout-right" type="button" data-button="triangle" style="--x:79.4%;--y:21.2%"><span>△</span><kbd data-map-for="triangle"></kbd></button>
<button class="twin-node twin-face callout-right" type="button" data-button="circle" style="--x:85.2%;--y:30.2%"><span>○</span><kbd data-map-for="circle"></kbd></button>
<button class="twin-node twin-face callout-bottom" type="button" data-button="cross" style="--x:79.4%;--y:40.2%"><span>×</span><kbd data-map-for="cross"></kbd></button>
<button class="twin-node twin-face callout-left" type="button" data-button="square" style="--x:73.5%;--y:30.2%"><span>□</span><kbd data-map-for="square"></kbd></button>
<button class="twin-node twin-stick" type="button" data-button="l3" style="--x:37.7%;--y:49%"><span><i id="leftStick"></i></span><kbd data-map-for="l3"></kbd></button>
<button class="twin-node twin-stick" type="button" data-button="r3" style="--x:66.1%;--y:49%"><span><i id="rightStick"></i></span><kbd data-map-for="r3"></kbd></button>
<button class="twin-node twin-stick-direction callout-top" type="button" data-button="left_stick_up" style="--x:37.7%;--y:42.5%"><span>↑</span><kbd data-map-for="left_stick_up"></kbd></button>
<button class="twin-node twin-stick-direction callout-right" type="button" data-button="left_stick_right" style="--x:42.8%;--y:49%"><span>→</span><kbd data-map-for="left_stick_right"></kbd></button>
<button class="twin-node twin-stick-direction callout-bottom" type="button" data-button="left_stick_down" style="--x:37.7%;--y:55.5%"><span>↓</span><kbd data-map-for="left_stick_down"></kbd></button>
<button class="twin-node twin-stick-direction callout-left" type="button" data-button="left_stick_left" style="--x:32.6%;--y:49%"><span>←</span><kbd data-map-for="left_stick_left"></kbd></button>
<button class="twin-node twin-stick-direction callout-top" type="button" data-button="right_stick_up" style="--x:66.1%;--y:42.5%"><span>↑</span><kbd data-map-for="right_stick_up"></kbd></button>
<button class="twin-node twin-stick-direction callout-right" type="button" data-button="right_stick_right" style="--x:71.2%;--y:49%"><span>→</span><kbd data-map-for="right_stick_right"></kbd></button>
<button class="twin-node twin-stick-direction callout-bottom" type="button" data-button="right_stick_down" style="--x:66.1%;--y:55.5%"><span>↓</span><kbd data-map-for="right_stick_down"></kbd></button>
<button class="twin-node twin-stick-direction callout-left" type="button" data-button="right_stick_left" style="--x:61%;--y:49%"><span>←</span><kbd data-map-for="right_stick_left"></kbd></button>
<button class="twin-node twin-center" type="button" data-button="ps" style="--x:52%;--y:49%"><span>PS</span><kbd data-map-for="ps"></kbd></button>
<button class="twin-node twin-center twin-mute" type="button" data-button="mute" style="--x:52%;--y:57%"><span>MIC</span><kbd data-map-for="mute"></kbd></button>
</div>
<div id="twinReadout" class="twin-readout"><span>DIGITAL TWIN</span><strong id="twinButtonName">等待输入</strong><kbd id="twinMappingValue">—</kbd></div>
<div class="axis-monitor">
<div><span>L 摇杆</span><strong id="leftAxisValue">0.00 / 0.00</strong></div>
<div><span>R 摇杆</span><strong id="rightAxisValue">0.00 / 0.00</strong></div>
<div><span>L2 / R2</span><strong id="triggerValue">0% / 0%</strong></div>
<div><span>触摸板</span><strong id="touchpadPosition">—</strong></div>
</div>
<div class="pressed-strip"><span>当前按键</span><strong id="pressedButtons">—</strong></div>
</section>
<section class="mapping-panel" aria-label="映射配置">
<div class="section-heading"><div><span class="section-kicker">KEYBOARD OUTPUT</span><h3>映射配置</h3></div><span id="mappingCount" class="mapping-count">0 / 27</span></div>
<div class="mapping-filter" role="group" aria-label="映射筛选"><button class="is-active" type="button" data-filter="all">全部</button><button type="button" data-filter="face">主按键</button><button type="button" data-filter="control">方向肩键</button><button type="button" data-filter="stick">摇杆</button><button type="button" data-filter="system">系统</button></div>
<div id="mappingList" class="mapping-list"></div>
</section>
</div>
</section>
<section id="touchpadView" class="view">
<div class="view-header"><div><p class="eyebrow">02 / TOUCHPAD GESTURES</p><h2>触摸板</h2></div><span id="touchpadLiveBadge" class="badge">等待触点</span></div>
<div class="touchpad-workspace">
<section class="touchpad-monitor-panel" aria-label="触摸板实时输入">
<div class="section-heading"><div><span class="section-kicker">LIVE TOUCH</span><h3>触点数字孪生</h3></div><strong id="touchpadLiveCoordinates" class="touchpad-coordinate">— / —</strong></div>
<div id="touchpadSurface" class="touchpad-surface">
<span class="touchpad-direction touchpad-direction-left">←</span>
<span class="touchpad-direction touchpad-direction-right">→</span>
<i id="touchpadCursor" class="touchpad-cursor" aria-hidden="true"></i>
<div class="touchpad-centerline" aria-hidden="true"></div>
</div>
<div class="touchpad-telemetry">
<div><span>激活方式</span><strong>触点滑动</strong></div>
<div><span>本次位移</span><strong id="touchpadGestureDelta">0 px</strong></div>
<div><span>最近手势</span><strong id="touchpadLastGesture">—</strong></div>
</div>
</section>
<section class="touchpad-controls-panel" aria-label="触摸板手势配置">
<div class="touchpad-gesture-header">
<div><span class="section-kicker">DESKTOP NAVIGATION</span><h3>虚拟桌面切换</h3></div>
<label class="status-link-toggle"><input id="touchpadGestureToggle" type="checkbox" checked /><span class="switch-track" aria-hidden="true"><i></i></span><strong>启用四指手势</strong></label>
</div>
<div class="touchpad-route-list">
<div><span class="route-arrow">←</span><span><small>单指左滑</small><strong>原生四指手势:上一个桌面</strong></span><kbd id="touchpadDriverLeft">检测 HID</kbd></div>
<div><span class="route-arrow">→</span><span><small>单指右滑</small><strong>原生四指手势:下一个桌面</strong></span><kbd id="touchpadDriverRight">检测 HID</kbd></div>
</div>
<div class="touchpad-gesture-status"><span>识别状态</span><b id="touchpadGestureState">待机</b></div>
<div class="touchpad-option-row"><span>切换时静音</span><label class="status-link-toggle"><input id="touchpadMuteToggle" type="checkbox" /><span class="switch-track" aria-hidden="true"><i></i></span><strong>系统静音</strong></label></div>
<label class="touchpad-threshold"><span>触发距离</span><output id="touchpadGestureThresholdOutput">320 px</output><input id="touchpadGestureThreshold" class="range-input" type="range" min="160" max="800" step="20" value="320" /></label>
</section>
</div>
</section>
<section id="lightingView" class="view">
<div class="view-header"><div><p class="eyebrow">03 / STATUS LIGHT</p><h2>状态灯自定义</h2></div><span id="lightOutputBadge" class="badge">未应用</span></div>
<div class="lighting-workspace">
<section class="light-preview-panel">
<div class="section-heading"><div><span class="section-kicker">LIVE PREVIEW</span><h3 id="effectTitle">静态常亮</h3></div><div id="colorChip" class="color-chip"></div></div>
<div id="lightPreview" class="light-preview"><div class="light-preview-device"><span class="preview-bar preview-bar-left"></span><span class="preview-bar preview-bar-right"></span><div id="previewPlayers" class="preview-player-lights"><i></i><i></i><i class="is-on"></i><i></i><i></i></div></div></div>
<div class="light-telemetry"><div><span>颜色</span><strong id="telemetryHex">#38DDB2</strong></div><div><span>RGB</span><strong id="telemetryRgb">56 / 221 / 178</strong></div><div><span>指示灯</span><strong id="telemetryMask">0x04</strong></div></div>
</section>
<section class="light-controls-panel">
<div class="codex-light-panel">
<div class="codex-light-header">
<div><span class="section-kicker">CODEX LIVE STATUS</span><h3>Codex 任务联动</h3></div>
<label class="status-link-toggle"><input id="codexStatusToggle" type="checkbox" checked /><span class="switch-track" aria-hidden="true"><i></i></span><strong>自动跟随</strong></label>
</div>
<div class="codex-state-grid" aria-label="Codex 状态灯优先级">
<div class="codex-state-row" data-codex-state="approval"><span class="state-light state-light-approval"></span><strong>待审批</strong><span>黄灯闪烁</span><b>优先 1</b></div>
<div class="codex-state-row" data-codex-state="working"><span class="state-light state-light-working"></span><strong>工作中</strong><span>红色呼吸</span><b>优先 2</b></div>
<div class="codex-state-row" data-codex-state="idle"><span class="state-light state-light-idle"></span><strong>空闲</strong><span>绿灯常亮</span><b>优先 3</b></div>
</div>
<div class="codex-current-state"><span id="codexStateDot" class="state-light"></span><div><span>当前状态</span><strong id="codexStateLabel">正在连接 Codex</strong></div><small id="codexStateMeta">读取本机任务状态</small></div>
</div>
<div class="color-control-grid manual-light-control">
<div class="color-wheel-wrap"><canvas id="colorWheel" width="180" height="180" tabindex="0" aria-label="色轮"></canvas></div>
<div class="color-fields">
<label class="hex-field">HEX<input id="hexInput" type="text" value="#38DDB2" maxlength="7" /></label>
<div class="rgb-grid"><label>R<input id="redInput" type="number" min="0" max="255" value="56" /></label><label>G<input id="greenInput" type="number" min="0" max="255" value="221" /></label><label>B<input id="blueInput" type="number" min="0" max="255" value="178" /></label></div>
<div class="swatches" role="group" aria-label="推荐颜色"><button class="swatch is-selected" data-color="#38DDB2" style="--swatch:#38DDB2" aria-label="薄荷绿"></button><button class="swatch" data-color="#58A6FF" style="--swatch:#58A6FF" aria-label="冷蓝"></button><button class="swatch" data-color="#D26BFF" style="--swatch:#D26BFF" aria-label="洋红"></button><button class="swatch" data-color="#FF5A68" style="--swatch:#FF5A68" aria-label="珊瑚红"></button><button class="swatch" data-color="#F4C94C" style="--swatch:#F4C94C" aria-label="琥珀黄"></button><button class="swatch" data-color="#F4F7F9" style="--swatch:#F4F7F9" aria-label="白色"></button></div>
</div>
</div>
<div class="control-row manual-light-control"><div class="field-label"><span>亮度</span><output id="brightnessOutput">100%</output></div><input id="brightness" class="range-input" type="range" min="0" max="100" value="100" /></div>
<div class="control-row manual-light-control"><div class="field-label"><span>灯效</span></div><div id="effectControls" class="segmented-control"><button class="is-active" data-effect="static">常亮</button><button data-effect="blink">闪烁</button><button data-effect="breathe">呼吸</button></div></div>
<div class="control-row speed-row manual-light-control"><div class="field-label"><span>变化速度</span><output id="speedOutput">中速</output></div><input id="speed" class="range-input" type="range" min="1" max="5" value="3" /></div>
<div class="control-row player-row manual-light-control"><div class="field-label"><span>玩家指示灯</span><output id="playerOutput">P1</output></div><div id="playerPresets" class="player-presets"><button class="is-active" data-player="1">P1</button><button data-player="2">P2</button><button data-player="3">P3</button><button data-player="4">P4</button><button data-player="5">P5</button></div><div id="playerLeds" class="player-leds"><button data-index="0"><i></i></button><button data-index="1"><i></i></button><button class="is-on" data-index="2"><i></i></button><button data-index="3"><i></i></button><button data-index="4"><i></i></button></div></div>
<div class="light-actions manual-light-control"><button id="turnOffButton" class="button button-secondary" type="button">关闭灯光</button><button id="applyButton" class="button button-primary" type="button">应用状态灯</button></div>
</section>
</div>
</section>
<section id="triggersView" class="view">
<div class="view-header"><div><p class="eyebrow">04 / ADAPTIVE TRIGGERS</p><h2>自适应扳机</h2></div><span id="triggerOutputBadge" class="badge">未应用</span></div>
<div class="trigger-workspace">
<section class="trigger-preview-panel">
<div class="section-heading"><div><span class="section-kicker">TRAVEL PROFILE</span><h3>扳机行程</h3></div><span class="trigger-usb-badge">USB</span></div>
<div class="trigger-preview-stage">
<div class="trigger-preview" data-trigger-preview="left"><div class="trigger-preview-head"><strong>L2</strong><span id="leftTriggerModeLabel">关闭</span></div><div class="trigger-rail"><i class="trigger-current" id="leftTriggerCurrent"></i><span class="trigger-resistance"></span><b class="trigger-break"></b></div><div class="trigger-scale"><span>0%</span><span>按压行程</span><span>100%</span></div></div>
<div class="trigger-preview" data-trigger-preview="right"><div class="trigger-preview-head"><strong>R2</strong><span id="rightTriggerModeLabel">枪械断点</span></div><div class="trigger-rail"><i class="trigger-current" id="rightTriggerCurrent"></i><span class="trigger-resistance"></span><b class="trigger-break"></b></div><div class="trigger-scale"><span>0%</span><span>按压行程</span><span>100%</span></div></div>
</div>
<div class="trigger-legend"><span><i class="legend-live"></i>实时位置</span><span><i class="legend-zone"></i>阻力区间</span><span><i class="legend-break"></i>触发断点</span></div>
</section>
<section class="trigger-controls-panel">
<div class="trigger-preset-row"><div><span class="section-kicker">QUICK PRESET</span><h3>快速配置</h3></div><button id="triggerGunPreset" class="button button-secondary" type="button">双侧枪械</button></div>
<div class="trigger-control-grid">
<section class="trigger-control" data-trigger-control="left">
<div class="trigger-control-head"><strong>L2</strong><output id="leftTriggerSummary">关闭</output></div>
<div class="trigger-mode segmented-control"><button data-trigger-side="left" data-trigger-mode="off" class="is-active">关闭</button><button data-trigger-side="left" data-trigger-mode="feedback">阻力</button><button data-trigger-side="left" data-trigger-mode="weapon">枪械</button></div>
<label class="trigger-range-row"><span>起始位置</span><output id="leftTriggerStartOutput">30%</output><input id="leftTriggerStart" class="range-input" type="range" min="0" max="9" value="3" /></label>
<label class="trigger-range-row trigger-end-row"><span>断点结束</span><output id="leftTriggerEndOutput">60%</output><input id="leftTriggerEnd" class="range-input" type="range" min="1" max="9" value="6" /></label>
<label class="trigger-range-row"><span>阻力强度</span><output id="leftTriggerStrengthOutput">5 / 8</output><input id="leftTriggerStrength" class="range-input" type="range" min="1" max="8" value="5" /></label>
</section>
<section class="trigger-control" data-trigger-control="right">
<div class="trigger-control-head"><strong>R2</strong><output id="rightTriggerSummary">枪械断点</output></div>
<div class="trigger-mode segmented-control"><button data-trigger-side="right" data-trigger-mode="off">关闭</button><button data-trigger-side="right" data-trigger-mode="feedback">阻力</button><button data-trigger-side="right" data-trigger-mode="weapon" class="is-active">枪械</button></div>
<label class="trigger-range-row"><span>起始位置</span><output id="rightTriggerStartOutput">30%</output><input id="rightTriggerStart" class="range-input" type="range" min="0" max="9" value="3" /></label>
<label class="trigger-range-row trigger-end-row"><span>断点结束</span><output id="rightTriggerEndOutput">60%</output><input id="rightTriggerEnd" class="range-input" type="range" min="1" max="9" value="6" /></label>
<label class="trigger-range-row"><span>阻力强度</span><output id="rightTriggerStrengthOutput">5 / 8</output><input id="rightTriggerStrength" class="range-input" type="range" min="1" max="8" value="5" /></label>
</section>
</div>
<div class="trigger-actions"><button id="disableTriggersButton" class="button button-secondary" type="button">全部关闭</button><button id="applyTriggersButton" class="button button-primary" type="button">应用扳机效果</button></div>
</section>
</div>
</section>
</main>
</div>
<footer class="activity-bar"><div><span class="activity-label">ACTIVITY</span><strong id="activityMessage">HUB 已就绪</strong></div><time id="activityTime"></time></footer>
</div>
<dialog id="messageDialog" class="message-dialog"><p id="dialogEyebrow" class="eyebrow">VIBECODING HUB</p><h2 id="dialogTitle">本地服务未连接</h2><p id="dialogMessage"></p><button id="dialogCloseButton" class="button button-primary" type="button">知道了</button></dialog>
<script src="./app.js?v=14"></script>
</body>
</html>