Skip to content

Commit e6714bd

Browse files
authored
Merge pull request #152 from itmisx/feat/web-balance-collapse
✨ feat: web-balance-collapse
2 parents 84c3f2a + 14a2cf3 commit e6714bd

5 files changed

Lines changed: 72 additions & 6 deletions

File tree

tui/model.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2279,8 +2279,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
22792279
return m, nil
22802280

22812281
case balanceMsg:
2282-
// 余额查询回执:更新右栏「模型厂商」段展示的剩余金额。
2282+
// 余额查询回执:更新右栏「模型厂商」段展示的剩余金额,并广播给 web 端动态更新
22832283
m.applyBalance(msg)
2284+
m.broadcast(web.Event{Kind: "balance", Text: m.balance})
22842285
return m, nil
22852286

22862287
case agent.VisionUnsupportedMsg:

web/hub.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ type Snapshot struct {
6969
Sandbox string `json:"sandbox"` // off | native | docker
7070
WorkingMode string `json:"workingMode"` // karpathy | openspec | superpowers
7171
CodeGraph string `json:"codegraph"` // 代码图谱状态 token
72+
Balance string `json:"balance"` // 账户剩余余额展示串(如 "¥110.00");"" 未探到,"-" 不支持
7273
Sessions []SessionInfo `json:"sessions"`
7374
}
7475

@@ -332,6 +333,10 @@ func (h *Hub) apply(ev Event) Event {
332333
h.snap.CodeGraph = ev.Text
333334
}
334335

336+
case "balance":
337+
// 余额可能从有值变 "-"(切到不支持的供应商),不能用非空守卫,直接覆盖。
338+
h.snap.Balance = ev.Text
339+
335340
case "sessions":
336341
h.snap.Sessions = append([]SessionInfo(nil), ev.Sessions...)
337342

web/static/app.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,14 @@ const I18N = {
5858
'skill.noresult': '无结果',
5959
workspace: '工作区',
6060
'panel.vendor': '模型厂商',
61+
'panel.endpoint': '接口',
62+
'panel.balance': '余额',
6163
'panel.curmodel': '当前模型',
6264
'panel.context': '上下文',
65+
'pane.hide_sessions': '收起会话栏',
66+
'pane.show_sessions': '展开会话栏',
67+
'pane.hide_status': '收起状态栏',
68+
'pane.show_status': '展开状态栏',
6369
'panel.todo': '待办',
6470
'panel.plan': '计划',
6571
'panel.tools': '工具调用',
@@ -139,8 +145,14 @@ const I18N = {
139145
'skill.noresult': 'No results',
140146
workspace: 'Workspace',
141147
'panel.vendor': 'Vendor',
148+
'panel.endpoint': 'Endpoint',
149+
'panel.balance': 'Balance',
142150
'panel.curmodel': 'Model',
143151
'panel.context': 'Context',
152+
'pane.hide_sessions': 'Collapse sessions',
153+
'pane.show_sessions': 'Expand sessions',
154+
'pane.hide_status': 'Collapse status',
155+
'pane.show_status': 'Expand status',
144156
'panel.todo': 'Todo',
145157
'panel.plan': 'Plan',
146158
'panel.tools': 'Tool Calls',
@@ -214,7 +226,11 @@ createApp({
214226
sandbox: 'native',
215227
workingMode: 'karpathy',
216228
codegraph: '',
229+
balance: '', // 账户剩余余额展示串(¥110.00);"" 不显示,"-" 不支持
217230
sessions: [],
231+
// 两侧栏折叠态(本地持久化,刷新保留)
232+
sidebarCollapsed: localStorage.getItem('deepx.sidebarCollapsed') === '1',
233+
statusCollapsed: localStorage.getItem('deepx.statusCollapsed') === '1',
218234
menuOpen: null, // 当前展开"…"菜单的会话 id
219235
routingOptions: ROUTING_OPTIONS,
220236
modeOptions: MODE_OPTIONS,
@@ -391,6 +407,15 @@ createApp({
391407
ta.style.height = 'auto';
392408
ta.style.height = Math.min(ta.scrollHeight, 200) + 'px';
393409
},
410+
// 折叠/展开左侧会话栏 / 右侧状态栏,持久化到 localStorage(刷新保留)。
411+
toggleSidebar() {
412+
this.sidebarCollapsed = !this.sidebarCollapsed;
413+
localStorage.setItem('deepx.sidebarCollapsed', this.sidebarCollapsed ? '1' : '0');
414+
},
415+
toggleStatus() {
416+
this.statusCollapsed = !this.statusCollapsed;
417+
localStorage.setItem('deepx.statusCollapsed', this.statusCollapsed ? '1' : '0');
418+
},
394419
syncMention() {
395420
const ta = this.$refs.ta;
396421
if (!ta) return;
@@ -654,6 +679,7 @@ createApp({
654679
if (s.sandbox) this.sandbox = s.sandbox;
655680
if (s.workingMode) this.workingMode = s.workingMode;
656681
this.codegraph = s.codegraph || '';
682+
this.balance = s.balance || '';
657683
this.sessions = s.sessions || [];
658684
// 推断流式气泡:最后一条是 assistant 且还在 streaming 则继续往里追加
659685
const last = this.messages.length - 1;
@@ -789,6 +815,10 @@ createApp({
789815
case 'codegraph':
790816
if (ev.text) this.codegraph = ev.text;
791817
break;
818+
case 'balance':
819+
// 余额可能从有值变 "-"(切到不支持的供应商),直接覆盖,不用非空守卫。
820+
this.balance = ev.text || '';
821+
break;
792822
case 'sessions':
793823
this.sessions = ev.sessions || [];
794824
break;

web/static/index.html

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
<main class="layout">
2626
<!-- 最左:会话列表(顶部新建按钮) -->
27-
<nav class="sessions-pane">
27+
<nav class="sessions-pane" :class="{ collapsed: sidebarCollapsed }">
2828
<button class="new-session-btn" :disabled="streaming" @click="newSession">{{ t('session.new') }}</button>
2929
<div class="sessions-list">
3030
<div v-if="!sessions.length" class="empty"></div>
@@ -54,6 +54,18 @@
5454

5555
<!-- 中:聊天 -->
5656
<section class="chat">
57+
<!-- 顶栏:左右两个折叠按钮(始终可见,折叠后用它再展开) -->
58+
<div class="chat-topbar">
59+
<button class="pane-toggle" @click="toggleSidebar"
60+
:title="sidebarCollapsed ? t('pane.show_sessions') : t('pane.hide_sessions')">
61+
{{ sidebarCollapsed ? '☰' : '⟨' }}
62+
</button>
63+
<div class="topbar-spacer"></div>
64+
<button class="pane-toggle" @click="toggleStatus"
65+
:title="statusCollapsed ? t('pane.show_status') : t('pane.hide_status')">
66+
{{ statusCollapsed ? '☷' : '⟩' }}
67+
</button>
68+
</div>
5769
<div class="messages" ref="msgList">
5870
<!-- 空会话:补一句欢迎语,避免一片空白 -->
5971
<div v-if="!messages.length && !streaming" class="welcome">
@@ -197,15 +209,16 @@
197209
</section>
198210

199211
<!-- 右:状态(workspace 段在最上,下面状态/规划/工具三段常驻,无内容时留空) -->
200-
<aside class="status">
212+
<aside class="status" :class="{ collapsed: statusCollapsed }">
201213
<div class="sec">
202214
<div class="sec-title">◆ {{ t('workspace') }}</div>
203215
<div class="ws-path" :title="workspace">{{ workspace || '—' }}</div>
204216
</div>
205217

206218
<div class="sec" v-if="vendor">
207219
<div class="sec-title">◆ {{ t('panel.vendor') }}</div>
208-
<div class="ws-path" :title="vendor">{{ vendor }}</div>
220+
<div class="kv"><span>{{ t('panel.endpoint') }}</span><b class="path" :title="vendor">{{ vendor }}</b></div>
221+
<div class="kv" v-if="balance"><span>{{ t('panel.balance') }}</span><b>{{ balance }}</b></div>
209222
</div>
210223

211224
<div class="sec">

web/static/styles.css

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,23 @@ body {
6363
background: var(--panel); overflow-y: auto; padding: 14px;
6464
}
6565

66+
/* 两侧栏折叠:收到 0 宽并去掉边框/内边距,中间聊天区自动撑满 */
67+
.sessions-pane.collapsed, .status.collapsed {
68+
width: 0; min-width: 0; padding: 0; border: 0; overflow: hidden;
69+
}
70+
/* 中间栏顶部:左右两个折叠按钮始终可见(折叠后靠它再展开) */
71+
.chat-topbar {
72+
display: flex; align-items: center; gap: 8px;
73+
padding: 6px 10px; border-bottom: 1px solid var(--border); flex-shrink: 0;
74+
}
75+
.chat-topbar .topbar-spacer { flex: 1; }
76+
.pane-toggle {
77+
background: transparent; border: 1px solid var(--border); color: var(--dim);
78+
border-radius: 6px; padding: 2px 9px; cursor: pointer; font-size: 13px; line-height: 1.4;
79+
transition: color .12s, border-color .12s;
80+
}
81+
.pane-toggle:hover { color: var(--fg); border-color: var(--accent2); }
82+
6683
/* 聊天消息 */
6784
.messages { flex: 1; overflow-y: auto; padding: 18px 20px; }
6885
/* 空会话欢迎语 */
@@ -144,9 +161,9 @@ body {
144161
/* 右栏 section */
145162
.sec { margin-bottom: 20px; }
146163
.sec-title { font-size: 11px; color: var(--accent); font-weight: 700; letter-spacing: 1px; margin-bottom: 8px; }
147-
.kv { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; padding: 2px 0; }
164+
.kv { display: flex; justify-content: flex-start; gap: 6px; font-size: 12px; padding: 2px 0; }
148165
.kv span { color: var(--dim); flex-shrink: 0; }
149-
.kv b { font-weight: 500; text-align: right; word-break: break-all; }
166+
.kv b { font-weight: 500; word-break: break-all; }
150167
.kv b.active { color: var(--accent); }
151168
.kv b.path { color: var(--cyan); }
152169

0 commit comments

Comments
 (0)