@zaofan/dsh-qqbot 1.10.22 → 1.10.23

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.
@@ -19,15 +19,20 @@ window.__ModuleLoader__.load({
19
19
  var inputStyle = { marginLeft: 8, padding: '2px 6px', border: '1px solid #8884', borderRadius: 4, background: 'transparent', color: 'inherit', width: 110 }
20
20
  var wideStyle = { ...inputStyle, width: 260 }
21
21
  var fullStyle = { ...inputStyle, width: '92%', display: 'block', margin: '4px 0 8px' }
22
- var boxStyle = { border: '1px solid #e5e6eb', borderRadius: 8, padding: '10px 14px 12px', margin: '8px 0', background: '#fff' }
23
- var sectionTitle = { fontWeight: 600, margin: '10px 0 4px', fontSize: 14, color: '#1f2329' }
22
+ var boxStyle = { border: '1px solid var(--qqs-border,#e5e6eb)', borderRadius: 8, padding: '10px 14px 12px', margin: '8px 0', background: 'var(--qqs-card,#fff)' }
23
+ var sectionTitle = { fontWeight: 600, margin: '10px 0 4px', fontSize: 14, color: 'var(--qqs-text,#1f2329)' }
24
24
 
25
25
  // ── 迷你设计系统(2026-09-05 专家团定稿; 深色柔和适配宿主, 不刺眼) ──
26
26
  // 宿主 dsh web 为深色主题 → 卡片用半透明深色、文字浅色、主色用低饱和紫(贴合 #9775fa 系)
27
27
  var T = {
28
- bg: 'transparent', card: '#ffffff', cardHi: '#fafafa', cardSolid: '#f4f5f8', border: '#e2e5ea', borderLight: '#eef0f3',
29
- text: '#1f2329', text2: '#4e5560', text3: '#8a919c',
30
- primary: '#7c6cf0', primary2: '#6b5ae6', primaryBg: '#7c6cf01a', primaryBorder: '#7c6cf04d',
28
+ // 2026-10-22 P0:结构色改走 CSS token(定义在 QQS_THEME_CSS,宿主切 body[data-ds-dark-theme] 时自动变)
29
+ // 每个 var 都带亮色回退:变量表没加载时回退亮色,绝不出现 unset/透明
30
+ bg: 'transparent',
31
+ card: 'var(--qqs-card,#ffffff)', cardHi: 'var(--qqs-card-hi,#fafafa)', cardSolid: 'var(--qqs-card-solid,#f4f5f8)',
32
+ border: 'var(--qqs-border,#e2e5ea)', borderLight: 'var(--qqs-border-light,#eef0f3)',
33
+ text: 'var(--qqs-text,#1f2329)', text2: 'var(--qqs-text2,#4e5560)', text3: 'var(--qqs-text3,#8a919c)',
34
+ dangerSoft: '#e5484d88',
35
+ primary: '#7c6cf0', primary2: '#6b5ae6', primaryBg: 'var(--qqs-primary-bg,#7c6cf01a)', primaryBorder: 'var(--qqs-primary-border,#7c6cf04d)',
31
36
  danger: '#e5484d', dangerBg: '#e5484d14',
32
37
  success: '#1f9e4f', successBg: '#1f9e4f14',
33
38
  warn: '#d97706', warnBg: '#d9770614',
@@ -43,7 +48,7 @@ window.__ModuleLoader__.load({
43
48
  padding: size === 'sm' ? '2px 10px' : '4px 14px', fontSize: size === 'sm' ? 12 : 13, lineHeight: '20px', whiteSpace: 'nowrap',
44
49
  transition: 'background .15s, border-color .15s, color .15s',
45
50
  }
46
- if (variant === 'primary') return { ...base, background: T.primaryBg, color: T.primary, borderColor: T.primaryBorder, fontWeight: 600 }
51
+ if (variant === 'primary') return { ...base, background: T.primaryBg, color: 'var(--qqs-primary-fg,#6b5ae6)', borderColor: T.primaryBorder, fontWeight: 600 }
47
52
  if (variant === 'danger') return { ...base, background: T.dangerBg, color: T.danger, borderColor: '#f7656044', fontWeight: 600 }
48
53
  if (variant === 'ghost') return { ...base, background: 'transparent', color: T.text2 }
49
54
  return { ...base, background: T.card, color: T.text }
@@ -1125,8 +1130,8 @@ window.__ModuleLoader__.load({
1125
1130
  h('label', { style: { fontSize: 13, whiteSpace: 'nowrap' } }, h('input', { className: 'qqs-inp', type: 'checkbox', className: 'qqs-cb', checked: untagged, onChange: function (e) { setUntagged(e.target.checked) } }), ' 只看没打标的'),
1126
1131
  h('button', { className: 'qqs-btn', onClick: function () { setImp(true) } }, '导入'),
1127
1132
  h('button', { className: 'qqs-btn', onClick: load }, '刷新')),
1128
- h('p', { style: { fontSize: 12, color: '#888' } }, '共 ' + items.length + ' 张。点图看大图并编辑标签/描述;勾选后底部批量操作。'),
1129
- items.length === 0 ? h('p', { style: { color: '#888', padding: 20, textAlign: 'center' } }, '这里还没有图' + (untagged ? '(没有未打标的图了 🎉)' : ',点右上角「导入」或等群里发图自动收藏')) : null,
1133
+ h('p', { style: { fontSize: 12, color: 'var(--qqs-text2,#888)' } }, '共 ' + items.length + ' 张。点图看大图并编辑标签/描述;勾选后底部批量操作。'),
1134
+ items.length === 0 ? h('p', { style: { color: 'var(--qqs-text2,#888)', padding: 20, textAlign: 'center' } }, '这里还没有图' + (untagged ? '(没有未打标的图了 🎉)' : ',点右上角「导入」或等群里发图自动收藏')) : null,
1130
1135
  h('div', { ref: gridRef, onMouseDown: onGridDown, style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(104px,1fr))', gap: 14, padding: 14, userSelect: 'none', cursor: 'crosshair', minHeight: 120 } },
1131
1136
  items.map(function (it) {
1132
1137
  var on = sel.includes(it.id)
@@ -1139,11 +1144,11 @@ window.__ModuleLoader__.load({
1139
1144
  })),
1140
1145
  h('div', { style: { height: 120, cursor: 'crosshair', userSelect: 'none' } }),
1141
1146
  sel.length ? h('div', { style: { position: 'sticky', bottom: 8, marginTop: 10, background: 'rgba(255,255,255,.86)', border: '1px solid #00000030', borderRadius: 12, padding: '8px 12px', display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', boxShadow: '0 6px 22px rgba(0,0,0,.18)', backdropFilter: 'blur(4px)' } },
1142
- h('span', { style: { fontWeight: 800, color: '#171a21' } }, '已选 ' + sel.length + ' 张'),
1147
+ h('span', { style: { fontWeight: 800, color: 'var(--qqs-text,#171a21)' } }, '已选 ' + sel.length + ' 张'),
1143
1148
  layer !== 'trash' ? h('button', { onClick: function () { batch('promote') }, style: { font: 'inherit', cursor: 'pointer', padding: '4px 12px', borderRadius: 9, border: '1px solid #2f9e4499', background: 'rgba(47,158,68,.12)', color: '#1d7a31', fontWeight: 700, fontSize: 13 } }, '移入收藏 ★') : null,
1144
1149
  layer !== 'trash' ? h('button', { onClick: function () { batch('trash') }, style: { font: 'inherit', cursor: 'pointer', padding: '4px 12px', borderRadius: 9, border: '1px solid #e8590c99', background: 'rgba(232,89,12,.12)', color: '#c2450a', fontWeight: 700, fontSize: 13 } }, '送回收站') : null,
1145
1150
  layer === 'trash' ? h('button', { onClick: function () { batch('restore') }, style: { font: 'inherit', cursor: 'pointer', padding: '4px 12px', borderRadius: 9, border: '1px solid #2f9e4499', background: 'rgba(47,158,68,.12)', color: '#1d7a31', fontWeight: 700, fontSize: 13 } }, '恢复') : null,
1146
- h('button', { onClick: function () { setSel([]) }, style: { font: 'inherit', cursor: 'pointer', padding: '4px 12px', borderRadius: 9, border: '1px solid #00000030', background: 'rgba(255,255,255,.7)', color: '#444', fontWeight: 600, fontSize: 13 } }, '取消')) : null,
1151
+ h('button', { onClick: function () { setSel([]) }, style: { font: 'inherit', cursor: 'pointer', padding: '4px 12px', borderRadius: 9, border: '1px solid #00000030', background: 'rgba(255,255,255,.7)', color: 'var(--qqs-text,#444)', fontWeight: 600, fontSize: 13 } }, '取消')) : null,
1147
1152
  mq ? h('div', { style: { position: 'fixed', left: mq.x0, top: mq.y0, width: Math.max(0, mq.x1 - mq.x0), height: Math.max(0, mq.y1 - mq.y0), border: '1px dashed #5b9dff', background: '#5b9dff22', pointerEvents: 'none', zIndex: 500 } }) : null,
1148
1153
  msg ? h('p', { style: { fontSize: 13, color: '#2f9e44' } }, msg) : null,
1149
1154
  box ? h(Lightbox, { item: box, storeDir: DD || undefined, onClose: function () { setBox(null); load() }, onChanged: load }) : null,
@@ -1293,18 +1298,18 @@ window.__ModuleLoader__.load({
1293
1298
  setTargets(list)
1294
1299
  }
1295
1300
  // 保存: 整表(行→分组已实时同步)全量 patch
1296
- // 2026-10-22(主人定):扫码拿到凭据后自动保存,用户不用再手动点「保存」
1297
- function autoSaveAfterBind(list) {
1298
- setMsg('💾 自动保存中…')
1299
- setTimeout(function () {
1300
- try {
1301
- setBusy('')
1302
- save(list, true)
1303
- } catch (e) {
1304
- setMsg('扫码成功但自动保存失败: ' + (e && e.message ? e.message : e) + ' —— 请手动点保存')
1305
- }
1306
- }, 150)
1307
- }
1301
+ // 2026-10-22(主人定):扫码拿到凭据后自动保存,用户不用再手动点「保存」
1302
+ function autoSaveAfterBind(list) {
1303
+ setMsg('💾 自动保存中…')
1304
+ setTimeout(function () {
1305
+ try {
1306
+ setBusy('')
1307
+ save(list, true)
1308
+ } catch (e) {
1309
+ setMsg('扫码成功但自动保存失败: ' + (e && e.message ? e.message : e) + ' —— 请手动点保存')
1310
+ }
1311
+ }, 150)
1312
+ }
1308
1313
  function save(listOverride) {
1309
1314
  setMsg('保存中…')
1310
1315
  var v = cfg || {}
@@ -1459,14 +1464,14 @@ window.__ModuleLoader__.load({
1459
1464
  h('div', { style: { fontWeight: 700, fontSize: 13 } }, '② 她答应你的定时提醒(在 QQ 里说一声就能建)'),
1460
1465
  h('p', { style: { fontSize: T.fsSm, color: T.text3 } }, '这些是她在 QQ 里应你要求安排的提醒。这里只管看/开关/删除;一次性到点自动消失。'),
1461
1466
  jobs === null ? h('p', { style: { fontSize: T.fsSm, color: T.text3 }, padding: 10 }, '加载中…') : null,
1462
- jobs !== null && jobs.length === 0 ? h('p', { style: { color: '#888', padding: 14, textAlign: 'center', fontSize: T.fsSm } }, '还没有这类提醒。去 QQ 里让她安排一个,就会出现在这里。') : null,
1467
+ jobs !== null && jobs.length === 0 ? h('p', { style: { color: 'var(--qqs-text2,#888)', padding: 14, textAlign: 'center', fontSize: T.fsSm } }, '还没有这类提醒。去 QQ 里让她安排一个,就会出现在这里。') : null,
1463
1468
  (jobs || []).map(function (j) {
1464
1469
  var disabled = busyId === j.id
1465
- // 2026-10-22 修:台账(groups.json / known-chats)只是本地缓存,可能为空或滞后,
1466
- // 查不到 openid ≠ 群不存在(实测:群正常、定时任务照发,却被标红“群已失效”)。
1467
- // 故不再据此标失效;真要判定需调 QQ API 探测。
1470
+ // 2026-10-22 修:台账(groups.json / known-chats)只是本地缓存,可能为空或滞后,
1471
+ // 查不到 openid ≠ 群不存在(实测:群正常、定时任务照发,却被标红“群已失效”)。
1472
+ // 故不再据此标失效;真要判定需调 QQ API 探测。
1468
1473
  var deadGroup = false
1469
- return h('div', { key: j.id, style: { border: '1px solid ' + (deadGroup ? T.danger + '88' : (j.enabled ? T.border : '#ffa94d66')), borderRadius: T.radius, padding: '8px 10px', margin: '6px 0', background: '#fff', opacity: j.enabled ? 1 : 0.72 } },
1474
+ return h('div', { key: j.id, style: { border: '1px solid ' + (deadGroup ? T.dangerSoft : (j.enabled ? T.border : '#ffa94d66')), borderRadius: T.radius, padding: '8px 10px', margin: '6px 0', background: 'var(--qqs-card,#fff)', opacity: j.enabled ? 1 : 0.72 } },
1470
1475
  h('div', { style: { display: 'flex', gap: 6, alignItems: 'center', flexWrap: 'wrap' } },
1471
1476
  chip(j.kind),
1472
1477
  h('span', { style: { fontWeight: 600, fontSize: T.fsSm } }, fmtWhen(j)),
@@ -1479,7 +1484,7 @@ window.__ModuleLoader__.load({
1479
1484
  j.prompt ? h('div', { style: { fontSize: T.fsSm, color: '#cfd3dc', background: '#ffffff0a', border: '1px solid #ffffff14', borderRadius: T.radius, padding: '4px 8px', marginTop: 4, whiteSpace: 'pre-wrap', wordBreak: 'break-all' } }, j.prompt) : null)
1480
1485
  }),
1481
1486
  msg ? h('p', { style: { fontSize: T.fsSm, color: T.success } }, msg) : null))
1482
- return h('div', { style: { width: '100%' } },
1487
+ return h('div', { style: { width: '100%', color: 'var(--qqs-text,#1f2329)' } },
1483
1488
  h('div', { style: { display: 'flex', gap: 14, alignItems: 'flex-start', flexWrap: 'wrap' } }, leftCol, rightCol),
1484
1489
  props && props.close ? h('button', { className: 'qqs-btn', onClick: props.close, style: { float: 'right', marginTop: 6 } }, '完成') : null)
1485
1490
  }
@@ -1552,14 +1557,14 @@ window.__ModuleLoader__.load({
1552
1557
  var acctLine = (accts && accts.length > 1) || (accts && accts.length === 1)
1553
1558
  return h('div', { style: { width: '100%' } },
1554
1559
  // ── 一级: 账号选择条(身份带) ──
1555
- h('div', { style: { display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', margin: '2px 0 10px', padding: '6px 10px', border: '1px solid #b197fc55', borderRadius: 12, background: 'linear-gradient(90deg,#b197fc22,#b197fc0a)' } },
1556
- h('span', { style: { fontSize: 13, fontWeight: 800, color: '#171a21', whiteSpace: 'nowrap' } }, '🤖 正在查看:'),
1560
+ h('div', { style: { display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', margin: '2px 0 10px', padding: '6px 10px', border: '1px solid #b197fc55', borderRadius: 12, background: 'linear-gradient(90deg,#b197fc22,#b197fc0a)', color: 'var(--qqs-text,#1f2329)' } },
1561
+ h('span', { style: { fontSize: 13, fontWeight: 800, color: 'var(--qqs-text,#171a21)', whiteSpace: 'nowrap' } }, '🤖 正在查看:'),
1557
1562
  accts && accts.length > 0
1558
1563
  ? h('select', { className: 'qqs-inp', style: { padding: '4px 8px', fontWeight: 700 }, value: ac ? ac.id : '', onChange: function (e) { chooseAcct(e.target.value) } },
1559
1564
  accts.map(function (a) {
1560
1565
  return h('option', { key: a.id, value: a.id }, a.id + (a.appId ? ' (AppID ' + a.appId + ')' : '') + (a.disabled ? ' [停用]' : ''))
1561
1566
  }))
1562
- : h('span', { style: { fontSize: 13, color: '#888' } }, '无账号… 去「账号与预设」添加'),
1567
+ : h('span', { style: { fontSize: 13, color: 'var(--qqs-text2,#888)' } }, '无账号… 去「账号与预设」添加'),
1563
1568
  ac ? h('span', { style: { fontSize: 12, color: '#6d28d9', whiteSpace: 'nowrap' } }, ac.dataDir ? '数据目录: ' + ac.dataDir : '') : null,
1564
1569
  h('span', { style: { flex: 1 } }),
1565
1570
  h('span', { style: { fontSize: 12, color: '#8a97ad' } }, '设置/图库/定时 都跟随上面选的机器人')),
@@ -1571,7 +1576,7 @@ window.__ModuleLoader__.load({
1571
1576
  return h('button', { key: t[0], onClick: function () { choose(t[0]) },
1572
1577
  style: {
1573
1578
  flex: 1, minWidth: 0, cursor: 'pointer', font: 'inherit',
1574
- color: '#171a21', fontSize: 14, textAlign: 'center',
1579
+ color: 'var(--qqs-text,#171a21)', fontSize: 14, textAlign: 'center',
1575
1580
  whiteSpace: 'nowrap', padding: '9px 8px', borderRadius: 14,
1576
1581
  border: '1px solid ' + (on ? col : col + 'a6'),
1577
1582
  background: 'linear-gradient(165deg,' + col + (on ? '66' : '40') + ',' + col + (on ? '1f' : '14') + ')',
@@ -1667,17 +1672,17 @@ window.__ModuleLoader__.load({
1667
1672
  var used = new Set((insts || []).map(function (x) { return x.id }))
1668
1673
  var n = 2
1669
1674
  while (used.has(base + '-' + n)) n += 1
1670
- var next = (insts || []).concat([{ id: base + '-' + n, appId: cred.appId, appSecret: cred.appSecret, preset: '', cwd: '', disabled: false, _bound: true }])
1671
- setInsts(next)
1675
+ var next = (insts || []).concat([{ id: base + '-' + n, appId: cred.appId, appSecret: cred.appSecret, preset: '', cwd: '', disabled: false, _bound: true }])
1676
+ setInsts(next)
1672
1677
  return next
1673
1678
  }
1674
1679
  function save(listOverride, force) {
1675
1680
  if (busy && force !== true) return
1676
1681
  setBusy('save'); setMsg('保存中…')
1677
- // ⚠️ 2026-10-22 修(卡在「保存中」的根因):保存按钮写的是 onClick: save,React 会把
1678
- // MouseEvent 当第一个参数传进来;如果直接当列表用,.filter 会抛 TypeError,
1679
- // busy 永远停在 save ⇒ 界面一直转圈。只接受数组,其余一律回落到当前 insts。
1680
- if (!Array.isArray(listOverride)) listOverride = null
1682
+ // ⚠️ 2026-10-22 修(卡在「保存中」的根因):保存按钮写的是 onClick: save,React 会把
1683
+ // MouseEvent 当第一个参数传进来;如果直接当列表用,.filter 会抛 TypeError,
1684
+ // busy 永远停在 save ⇒ 界面一直转圈。只接受数组,其余一律回落到当前 insts。
1685
+ if (!Array.isArray(listOverride)) listOverride = null
1681
1686
  var list = (listOverride || insts || []).filter(function (x) { return x.id && (x.appId || x.appSecret || x.hasSecret || !x._new || x._bound) })
1682
1687
  // 空账号(全空且没绑定)不保存; 全新手动号若两凭据都空则提示(hasSecret=已保存的账号不算空)
1683
1688
  var blanks = list.filter(function (x) { return !x.appSecret && !x.hasSecret && !x._bound })
@@ -1717,7 +1722,7 @@ window.__ModuleLoader__.load({
1717
1722
  fetch(API_BIND + '/poll?id=' + encodeURIComponent(b.id)).then(function (r) { return r.json() }).then(function (p) {
1718
1723
  if (p.status === 'done') {
1719
1724
  clearInterval(pollRef.current); pollRef.current = null
1720
- var nextList = addBound({ appId: p.appId, appSecret: p.appSecret })
1725
+ var nextList = addBound({ appId: p.appId, appSecret: p.appSecret })
1721
1726
  setTimeout(function () { autoSaveAfterBind(nextList) }, 200)
1722
1727
  setMsg('🎉 扫码成功, 正在自动保存…')
1723
1728
  setBind(null)
@@ -1801,13 +1806,13 @@ window.__ModuleLoader__.load({
1801
1806
  }).catch(function (e) { setEditBusy(false); setEditMsg('保存异常: ' + e.message) })
1802
1807
  }
1803
1808
  var st = { width: '100%', padding: '5px 8px', boxSizing: 'border-box' }
1804
- return h('div', { style: { maxWidth: 860 } },
1809
+ return h('div', { style: { maxWidth: 860, background: 'var(--qqs-card,#fff)', border: '1px solid var(--qqs-border,#e2e5ea)', borderRadius: 12, padding: '14px 16px', color: 'var(--qqs-text,#1f2329)' } },
1805
1810
  h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: 8 } },
1806
1811
  h('h2', { style: { margin: 0 } }, '账号与预设'),
1807
1812
  h('div', { style: { display: 'flex', gap: 6, alignItems: 'center' } },
1808
1813
  h('button', { className: 'qqs-btn', title: '保存账号配置(保存后重启生效)', onClick: save, disabled: busy === 'save', style: { fontSize: 16, padding: '4px 12px', lineHeight: '20px' } }, '💾'),
1809
1814
  h('button', { className: 'qqs-btn', title: '重新读取(放弃未保存的修改)', onClick: function () { load() }, style: { fontSize: 16, padding: '4px 12px', lineHeight: '20px' } }, '🔄'))),
1810
- h('p', { style: { fontSize: 12, color: '#888' } }, '一个 QQ 机器人 = 一个账号实例(AppID/AppSecret)。想同时开几个机器人就加几个实例,每个可以配不同的 agent 预设(人格)与工作目录(各人各数据,不串)。⚠️ appSecret 会明文存在本机 cordis.patch.yml(改前自动备份 .bak),别把配置文件传上网。'),
1815
+ h('p', { style: { fontSize: 12, color: 'var(--qqs-text2,#888)' } }, '一个 QQ 机器人 = 一个账号实例(AppID/AppSecret)。想同时开几个机器人就加几个实例,每个可以配不同的 agent 预设(人格)与工作目录(各人各数据,不串)。⚠️ appSecret 会明文存在本机 cordis.patch.yml(改前自动备份 .bak),别把配置文件传上网。'),
1811
1816
  h('div', { style: sectionTitle }, '① 机器人账号(改完点保存, 重启生效)'),
1812
1817
  (insts === null ? h('p', null, '加载中…') : null),
1813
1818
  (insts || []).map(function (it, i) {
@@ -1818,10 +1823,10 @@ window.__ModuleLoader__.load({
1818
1823
  if (selInvalid) opts.unshift({ id: it.preset, label: '⚠️ ' + it.preset + '(预设不存在, 请重选)' })
1819
1824
  // 默认收起: 老账号折叠, 新建(_new/_bound)展开待填; 用户手动切换后以 collapsed 为准
1820
1825
  var folded = collapsed[it.id] !== undefined ? !!collapsed[it.id] : (!it._new && !it._bound)
1821
- return h('div', { key: it.id, style: { border: '1px solid ' + (it.disabled ? '#ffa94d66' : '#00000026'), borderRadius: 10, padding: '8px 12px', margin: '8px 0', background: 'rgba(255,255,255,.5)' } },
1826
+ return h('div', { key: it.id, style: { border: '1px solid ' + (it.disabled ? '#ffa94d66' : '#00000026'), borderRadius: 10, padding: '8px 12px', margin: '8px 0', background: 'var(--qqs-card-hi,#fafafa)', color: 'var(--qqs-text,#1f2329)' } },
1822
1827
  h('div', { style: { display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' } },
1823
1828
  h('button', { className: 'qqs-btn', title: folded ? '展开设置' : '收起设置', onClick: function () { toggleCollapse(it.id) }, style: { padding: '1px 7px', fontSize: 13, lineHeight: '16px', background: '#0000000d', borderColor: '#00000026' } }, folded ? '▸' : '▾'),
1824
- h('span', { style: { fontWeight: 800, color: '#171a21', cursor: 'pointer', userSelect: 'none' }, onClick: function () { toggleCollapse(it.id) } }, it._bound ? '📱 扫码绑定' : (it._new ? '🆕 新账号' : '🤖 账号')),
1829
+ h('span', { style: { fontWeight: 800, color: 'var(--qqs-text,#171a21)', cursor: 'pointer', userSelect: 'none' }, onClick: function () { toggleCollapse(it.id) } }, it._bound ? '📱 扫码绑定' : (it._new ? '🆕 新账号' : '🤖 账号')),
1825
1830
  h('input', { className: 'qqs-inp', style: Object.assign({ width: 170 }, st), value: it.id, disabled: !it._new && !it._bound, onChange: function (e) { upd(i, { id: e.target.value }) }, placeholder: '实例 id(如 im-qqbot-2)' }),
1826
1831
  h('label', { style: { fontSize: 13, whiteSpace: 'nowrap' } },
1827
1832
  h('input', { className: 'qqs-cb', type: 'checkbox', checked: !it.disabled, onChange: function (e) { upd(i, { disabled: !e.target.checked }) } }), ' 启用'),
@@ -1831,13 +1836,13 @@ window.__ModuleLoader__.load({
1831
1836
  inputRow('AppID: ', h('input', { className: 'qqs-inp', style: Object.assign({ width: 220 }, st), value: it.appId || '', onChange: function (e) { upd(i, { appId: e.target.value }) }, placeholder: '如 1234567890' })),
1832
1837
  inputRow('AppSecret: ', h('input', { className: 'qqs-inp', type: 'password', style: Object.assign({ width: 320 }, st), value: (it.appSecret === SECRET_MASK || (!it.appSecret && it.hasSecret)) ? '' : (it.appSecret || ''), onChange: function (e) { upd(i, { appSecret: e.target.value }) }, placeholder: (it.hasSecret && !it._new) ? '已保存(留空/掩码=保留原值; 填新值=更换)' : '扫码绑定会自动填; 也可手动填(两个都要填全才不弹码)' })),
1833
1838
  inputRow('Agent 预设(人格): ', (function () { if (presets.length === 0 && !selInvalid) {
1834
- return h('span', { className: 'qqs-inp', style: { display: 'inline-block', verticalAlign: 'middle', padding: '5px 10px', fontSize: 12, color: '#e8590c', background: '#fff5f0', borderRadius: 6 } }, '⚠️ 还没有任何 Agent 预设——请在下方②新建/复制一个')
1839
+ return h('span', { className: 'qqs-inp', style: { display: 'inline-block', verticalAlign: 'middle', padding: '5px 10px', fontSize: 12, color: '#e8590c', background: 'var(--qqs-warn-bg,#fff5f0)', borderRadius: 6 } }, '⚠️ 还没有任何 Agent 预设——请在下方②新建/复制一个')
1835
1840
  } return h('select', { className: 'qqs-inp', style: { width: 320, padding: '4px 8px' }, value: it.preset || '', onChange: function (e) { upd(i, { preset: e.target.value }) } }, opts.map(function (o) { return h('option', { key: o.id, value: o.id, style: selInvalid && o.id === it.preset ? { color: '#e03131' } : null }, o.label) })) })()),
1836
1841
  inputRow('工作目录(各账号数据放这, 留空=默认): ', h('input', { className: 'qqs-inp', style: Object.assign({ width: '90%' }, st), value: it.cwd || '', onChange: function (e) { upd(i, { cwd: e.target.value }) }, placeholder: '如 D:\\bots\\二号机' })),
1837
1842
  (function () {
1838
1843
  var ws = (workspaces || []).filter(function (w) { return w.path && w.count > 0 })
1839
1844
  if (ws.length === 0) return null
1840
- return h('div', { style: { margin: '2px 0 4px', fontSize: 12, color: '#555' } },
1845
+ return h('div', { style: { margin: '2px 0 4px', fontSize: 12, color: 'var(--qqs-text,#555)' } },
1841
1846
  '📁 已有 dsh 会话的工作区(点选填入上方): ',
1842
1847
  ws.map(function (w) {
1843
1848
  return h('button', { key: w.dir, className: 'qqs-btn', style: { fontSize: 11, padding: '1px 8px', margin: '2px 4px 2px 0' }, onClick: function () { upd(i, { cwd: w.path }) } },
@@ -1846,33 +1851,33 @@ window.__ModuleLoader__.load({
1846
1851
  })())))
1847
1852
  }),
1848
1853
  h('div', { style: { position: 'relative', display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center', margin: '8px 0' } },
1849
- h('button', { className: 'qqs-btn', onClick: function () { setAddMenu(!addMenu) }, style: { borderColor: '#b197fc99', color: '#171a21', fontWeight: 700 } }, addMenu ? '✕ 关闭' : '➕ 添加账号'),
1850
- h('span', { style: { fontSize: 12, color: '#888' } }, '点加号选: 扫码绑定 或 手动填凭据'),
1854
+ h('button', { className: 'qqs-btn', onClick: function () { setAddMenu(!addMenu) }, style: { borderColor: '#b197fc99', color: 'var(--qqs-text,#171a21)', fontWeight: 700 } }, addMenu ? '✕ 关闭' : '➕ 添加账号'),
1855
+ h('span', { style: { fontSize: 12, color: 'var(--qqs-text2,#888)' } }, '点加号选: 扫码绑定 或 手动填凭据'),
1851
1856
  (addMenu
1852
- ? h('div', { style: { position: 'absolute', top: '100%', left: 0, marginTop: 6, zIndex: 60, minWidth: 280, background: '#fff', border: '1px solid #d9c6ff', borderRadius: 10, boxShadow: '0 10px 28px rgba(60,40,140,.18)', padding: 6, display: 'flex', flexDirection: 'column', gap: 4 } },
1853
- h('button', { className: 'qqs-btn', style: { display: 'flex', alignItems: 'center', gap: 10, textAlign: 'left', padding: '8px 10px', justifyContent: 'flex-start', background: '#f3f0ff', borderColor: '#d0bfff' }, onClick: function () { setAddMenu(false); startBind() } },
1857
+ ? h('div', { style: { position: 'absolute', top: '100%', left: 0, marginTop: 6, zIndex: 60, minWidth: 280, background: 'var(--qqs-card,#fff)', border: '1px solid var(--qqs-border,#d9c6ff)', borderRadius: 10, boxShadow: '0 10px 28px rgba(60,40,140,.18)', padding: 6, display: 'flex', flexDirection: 'column', gap: 4 } },
1858
+ h('button', { className: 'qqs-btn', style: { display: 'flex', alignItems: 'center', gap: 10, textAlign: 'left', padding: '8px 10px', justifyContent: 'flex-start', background: 'var(--qqs-card-hi,#f3f0ff)', borderColor: 'var(--qqs-border,#d0bfff)' }, onClick: function () { setAddMenu(false); startBind() } },
1854
1859
  h('span', { style: { fontSize: 20 } }, '📱'),
1855
1860
  h('span', null,
1856
- h('b', { style: { color: '#171a21' } }, '扫码绑定新机器人'),
1857
- h('div', { style: { fontSize: 11, color: '#777' } }, '推荐 — 手机 QQ 扫码自动填凭据'))),
1861
+ h('b', { style: { color: 'var(--qqs-text,#171a21)' } }, '扫码绑定新机器人'),
1862
+ h('div', { style: { fontSize: 11, color: 'var(--qqs-text2,#777)' } }, '推荐 — 手机 QQ 扫码自动填凭据'))),
1858
1863
  h('button', { className: 'qqs-btn', style: { display: 'flex', alignItems: 'center', gap: 10, textAlign: 'left', padding: '8px 10px', justifyContent: 'flex-start' }, onClick: function () { setAddMenu(false); addBlank() } },
1859
1864
  h('span', { style: { fontSize: 20 } }, '✍️'),
1860
1865
  h('span', null,
1861
- h('b', { style: { color: '#171a21' } }, '手动新建账号'),
1862
- h('div', { style: { fontSize: 11, color: '#777' } }, '自己填写 AppID / AppSecret'))))
1866
+ h('b', { style: { color: 'var(--qqs-text,#171a21)' } }, '手动新建账号'),
1867
+ h('div', { style: { fontSize: 11, color: 'var(--qqs-text2,#777)' } }, '自己填写 AppID / AppSecret'))))
1863
1868
  : null)),
1864
1869
  h('div', { style: { ...sectionTitle, marginTop: 16, display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' } },
1865
1870
  '② Agent 预设(人格库)',
1866
- h('button', { className: 'qqs-btn', style: { fontSize: 12, padding: '2px 10px', borderColor: '#2b8a3e99', color: '#171a21' }, onClick: function () { setCopy({ fromStandard: true, sourceId: 'standard' }); setCopyId(''); setCopyName('') } }, '➕ 从标准模式新建(带QQ工具)')),
1867
- h('p', { style: { fontSize: 12, color: '#888' } }, PRESET_HINT),
1868
- h('p', { style: { fontSize: 12, color: '#364fc7', background: '#edf2ff', borderRadius: 6, padding: '6px 10px' } }, '💡 QQ 工具(send_media/发图等)现在由机器人会话自动挂载(2026-09-06 起), 不再依赖预设是否带标记——任意预设都能在 QQ 用; 「从标准模式新建」的副本仍会自带标记供识别。'),
1871
+ h('button', { className: 'qqs-btn', style: { fontSize: 12, padding: '2px 10px', borderColor: '#2b8a3e99', color: 'var(--qqs-text,#171a21)' }, onClick: function () { setCopy({ fromStandard: true, sourceId: 'standard' }); setCopyId(''); setCopyName('') } }, '➕ 从标准模式新建(带QQ工具)')),
1872
+ h('p', { style: { fontSize: 12, color: 'var(--qqs-text2,#888)' } }, PRESET_HINT),
1873
+ h('p', { style: { fontSize: 12, color: 'var(--qqs-text,#364fc7)', background: 'var(--qqs-preset-bg,#edf2ff)', borderRadius: 6, padding: '6px 10px' } }, '💡 QQ 工具(send_media/发图等)现在由机器人会话自动挂载(2026-09-06 起), 不再依赖预设是否带标记——任意预设都能在 QQ 用; 「从标准模式新建」的副本仍会自带标记供识别。'),
1869
1874
  h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(190px,1fr))', gap: 10, margin: '8px 0' } },
1870
1875
  presets.map(function (p) {
1871
- return h('div', { key: p.id, style: { border: '1px solid #00000026', borderRadius: 10, padding: '10px 12px', background: 'rgba(255,255,255,.5)' } },
1876
+ return h('div', { key: p.id, style: { border: '1px solid var(--qqs-preset-border,#c7dbff)', borderRadius: 10, padding: '10px 12px', background: 'var(--qqs-preset-bg,#eef4ff)' } },
1872
1877
  h('div', { style: { display: 'flex', alignItems: 'center', gap: 6 } },
1873
- h('span', { style: { fontWeight: 800, color: '#171a21' } }, p.name),
1878
+ h('span', { style: { fontWeight: 800, color: 'var(--qqs-text,#171a21)' } }, p.name),
1874
1879
  h('span', { style: { fontSize: 10, padding: '1px 6px', borderRadius: 8, color: '#fff', background: p.hasChannelTools ? '#2b8a3e' : '#5b9dff' } }, p.hasChannelTools ? 'QQ工具' : '会话自动挂载')),
1875
- h('div', { style: { fontSize: 12, color: '#666', margin: '4px 0' } }, 'id=' + p.id),
1880
+ h('div', { style: { fontSize: 12, color: 'var(--qqs-text2,#666)', margin: '4px 0' } }, 'id=' + p.id),
1876
1881
  h('div', { style: { display: 'flex', gap: 6, flexWrap: 'wrap' } },
1877
1882
  h('button', { className: 'qqs-btn', style: { padding: '2px 10px', fontSize: 12 }, onClick: function () { setCopy({ sourceId: p.id }); setCopyId(''); setCopyName('') } }, '复制'),
1878
1883
  h('button', { className: 'qqs-btn', style: { padding: '2px 10px', fontSize: 12, borderColor: '#1971c299' }, onClick: function () { openPresetEditor(p) } }, '✏️ 人格'),
@@ -1891,15 +1896,15 @@ window.__ModuleLoader__.load({
1891
1896
  h('h3', { style: { marginTop: 0 } }, '✏️ 人格编辑器 — ' + editP.name + ' (' + editP.id + ')'),
1892
1897
  h('div', { style: { display: 'flex', gap: 8, alignItems: 'center', margin: '2px 0 6px', flexWrap: 'wrap' } },
1893
1898
  h('label', { style: { fontSize: 13 } }, '文件: '),
1894
- h('select', { className: 'qqs-inp', style: { padding: '4px 8px', color: '#1f2329', maxWidth: 360 }, value: editFile, onChange: function (e) { pickEditFile(e.target.value) } },
1899
+ h('select', { className: 'qqs-inp', style: { padding: '4px 8px', color: 'var(--qqs-text,#1f2329)', maxWidth: 360 }, value: editFile, onChange: function (e) { pickEditFile(e.target.value) } },
1895
1900
  editFiles.map(function (fl) { return h('option', { key: fl.name, value: fl.name }, fl.name + ' (' + Math.max(1, Math.ceil(fl.size / 1024)) + 'KB)') })),
1896
1901
  h('span', { style: { fontSize: 12, color: editP.writable === false ? '#ffa94d' : '#7fd8a8' } }, editP.writable === false ? '🔒 只读(内置预设, 请先复制一份再改)' : (editP.writable ? '✅ 可编辑(你的副本)' : '⏳ 读取权限中…'))),
1897
1902
  h('p', { style: { fontSize: 12, color: '#9fb0c9', margin: '2px 0 6px' } }, '提示: agent.cordis.yml 里 persona 插件 config.text 就是人设正文; 直接整文件编辑, 保存后新会话生效。'),
1898
- h('textarea', { className: 'qqs-inp', style: { width: '100%', boxSizing: 'border-box', flex: 1, minHeight: 300, fontFamily: 'ui-monospace,Consolas,monospace', fontSize: 12, lineHeight: 1.5, color: '#1f2329', whiteSpace: 'pre', resize: 'vertical', background: '#fff' }, value: editContent, readOnly: editP.writable === false, spellCheck: false, onChange: function (e) { setEditContent(e.target.value) } }),
1903
+ h('textarea', { className: 'qqs-inp', style: { width: '100%', boxSizing: 'border-box', flex: 1, minHeight: 300, fontFamily: 'ui-monospace,Consolas,monospace', fontSize: 12, lineHeight: 1.5, color: 'var(--qqs-text,#1f2329)', whiteSpace: 'pre', resize: 'vertical', background: '#fff' }, value: editContent, readOnly: editP.writable === false, spellCheck: false, onChange: function (e) { setEditContent(e.target.value) } }),
1899
1904
  (editMsg ? h('p', { style: { fontSize: 12, color: '#ffa94d', margin: '4px 0' } }, editMsg) : null),
1900
1905
  h('div', { style: { textAlign: 'right', marginTop: 8 } },
1901
1906
  h('button', { className: 'qqs-btn', onClick: function () { if (!editBusy) setEditP(null) }, style: { marginRight: 8 } }, '关闭'),
1902
- (editP.writable === false ? null : h('button', { className: 'qqs-btn', onClick: saveEditFile, disabled: editBusy || editP.writable === undefined, style: { borderColor: '#2f9e4499', color: '#171a21' } }, editBusy ? '保存中…' : '💾 保存')))))
1907
+ (editP.writable === false ? null : h('button', { className: 'qqs-btn', onClick: saveEditFile, disabled: editBusy || editP.writable === undefined, style: { borderColor: '#2f9e4499', color: 'var(--qqs-text,#171a21)' } }, editBusy ? '保存中…' : '💾 保存')))))
1903
1908
  : null,
1904
1909
  bind ? h('div', { style: { position: 'fixed', inset: 0, background: '#000c', zIndex: 999, display: 'flex', alignItems: 'center', justifyContent: 'center' } },
1905
1910
  h('div', { className: 'qqs-modal', style: { background: '#22252e', color: '#e8e8e8', borderRadius: 12, padding: 14, maxWidth: 620, width: '94%' }, onClick: function (e) { e.stopPropagation() } },
@@ -1922,8 +1927,33 @@ window.__ModuleLoader__.load({
1922
1927
  props && props.close ? h('button', { className: 'qqs-btn', onClick: props.close, style: { float: 'right', marginTop: 6 } }, '完成') : null)
1923
1928
  }
1924
1929
 
1925
- var QQS_CSS = ".qqs-btn{font:inherit;color:#333;background:linear-gradient(180deg,#ffffff,#f5f6f8);border:1px solid #d0d5dd;border-radius:9px;padding:5px 13px;cursor:pointer;transition:all .15s}.qqs-btn:hover{background:#ffffff;border-color:#7c6cf0;color:#7c6cf0}.qqs-btn:active{transform:translateY(1px)}.qqs-inp,.qqs-area{font:inherit;color:#1f2329;background:#ffffff;border:1px solid #d0d5dd;border-radius:9px;padding:5px 10px;outline:none;transition:border-color .15s}.qqs-inp::placeholder,.qqs-area::placeholder{color:#9aa1ab}.qqs-inp:focus,.qqs-area:focus{border-color:#7c6cf0;box-shadow:0 0 0 2px #7c6cf033}.qqs-cb{accent-color:#7c6cf0;width:15px;height:15px}.qqs-card{transition:box-shadow .15s,border-color .15s}.qqs-card:hover{box-shadow:0 2px 10px #0002}.qqs-panel{background:linear-gradient(180deg,#ffffff,#f7f8fa);border:1px solid #e2e5ea;border-radius:16px;padding:16px;box-shadow:0 10px 34px #0002}.qqs-toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;background:#f7f8fa;border:1px solid #e2e5ea;border-radius:12px;padding:8px 10px;margin-bottom:10px}.qqs-modal{background:#ffffff;color:#1f2329}"
1926
- function ensureCss() { try { if (!document.getElementById('qqs-css')) { var st = document.createElement('style'); st.id = 'qqs-css'; st.textContent = QQS_CSS; document.head.appendChild(st) } } catch (e) {} }
1930
+ var QQS_CSS = ".qqs-btn{font:inherit;color:var(--qqs-text,#1f2329);background:var(--qqs-card,#fff);border:1px solid var(--qqs-border,#d0d5dd);border-radius:9px;padding:5px 13px;cursor:pointer;transition:all .15s}.qqs-btn:hover{background:var(--qqs-card-hi,#fafafa);border-color:#7c6cf0;color:#7c6cf0}.qqs-btn:active{transform:translateY(1px)}.qqs-inp,.qqs-area{font:inherit;color:var(--qqs-text,#1f2329);background:var(--qqs-input,#fff);border:1px solid var(--qqs-border,#d0d5dd);border-radius:9px;padding:5px 10px;outline:none;transition:border-color .15s}.qqs-inp::placeholder,.qqs-area::placeholder{color:var(--qqs-text3,#9aa1ab)}.qqs-inp:focus,.qqs-area:focus{border-color:#7c6cf0;box-shadow:0 0 0 2px #7c6cf033}.qqs-cb{accent-color:#7c6cf0;width:15px;height:15px}.qqs-card{transition:box-shadow .15s,border-color .15s}.qqs-card:hover{box-shadow:0 2px 10px #0002}.qqs-panel{background:var(--qqs-panel,#fff);border:1px solid var(--qqs-border,#e2e5ea);border-radius:16px;padding:16px;box-shadow:0 10px 34px #0002;color:var(--qqs-text,#1f2329)}.qqs-toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;background:var(--qqs-toolbar,#f7f8fa);border:1px solid var(--qqs-border,#e2e5ea);border-radius:12px;padding:8px 10px;margin-bottom:10px}.qqs-modal{background:var(--qqs-panel,#fff);color:var(--qqs-text,#1f2329)}"
1931
+ var QQS_THEME_CSS = [
1932
+ // ① 亮色 token(默认)
1933
+ 'body{',
1934
+ '--qqs-card:#ffffff;--qqs-card-hi:#fafafa;--qqs-card-solid:#f4f5f8;',
1935
+ '--qqs-border:#e2e5ea;--qqs-border-light:#eef0f3;',
1936
+ '--qqs-text:#1f2329;--qqs-text2:#4e5560;--qqs-text3:#8a919c;',
1937
+ '--qqs-panel:#ffffff;--qqs-toolbar:#f7f8fa;--qqs-input:#ffffff;',
1938
+ '--qqs-dock-panel:#ffffff;--qqs-dock-body:#f5f6f8;--qqs-bubble-in:#ffffff;',
1939
+ '--qqs-primary-bg:#7c6cf01a;--qqs-primary-border:#7c6cf04d;--qqs-primary-fg:#6b5ae6;--qqs-warn-bg:#fff5f0;',
1940
+ '--qqs-preset-bg:#eef4ff;--qqs-preset-border:#c7dbff;',
1941
+ '}',
1942
+ // ② 暗色 token(宿主 ThemePresenter 在 scheme===dark 时给 body 加属性)
1943
+ 'body[data-ds-dark-theme]{',
1944
+ '--qqs-card:#232834;--qqs-card-hi:#2b3140;--qqs-card-solid:#2a3040;',
1945
+ '--qqs-border:#3a4152;--qqs-border-light:#333a49;',
1946
+ '--qqs-text:#e8eaf0;--qqs-text2:#c3cad6;--qqs-text3:#a3abb9;',
1947
+ '--qqs-panel:#232834;--qqs-toolbar:#272d3a;--qqs-input:#2b3140;',
1948
+ '--qqs-dock-panel:#232834;--qqs-dock-body:#1e232e;--qqs-bubble-in:#2b3140;',
1949
+ '--qqs-primary-bg:#7c6cf033;--qqs-primary-border:#7c6cf080;--qqs-primary-fg:#ffffff;--qqs-warn-bg:#3a2a20;',
1950
+ '--qqs-preset-bg:#1e2b3f;--qqs-preset-border:#2f4463;',
1951
+ '}',
1952
+ // ③ 独立规则(★不能写进上面的 body{} 里,否则整块 CSS 解析失败)
1953
+ '.qqs-panel,.qqs-toolbar,.qqs-modal,.qqs-card{color:var(--qqs-text,#1f2329)}',
1954
+ 'body[data-ds-dark-theme] .qqs-panel,body[data-ds-dark-theme] .qqs-toolbar,body[data-ds-dark-theme] .qqs-modal,body[data-ds-dark-theme] .qqs-card{color:var(--qqs-text,#e8eaf0)}',
1955
+ ].join('')
1956
+ function ensureCss() { try { if (!document.getElementById('qqs-css')) { var st = document.createElement('style'); st.id = 'qqs-css'; st.textContent = QQS_CSS + QQS_THEME_CSS; document.head.appendChild(st) } } catch (e) {} }
1927
1957
 
1928
1958
  // ── 审批双通道 · Web 浮层(右下角小卡片) ──
1929
1959
  // 轮询 host 待办池(与 QQ 按钮/文本码共用同一 pending), 有点击即 POST 结算。
@@ -3297,36 +3327,36 @@ var QQS_CSS = ".qqs-btn{font:inherit;color:#333;background:linear-gradient(180de
3297
3327
  var el = panel && panel.querySelector('#dk-ar-hint')
3298
3328
  if (el) el.textContent = state.arMsg
3299
3329
  }
3300
- /**
3301
- * 只保存 autoRecall(2026-10-20 修 BUG):
3302
- * 之前复用 saveGroupAdmin,会把 enabled/轮询这些**不在本页的字段**用 state 旧值一起提交(state.gaEnabled 本页无控件回读)
3303
- * → 保存自动撤回时顺手把「群管理」关掉了。改为只 patch 本页字段。
3304
- */
3305
- function saveAutoRecallOnly() {
3306
- arHint('保存中…')
3307
- fetch(READ + (state.ns ? '?' + outNsQ() : '')).then(function (r) { return r.json() }).then(function (d) {
3308
- if (!d || !d.value) { arHint('✗ 保存失败: 读取当前设置失败'); return }
3309
- var cur = d.value
3310
- var patch = Object.assign({}, cur)
3311
- patch.groupAdmin = Object.assign({}, cur.groupAdmin || {}, {
3312
- autoRecall: {
3313
- enabled: state.arOn === true,
3314
- mode: state.arMode === 'drop' ? 'drop' : 'keep',
3315
- keywords: String(state.arKws || '').split(String.fromCharCode(10)).map(function (x) { return x.trim() }).filter(Boolean),
3316
- kinds: (state.arKinds || []).slice(),
3317
- muteSeconds: Math.max(0, parseInt(state.arMute, 10) || 0),
3318
- dryRun: state.arDry === true,
3319
- },
3320
- })
3321
- return fetch(UPDATE, {
3322
- method: 'POST', headers: { 'content-type': 'application/json' },
3323
- body: JSON.stringify({ ns: state.ns || undefined, patch: patch, expectedRevision: d.revision }),
3324
- }).then(function (r) { return r.json().catch(function () { return null }) }).then(function (d2) {
3325
- if (d2 && d2.value) { state.hubRev = d2.revision; arHint('✓ 自动撤回已保存(live 生效,立刻按新规则执行)') }
3326
- else arHint('✗ 保存失败: ' + ((d2 && d2.error) || '未知错误'))
3327
- }).catch(function () { arHint('✗ 保存异常') })
3328
- }).catch(function () { arHint('✗ 读取当前设置失败') })
3329
- }
3330
+ /**
3331
+ * 只保存 autoRecall(2026-10-20 修 BUG):
3332
+ * 之前复用 saveGroupAdmin,会把 enabled/轮询这些**不在本页的字段**用 state 旧值一起提交(state.gaEnabled 本页无控件回读)
3333
+ * → 保存自动撤回时顺手把「群管理」关掉了。改为只 patch 本页字段。
3334
+ */
3335
+ function saveAutoRecallOnly() {
3336
+ arHint('保存中…')
3337
+ fetch(READ + (state.ns ? '?' + outNsQ() : '')).then(function (r) { return r.json() }).then(function (d) {
3338
+ if (!d || !d.value) { arHint('✗ 保存失败: 读取当前设置失败'); return }
3339
+ var cur = d.value
3340
+ var patch = Object.assign({}, cur)
3341
+ patch.groupAdmin = Object.assign({}, cur.groupAdmin || {}, {
3342
+ autoRecall: {
3343
+ enabled: state.arOn === true,
3344
+ mode: state.arMode === 'drop' ? 'drop' : 'keep',
3345
+ keywords: String(state.arKws || '').split(String.fromCharCode(10)).map(function (x) { return x.trim() }).filter(Boolean),
3346
+ kinds: (state.arKinds || []).slice(),
3347
+ muteSeconds: Math.max(0, parseInt(state.arMute, 10) || 0),
3348
+ dryRun: state.arDry === true,
3349
+ },
3350
+ })
3351
+ return fetch(UPDATE, {
3352
+ method: 'POST', headers: { 'content-type': 'application/json' },
3353
+ body: JSON.stringify({ ns: state.ns || undefined, patch: patch, expectedRevision: d.revision }),
3354
+ }).then(function (r) { return r.json().catch(function () { return null }) }).then(function (d2) {
3355
+ if (d2 && d2.value) { state.hubRev = d2.revision; arHint('✓ 自动撤回已保存(live 生效,立刻按新规则执行)') }
3356
+ else arHint('✗ 保存失败: ' + ((d2 && d2.error) || '未知错误'))
3357
+ }).catch(function () { arHint('✗ 保存异常') })
3358
+ }).catch(function () { arHint('✗ 读取当前设置失败') })
3359
+ }
3330
3360
  function saveGroupAdmin() {
3331
3361
  state.gaBusy = 'ga'; gaHint('保存中…'); arHint('保存中…')
3332
3362
  var doSave = function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaofan/dsh-qqbot",
3
- "version": "1.10.22",
3
+ "version": "1.10.23",
4
4
  "description": "QQ Bot IM channel plugin for deepseek-harness (dsh)",
5
5
  "type": "module",
6
6
  "main": "./entry.js",