dsh-remote-plugin 0.6.5 → 0.6.7
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.
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/apk/dsh-remote.apk +0 -0
- package/gateway-stats.cjs +9 -2
- package/gateway.cjs +292 -7
- package/index.mjs +61 -12
- package/package.json +1 -1
- package/public/app.js +647 -54
- package/public/desktop/desktop.css +79 -5
- package/public/desktop/desktop.html +75 -7
- package/public/desktop/desktop.js +418 -22
- package/public/desktop/i18n.js +33 -1
- package/public/index.html +108 -13
- package/public/styles.css +82 -4
- package/public/update.json +12 -4
- package/public/version.json +1 -1
package/public/index.html
CHANGED
|
@@ -31,9 +31,23 @@
|
|
|
31
31
|
<!-- 会话列表 -->
|
|
32
32
|
<section id="view-home" class="view">
|
|
33
33
|
<div class="stat-strip" id="stat-strip"></div>
|
|
34
|
+
<div id="workbench-bar" class="workbench-bar unbound">
|
|
35
|
+
<button id="wb-toggle" class="wb-toggle" type="button" aria-expanded="false">
|
|
36
|
+
<span id="wb-label" class="wb-label" data-i18n="wb.unbound">未绑定工作台</span>
|
|
37
|
+
<span class="wb-chevron" aria-hidden="true">▾</span>
|
|
38
|
+
</button>
|
|
39
|
+
<div id="wb-panel" class="wb-panel hidden"></div>
|
|
40
|
+
</div>
|
|
34
41
|
<div class="section-head">
|
|
35
42
|
<span data-i18n="nav.sessions">会话</span>
|
|
36
|
-
<
|
|
43
|
+
<div class="section-actions">
|
|
44
|
+
<select id="session-sort" class="session-sort" data-i18n-aria="sessions.sortLabel">
|
|
45
|
+
<option value="time" data-i18n="sessions.sortTime">按时间</option>
|
|
46
|
+
<option value="workspace" data-i18n="sessions.sortWorkspace">按工作区</option>
|
|
47
|
+
</select>
|
|
48
|
+
<button id="btn-new-workspace" class="mini-btn" data-i18n="home.newWorkspace">+ 工作区</button>
|
|
49
|
+
<button id="btn-new-session" class="mini-btn" data-i18n="home.newSession">+ 新会话</button>
|
|
50
|
+
</div>
|
|
37
51
|
</div>
|
|
38
52
|
<div id="session-list" class="session-list"></div>
|
|
39
53
|
<div id="home-empty" class="empty hidden" data-i18n="home.empty">暂无会话</div>
|
|
@@ -44,6 +58,7 @@
|
|
|
44
58
|
<div class="fs-head">
|
|
45
59
|
<button id="fs-up" class="icon-btn" data-i18n-title="fs.up" data-i18n-aria="fs.up">‹</button>
|
|
46
60
|
<div id="fs-path" class="fs-path" data-i18n="fs.loading">加载中…</div>
|
|
61
|
+
<button id="fs-new-workspace" class="mini-btn" data-i18n="fs.newWorkspace">新建工作区</button>
|
|
47
62
|
<button id="fs-upload-btn" class="mini-btn" data-i18n="fs.upload">上传</button>
|
|
48
63
|
<button id="fs-refresh" class="icon-btn" data-i18n-title="a11y.refresh" data-i18n-aria="a11y.refresh">⟳</button>
|
|
49
64
|
</div>
|
|
@@ -99,6 +114,11 @@
|
|
|
99
114
|
<button class="menu-chip" data-cmd="/permission" data-i18n="menu.permission">/permission 切换权限预设</button>
|
|
100
115
|
<button class="menu-chip" data-cmd="/plan" data-i18n="menu.plan">/plan 进入/退出计划模式</button>
|
|
101
116
|
</div>
|
|
117
|
+
<div class="menu-chips hidden" id="permission-submenu">
|
|
118
|
+
<button class="menu-chip perm-opt" data-perm="read-only" data-i18n="perm.readOnly">read-only</button>
|
|
119
|
+
<button class="menu-chip perm-opt" data-perm="workspace-write" data-i18n="perm.workspaceWrite">workspace-write</button>
|
|
120
|
+
<button class="menu-chip perm-opt" data-perm="danger-full-access" data-i18n="perm.dangerFullAccess">danger-full-access</button>
|
|
121
|
+
</div>
|
|
102
122
|
</div>
|
|
103
123
|
<div class="menu-group hidden" id="preset-menu-group">
|
|
104
124
|
<div class="menu-title" data-i18n="presets.menuTitle">预设</div>
|
|
@@ -213,6 +233,13 @@
|
|
|
213
233
|
<div><div class="setting-name" data-i18n="settings.toolsTitle">显示工具调用</div><div class="setting-desc" data-i18n="settings.toolsDesc">关闭后隐藏 🔧/📦 工具调用与结果</div></div>
|
|
214
234
|
<label class="switch"><input type="checkbox" id="opt-tools"><span class="slider"></span></label>
|
|
215
235
|
</div>
|
|
236
|
+
<div class="setting-row">
|
|
237
|
+
<div><div class="setting-name" data-i18n="settings.mobileEnterTitle">手机回车行为</div><div class="setting-desc" data-i18n="settings.mobileEnterDesc">选择手机端按 Enter 时换行或直接发送</div></div>
|
|
238
|
+
<select id="mobile-enter-action" class="setting-select">
|
|
239
|
+
<option value="newline" data-i18n="settings.mobileEnterNewline">回车换行</option>
|
|
240
|
+
<option value="send" data-i18n="settings.mobileEnterSend">回车发送</option>
|
|
241
|
+
</select>
|
|
242
|
+
</div>
|
|
216
243
|
<div class="setting-row">
|
|
217
244
|
<div><div class="setting-name" data-i18n="presets.title">预设提示词</div><div class="setting-desc" data-i18n="presets.desc">常用提示词,对话界面一键插入(最多 20 条)</div></div>
|
|
218
245
|
<button id="btn-preset-add" class="mini-btn" data-i18n="presets.add">新增</button>
|
|
@@ -328,6 +355,13 @@
|
|
|
328
355
|
<div><div class="setting-name" data-i18n="settings.hostTitle">DSH 状态</div><div class="setting-desc" id="host-desc" data-i18n="settings.hostProbing">探测中…</div></div>
|
|
329
356
|
<button id="btn-host-describe" class="mini-btn" data-i18n="settings.probe">探测</button>
|
|
330
357
|
</div>
|
|
358
|
+
<div class="setting-row">
|
|
359
|
+
<div><div class="setting-name" data-i18n="settings.dshControlTitle">远程启动 DSH</div><div class="setting-desc" id="dsh-control-desc" data-i18n="settings.dshControlProbing">检查本机服务状态…</div></div>
|
|
360
|
+
<div class="setting-actions">
|
|
361
|
+
<button id="btn-dsh-start" class="mini-btn" data-i18n="settings.dshStart">启动</button>
|
|
362
|
+
<button id="btn-dsh-restart" class="mini-btn" data-i18n="settings.dshRestart">重启</button>
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
331
365
|
<div class="setting-row">
|
|
332
366
|
<div><div class="setting-name" data-i18n="settings.updateTitle">检查更新</div><div class="setting-desc" id="update-desc" data-i18n="settings.updateLoading">加载中…</div>
|
|
333
367
|
<button id="btn-download-update" class="mini-btn hidden" style="margin-top:6px" data-i18n="settings.downloadUpdate">下载并安装更新</button>
|
|
@@ -418,6 +452,37 @@
|
|
|
418
452
|
</div>
|
|
419
453
|
</div>
|
|
420
454
|
|
|
455
|
+
<!-- 新建工作区模态 -->
|
|
456
|
+
<div id="modal-workspace" class="modal hidden">
|
|
457
|
+
<div class="modal-card">
|
|
458
|
+
<div class="modal-title" data-i18n="workspace.createTitle">新建工作区</div>
|
|
459
|
+
<div class="modal-body">
|
|
460
|
+
<p class="workspace-create-desc" data-i18n="workspace.createDesc">将在当前文件目录下创建文件夹,并自动打开新会话。</p>
|
|
461
|
+
<div class="workspace-create-location"><span data-i18n="workspace.parent">父目录</span><code id="workspace-parent-path">~</code></div>
|
|
462
|
+
<input id="workspace-name" class="fb-input" maxlength="120" autocomplete="off" data-i18n-placeholder="workspace.namePlaceholder" placeholder="例如:my-project">
|
|
463
|
+
</div>
|
|
464
|
+
<div class="modal-actions">
|
|
465
|
+
<button id="workspace-cancel" class="btn subtle" data-i18n="workspace.cancel">取消</button>
|
|
466
|
+
<button id="workspace-create" class="btn primary" data-i18n="workspace.create">创建并打开</button>
|
|
467
|
+
</div>
|
|
468
|
+
</div>
|
|
469
|
+
</div>
|
|
470
|
+
|
|
471
|
+
<div id="modal-archive" class="modal hidden">
|
|
472
|
+
<div class="modal-card archive-modal-card">
|
|
473
|
+
<div class="modal-title" data-i18n="session.archiveTitle">确认归档会话</div>
|
|
474
|
+
<p class="archive-modal-desc" data-i18n="session.archiveDesc">归档后会话将从普通列表隐藏,但不会删除对话记录。</p>
|
|
475
|
+
<div class="archive-summary">
|
|
476
|
+
<div class="archive-summary-row"><span data-i18n="session.archiveConversation">对话</span><strong id="archive-session-title"></strong></div>
|
|
477
|
+
<div class="archive-summary-row"><span data-i18n="session.archiveWorkspace">工作区</span><code id="archive-session-workspace"></code></div>
|
|
478
|
+
</div>
|
|
479
|
+
<div class="modal-actions">
|
|
480
|
+
<button id="archive-cancel" class="btn subtle" data-i18n="session.archiveCancel">取消</button>
|
|
481
|
+
<button id="archive-confirm" class="btn archive-confirm-btn" data-i18n="session.archiveConfirmAction">确认归档</button>
|
|
482
|
+
</div>
|
|
483
|
+
</div>
|
|
484
|
+
</div>
|
|
485
|
+
|
|
421
486
|
<!-- goal 模态 -->
|
|
422
487
|
<div id="modal-goal" class="modal hidden">
|
|
423
488
|
<div class="modal-card">
|
|
@@ -484,6 +549,20 @@
|
|
|
484
549
|
</div>
|
|
485
550
|
</div>
|
|
486
551
|
|
|
552
|
+
<!-- 远程公告模态 -->
|
|
553
|
+
<div id="modal-announcement" class="modal hidden" role="dialog" aria-modal="true">
|
|
554
|
+
<div class="modal-card announcement-card">
|
|
555
|
+
<div class="announcement-kicker" data-i18n="announcement.label">公告</div>
|
|
556
|
+
<div id="announcement-title" class="modal-title"></div>
|
|
557
|
+
<div id="announcement-content" class="modal-body announcement-content"></div>
|
|
558
|
+
<a id="announcement-action" class="announcement-action hidden" target="_blank" rel="noopener"></a>
|
|
559
|
+
<div class="modal-actions">
|
|
560
|
+
<button id="announcement-later" class="btn subtle" data-i18n="announcement.later">稍后再看</button>
|
|
561
|
+
<button id="announcement-confirm" class="btn primary" data-i18n="announcement.gotIt">知道了</button>
|
|
562
|
+
</div>
|
|
563
|
+
</div>
|
|
564
|
+
</div>
|
|
565
|
+
|
|
487
566
|
<div id="toast" class="toast hidden"></div>
|
|
488
567
|
|
|
489
568
|
<script>
|
|
@@ -502,8 +581,12 @@
|
|
|
502
581
|
'statsPage.peak': '高峰', 'statsPage.off': '空闲', 'statsPage.days': '近 {n} 天',
|
|
503
582
|
'statsPage.gatewayDown': '统计需要网关运行', 'statsPage.empty': '暂无统计,产生会话后自动聚合',
|
|
504
583
|
'statsPage.note': '注:本数据仅在使用 DeepSeek 官方 API 时估算;基于 token 计算,与官网账单可能有出入,一切以官网为准。统计自 2026-08-17 定价生效日起。',
|
|
505
|
-
'home.newSession': '+ 新会话', 'home.empty': '暂无会话', 'home.createFailed': '新建会话失败', 'home.created': '会话已创建',
|
|
584
|
+
'home.newSession': '+ 新会话', 'home.newWorkspace': '+ 工作区', 'home.empty': '暂无会话', 'home.createFailed': '新建会话失败', 'home.created': '会话已创建',
|
|
585
|
+
'wb.unbound': '未绑定工作台', 'wb.bound': '绑定 {title}', 'wb.noProjects': '暂无项目', 'wb.noSessions': '暂无会话', 'wb.newSession': '新会话', 'wb.flatHidden': '工作台会话已收起({n} 个)', 'wb.archivedHidden': '------隐藏已归档会话------', 'wb.archivedShown': '------显示已归档会话------',
|
|
586
|
+
'workspace.createTitle': '新建工作区', 'workspace.createDesc': '将在当前文件目录下创建文件夹,并自动打开新会话。', 'workspace.parent': '父目录', 'workspace.namePlaceholder': '例如:my-project', 'workspace.cancel': '取消', 'workspace.create': '创建并打开', 'workspace.nameRequired': '请输入工作区名称', 'workspace.exists': '该目录已存在', 'workspace.invalidName': '名称不能包含路径分隔符', 'workspace.createFailed': '创建工作区失败:{msg}', 'workspace.created': '工作区已创建', 'workspace.createdNoSession': '工作区已创建,但新会话未能打开',
|
|
587
|
+
'workspace.createTitle': '新建工作区', 'workspace.createDesc': '将在当前文件目录下创建文件夹,并自动打开新会话。', 'workspace.parent': '父目录', 'workspace.namePlaceholder': '例如:my-project', 'workspace.cancel': '取消', 'workspace.create': '创建并打开', 'workspace.nameRequired': '请输入工作区名称', 'workspace.created': '工作区已创建', 'workspace.sessionFailed': '目录已创建,但新会话打开失败:{msg}',
|
|
506
588
|
'sessions.running': '运行中', 'sessions.statRunning': '运行中', 'sessions.statPending': '待处理', 'sessions.statTotal': '会话总数',
|
|
589
|
+
'sessions.sortLabel': '会话排序', 'sessions.sortTime': '按时间', 'sessions.sortWorkspace': '按工作区', 'sessions.workspace': '工作区', 'sessions.workspaceUnknown': '未指定工作区',
|
|
507
590
|
'sessions.queueBadge': '队列 {n}', 'sessions.goalBadge': '目标·{phase}',
|
|
508
591
|
'sessions.cacheFallback': '网络不可用:显示本地缓存的会话列表',
|
|
509
592
|
'err.badResponse': '坏响应', 'err.dshError': 'DSH 返回错误', 'err.accessDenied': '访问被拒绝:请检查令牌',
|
|
@@ -535,7 +618,7 @@
|
|
|
535
618
|
'stream.error': '事件流错误:{msg}',
|
|
536
619
|
'session.loading': '加载中…', 'session.unknown': '未知会话', 'session.running': '运行中', 'session.interrupted': '已中断',
|
|
537
620
|
'session.stop': '停止', 'session.history': '对话', 'session.errorMsg': '会话出错:{msg}',
|
|
538
|
-
'session.confirmStop': '停止当前会话正在运行的任务?', 'session.stopFailed': '停止失败', 'session.stopRequested': '已请求停止',
|
|
621
|
+
'session.confirmStop': '停止当前会话正在运行的任务?', 'session.stopFailed': '停止失败', 'session.stopRequested': '已请求停止', 'session.archive': '归档', 'session.archiveConfirm': '归档这个会话?归档后可在“显示已归档会话”中打开。', 'session.archiveFailed': '归档失败:{msg}', 'session.archived': '会话已归档', 'session.archiveTitle': '确认归档会话', 'session.archiveDesc': '归档后会话将从普通列表隐藏,但不会删除对话记录。', 'session.archiveConversation': '对话', 'session.archiveWorkspace': '工作区', 'session.archiveCancel': '取消', 'session.archiveConfirmAction': '确认归档',
|
|
539
622
|
'notify.approvalTitle': '工具审批', 'notify.approvalBody': '{tool} 需要批准', 'notify.questionTitle': 'DSH 提问', 'notify.questionBody': '需要你回答',
|
|
540
623
|
'notify.permissionFailed': '通知权限申请失败:{msg}',
|
|
541
624
|
'history.loading': '加载历史…', 'history.cacheFallback': '网络不可用:显示本地缓存的历史', 'history.loadFailed': '加载历史失败:{msg}', 'history.retry': '重试',
|
|
@@ -565,16 +648,17 @@
|
|
|
565
648
|
'menu.compact': '/compact 压缩对话历史', 'menu.export': '/export 导出会话日志 ZIP',
|
|
566
649
|
'menu.feedback': '/feedback 反馈当前会话', 'menu.goal': '/goal 设置/查看任务目标',
|
|
567
650
|
'menu.permission': '/permission 切换权限预设', 'menu.plan': '/plan 进入/退出计划模式',
|
|
651
|
+
'perm.readOnly': 'read-only', 'perm.workspaceWrite': 'workspace-write', 'perm.dangerFullAccess': 'danger-full-access',
|
|
568
652
|
'menu.modelTitle': '模型切换', 'menu.refresh': '刷新', 'menu.modelAuto': '点开时自动加载', 'menu.effortTitle': '思考深度',
|
|
569
653
|
'composer.placeholder': '给 DSH 发消息…', 'composer.send': '发送',
|
|
570
654
|
'pending.title': '待处理', 'pending.count': '{n} 项', 'pending.approvalTitle': '🔧 {tool} 请求批准', 'pending.noReason': '无说明',
|
|
571
655
|
'pending.allow': '允许', 'pending.reject': '拒绝', 'pending.question': '❓ {question}',
|
|
572
656
|
'pending.questionCount': '共 {n} 个问题', 'pending.answer': '去回答', 'pending.empty': '暂无待处理事项',
|
|
573
|
-
'pending.allowed': '已允许', 'pending.rejected': '已拒绝', 'pending.stale': '审批已不在待处理状态',
|
|
657
|
+
'pending.allowed': '已允许', 'pending.rejected': '已拒绝', 'pending.stale': '审批已不在待处理状态', 'pending.submitFailed': '审批提交失败:{msg}',
|
|
574
658
|
'question.customPlaceholder': '其他 / 自定义回答(可选)', 'question.needAnswer': '请先选择或填写回答',
|
|
575
|
-
'question.submitted': '已提交回答', 'question.stale': '提问已不在待处理状态',
|
|
659
|
+
'question.submitted': '已提交回答', 'question.stale': '提问已不在待处理状态', 'question.submitFailed': '回答提交失败:{msg}',
|
|
576
660
|
'jobs.title': '后台任务', 'jobs.empty': '暂无后台任务',
|
|
577
|
-
'fs.loading': '加载中…', 'fs.up': '返回上级', 'fs.upload': '上传', 'fs.pause': '暂停', 'fs.resume': '继续', 'fs.cancel': '取消',
|
|
661
|
+
'fs.loading': '加载中…', 'fs.up': '返回上级', 'fs.newWorkspace': '新建工作区', 'fs.upload': '上传', 'fs.pause': '暂停', 'fs.resume': '继续', 'fs.cancel': '取消',
|
|
578
662
|
'fs.pullDown': '下拉刷新', 'fs.pullRelease': '松开刷新', 'fs.refreshing': '刷新中…',
|
|
579
663
|
'fs.noToken': '未设置令牌', 'fs.goSettings': '请先到「设置」页粘贴网关令牌',
|
|
580
664
|
'fs.notFound': '目录不存在', 'fs.forbidden': '路径不在允许范围内',
|
|
@@ -625,7 +709,7 @@
|
|
|
625
709
|
'peakRemind.peak0912': '高峰 9:00-12:00', 'peakRemind.off1214': '空闲 12:00-14:00',
|
|
626
710
|
'peakRemind.peak1418': '高峰 14:00-18:00', 'peakRemind.off1809': '空闲 18:00-次日 9:00',
|
|
627
711
|
'peakRemind.browserOnly': '峰谷提醒仅在 App 内有效',
|
|
628
|
-
'peakRemind.on': '峰谷提醒已开启', 'peakRemind.off': '峰谷提醒已关闭',
|
|
712
|
+
'peakRemind.on': '峰谷提醒已开启', 'peakRemind.off': '峰谷提醒已关闭', 'peakRemind.failed': '峰谷提醒服务启动失败,请重试',
|
|
629
713
|
'settings.bgTitle': '后台轮询', 'settings.bgDesc': '退后台后由前台服务定时拉取事件,待办审批/提问不遗漏',
|
|
630
714
|
'settings.bgIntervalTitle': '轮询间隔', 'settings.bgIntervalDesc': '灭屏后系统可能拉长间隔(Doze 平台限制)',
|
|
631
715
|
'settings.bgInterval30s': '30 秒', 'settings.bgInterval1m': '1 分钟', 'settings.bgInterval5m': '5 分钟', 'settings.bgInterval15m': '15 分钟',
|
|
@@ -640,12 +724,14 @@
|
|
|
640
724
|
'presets.nameEmpty': '名称不能为空', 'presets.nameTooLong': '名称不能超过 20 字', 'presets.textTooLong': '内容不能超过 2000 字', 'presets.limit': '最多 20 条预设', 'presets.added': '预设已添加',
|
|
641
725
|
'presets.confirmDelete': '删除预设「{name}」?', 'presets.saved': '预设已保存', 'presets.deleted': '预设已删除',
|
|
642
726
|
'settings.toolsTitle': '显示工具调用', 'settings.toolsDesc': '关闭后隐藏 🔧/📦 工具调用与结果',
|
|
727
|
+
'settings.mobileEnterTitle': '手机回车行为', 'settings.mobileEnterDesc': '选择手机端按 Enter 时换行或直接发送', 'settings.mobileEnterNewline': '回车换行', 'settings.mobileEnterSend': '回车发送',
|
|
643
728
|
'settings.langTitle': '语言 / Language', 'settings.langDesc': '界面语言,跟随系统或手动切换',
|
|
644
729
|
'settings.themeTitle': '皮肤', 'settings.themeDesc': '默认深空 / 落日 / 易北爱乐厅 / 草原孤塔',
|
|
645
730
|
'theme.default': '默认深空', 'theme.dark': '落日', 'theme.light': '易北爱乐厅', 'theme.neutral': '草原孤塔',
|
|
646
731
|
'theme.panelTitle': '选择配色', 'theme.close': '关闭',
|
|
647
732
|
'settings.tokenTitle': '访问令牌', 'settings.change': '更换',
|
|
648
733
|
'settings.hostTitle': 'DSH 状态', 'settings.hostProbing': '探测中…', 'settings.probe': '探测', 'settings.probeFailed': '探测失败',
|
|
734
|
+
'settings.dshControlTitle': '远程启动 DSH', 'settings.dshControlProbing': '检查本机服务状态…', 'settings.dshRunning': '运行中', 'settings.dshStopped': '已停止', 'settings.dshUnsupported': '当前系统未配置可控的 DSH 服务', 'settings.dshStart': '启动', 'settings.dshRestart': '重启', 'settings.dshStarting': '正在{action} DSH…', 'settings.dshStarted': 'DSH 已{action}', 'settings.dshFailed': 'DSH 操作失败:{msg}',
|
|
649
735
|
'settings.hostDesc': 'DSH {version} · {cwd} · 附加会话 {n}',
|
|
650
736
|
'settings.updateTitle': '检查更新', 'settings.updateLoading': '加载中…', 'settings.downloadUpdate': '下载并安装更新', 'settings.check': '检查',
|
|
651
737
|
'settings.feedbackTitle': '反馈渠道', 'settings.feedbackDesc': 'GitHub / Gitee / B站:反馈 bug、提建议、唠嗑',
|
|
@@ -667,6 +753,7 @@
|
|
|
667
753
|
'modal.approvalTitle': '工具审批', 'modal.reject': '拒绝', 'modal.allowOnce': '允许一次',
|
|
668
754
|
'modal.questionTitle': 'DSH 需要你回答', 'modal.later': '稍后', 'modal.submit': '提交',
|
|
669
755
|
'modal.goalTitle': '目标控制', 'modal.close': '关闭', 'modal.updateGoal': '更新目标',
|
|
756
|
+
'announcement.label': '公告', 'announcement.later': '稍后再看', 'announcement.gotIt': '知道了', 'announcement.open': '查看详情',
|
|
670
757
|
'modal.statsTitle': '本轮统计',
|
|
671
758
|
'time.justNow': '刚刚', 'time.minAgo': ' 分钟前', 'time.hourAgo': ' 小时前'
|
|
672
759
|
},
|
|
@@ -684,8 +771,12 @@
|
|
|
684
771
|
'statsPage.peak': 'Peak', 'statsPage.off': 'Off-peak', 'statsPage.days': 'Last {n} days',
|
|
685
772
|
'statsPage.gatewayDown': 'Stats require the gateway', 'statsPage.empty': 'No stats yet — they aggregate as sessions happen',
|
|
686
773
|
'statsPage.note': 'Note: estimates assume the official DeepSeek API. Token-based calculation may differ from the official bill; always defer to deepseek.com. Stats start from the 2026-08-17 pricing date.',
|
|
687
|
-
'home.newSession': '+ New session', 'home.empty': 'No sessions yet', 'home.createFailed': 'Failed to create session', 'home.created': 'Session created',
|
|
774
|
+
'home.newSession': '+ New session', 'home.newWorkspace': '+ Workspace', 'home.empty': 'No sessions yet', 'home.createFailed': 'Failed to create session', 'home.created': 'Session created',
|
|
775
|
+
'wb.unbound': 'No workbench bound', 'wb.bound': 'Bound {title}', 'wb.noProjects': 'No projects', 'wb.noSessions': 'No sessions', 'wb.newSession': 'New session', 'wb.flatHidden': 'Workbench sessions folded ({n})', 'wb.archivedHidden': '------ Hide archived ------', 'wb.archivedShown': '------ Show archived ------',
|
|
776
|
+
'workspace.createTitle': 'New workspace', 'workspace.createDesc': 'Create a folder in the current file directory and open a new session there.', 'workspace.parent': 'Parent folder', 'workspace.namePlaceholder': 'For example: my-project', 'workspace.cancel': 'Cancel', 'workspace.create': 'Create & open', 'workspace.nameRequired': 'Enter a workspace name', 'workspace.exists': 'That folder already exists', 'workspace.invalidName': 'The name cannot contain path separators', 'workspace.createFailed': 'Could not create workspace: {msg}', 'workspace.created': 'Workspace created', 'workspace.createdNoSession': 'Workspace created, but the new session could not be opened',
|
|
777
|
+
'workspace.createTitle': 'New workspace', 'workspace.createDesc': 'Create a folder in the current file directory and open a new session there.', 'workspace.parent': 'Parent folder', 'workspace.namePlaceholder': 'For example: my-project', 'workspace.cancel': 'Cancel', 'workspace.create': 'Create & open', 'workspace.nameRequired': 'Enter a workspace name', 'workspace.created': 'Workspace created', 'workspace.sessionFailed': 'Folder created, but the new session could not be opened: {msg}',
|
|
688
778
|
'sessions.running': 'Running', 'sessions.statRunning': 'Running', 'sessions.statPending': 'Pending', 'sessions.statTotal': 'Sessions',
|
|
779
|
+
'sessions.sortLabel': 'Session sort', 'sessions.sortTime': 'By time', 'sessions.sortWorkspace': 'By workspace', 'sessions.workspace': 'Workspace', 'sessions.workspaceUnknown': 'No workspace',
|
|
689
780
|
'sessions.queueBadge': 'Queue {n}', 'sessions.goalBadge': 'Goal·{phase}',
|
|
690
781
|
'sessions.cacheFallback': 'Network unavailable: showing cached session list',
|
|
691
782
|
'err.badResponse': 'Bad response', 'err.dshError': 'DSH returned an error', 'err.accessDenied': 'Access denied: check your token',
|
|
@@ -717,7 +808,7 @@
|
|
|
717
808
|
'stream.error': 'Event stream error: {msg}',
|
|
718
809
|
'session.loading': 'Loading…', 'session.unknown': 'Unknown session', 'session.running': 'Running', 'session.interrupted': 'Interrupted',
|
|
719
810
|
'session.stop': 'Stop', 'session.history': 'Conversation', 'session.errorMsg': 'Session error: {msg}',
|
|
720
|
-
'session.confirmStop': 'Stop the currently running task in this session?', 'session.stopFailed': 'Stop failed', 'session.stopRequested': 'Stop requested',
|
|
811
|
+
'session.confirmStop': 'Stop the currently running task in this session?', 'session.stopFailed': 'Stop failed', 'session.stopRequested': 'Stop requested', 'session.archive': 'Archive', 'session.archiveConfirm': 'Archive this session? You can open it from “Show archived”.', 'session.archiveFailed': 'Archive failed: {msg}', 'session.archived': 'Session archived', 'session.archiveTitle': 'Confirm archive', 'session.archiveDesc': 'The session will be hidden from the normal list, but its conversation will not be deleted.', 'session.archiveConversation': 'Conversation', 'session.archiveWorkspace': 'Workspace', 'session.archiveCancel': 'Cancel', 'session.archiveConfirmAction': 'Archive session',
|
|
721
812
|
'notify.approvalTitle': 'Tool approval', 'notify.approvalBody': '{tool} needs approval', 'notify.questionTitle': 'DSH question', 'notify.questionBody': 'Needs your answer',
|
|
722
813
|
'notify.permissionFailed': 'Notification permission failed: {msg}',
|
|
723
814
|
'history.loading': 'Loading history…', 'history.cacheFallback': 'Network unavailable: showing cached history', 'history.loadFailed': 'Failed to load history: {msg}', 'history.retry': 'Retry',
|
|
@@ -747,16 +838,17 @@
|
|
|
747
838
|
'menu.compact': '/compact Compress conversation history', 'menu.export': '/export Export session log ZIP',
|
|
748
839
|
'menu.feedback': '/feedback Feedback current session', 'menu.goal': '/goal Set/view task goal',
|
|
749
840
|
'menu.permission': '/permission Switch permission preset', 'menu.plan': '/plan Enter/exit plan mode',
|
|
841
|
+
'perm.readOnly': 'read-only', 'perm.workspaceWrite': 'workspace-write', 'perm.dangerFullAccess': 'danger-full-access',
|
|
750
842
|
'menu.modelTitle': 'Model', 'menu.refresh': 'Refresh', 'menu.modelAuto': 'Auto-loads when opened', 'menu.effortTitle': 'Reasoning effort',
|
|
751
843
|
'composer.placeholder': 'Message DSH…', 'composer.send': 'Send',
|
|
752
844
|
'pending.title': 'Inbox', 'pending.count': '{n} items', 'pending.approvalTitle': '🔧 {tool} requests approval', 'pending.noReason': 'No reason given',
|
|
753
845
|
'pending.allow': 'Allow', 'pending.reject': 'Reject', 'pending.question': '❓ {question}',
|
|
754
846
|
'pending.questionCount': '{n} questions', 'pending.answer': 'Answer', 'pending.empty': 'Nothing pending',
|
|
755
|
-
'pending.allowed': 'Allowed', 'pending.rejected': 'Rejected', 'pending.stale': 'Approval is no longer pending',
|
|
847
|
+
'pending.allowed': 'Allowed', 'pending.rejected': 'Rejected', 'pending.stale': 'Approval is no longer pending', 'pending.submitFailed': 'Approval failed: {msg}',
|
|
756
848
|
'question.customPlaceholder': 'Other / custom answer (optional)', 'question.needAnswer': 'Select or type an answer first',
|
|
757
|
-
'question.submitted': 'Answer submitted', 'question.stale': 'Question is no longer pending',
|
|
849
|
+
'question.submitted': 'Answer submitted', 'question.stale': 'Question is no longer pending', 'question.submitFailed': 'Answer failed: {msg}',
|
|
758
850
|
'jobs.title': 'Background jobs', 'jobs.empty': 'No background jobs',
|
|
759
|
-
'fs.loading': 'Loading…', 'fs.up': 'Up one level', 'fs.upload': 'Upload', 'fs.pause': 'Pause', 'fs.resume': 'Resume', 'fs.cancel': 'Cancel',
|
|
851
|
+
'fs.loading': 'Loading…', 'fs.up': 'Up one level', 'fs.newWorkspace': 'New workspace', 'fs.upload': 'Upload', 'fs.pause': 'Pause', 'fs.resume': 'Resume', 'fs.cancel': 'Cancel',
|
|
760
852
|
'fs.pullDown': 'Pull to refresh', 'fs.pullRelease': 'Release to refresh', 'fs.refreshing': 'Refreshing…',
|
|
761
853
|
'fs.noToken': 'No token set', 'fs.goSettings': 'Go to Settings and paste the gateway token first',
|
|
762
854
|
'fs.notFound': 'Directory not found', 'fs.forbidden': 'Path is outside the allowed roots',
|
|
@@ -807,7 +899,7 @@
|
|
|
807
899
|
'peakRemind.peak0912': 'Peak 9:00-12:00', 'peakRemind.off1214': 'Off-peak 12:00-14:00',
|
|
808
900
|
'peakRemind.peak1418': 'Peak 14:00-18:00', 'peakRemind.off1809': 'Off-peak 18:00-9:00 next day',
|
|
809
901
|
'peakRemind.browserOnly': 'Peak reminders only work in the app',
|
|
810
|
-
'peakRemind.on': 'Peak reminders enabled', 'peakRemind.off': 'Peak reminders disabled',
|
|
902
|
+
'peakRemind.on': 'Peak reminders enabled', 'peakRemind.off': 'Peak reminders disabled', 'peakRemind.failed': 'Could not start peak reminder service; try again',
|
|
811
903
|
'settings.bgTitle': 'Background polling', 'settings.bgDesc': 'A foreground service polls events while the app is in the background, so approvals/questions are not missed',
|
|
812
904
|
'settings.bgIntervalTitle': 'Polling interval', 'settings.bgIntervalDesc': 'Screen-off may stretch the interval (Doze platform limit)',
|
|
813
905
|
'settings.bgInterval30s': '30 seconds', 'settings.bgInterval1m': '1 minute', 'settings.bgInterval5m': '5 minutes', 'settings.bgInterval15m': '15 minutes',
|
|
@@ -822,12 +914,14 @@
|
|
|
822
914
|
'presets.nameEmpty': 'Name cannot be empty', 'presets.nameTooLong': 'Name must be ≤20 characters', 'presets.textTooLong': 'Content must be ≤2000 characters', 'presets.limit': 'At most 20 presets', 'presets.added': 'Preset added',
|
|
823
915
|
'presets.confirmDelete': 'Delete preset "{name}"?', 'presets.saved': 'Preset saved', 'presets.deleted': 'Preset deleted',
|
|
824
916
|
'settings.toolsTitle': 'Show tool calls', 'settings.toolsDesc': 'Hide 🔧/📦 tool calls and results when off',
|
|
917
|
+
'settings.mobileEnterTitle': 'Mobile Enter behavior', 'settings.mobileEnterDesc': 'Choose whether Enter inserts a newline or sends', 'settings.mobileEnterNewline': 'Enter = newline', 'settings.mobileEnterSend': 'Enter = send',
|
|
825
918
|
'settings.langTitle': 'Language / 语言', 'settings.langDesc': 'UI language, follows system or switch manually',
|
|
826
919
|
'settings.themeTitle': 'Theme', 'settings.themeDesc': 'Default deep space / Sunset / Elbphilharmonie / Prairie Tower',
|
|
827
920
|
'theme.default': 'Default', 'theme.dark': 'Sunset', 'theme.light': 'Elbphilharmonie', 'theme.neutral': 'Prairie Tower',
|
|
828
921
|
'theme.panelTitle': 'Choose theme', 'theme.close': 'Close',
|
|
829
922
|
'settings.tokenTitle': 'Access token', 'settings.change': 'Change',
|
|
830
923
|
'settings.hostTitle': 'DSH status', 'settings.hostProbing': 'Probing…', 'settings.probe': 'Probe', 'settings.probeFailed': 'Probe failed',
|
|
924
|
+
'settings.dshControlTitle': 'Remote DSH control', 'settings.dshControlProbing': 'Checking local service…', 'settings.dshRunning': 'Running', 'settings.dshStopped': 'Stopped', 'settings.dshUnsupported': 'No controllable DSH service is configured', 'settings.dshStart': 'Start', 'settings.dshRestart': 'Restart', 'settings.dshStarting': '{action}ing DSH…', 'settings.dshStarted': 'DSH {action}ed', 'settings.dshFailed': 'DSH operation failed: {msg}',
|
|
831
925
|
'settings.hostDesc': 'DSH {version} · {cwd} · {n} attached sessions',
|
|
832
926
|
'settings.updateTitle': 'Check for updates', 'settings.updateLoading': 'Loading…', 'settings.downloadUpdate': 'Download & install update', 'settings.check': 'Check',
|
|
833
927
|
'settings.feedbackTitle': 'Feedback', 'settings.feedbackDesc': 'GitHub / Gitee / Bilibili: report bugs, suggest features, or just chat',
|
|
@@ -849,6 +943,7 @@
|
|
|
849
943
|
'modal.approvalTitle': 'Tool approval', 'modal.reject': 'Reject', 'modal.allowOnce': 'Allow once',
|
|
850
944
|
'modal.questionTitle': 'DSH needs your answer', 'modal.later': 'Later', 'modal.submit': 'Submit',
|
|
851
945
|
'modal.goalTitle': 'Goal control', 'modal.close': 'Close', 'modal.updateGoal': 'Update goal',
|
|
946
|
+
'announcement.label': 'Announcement', 'announcement.later': 'Later', 'announcement.gotIt': 'Got it', 'announcement.open': 'View details',
|
|
852
947
|
'modal.statsTitle': 'This round',
|
|
853
948
|
'time.justNow': 'just now', 'time.minAgo': ' min ago', 'time.hourAgo': ' hr ago'
|
|
854
949
|
}
|
package/public/styles.css
CHANGED
|
@@ -120,9 +120,17 @@ a.mini-btn { text-decoration: none; display: inline-flex; align-items: center; }
|
|
|
120
120
|
|
|
121
121
|
.section-head {
|
|
122
122
|
display: flex; align-items: center; justify-content: space-between;
|
|
123
|
-
margin: 14px 2px 8px; font-size: 13px; font-weight: 700; color: var(--dsr-muted);
|
|
123
|
+
gap: 8px; min-width: 0; margin: 14px 2px 8px; font-size: 13px; font-weight: 700; color: var(--dsr-muted);
|
|
124
124
|
letter-spacing: 1px;
|
|
125
125
|
}
|
|
126
|
+
.section-head > span:first-child { min-width: 0; }
|
|
127
|
+
.section-actions { display: flex; align-items: center; justify-content: flex-end; gap: 6px; min-width: 0; flex-wrap: wrap; }
|
|
128
|
+
.session-sort {
|
|
129
|
+
min-width: 0; max-width: 112px; height: 30px; padding: 0 7px;
|
|
130
|
+
color: var(--dsr-muted); background: var(--dsr-panel); border: 1px solid var(--dsr-line);
|
|
131
|
+
border-radius: 8px; font: inherit; font-size: 11px; outline: none;
|
|
132
|
+
}
|
|
133
|
+
.session-sort:focus { border-color: var(--dsr-accent-line); color: var(--dsr-text); }
|
|
126
134
|
.section-head.small { margin-top: 6px; }
|
|
127
135
|
|
|
128
136
|
/* ---------- Token 统计(移动端) ---------- */
|
|
@@ -155,7 +163,7 @@ a.mini-btn { text-decoration: none; display: inline-flex; align-items: center; }
|
|
|
155
163
|
.session-list { display: flex; flex-direction: column; gap: 8px; }
|
|
156
164
|
.session-card {
|
|
157
165
|
background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: var(--dsr-radius);
|
|
158
|
-
padding: 12px 13px; position: relative; overflow: hidden;
|
|
166
|
+
flex: 0 0 auto; padding: 12px 13px; position: relative; overflow: hidden;
|
|
159
167
|
}
|
|
160
168
|
.session-card:active { background: var(--dsr-panel-2); }
|
|
161
169
|
.session-card.current { border-color: var(--dsr-accent-line); box-shadow: 0 0 0 1px var(--dsr-accent-soft); }
|
|
@@ -164,6 +172,20 @@ a.mini-btn { text-decoration: none; display: inline-flex; align-items: center; }
|
|
|
164
172
|
text-overflow: ellipsis; padding-right: 44px;
|
|
165
173
|
}
|
|
166
174
|
.sc-meta { display: flex; gap: 8px; align-items: center; margin-top: 4px; font-size: 12px; color: var(--dsr-muted); flex-wrap: wrap; }
|
|
175
|
+
.sc-workspace {
|
|
176
|
+
min-width: 0; margin-top: 5px; padding-right: 28px; color: var(--dsr-muted); font-size: 11px;
|
|
177
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
178
|
+
}
|
|
179
|
+
.session-group-label {
|
|
180
|
+
display: flex; align-items: center; gap: 6px; flex: 0 0 auto; min-width: 0; min-height: 28px;
|
|
181
|
+
box-sizing: border-box; margin: 8px 2px 0; padding: 6px 8px 4px; border-bottom: 1px solid var(--dsr-line);
|
|
182
|
+
color: var(--dsr-accent-strong); font-size: 11px; font-weight: 700;
|
|
183
|
+
}
|
|
184
|
+
.session-group-icon { flex: 0 0 auto; color: var(--dsr-accent-2); font-size: 12px; }
|
|
185
|
+
.session-group-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
186
|
+
.session-list.workspace-sorted .sc-workspace { display: none; }
|
|
187
|
+
.session-list.workspace-sorted .session-card { padding-top: 11px; padding-bottom: 11px; }
|
|
188
|
+
}
|
|
167
189
|
.sc-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dsr-line); display: inline-block; }
|
|
168
190
|
.sc-dot.running { background: var(--dsr-warning); box-shadow: 0 0 8px var(--dsr-warning-line); animation: pulse 1.6s infinite; }
|
|
169
191
|
.sc-dot.pending { background: var(--dsr-accent-2); box-shadow: 0 0 8px var(--dsr-accent-2-line); }
|
|
@@ -174,8 +196,38 @@ a.mini-btn { text-decoration: none; display: inline-flex; align-items: center; }
|
|
|
174
196
|
}
|
|
175
197
|
.sc-badge.goal-active { background: var(--dsr-info-soft); color: var(--dsr-info); border-color: var(--dsr-info-line); }
|
|
176
198
|
.sc-arrow { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); color: var(--dsr-muted); }
|
|
199
|
+
.session-swipe { position: relative; overflow: hidden; border-radius: var(--dsr-radius); background: var(--dsr-error); touch-action: pan-y; }
|
|
200
|
+
.session-swipe .session-card { position: relative; z-index: 1; transform: translateX(var(--swipe-x, 0)); transition: transform .18s ease; }
|
|
201
|
+
.session-swipe.revealed .session-card { transform: translateX(-92px); }
|
|
202
|
+
.sc-archive-btn { position: absolute; inset: 0 0 0 auto; z-index: 0; width: 92px; display: grid; place-items: center; padding: 0; background: var(--dsr-error); color: #fff; font-size: 13px; font-weight: 700; }
|
|
203
|
+
.sc-archive-btn:active { filter: brightness(.9); }
|
|
177
204
|
.empty { text-align: center; color: var(--dsr-muted); padding: 34px 0; }
|
|
178
205
|
|
|
206
|
+
/* ---------- 工作台与归档会话 ---------- */
|
|
207
|
+
.workbench-bar { margin: 0 0 2px; border-radius: var(--dsr-radius); overflow: hidden; }
|
|
208
|
+
.workbench-bar .wb-toggle {
|
|
209
|
+
width: 100%; display: flex; align-items: center; gap: 8px; padding: 10px 13px;
|
|
210
|
+
font: inherit; text-align: left; border: 1px solid var(--dsr-line);
|
|
211
|
+
background: var(--dsr-panel); color: var(--dsr-text);
|
|
212
|
+
}
|
|
213
|
+
.workbench-bar.unbound .wb-toggle { color: var(--dsr-muted); cursor: default; }
|
|
214
|
+
.workbench-bar.unbound .wb-chevron { visibility: hidden; }
|
|
215
|
+
.workbench-bar.bound .wb-toggle { background: var(--dsr-accent-soft); border-color: var(--dsr-accent-line); color: var(--dsr-accent-strong); font-weight: 600; }
|
|
216
|
+
.wb-label { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
217
|
+
.wb-chevron { flex-shrink: 0; font-size: 11px; color: var(--dsr-muted); transition: transform .15s ease; }
|
|
218
|
+
.workbench-bar.bound .wb-toggle[aria-expanded="true"] .wb-chevron { transform: rotate(180deg); }
|
|
219
|
+
.wb-panel { background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); border-top: none; border-radius: 0 0 var(--dsr-radius) var(--dsr-radius); padding: 8px; display: flex; flex-direction: column; gap: 6px; }
|
|
220
|
+
.wb-project { background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 10px; overflow: hidden; }
|
|
221
|
+
.wb-project-head { display: flex; align-items: center; gap: 7px; padding: 9px 10px; cursor: pointer; }
|
|
222
|
+
.wb-project-title { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
223
|
+
.wb-new { padding: 3px 9px; font-size: 12px; }
|
|
224
|
+
.wb-sessions { display: flex; flex-direction: column; gap: 4px; padding: 0 6px 6px; }
|
|
225
|
+
.wb-session { width: 100%; display: flex; align-items: center; gap: 8px; background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); border-radius: 8px; padding: 7px 9px; text-align: left; color: var(--dsr-text); font: inherit; }
|
|
226
|
+
.wb-session-title { flex: 1; min-width: 0; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
227
|
+
.wb-session-meta { flex-shrink: 0; font-size: 11px; color: var(--dsr-muted); }
|
|
228
|
+
.wb-empty { font-size: 12px; color: var(--dsr-muted); text-align: center; padding: 10px 0; }
|
|
229
|
+
.archived-toggle { width: 100%; display: block; text-align: center; padding: 9px 0; margin-top: 2px; border-radius: 9px; background: var(--dsr-panel); border: 1px dashed var(--dsr-line); color: var(--dsr-muted); font-size: 12px; }
|
|
230
|
+
|
|
179
231
|
/* ---------- 会话详情 ---------- */
|
|
180
232
|
body.in-session { overflow: hidden; height: 100vh; height: 100dvh; }
|
|
181
233
|
body.in-session .topbar { display: none; }
|
|
@@ -404,9 +456,9 @@ body.in-session .main { padding-bottom: 84px; }
|
|
|
404
456
|
.job-state { font-size: 12px; color: var(--dsr-muted); margin-top: 3px; }
|
|
405
457
|
|
|
406
458
|
/* ---------- 文件传输 ---------- */
|
|
407
|
-
.fs-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
|
|
459
|
+
.fs-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
|
|
408
460
|
.fs-path {
|
|
409
|
-
flex: 1; min-width: 0; font-size: 12.5px; color: var(--dsr-muted);
|
|
461
|
+
flex: 1 1 150px; min-width: 0; font-size: 12.5px; color: var(--dsr-muted);
|
|
410
462
|
background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 10px;
|
|
411
463
|
padding: 8px 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
412
464
|
}
|
|
@@ -460,6 +512,7 @@ body.in-session .main { padding-bottom: 84px; }
|
|
|
460
512
|
.setting-name { font-size: 14.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
461
513
|
.setting-desc { font-size: 12px; color: var(--dsr-muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
462
514
|
.setting-desc.expanded { white-space: normal; overflow: visible; text-overflow: clip; word-break: break-word; }
|
|
515
|
+
.setting-select { min-width: 112px; max-width: 145px; padding: 7px 9px; border-radius: 10px; border: 1px solid var(--dsr-line); background: var(--dsr-bg-2); color: var(--dsr-text); font: inherit; font-size: 12px; }
|
|
463
516
|
.setting-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
|
|
464
517
|
.about { text-align: center; color: var(--dsr-muted); font-size: 12px; margin-top: 16px; line-height: 1.8; }
|
|
465
518
|
|
|
@@ -612,6 +665,9 @@ body.in-session .main { padding-bottom: 84px; }
|
|
|
612
665
|
}
|
|
613
666
|
.modal-title { font-size: 16px; font-weight: 700; margin-bottom: 10px; }
|
|
614
667
|
.modal-body { font-size: 14px; }
|
|
668
|
+
.workspace-create-desc { margin: 0 0 12px; color: var(--dsr-muted); line-height: 1.55; }
|
|
669
|
+
.workspace-create-location { display: flex; align-items: center; gap: 8px; min-width: 0; margin-bottom: 10px; color: var(--dsr-muted); font-size: 12px; }
|
|
670
|
+
.workspace-create-location code { min-width: 0; flex: 1; padding: 7px 9px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsr-text); background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 9px; }
|
|
615
671
|
.modal-body .q-item { background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 12px; padding: 11px 12px; margin-bottom: 10px; }
|
|
616
672
|
.modal-body .q-text { font-weight: 600; margin-bottom: 8px; }
|
|
617
673
|
.modal-body .q-option {
|
|
@@ -623,6 +679,19 @@ body.in-session .main { padding-bottom: 84px; }
|
|
|
623
679
|
border: 1px solid var(--dsr-line); border-radius: 10px; padding: 9px 11px; font: inherit; outline: none;
|
|
624
680
|
}
|
|
625
681
|
.modal-actions { display: flex; gap: 9px; margin-top: 14px; }
|
|
682
|
+
.archive-modal-desc { margin: 0 0 12px; color: var(--dsr-muted); line-height: 1.55; }
|
|
683
|
+
.archive-summary { border: 1px solid var(--dsr-line); border-radius: 12px; background: var(--dsr-panel); padding: 10px 12px; }
|
|
684
|
+
.archive-summary-row { display: grid; grid-template-columns: 62px minmax(0, 1fr); gap: 10px; align-items: start; padding: 6px 0; font-size: 13px; }
|
|
685
|
+
.archive-summary-row + .archive-summary-row { border-top: 1px solid var(--dsr-line); }
|
|
686
|
+
.archive-summary-row > span { color: var(--dsr-muted); }
|
|
687
|
+
.archive-summary-row strong, .archive-summary-row code { min-width: 0; color: var(--dsr-text); overflow-wrap: anywhere; word-break: break-word; }
|
|
688
|
+
.archive-confirm-btn { flex: 1; padding: 11px 14px; border-radius: 12px; font-size: 15px; font-weight: 700; border: 1px solid var(--dsr-error); background: var(--dsr-error); color: #fff; }
|
|
689
|
+
.archive-confirm-btn:active { filter: brightness(.9); }
|
|
690
|
+
.announcement-card { border-top: 3px solid var(--dsr-accent); }
|
|
691
|
+
.announcement-kicker { color: var(--dsr-accent-strong); font-size: 12px; font-weight: 700; letter-spacing: .04em; margin-bottom: 6px; }
|
|
692
|
+
.announcement-content { line-height: 1.7; overflow-wrap: anywhere; word-break: break-word; }
|
|
693
|
+
.announcement-action { display: inline-block; margin-top: 12px; color: var(--dsr-accent-strong); font-size: 13px; font-weight: 600; text-decoration: none; }
|
|
694
|
+
.announcement-action:hover { text-decoration: underline; }
|
|
626
695
|
.kv { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; padding: 3px 0; }
|
|
627
696
|
.kv .k { color: var(--dsr-muted); } .kv .v { word-break: break-all; text-align: right; }
|
|
628
697
|
|
|
@@ -635,6 +704,15 @@ body.in-session .main { padding-bottom: 84px; }
|
|
|
635
704
|
@media (max-width: 720px) {
|
|
636
705
|
#btn-theme .t-label { display: none; }
|
|
637
706
|
#btn-theme .theme-swatch-dot { margin-right: 0; }
|
|
707
|
+
.section-actions { gap: 4px; }
|
|
708
|
+
.section-actions .session-sort { max-width: 98px; }
|
|
709
|
+
.section-actions .mini-btn { max-width: 92px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
710
|
+
.topbar { padding-left: 10px; padding-right: 10px; }
|
|
711
|
+
.topbar-right { gap: 4px; min-width: 0; }
|
|
712
|
+
.topbar-right .topbar-btn.icon-btn { width: 38px; height: 38px; }
|
|
713
|
+
.topbar-right .topbar-btn.conn-badge { max-width: 72px; padding-left: 8px; padding-right: 8px; overflow: hidden; text-overflow: ellipsis; }
|
|
714
|
+
.setting-row { align-items: flex-start; flex-wrap: wrap; }
|
|
715
|
+
.setting-row > .setting-actions { width: 100%; justify-content: flex-end; }
|
|
638
716
|
}
|
|
639
717
|
.theme-panel-list { display: flex; flex-direction: column; gap: 8px; }
|
|
640
718
|
.theme-option {
|
package/public/update.json
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.6.
|
|
2
|
+
"version": "0.6.7",
|
|
3
3
|
"apkUrl": "dsh-remote.apk",
|
|
4
|
-
"sha256": "
|
|
5
|
-
"releasedAt": "2026-08-
|
|
6
|
-
"notes": "
|
|
4
|
+
"sha256": "c2cb5b68c8fef1eabe4e1e669f03d41815b923d5568e325bb04d5d7a1fbd122a",
|
|
5
|
+
"releasedAt": "2026-08-21T10:34:07.760Z",
|
|
6
|
+
"notes": "修复手机端左滑归档松手后按钮不固定;新增云端公告弹窗,支持按 App 版本和有效期定向发布;新增工作台绑定与项目级会话;新增手机端左滑归档和二次确认;新增手机回车行为设置;新增归档会话折叠和 /permission 参数选择。",
|
|
7
7
|
"history": [
|
|
8
|
+
{
|
|
9
|
+
"version": "0.6.7",
|
|
10
|
+
"notes": "修复手机端左滑归档松手后按钮不固定;新增云端公告弹窗,支持按 App 版本和有效期定向发布;新增工作台绑定与项目级会话;新增手机端左滑归档和二次确认;新增手机回车行为设置;新增归档会话折叠和 /permission 参数选择。"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"version": "0.6.6",
|
|
14
|
+
"notes": "新增新建工作区,按当前文件目录创建文件夹并自动打开会话;优化工作区排序分组、路径显示和小屏布局。"
|
|
15
|
+
},
|
|
8
16
|
{
|
|
9
17
|
"version": "0.6.5",
|
|
10
18
|
"notes": "连接稳定性全面优化:25 秒心跳保活(WiFi 切换 / NAT 超时不再假活);60 秒无消息自动重连,指数退避重连(1s → 30s 上限 + 抖动);网关死连接自动清理(60 秒无数据双向销毁);断网自动检测与恢复(离线 / 重连中倒计时 / 连接失败状态可见);降级轮询恢复优化。"
|
package/public/version.json
CHANGED