@wendongfly/myhi 1.0.56 → 1.0.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/chat.html +45 -5
  2. package/package.json +1 -1
package/dist/chat.html CHANGED
@@ -215,6 +215,7 @@
215
215
  <button class="top-btn" onclick="goBack()" title="返回">
216
216
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
217
217
  </button>
218
+ <button class="top-btn" onclick="showUsage()" title="用量" style="font-size:0.7rem;color:var(--muted)">用量</button>
218
219
  <button class="top-btn" id="logout-btn" onclick="doLogout()" title="退出" style="display:none;color:#f0883e">
219
220
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
220
221
  </button>
@@ -223,14 +224,14 @@
223
224
  <div id="status-bar">
224
225
  <span class="sb-item" id="work-status"><span class="sb-dot idle"></span> 空闲</span>
225
226
  <span id="mode-badge" onclick="switchMode()">默认</span>
226
- <span id="control-badge" class="readonly" onclick="toggleControl()">只读</span>
227
+ <span id="control-badge" class="readonly" style="display:none">只读</span>
227
228
  <span id="viewer-count" class="sb-item"></span>
228
229
  </div>
229
230
 
230
231
  <div id="chat-area"></div>
231
232
 
232
233
  <div id="input-area">
233
- <div id="readonly-overlay">只读模式 — 点击状态栏"获取控制"开始输入</div>
234
+ <div id="readonly-overlay" style="display:none"></div>
234
235
  <div id="input-box">
235
236
  <div id="img-preview">
236
237
  <img id="img-preview-thumb" src="" alt="">
@@ -335,6 +336,45 @@
335
336
  fetch('/api/me').then(r => r.json()).then(data => {
336
337
  if (data.exclusive || data.hasUsers) document.getElementById('logout-btn').style.display = '';
337
338
  }).catch(() => {});
339
+ window.showUsage = async () => {
340
+ try {
341
+ const res = await fetch('/api/usage');
342
+ const data = await res.json();
343
+ let html = '<div style="padding:1.25rem;max-width:500px">';
344
+ html += '<h3 style="margin:0 0 1rem;font-size:1rem">Claude 用量统计</h3>';
345
+ if (data.rateLimit) {
346
+ const rl = data.rateLimit;
347
+ const remaining = Math.max(0, Math.ceil((new Date(rl.resetsAt * 1000) - Date.now()) / 60000));
348
+ html += '<div style="margin-bottom:1rem;padding:0.8rem;background:var(--bg);border-radius:8px">';
349
+ html += '<div style="font-size:0.85rem;font-weight:600;margin-bottom:0.4rem">5小时窗口</div>';
350
+ html += `<div style="font-size:0.8rem;color:var(--muted)">状态: ${rl.status === 'allowed' ? '✓ 正常' : '⚠ 受限'} 重置: ${remaining}分钟后</div></div>`;
351
+ }
352
+ if (data.sevenDay) {
353
+ const s = data.sevenDay;
354
+ html += '<div style="margin-bottom:1rem;padding:0.8rem;background:var(--bg);border-radius:8px">';
355
+ html += '<div style="font-size:0.85rem;font-weight:600;margin-bottom:0.4rem">近7天</div>';
356
+ html += `<div style="font-size:0.8rem;color:var(--muted)">消息: ${s.messageCount.toLocaleString()} 会话: ${s.sessionCount} 工具: ${s.toolCallCount.toLocaleString()}</div></div>`;
357
+ }
358
+ if (data.activeSessions?.length) {
359
+ html += '<div style="margin-bottom:1rem;padding:0.8rem;background:var(--bg);border-radius:8px">';
360
+ html += '<div style="font-size:0.85rem;font-weight:600;margin-bottom:0.4rem">当前会话</div>';
361
+ for (const s of data.activeSessions) {
362
+ if (!s.usage) continue;
363
+ html += `<div style="font-size:0.8rem;color:var(--muted)">${s.title}: ${s.usage.queryCount}次, $${s.usage.totalCostUSD.toFixed(4)}</div>`;
364
+ }
365
+ html += '</div>';
366
+ }
367
+ html += '<button onclick="this.parentElement.parentElement.remove()" style="margin-top:0.5rem;width:100%;padding:0.6rem;background:var(--accent);color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:0.85rem">关闭</button></div>';
368
+ const overlay = document.createElement('div');
369
+ overlay.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:999;display:flex;align-items:center;justify-content:center';
370
+ overlay.onclick = (e) => { if (e.target === overlay) overlay.remove(); };
371
+ const box = document.createElement('div');
372
+ box.style.cssText = 'background:var(--surface);border-radius:16px;max-height:80vh;overflow-y:auto;width:90%;max-width:400px';
373
+ box.innerHTML = html;
374
+ overlay.appendChild(box);
375
+ document.body.appendChild(overlay);
376
+ } catch (err) { alert('获取用量失败: ' + err.message); }
377
+ };
338
378
  window.doLogout = () => {
339
379
  if (!confirm('确定退出登录?当前所有会话将被关闭。')) return;
340
380
  fetch('/logout', { method: 'POST' }).then(() => { location.href = '/login'; });
@@ -1314,7 +1354,7 @@
1314
1354
  };
1315
1355
  function selectModel(m) {
1316
1356
  closeModelSheet();
1317
- if (!isController) { addStatusMessage('请先获取控制权'); return; }
1357
+ if (!isController) { if (canTakeControl()) socket.emit('take-control', { sessionId: SESSION_ID }); else { addStatusMessage('其他用户控制中'); return; } }
1318
1358
  if (currentSession?.mode === 'agent') {
1319
1359
  // Agent 模式:通过命令设置
1320
1360
  cmdInput.value = '/model ' + m.id;
@@ -1334,7 +1374,7 @@
1334
1374
 
1335
1375
  // ── 恢复会话 ──────────────────────────────────
1336
1376
  window.openResumeSheet = async function() {
1337
- if (!isController) { addStatusMessage('请先获取控制权'); return; }
1377
+ if (!isController) { if (canTakeControl()) socket.emit('take-control', { sessionId: SESSION_ID }); else { addStatusMessage('其他用户控制中'); return; } }
1338
1378
  const list = document.getElementById('resume-list');
1339
1379
  list.innerHTML = '<div style="text-align:center;padding:1rem;color:#8b949e">加载中...</div>';
1340
1380
  document.getElementById('resume-sheet').classList.add('open');
@@ -1382,7 +1422,7 @@
1382
1422
 
1383
1423
  // ── 压缩对话 ──────────────────────────────────
1384
1424
  window.doCompact = function() {
1385
- if (!isController) { addStatusMessage('请先获取控制权'); return; }
1425
+ if (!isController) { if (canTakeControl()) socket.emit('take-control', { sessionId: SESSION_ID }); else { addStatusMessage('其他用户控制中'); return; } }
1386
1426
  if (currentSession?.mode === 'agent') {
1387
1427
  cmdInput.value = '/compact';
1388
1428
  sendCommand();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wendongfly/myhi",
3
- "version": "1.0.56",
3
+ "version": "1.0.58",
4
4
  "description": "Web-based terminal sharing with chat UI — control your terminal from phone via LAN/Tailscale",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",