@fg-lab/amadeus-qq 1.2.1 → 1.2.2
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/LICENSE +21 -21
- package/README.md +55 -53
- package/README.zh-CN.md +51 -51
- package/REFERENCE.md +49 -49
- package/cordis.patch.yml +6 -6
- package/docs/DATA_MIGRATION.md +26 -26
- package/docs/INSTALL_V1_2.md +22 -22
- package/docs/PUBLISHING.md +28 -26
- package/docs/RELEASE_CHECKLIST.md +23 -23
- package/docs/RELEASE_NOTES.md +38 -38
- package/docs/UPGRADE_POLICY.md +26 -26
- package/docs/verification/IMAGE_READ_FIX_2026-11-07.md +22 -0
- package/docs/verification/LIFE_QQ_BOUNDARY_2026-11-07.md +20 -0
- package/lib/client.js +372 -372
- package/package.json +94 -91
- package/preset.patch.yml +63 -0
- package/scripts/symlink-security.mjs +1 -1
- package/src/account-profile.js +223 -223
- package/src/admin-http.js +361 -361
- package/src/audio.js +428 -428
- package/src/capabilities.js +785 -785
- package/src/client/factory.template.js +82 -82
- package/src/client/logic.js +290 -290
- package/src/config.js +2 -0
- package/src/console/console.css +28 -28
- package/src/console/console.js +3 -0
- package/src/console/index.html +67 -67
- package/src/core.js +21 -4
- package/src/files.js +230 -230
- package/src/index.js +135 -8
- package/src/lease.js +42 -42
- package/src/media.js +66 -3
- package/src/napcat-action-names.js +186 -186
- package/src/native-asr.js +112 -112
- package/src/onebot.js +378 -378
- package/src/outbound-media.js +309 -309
- package/src/owner-workspace.js +394 -394
- package/src/permissions.js +20 -0
- package/src/preset-guard.mjs +16 -2
- package/src/qzone-provider.js +628 -628
- package/src/session-provenance.js +74 -74
- package/src/setup.js +255 -255
- package/src/web-console.js +9 -9
package/src/console/console.css
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
:root{
|
|
2
|
-
--bg:#f5f8fa;--paper:#fff;--ink:#192b39;--ink2:#233748;--muted:#728397;--muted2:#98a8b6;
|
|
3
|
-
--line:#e6edf1;--line-strong:#dae5eb;--soft:#f7fafb;--green:#0b875c;--green-soft:#e8f7ef;--green-ink:#08704e;
|
|
4
|
-
--blue:#2679c7;--blue-soft:#edf5fe;--orange:#d77b20;--orange-soft:#fff3e6;--pink:#a967cc;--pink-soft:#f8f0fc;
|
|
5
|
-
--warning:#a87826;--warning-soft:#fff9e8;--danger:#b85a56;--danger-soft:#fff0ed;
|
|
6
|
-
--shadow:0 12px 34px rgba(22,55,73,.045);--shadow2:0 8px 30px rgba(21,46,69,.08)
|
|
7
|
-
}
|
|
8
|
-
[data-theme="dark"]{
|
|
9
|
-
--bg:#131d25;--paper:#1b2932;--ink:#eaf3f4;--ink2:#d9e5e9;--muted:#a0b4bf;--muted2:#7f97a6;
|
|
10
|
-
--line:#30404b;--line-strong:#405363;--soft:#22333e;--green:#78d6af;--green-soft:#1b4639;--green-ink:#91e6bf;
|
|
11
|
-
--blue:#8fc0f1;--blue-soft:#263f58;--orange:#f4bd80;--orange-soft:#4c392b;--pink:#e3b3f2;--pink-soft:#45314f;
|
|
12
|
-
--warning:#f0cd8c;--warning-soft:#473e2c;--danger:#ecaaa0;--danger-soft:#4b2e30;
|
|
13
|
-
--shadow:0 12px 32px rgba(0,0,0,.13);--shadow2:0 10px 36px rgba(0,0,0,.2)
|
|
14
|
-
}
|
|
15
|
-
*{box-sizing:border-box}html{scrollbar-gutter:stable}body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.58 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",Arial,sans-serif;letter-spacing:.002em}button,input,select,textarea{font:inherit;color:inherit}button{cursor:pointer}button:disabled{opacity:.55;cursor:not-allowed}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible{outline:2px solid var(--green);outline-offset:2px}a{color:var(--green);text-decoration:none}a:hover{text-decoration:underline}h1,h2,h3,h4,p{margin-top:0}h1{font-size:26px;letter-spacing:-.04em;margin-bottom:3px;line-height:1.35}h2{font-size:19px;letter-spacing:-.025em;margin-bottom:6px}h3{font-size:15px;margin-bottom:6px}p{color:var(--muted)}.icon{width:18px;height:18px;flex-shrink:0;display:inline-block;vertical-align:middle;stroke:currentColor;fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.85}.icon.sm{width:15px;height:15px}.icon.lg{width:22px;height:22px}.app{display:grid;grid-template-columns:220px minmax(0,1fr);min-height:100vh}.sidebar{background:var(--paper);border-right:1px solid var(--line);padding:21px 14px 17px;position:sticky;top:0;height:100vh;display:flex;flex-direction:column;gap:27px;z-index:5}.brand{display:flex;gap:10px;align-items:center;padding:1px 7px}.brand-logo{position:relative;width:37px;height:37px;border-radius:13px;background:linear-gradient(135deg,#159d78,#2764b0);display:grid;place-items:center;color:white;font-weight:900;font-size:17px;letter-spacing:-.1em;box-shadow:0 6px 13px #1c8f9250}.brand-logo:after{content:"";position:absolute;right:1px;top:1px;background:#91e2c0;width:9px;height:9px;border-radius:50%;border:2px solid var(--paper)}.brand-label{font-size:15px;font-weight:800;line-height:1.1;letter-spacing:-.02em}.brand-sub{font-size:10px;color:var(--muted);margin-top:4px}.brand-tag{color:var(--green-ink);background:var(--green-soft);border-radius:100px;font-size:10px;padding:2px 7px;margin-left:4px;font-weight:700}.nav-label{color:var(--muted2);padding:0 12px;font-size:10px;font-weight:800;letter-spacing:.1em;margin-bottom:9px}.nav{display:grid;gap:6px}.nav button{border:0;background:transparent;width:100%;padding:11px 12px;border-radius:11px;text-align:left;display:flex;align-items:center;gap:12px;color:var(--ink2);font-size:13px;font-weight:550}.nav button:hover{background:var(--soft)}.nav button.active{background:var(--green-soft);color:var(--green-ink);font-weight:800}.nav button .icon{opacity:.75}.nav-divider{margin:6px 11px;border-bottom:1px solid var(--line)}.sidebar-bottom{margin-top:auto}.plugin-status{border:1px solid var(--line);border-radius:14px;padding:15px 13px;background:var(--soft)}.plugin-status .micro{font-size:11px;color:var(--muted)}.plugin-status strong{display:flex;align-items:center;gap:7px;margin:9px 0 5px;color:var(--green-ink)}.plugin-status p{font-size:11px;line-height:1.6;margin-bottom:10px}.plugin-status .idline{font-size:11px;display:flex;justify-content:space-between;margin:5px 0}.plugin-status .idline span:first-child{color:var(--muted)}.plugin-status .idline b{font-size:11px}.main{min-width:0;padding:25px 26px 50px}.main-width{max-width:1600px;margin:0 auto}.head{display:flex;justify-content:space-between;align-items:flex-start;gap:22px;margin-bottom:23px}.page-lead .eyebrow{font-size:10px;text-transform:uppercase;font-weight:750;letter-spacing:.17em;color:var(--green-ink);margin-bottom:6px}.page-lead p{font-size:12px;margin:0}.head-right{display:flex;gap:9px;align-items:stretch;flex-wrap:wrap;justify-content:flex-end}.head-status{padding:8px 12px;min-height:50px;background:var(--paper);border:1px solid var(--line);border-radius:12px;display:flex;align-items:center;gap:10px;min-width:137px;box-shadow:var(--shadow)}.head-status .label{font-size:10px;color:var(--muted)}.head-status strong{font-size:12px;display:block;line-height:1.25}.head-status .statusicon{width:31px;height:31px;border-radius:10px;background:var(--blue-soft);color:var(--blue);display:grid;place-items:center}.head-status.online .statusicon{background:var(--green-soft);color:var(--green-ink)}.head-status.online strong{color:var(--green-ink)}.demo-pill{display:inline-flex;align-items:center;padding:4px 9px;border-radius:100px;background:var(--soft);border:1px solid var(--line);font-size:10px;color:var(--muted);white-space:nowrap}.button{border:1px solid var(--line-strong);border-radius:10px;background:var(--paper);font-size:12px;font-weight:730;padding:9px 12px;display:inline-flex;align-items:center;justify-content:center;gap:7px;min-height:36px;white-space:nowrap}.button:hover{border-color:#9dcdbb;background:var(--soft)}.button.primary{color:#fff;background:#0b8c61;border-color:#0b8c61;box-shadow:0 4px 12px rgba(0,135,92,.12)}.button.primary:hover{background:#067851}.button.soft{border-color:#cceadb;background:var(--green-soft);color:var(--green-ink)}.button.ghost{background:transparent;border-color:transparent;color:var(--muted)}.button.mini{padding:6px 10px;min-height:29px;font-size:11px}.button.linklike{border:0;color:var(--blue);background:transparent;padding:0}.tag{display:inline-flex;gap:5px;align-items:center;white-space:nowrap;font-size:10px;font-weight:740;padding:3px 8px;background:var(--soft);color:var(--muted);border:1px solid var(--line);border-radius:50px}.tag.success{background:var(--green-soft);border-color:#c7e6d7;color:var(--green-ink)}.tag.info{background:var(--blue-soft);border-color:#d8e6f7;color:var(--blue)}.tag.warn{background:var(--warning-soft);border-color:#f0e3c3;color:var(--warning)}.tag.danger{background:var(--danger-soft);border-color:#ebccc8;color:var(--danger)}.tag.demo{border-style:dashed}.dot{width:7px;height:7px;border-radius:50%;display:inline-block;background:currentColor}.view{display:none;animation:fadein .12s ease}.view.active{display:block}@keyframes fadein{from{opacity:.6;transform:translateY(3px)}to{opacity:1;transform:translateY(0)}}.card{background:var(--paper);border:1px solid var(--line);border-radius:17px;box-shadow:var(--shadow)}.padded{padding:20px}.muted{color:var(--muted)}.micro{font-size:11px}.fine{font-size:12px;color:var(--muted)}.sect-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:22px 0 12px}.sect-head:first-child{margin-top:0}.sect-head h2{font-size:15px;margin:0}.section-sub{font-size:11px;color:var(--muted)}.stats-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:13px}.stat-card{padding:19px;min-height:129px}.stat-top{display:flex;justify-content:space-between;align-items:center;color:var(--muted);font-size:11px}.stat-icon{width:34px;height:34px;display:grid;place-items:center;border-radius:10px;background:var(--green-soft);color:var(--green-ink)}.stat-icon.blue{background:var(--blue-soft);color:var(--blue)}.stat-icon.orange{background:var(--orange-soft);color:var(--orange)}.stat-icon.pink{background:var(--pink-soft);color:var(--pink)}.stat-value{font-size:27px;font-weight:830;letter-spacing:-.05em;line-height:1.4;margin:9px 0 0}.stat-caption{font-size:11px;color:var(--muted)}.two-columns{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(300px,.95fr);gap:15px}.activity-row{display:flex;align-items:center;gap:13px;padding:13px 0;border-top:1px solid var(--line)}.activity-row:first-child{border-top:0}.activity-ico{display:grid;place-items:center;border-radius:11px;background:var(--blue-soft);color:var(--blue);width:34px;height:34px}.activity-content{flex:1;min-width:0}.activity-content strong{display:block;font-size:12px}.activity-content small{display:block;color:var(--muted);font-size:10px}.activity-time{font-size:10px;color:var(--muted2)}.flowline{display:grid;grid-template-columns:repeat(5,1fr);gap:7px}.flowstep{position:relative;border:1px solid var(--line);border-radius:12px;padding:15px 11px;background:var(--soft);min-height:86px}.flowstep span{color:var(--green-ink);font-size:10px;font-weight:800}.flowstep b{display:block;font-size:12px;margin-top:6px}.flowstep small{font-size:10px;color:var(--muted)}.callout{display:flex;align-items:flex-start;gap:11px;background:var(--green-soft);color:var(--green-ink);border:1px solid #cbe8d9;border-radius:12px;padding:13px 14px;font-size:12px}.callout p{color:var(--muted);font-size:11px;margin:4px 0 0}.scene-layout{display:grid;grid-template-columns:277px minmax(0,1fr);gap:15px;align-items:start}.scene-panel{padding:14px;position:sticky;top:15px}.scene-tabs{display:flex;background:var(--soft);padding:4px;border-radius:10px;gap:3px;margin-bottom:13px}.scene-tabs button{flex:1;border:0;border-radius:8px;background:transparent;color:var(--muted);padding:7px;font-size:11px;font-weight:700;white-space:nowrap}.scene-tabs button.active{background:var(--paper);color:var(--green-ink);box-shadow:0 2px 6px #00000008}.scene-tools{display:flex;gap:7px;margin-bottom:12px}.input{min-width:0;width:100%;border:1px solid var(--line-strong);border-radius:9px;background:var(--paper);padding:9px 11px;font-size:12px}.input:focus{border-color:var(--green)}.scene-tools .input{flex:1;width:auto}.scene-list{display:grid;gap:5px}.scene-item{display:flex;align-items:center;width:100%;text-align:left;border:1px solid transparent;background:transparent;gap:10px;padding:11px 9px;border-radius:12px}.scene-item:hover{background:var(--soft)}.scene-item.active{border-color:#a6dbc3;background:var(--green-soft)}.avatar{width:38px;height:38px;display:grid;place-items:center;border-radius:12px;color:var(--orange);background:var(--orange-soft);flex-shrink:0}.avatar.private{background:var(--blue-soft);color:var(--blue)}.scene-info{flex:1;min-width:0}.scene-info b{display:block;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.scene-info small{display:block;font-size:10px;color:var(--muted);line-height:1.5}.scene-item>.icon{color:var(--muted)}.scene-aside-foot{margin:17px 5px 2px;color:var(--muted);font-size:11px}.scene-detail{padding:21px 21px 16px;min-height:760px}.detail-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:18px}.detail-header-main{display:flex;gap:12px;align-items:center}.detail-header-main .avatar{height:43px;width:43px;border-radius:14px}.detail-header h2{font-size:20px;margin-bottom:2px}.detail-header p{font-size:11px;margin:0}.detail-action{display:flex;gap:7px;align-items:center}.divider{height:1px;background:var(--line);margin:20px 0}.mini-title{font-size:11px;color:var(--muted);font-weight:650;margin:0 0 8px}.workspace-banner{display:flex;align-items:center;gap:12px;background:var(--soft);border:1px solid var(--line);border-radius:11px;padding:12px 14px}.workspace-banner .statusicon{height:36px;width:36px;display:grid;place-items:center;border-radius:10px;background:var(--blue-soft);color:var(--blue)}.workspace-banner .grow{flex:1}.workspace-banner b{font-size:12px}.workspace-banner small{display:block;color:var(--muted);font-size:11px;margin-top:3px}.preset-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;gap:8px}.preset-header .small{font-size:10px;color:var(--muted)}.preset-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px}.preset-option{text-align:left;min-height:80px;border:1px solid var(--line);border-radius:11px;background:var(--paper);padding:11px;display:flex;flex-direction:column;gap:4px;position:relative;transition:border-color .15s,background .15s}.preset-option:hover{border-color:#91caae}.preset-option.active{background:var(--green-soft);border-color:#70c49c;box-shadow:0 0 0 1px #70c49c2e}.preset-option .p-head{display:flex;align-items:center;gap:5px}.preset-option b{font-size:12px;white-space:nowrap}.preset-option small{font-size:10px;color:var(--muted);line-height:1.42}.preset-option .check{margin-left:auto;color:var(--green-ink)}.preset-option:not(.active) .check{display:none}.preset-desc{margin-top:10px;padding:10px 12px;border-radius:10px;background:var(--soft);border:1px solid var(--line);font-size:11px;color:var(--muted)}.preset-desc strong{color:var(--ink)}.custom-alert{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:11px;padding:10px 12px;background:var(--warning-soft);border:1px solid #e9dfb9;border-radius:10px;font-size:11px;color:var(--warning)}.state-row{display:flex;align-items:center;justify-content:space-between;margin:20px 0 11px}.state-row strong{font-size:13px}.setting-groups{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.group-card{border:1px solid var(--line);border-radius:12px;background:var(--paper);overflow:hidden}.group-card summary{list-style:none;display:flex;align-items:center;gap:10px;padding:13px;cursor:pointer;min-height:67px}.group-card summary::-webkit-details-marker{display:none}.group-card summary:hover{background:var(--soft)}.group-icon{width:33px;height:33px;display:grid;place-items:center;border-radius:10px;background:var(--blue-soft);color:var(--blue);flex-shrink:0}.group-icon.green{background:var(--green-soft);color:var(--green-ink)}.group-icon.orange{background:var(--orange-soft);color:var(--orange)}.group-icon.pink{background:var(--pink-soft);color:var(--pink)}.group-summary{flex:1;min-width:0}.group-summary b{display:block;font-size:12px}.group-summary small{display:block;font-size:10px;color:var(--muted);white-space:normal}.group-card .arrow{color:var(--muted)}.group-card[open] .arrow{transform:rotate(90deg)}.group-content{padding:1px 13px 12px;border-top:1px solid var(--line)}.toggle-line{display:flex;gap:10px;align-items:center;padding:11px 0;border-bottom:1px solid var(--line)}.toggle-line:last-child{border:0}.toggle-line>div:first-child{flex:1;min-width:0}.toggle-line strong{font-size:11px;display:block}.toggle-line small{font-size:10px;color:var(--muted);display:block;margin-top:3px}.toggle-line.disabled{opacity:.6}.switch{display:flex;align-items:center;position:relative;cursor:pointer;min-width:34px}.switch input{position:absolute;opacity:0;width:36px;height:22px}.switch .track{height:21px;width:37px;display:block;position:relative;background:#c7d3d9;border-radius:999px;transition:background .16s}.switch .track:after{content:"";position:absolute;top:3px;left:3px;height:15px;width:15px;border-radius:50%;background:#fff;transition:left .16s}.switch input:checked+.track{background:#0e9b6a}.switch input:checked+.track:after{left:19px}.switch input:focus-visible+.track{outline:2px solid var(--green);outline-offset:3px}.switch input:disabled+.track{opacity:.52}.select-line{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 0;border-bottom:1px solid var(--line)}.select-line:last-child{border:0}.select-line b{font-size:11px}.select-line small{font-size:10px;color:var(--muted);display:block;margin-top:2px}.select-mini{background:var(--soft);border:1px solid var(--line);border-radius:8px;padding:7px 9px;font-size:11px;max-width:155px}.detail-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;padding-top:18px;border-top:1px solid var(--line);margin-top:20px}.detail-footer .fine{max-width:530px;font-size:11px}.detail-footer-actions{display:flex;gap:7px;flex-shrink:0}.capability-summary{background:var(--soft);border:1px solid var(--line);border-radius:11px;padding:12px;margin-top:12px;display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:11px}.capability-summary .soft{color:var(--muted)}.legend{font-size:10px;color:var(--muted)}.feature-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:13px}.feature-tile{padding:19px;min-height:184px}.feature-title{display:flex;align-items:center;gap:10px;margin-bottom:12px}.feature-title h3{margin:0}.feature-tile p{font-size:11px;margin:8px 0 12px;line-height:1.7}.feature-foot{display:flex;flex-wrap:wrap;gap:6px;margin-top:auto}.cap-list{display:grid;gap:7px;margin:13px 0}.cap-list div{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:8px 0;border-top:1px dashed var(--line);font-size:11px}.cap-list .tag{flex-shrink:0}.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:15px}.form-card{padding:20px}.form-card h3{display:flex;gap:8px;align-items:center}.form-card p{font-size:11px;line-height:1.75}.form-label{font-size:11px;font-weight:700;display:block;margin:12px 0 6px}.form-hint{color:var(--muted);font-size:10px;margin:6px 0}.form-row{display:flex;gap:8px;align-items:center}.form-row>*:first-child{flex:1}.status-table{width:100%;border-collapse:collapse;font-size:11px}.status-table td{padding:11px 4px;border-bottom:1px solid var(--line)}.status-table td:last-child{text-align:right}.status-table tr:last-child td{border:0}.status-table td:first-child{color:var(--muted)}.log-line{display:flex;align-items:start;gap:11px;padding:12px 0;border-top:1px solid var(--line);font-size:11px}.log-line:first-child{border:0}.log-time{font-family:ui-monospace,Consolas,monospace;color:var(--muted);white-space:nowrap}.check-flow{display:grid;gap:10px}.check-row{display:flex;align-items:center;gap:10px;padding:11px 13px;border-radius:10px;background:var(--soft);border:1px solid var(--line);font-size:11px}.check-row div{flex:1}.check-row b{display:block;font-size:12px}.check-row small{color:var(--muted)}.test-chip{color:var(--green-ink);font-weight:700;font-size:10px}.global-flags{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}.global-flags .tag{font-size:11px}.inline-notice{padding:12px 14px;border:1px solid var(--line);background:var(--soft);border-radius:11px;font-size:11px;color:var(--muted)}.footer{font-size:11px;color:var(--muted2);padding:30px 2px 0;text-align:center}.desktop-frame{max-width:690px;margin:15px auto;border:1px solid var(--line);border-radius:19px;padding:22px;background:var(--paper);box-shadow:var(--shadow2)}.desktop-inner{display:grid;grid-template-columns:160px minmax(0,1fr);gap:22px}.desktop-rail{border-right:1px solid var(--line);padding-right:14px}.desktop-rail div{font-size:12px;padding:10px;border-radius:9px;color:var(--muted)}.desktop-rail div.active{background:var(--green-soft);color:var(--green-ink);font-weight:700}.desktop-content h3{font-size:20px}.desktop-content p{font-size:11px}.desktop-summary{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin:15px 0}.desktop-summary .metric{padding:12px;border:1px solid var(--line);border-radius:10px;background:var(--soft)}.desktop-summary small{display:block;font-size:10px;color:var(--muted)}.desktop-summary b{font-size:12px}.demo-hint{display:flex;align-items:center;gap:7px;font-size:10px;color:var(--muted);margin-top:9px}.toast{position:fixed;bottom:22px;right:24px;max-width:390px;border-radius:13px;box-shadow:var(--shadow2);border:1px solid var(--line-strong);background:var(--paper);z-index:99;padding:13px 17px;color:var(--ink);font-size:12px;display:none}.toast.show{display:block}.toast strong{display:block;margin-bottom:3px}.modal{border:1px solid var(--line);background:var(--paper);color:var(--ink);border-radius:16px;padding:24px;width:min(430px,90vw);box-shadow:var(--shadow2)}.modal::backdrop{background:#16252a80;backdrop-filter:blur(3px)}.modal h2{margin-bottom:8px}.modal p{font-size:12px}.modal .actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.radio-pair{display:flex;gap:8px;margin:13px 0}.radio-pair label{border:1px solid var(--line);border-radius:9px;padding:10px 15px;font-size:12px;flex:1}.radio-pair input{accent-color:#0d9769}.scroll-guard{overflow:auto}.mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.hide{display:none!important}
|
|
16
|
-
@media(max-width:1300px){.app{grid-template-columns:195px minmax(0,1fr)}.main{padding:22px 18px}.head-status{min-width:117px}.scene-layout{grid-template-columns:238px minmax(0,1fr)}.setting-groups{grid-template-columns:1fr}.preset-grid{grid-template-columns:repeat(3,1fr)}}
|
|
17
|
-
@media(max-width:950px){.sidebar{position:relative;height:auto;min-height:100vh}.head{flex-direction:column}.head-right{justify-content:flex-start}.stats-grid{grid-template-columns:repeat(2,1fr)}.scene-layout{grid-template-columns:1fr}.scene-panel{position:static}.scene-list{grid-template-columns:repeat(2,minmax(0,1fr))}.feature-grid{grid-template-columns:repeat(2,1fr)}.two-columns{grid-template-columns:1fr}.preset-grid{grid-template-columns:repeat(4,1fr)}}
|
|
18
|
-
@media(max-width:650px){.app{display:block}.sidebar{height:auto;min-height:0;position:static;padding:13px 14px;gap:10px}.brand{padding:0}.nav{display:flex;overflow:auto;gap:3px}.nav-label,.sidebar-bottom,.nav-divider{display:none}.nav button{white-space:nowrap;padding:9px}.main{padding:18px 13px 30px}.head-status{min-width:auto}.head-right .head-status{flex:1}.scene-detail{padding:16px 12px}.scene-list{grid-template-columns:1fr}.preset-grid{grid-template-columns:repeat(2,1fr)}.stats-grid,.feature-grid,.form-grid,.setting-groups{grid-template-columns:1fr}.desktop-inner{grid-template-columns:1fr}.desktop-rail{display:none}.detail-footer{align-items:stretch;flex-direction:column}.detail-footer-actions{justify-content:flex-end}.flowline{grid-template-columns:repeat(2,1fr)}}
|
|
19
|
-
/* Explicit dark-preset surfaces for Chromium's dynamic data-theme repaint. */
|
|
20
|
-
html[data-theme="dark"] .preset-option{background-color:#233540;color:#eaf3f4;border-color:#405363}
|
|
21
|
-
html[data-theme="dark"] .preset-option.active{background-color:#1b4639;border-color:#70c49c;color:#eaf3f4}
|
|
22
|
-
html[data-theme="dark"] .preset-option:hover{background-color:#29423e}
|
|
23
|
-
html[data-theme="dark"] .preset-option.active:hover{background-color:#215641}
|
|
24
|
-
|
|
25
|
-
/* Runtime-only controls added to the approved visual language. */
|
|
26
|
-
.view{display:none}.view.active{display:block}.scene-choice{display:grid;gap:3px;width:100%;text-align:left;border:1px solid var(--line);border-radius:11px;padding:12px;background:var(--paper);margin:6px 0}.scene-choice:hover,.scene-choice.selected{border-color:var(--green);background:var(--green-soft)}.scene-choice small{color:var(--muted)}.scene-actions{display:flex;gap:8px;margin:14px 0 21px}.permission-group{border:1px solid var(--line);border-radius:12px;padding:11px 14px;margin:10px 0;background:var(--paper)}.permission-group summary{font-weight:700;cursor:pointer}.permission-row{display:grid;grid-template-columns:minmax(130px,1fr) minmax(145px,180px) minmax(100px,1fr);gap:10px;align-items:center;border-top:1px solid var(--line);padding:8px 0}.permission-row:first-of-type{margin-top:8px}.permission-row small{color:var(--muted);text-align:right}.notice-bad{border-color:#d88;color:#a33}.scene-panel .scene-list{display:block}.scene-detail .preset-grid{margin:12px 0}.scene-detail .preset-option{min-height:76px;text-align:left}.scene-detail .preset-option strong,.scene-detail .preset-option small{display:block}.scene-detail .preset-option small{font-size:10px;color:var(--muted)}.head-status{align-self:center}.form-card .form-label{margin-top:11px}.form-card .input{width:100%}.footer{margin-top:30px}
|
|
27
|
-
@media(max-width:650px){.permission-row{grid-template-columns:1fr 1fr}.permission-row small{grid-column:1 / -1;text-align:left}.scene-actions{flex-wrap:wrap}}
|
|
28
|
-
.global-deny-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:7px}.global-deny-option{display:flex;gap:7px;align-items:center;padding:8px;border:1px solid var(--line);border-radius:9px;font-size:11px;background:var(--soft)}.global-deny-option input{accent-color:var(--green)}@media(max-width:650px){.global-deny-grid{grid-template-columns:1fr}}
|
|
1
|
+
:root{
|
|
2
|
+
--bg:#f5f8fa;--paper:#fff;--ink:#192b39;--ink2:#233748;--muted:#728397;--muted2:#98a8b6;
|
|
3
|
+
--line:#e6edf1;--line-strong:#dae5eb;--soft:#f7fafb;--green:#0b875c;--green-soft:#e8f7ef;--green-ink:#08704e;
|
|
4
|
+
--blue:#2679c7;--blue-soft:#edf5fe;--orange:#d77b20;--orange-soft:#fff3e6;--pink:#a967cc;--pink-soft:#f8f0fc;
|
|
5
|
+
--warning:#a87826;--warning-soft:#fff9e8;--danger:#b85a56;--danger-soft:#fff0ed;
|
|
6
|
+
--shadow:0 12px 34px rgba(22,55,73,.045);--shadow2:0 8px 30px rgba(21,46,69,.08)
|
|
7
|
+
}
|
|
8
|
+
[data-theme="dark"]{
|
|
9
|
+
--bg:#131d25;--paper:#1b2932;--ink:#eaf3f4;--ink2:#d9e5e9;--muted:#a0b4bf;--muted2:#7f97a6;
|
|
10
|
+
--line:#30404b;--line-strong:#405363;--soft:#22333e;--green:#78d6af;--green-soft:#1b4639;--green-ink:#91e6bf;
|
|
11
|
+
--blue:#8fc0f1;--blue-soft:#263f58;--orange:#f4bd80;--orange-soft:#4c392b;--pink:#e3b3f2;--pink-soft:#45314f;
|
|
12
|
+
--warning:#f0cd8c;--warning-soft:#473e2c;--danger:#ecaaa0;--danger-soft:#4b2e30;
|
|
13
|
+
--shadow:0 12px 32px rgba(0,0,0,.13);--shadow2:0 10px 36px rgba(0,0,0,.2)
|
|
14
|
+
}
|
|
15
|
+
*{box-sizing:border-box}html{scrollbar-gutter:stable}body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.58 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",Arial,sans-serif;letter-spacing:.002em}button,input,select,textarea{font:inherit;color:inherit}button{cursor:pointer}button:disabled{opacity:.55;cursor:not-allowed}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible{outline:2px solid var(--green);outline-offset:2px}a{color:var(--green);text-decoration:none}a:hover{text-decoration:underline}h1,h2,h3,h4,p{margin-top:0}h1{font-size:26px;letter-spacing:-.04em;margin-bottom:3px;line-height:1.35}h2{font-size:19px;letter-spacing:-.025em;margin-bottom:6px}h3{font-size:15px;margin-bottom:6px}p{color:var(--muted)}.icon{width:18px;height:18px;flex-shrink:0;display:inline-block;vertical-align:middle;stroke:currentColor;fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.85}.icon.sm{width:15px;height:15px}.icon.lg{width:22px;height:22px}.app{display:grid;grid-template-columns:220px minmax(0,1fr);min-height:100vh}.sidebar{background:var(--paper);border-right:1px solid var(--line);padding:21px 14px 17px;position:sticky;top:0;height:100vh;display:flex;flex-direction:column;gap:27px;z-index:5}.brand{display:flex;gap:10px;align-items:center;padding:1px 7px}.brand-logo{position:relative;width:37px;height:37px;border-radius:13px;background:linear-gradient(135deg,#159d78,#2764b0);display:grid;place-items:center;color:white;font-weight:900;font-size:17px;letter-spacing:-.1em;box-shadow:0 6px 13px #1c8f9250}.brand-logo:after{content:"";position:absolute;right:1px;top:1px;background:#91e2c0;width:9px;height:9px;border-radius:50%;border:2px solid var(--paper)}.brand-label{font-size:15px;font-weight:800;line-height:1.1;letter-spacing:-.02em}.brand-sub{font-size:10px;color:var(--muted);margin-top:4px}.brand-tag{color:var(--green-ink);background:var(--green-soft);border-radius:100px;font-size:10px;padding:2px 7px;margin-left:4px;font-weight:700}.nav-label{color:var(--muted2);padding:0 12px;font-size:10px;font-weight:800;letter-spacing:.1em;margin-bottom:9px}.nav{display:grid;gap:6px}.nav button{border:0;background:transparent;width:100%;padding:11px 12px;border-radius:11px;text-align:left;display:flex;align-items:center;gap:12px;color:var(--ink2);font-size:13px;font-weight:550}.nav button:hover{background:var(--soft)}.nav button.active{background:var(--green-soft);color:var(--green-ink);font-weight:800}.nav button .icon{opacity:.75}.nav-divider{margin:6px 11px;border-bottom:1px solid var(--line)}.sidebar-bottom{margin-top:auto}.plugin-status{border:1px solid var(--line);border-radius:14px;padding:15px 13px;background:var(--soft)}.plugin-status .micro{font-size:11px;color:var(--muted)}.plugin-status strong{display:flex;align-items:center;gap:7px;margin:9px 0 5px;color:var(--green-ink)}.plugin-status p{font-size:11px;line-height:1.6;margin-bottom:10px}.plugin-status .idline{font-size:11px;display:flex;justify-content:space-between;margin:5px 0}.plugin-status .idline span:first-child{color:var(--muted)}.plugin-status .idline b{font-size:11px}.main{min-width:0;padding:25px 26px 50px}.main-width{max-width:1600px;margin:0 auto}.head{display:flex;justify-content:space-between;align-items:flex-start;gap:22px;margin-bottom:23px}.page-lead .eyebrow{font-size:10px;text-transform:uppercase;font-weight:750;letter-spacing:.17em;color:var(--green-ink);margin-bottom:6px}.page-lead p{font-size:12px;margin:0}.head-right{display:flex;gap:9px;align-items:stretch;flex-wrap:wrap;justify-content:flex-end}.head-status{padding:8px 12px;min-height:50px;background:var(--paper);border:1px solid var(--line);border-radius:12px;display:flex;align-items:center;gap:10px;min-width:137px;box-shadow:var(--shadow)}.head-status .label{font-size:10px;color:var(--muted)}.head-status strong{font-size:12px;display:block;line-height:1.25}.head-status .statusicon{width:31px;height:31px;border-radius:10px;background:var(--blue-soft);color:var(--blue);display:grid;place-items:center}.head-status.online .statusicon{background:var(--green-soft);color:var(--green-ink)}.head-status.online strong{color:var(--green-ink)}.demo-pill{display:inline-flex;align-items:center;padding:4px 9px;border-radius:100px;background:var(--soft);border:1px solid var(--line);font-size:10px;color:var(--muted);white-space:nowrap}.button{border:1px solid var(--line-strong);border-radius:10px;background:var(--paper);font-size:12px;font-weight:730;padding:9px 12px;display:inline-flex;align-items:center;justify-content:center;gap:7px;min-height:36px;white-space:nowrap}.button:hover{border-color:#9dcdbb;background:var(--soft)}.button.primary{color:#fff;background:#0b8c61;border-color:#0b8c61;box-shadow:0 4px 12px rgba(0,135,92,.12)}.button.primary:hover{background:#067851}.button.soft{border-color:#cceadb;background:var(--green-soft);color:var(--green-ink)}.button.ghost{background:transparent;border-color:transparent;color:var(--muted)}.button.mini{padding:6px 10px;min-height:29px;font-size:11px}.button.linklike{border:0;color:var(--blue);background:transparent;padding:0}.tag{display:inline-flex;gap:5px;align-items:center;white-space:nowrap;font-size:10px;font-weight:740;padding:3px 8px;background:var(--soft);color:var(--muted);border:1px solid var(--line);border-radius:50px}.tag.success{background:var(--green-soft);border-color:#c7e6d7;color:var(--green-ink)}.tag.info{background:var(--blue-soft);border-color:#d8e6f7;color:var(--blue)}.tag.warn{background:var(--warning-soft);border-color:#f0e3c3;color:var(--warning)}.tag.danger{background:var(--danger-soft);border-color:#ebccc8;color:var(--danger)}.tag.demo{border-style:dashed}.dot{width:7px;height:7px;border-radius:50%;display:inline-block;background:currentColor}.view{display:none;animation:fadein .12s ease}.view.active{display:block}@keyframes fadein{from{opacity:.6;transform:translateY(3px)}to{opacity:1;transform:translateY(0)}}.card{background:var(--paper);border:1px solid var(--line);border-radius:17px;box-shadow:var(--shadow)}.padded{padding:20px}.muted{color:var(--muted)}.micro{font-size:11px}.fine{font-size:12px;color:var(--muted)}.sect-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:22px 0 12px}.sect-head:first-child{margin-top:0}.sect-head h2{font-size:15px;margin:0}.section-sub{font-size:11px;color:var(--muted)}.stats-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:13px}.stat-card{padding:19px;min-height:129px}.stat-top{display:flex;justify-content:space-between;align-items:center;color:var(--muted);font-size:11px}.stat-icon{width:34px;height:34px;display:grid;place-items:center;border-radius:10px;background:var(--green-soft);color:var(--green-ink)}.stat-icon.blue{background:var(--blue-soft);color:var(--blue)}.stat-icon.orange{background:var(--orange-soft);color:var(--orange)}.stat-icon.pink{background:var(--pink-soft);color:var(--pink)}.stat-value{font-size:27px;font-weight:830;letter-spacing:-.05em;line-height:1.4;margin:9px 0 0}.stat-caption{font-size:11px;color:var(--muted)}.two-columns{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(300px,.95fr);gap:15px}.activity-row{display:flex;align-items:center;gap:13px;padding:13px 0;border-top:1px solid var(--line)}.activity-row:first-child{border-top:0}.activity-ico{display:grid;place-items:center;border-radius:11px;background:var(--blue-soft);color:var(--blue);width:34px;height:34px}.activity-content{flex:1;min-width:0}.activity-content strong{display:block;font-size:12px}.activity-content small{display:block;color:var(--muted);font-size:10px}.activity-time{font-size:10px;color:var(--muted2)}.flowline{display:grid;grid-template-columns:repeat(5,1fr);gap:7px}.flowstep{position:relative;border:1px solid var(--line);border-radius:12px;padding:15px 11px;background:var(--soft);min-height:86px}.flowstep span{color:var(--green-ink);font-size:10px;font-weight:800}.flowstep b{display:block;font-size:12px;margin-top:6px}.flowstep small{font-size:10px;color:var(--muted)}.callout{display:flex;align-items:flex-start;gap:11px;background:var(--green-soft);color:var(--green-ink);border:1px solid #cbe8d9;border-radius:12px;padding:13px 14px;font-size:12px}.callout p{color:var(--muted);font-size:11px;margin:4px 0 0}.scene-layout{display:grid;grid-template-columns:277px minmax(0,1fr);gap:15px;align-items:start}.scene-panel{padding:14px;position:sticky;top:15px}.scene-tabs{display:flex;background:var(--soft);padding:4px;border-radius:10px;gap:3px;margin-bottom:13px}.scene-tabs button{flex:1;border:0;border-radius:8px;background:transparent;color:var(--muted);padding:7px;font-size:11px;font-weight:700;white-space:nowrap}.scene-tabs button.active{background:var(--paper);color:var(--green-ink);box-shadow:0 2px 6px #00000008}.scene-tools{display:flex;gap:7px;margin-bottom:12px}.input{min-width:0;width:100%;border:1px solid var(--line-strong);border-radius:9px;background:var(--paper);padding:9px 11px;font-size:12px}.input:focus{border-color:var(--green)}.scene-tools .input{flex:1;width:auto}.scene-list{display:grid;gap:5px}.scene-item{display:flex;align-items:center;width:100%;text-align:left;border:1px solid transparent;background:transparent;gap:10px;padding:11px 9px;border-radius:12px}.scene-item:hover{background:var(--soft)}.scene-item.active{border-color:#a6dbc3;background:var(--green-soft)}.avatar{width:38px;height:38px;display:grid;place-items:center;border-radius:12px;color:var(--orange);background:var(--orange-soft);flex-shrink:0}.avatar.private{background:var(--blue-soft);color:var(--blue)}.scene-info{flex:1;min-width:0}.scene-info b{display:block;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.scene-info small{display:block;font-size:10px;color:var(--muted);line-height:1.5}.scene-item>.icon{color:var(--muted)}.scene-aside-foot{margin:17px 5px 2px;color:var(--muted);font-size:11px}.scene-detail{padding:21px 21px 16px;min-height:760px}.detail-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:18px}.detail-header-main{display:flex;gap:12px;align-items:center}.detail-header-main .avatar{height:43px;width:43px;border-radius:14px}.detail-header h2{font-size:20px;margin-bottom:2px}.detail-header p{font-size:11px;margin:0}.detail-action{display:flex;gap:7px;align-items:center}.divider{height:1px;background:var(--line);margin:20px 0}.mini-title{font-size:11px;color:var(--muted);font-weight:650;margin:0 0 8px}.workspace-banner{display:flex;align-items:center;gap:12px;background:var(--soft);border:1px solid var(--line);border-radius:11px;padding:12px 14px}.workspace-banner .statusicon{height:36px;width:36px;display:grid;place-items:center;border-radius:10px;background:var(--blue-soft);color:var(--blue)}.workspace-banner .grow{flex:1}.workspace-banner b{font-size:12px}.workspace-banner small{display:block;color:var(--muted);font-size:11px;margin-top:3px}.preset-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;gap:8px}.preset-header .small{font-size:10px;color:var(--muted)}.preset-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px}.preset-option{text-align:left;min-height:80px;border:1px solid var(--line);border-radius:11px;background:var(--paper);padding:11px;display:flex;flex-direction:column;gap:4px;position:relative;transition:border-color .15s,background .15s}.preset-option:hover{border-color:#91caae}.preset-option.active{background:var(--green-soft);border-color:#70c49c;box-shadow:0 0 0 1px #70c49c2e}.preset-option .p-head{display:flex;align-items:center;gap:5px}.preset-option b{font-size:12px;white-space:nowrap}.preset-option small{font-size:10px;color:var(--muted);line-height:1.42}.preset-option .check{margin-left:auto;color:var(--green-ink)}.preset-option:not(.active) .check{display:none}.preset-desc{margin-top:10px;padding:10px 12px;border-radius:10px;background:var(--soft);border:1px solid var(--line);font-size:11px;color:var(--muted)}.preset-desc strong{color:var(--ink)}.custom-alert{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:11px;padding:10px 12px;background:var(--warning-soft);border:1px solid #e9dfb9;border-radius:10px;font-size:11px;color:var(--warning)}.state-row{display:flex;align-items:center;justify-content:space-between;margin:20px 0 11px}.state-row strong{font-size:13px}.setting-groups{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.group-card{border:1px solid var(--line);border-radius:12px;background:var(--paper);overflow:hidden}.group-card summary{list-style:none;display:flex;align-items:center;gap:10px;padding:13px;cursor:pointer;min-height:67px}.group-card summary::-webkit-details-marker{display:none}.group-card summary:hover{background:var(--soft)}.group-icon{width:33px;height:33px;display:grid;place-items:center;border-radius:10px;background:var(--blue-soft);color:var(--blue);flex-shrink:0}.group-icon.green{background:var(--green-soft);color:var(--green-ink)}.group-icon.orange{background:var(--orange-soft);color:var(--orange)}.group-icon.pink{background:var(--pink-soft);color:var(--pink)}.group-summary{flex:1;min-width:0}.group-summary b{display:block;font-size:12px}.group-summary small{display:block;font-size:10px;color:var(--muted);white-space:normal}.group-card .arrow{color:var(--muted)}.group-card[open] .arrow{transform:rotate(90deg)}.group-content{padding:1px 13px 12px;border-top:1px solid var(--line)}.toggle-line{display:flex;gap:10px;align-items:center;padding:11px 0;border-bottom:1px solid var(--line)}.toggle-line:last-child{border:0}.toggle-line>div:first-child{flex:1;min-width:0}.toggle-line strong{font-size:11px;display:block}.toggle-line small{font-size:10px;color:var(--muted);display:block;margin-top:3px}.toggle-line.disabled{opacity:.6}.switch{display:flex;align-items:center;position:relative;cursor:pointer;min-width:34px}.switch input{position:absolute;opacity:0;width:36px;height:22px}.switch .track{height:21px;width:37px;display:block;position:relative;background:#c7d3d9;border-radius:999px;transition:background .16s}.switch .track:after{content:"";position:absolute;top:3px;left:3px;height:15px;width:15px;border-radius:50%;background:#fff;transition:left .16s}.switch input:checked+.track{background:#0e9b6a}.switch input:checked+.track:after{left:19px}.switch input:focus-visible+.track{outline:2px solid var(--green);outline-offset:3px}.switch input:disabled+.track{opacity:.52}.select-line{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 0;border-bottom:1px solid var(--line)}.select-line:last-child{border:0}.select-line b{font-size:11px}.select-line small{font-size:10px;color:var(--muted);display:block;margin-top:2px}.select-mini{background:var(--soft);border:1px solid var(--line);border-radius:8px;padding:7px 9px;font-size:11px;max-width:155px}.detail-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;padding-top:18px;border-top:1px solid var(--line);margin-top:20px}.detail-footer .fine{max-width:530px;font-size:11px}.detail-footer-actions{display:flex;gap:7px;flex-shrink:0}.capability-summary{background:var(--soft);border:1px solid var(--line);border-radius:11px;padding:12px;margin-top:12px;display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:11px}.capability-summary .soft{color:var(--muted)}.legend{font-size:10px;color:var(--muted)}.feature-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:13px}.feature-tile{padding:19px;min-height:184px}.feature-title{display:flex;align-items:center;gap:10px;margin-bottom:12px}.feature-title h3{margin:0}.feature-tile p{font-size:11px;margin:8px 0 12px;line-height:1.7}.feature-foot{display:flex;flex-wrap:wrap;gap:6px;margin-top:auto}.cap-list{display:grid;gap:7px;margin:13px 0}.cap-list div{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:8px 0;border-top:1px dashed var(--line);font-size:11px}.cap-list .tag{flex-shrink:0}.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:15px}.form-card{padding:20px}.form-card h3{display:flex;gap:8px;align-items:center}.form-card p{font-size:11px;line-height:1.75}.form-label{font-size:11px;font-weight:700;display:block;margin:12px 0 6px}.form-hint{color:var(--muted);font-size:10px;margin:6px 0}.form-row{display:flex;gap:8px;align-items:center}.form-row>*:first-child{flex:1}.status-table{width:100%;border-collapse:collapse;font-size:11px}.status-table td{padding:11px 4px;border-bottom:1px solid var(--line)}.status-table td:last-child{text-align:right}.status-table tr:last-child td{border:0}.status-table td:first-child{color:var(--muted)}.log-line{display:flex;align-items:start;gap:11px;padding:12px 0;border-top:1px solid var(--line);font-size:11px}.log-line:first-child{border:0}.log-time{font-family:ui-monospace,Consolas,monospace;color:var(--muted);white-space:nowrap}.check-flow{display:grid;gap:10px}.check-row{display:flex;align-items:center;gap:10px;padding:11px 13px;border-radius:10px;background:var(--soft);border:1px solid var(--line);font-size:11px}.check-row div{flex:1}.check-row b{display:block;font-size:12px}.check-row small{color:var(--muted)}.test-chip{color:var(--green-ink);font-weight:700;font-size:10px}.global-flags{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}.global-flags .tag{font-size:11px}.inline-notice{padding:12px 14px;border:1px solid var(--line);background:var(--soft);border-radius:11px;font-size:11px;color:var(--muted)}.footer{font-size:11px;color:var(--muted2);padding:30px 2px 0;text-align:center}.desktop-frame{max-width:690px;margin:15px auto;border:1px solid var(--line);border-radius:19px;padding:22px;background:var(--paper);box-shadow:var(--shadow2)}.desktop-inner{display:grid;grid-template-columns:160px minmax(0,1fr);gap:22px}.desktop-rail{border-right:1px solid var(--line);padding-right:14px}.desktop-rail div{font-size:12px;padding:10px;border-radius:9px;color:var(--muted)}.desktop-rail div.active{background:var(--green-soft);color:var(--green-ink);font-weight:700}.desktop-content h3{font-size:20px}.desktop-content p{font-size:11px}.desktop-summary{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin:15px 0}.desktop-summary .metric{padding:12px;border:1px solid var(--line);border-radius:10px;background:var(--soft)}.desktop-summary small{display:block;font-size:10px;color:var(--muted)}.desktop-summary b{font-size:12px}.demo-hint{display:flex;align-items:center;gap:7px;font-size:10px;color:var(--muted);margin-top:9px}.toast{position:fixed;bottom:22px;right:24px;max-width:390px;border-radius:13px;box-shadow:var(--shadow2);border:1px solid var(--line-strong);background:var(--paper);z-index:99;padding:13px 17px;color:var(--ink);font-size:12px;display:none}.toast.show{display:block}.toast strong{display:block;margin-bottom:3px}.modal{border:1px solid var(--line);background:var(--paper);color:var(--ink);border-radius:16px;padding:24px;width:min(430px,90vw);box-shadow:var(--shadow2)}.modal::backdrop{background:#16252a80;backdrop-filter:blur(3px)}.modal h2{margin-bottom:8px}.modal p{font-size:12px}.modal .actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.radio-pair{display:flex;gap:8px;margin:13px 0}.radio-pair label{border:1px solid var(--line);border-radius:9px;padding:10px 15px;font-size:12px;flex:1}.radio-pair input{accent-color:#0d9769}.scroll-guard{overflow:auto}.mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.hide{display:none!important}
|
|
16
|
+
@media(max-width:1300px){.app{grid-template-columns:195px minmax(0,1fr)}.main{padding:22px 18px}.head-status{min-width:117px}.scene-layout{grid-template-columns:238px minmax(0,1fr)}.setting-groups{grid-template-columns:1fr}.preset-grid{grid-template-columns:repeat(3,1fr)}}
|
|
17
|
+
@media(max-width:950px){.sidebar{position:relative;height:auto;min-height:100vh}.head{flex-direction:column}.head-right{justify-content:flex-start}.stats-grid{grid-template-columns:repeat(2,1fr)}.scene-layout{grid-template-columns:1fr}.scene-panel{position:static}.scene-list{grid-template-columns:repeat(2,minmax(0,1fr))}.feature-grid{grid-template-columns:repeat(2,1fr)}.two-columns{grid-template-columns:1fr}.preset-grid{grid-template-columns:repeat(4,1fr)}}
|
|
18
|
+
@media(max-width:650px){.app{display:block}.sidebar{height:auto;min-height:0;position:static;padding:13px 14px;gap:10px}.brand{padding:0}.nav{display:flex;overflow:auto;gap:3px}.nav-label,.sidebar-bottom,.nav-divider{display:none}.nav button{white-space:nowrap;padding:9px}.main{padding:18px 13px 30px}.head-status{min-width:auto}.head-right .head-status{flex:1}.scene-detail{padding:16px 12px}.scene-list{grid-template-columns:1fr}.preset-grid{grid-template-columns:repeat(2,1fr)}.stats-grid,.feature-grid,.form-grid,.setting-groups{grid-template-columns:1fr}.desktop-inner{grid-template-columns:1fr}.desktop-rail{display:none}.detail-footer{align-items:stretch;flex-direction:column}.detail-footer-actions{justify-content:flex-end}.flowline{grid-template-columns:repeat(2,1fr)}}
|
|
19
|
+
/* Explicit dark-preset surfaces for Chromium's dynamic data-theme repaint. */
|
|
20
|
+
html[data-theme="dark"] .preset-option{background-color:#233540;color:#eaf3f4;border-color:#405363}
|
|
21
|
+
html[data-theme="dark"] .preset-option.active{background-color:#1b4639;border-color:#70c49c;color:#eaf3f4}
|
|
22
|
+
html[data-theme="dark"] .preset-option:hover{background-color:#29423e}
|
|
23
|
+
html[data-theme="dark"] .preset-option.active:hover{background-color:#215641}
|
|
24
|
+
|
|
25
|
+
/* Runtime-only controls added to the approved visual language. */
|
|
26
|
+
.view{display:none}.view.active{display:block}.scene-choice{display:grid;gap:3px;width:100%;text-align:left;border:1px solid var(--line);border-radius:11px;padding:12px;background:var(--paper);margin:6px 0}.scene-choice:hover,.scene-choice.selected{border-color:var(--green);background:var(--green-soft)}.scene-choice small{color:var(--muted)}.scene-actions{display:flex;gap:8px;margin:14px 0 21px}.permission-group{border:1px solid var(--line);border-radius:12px;padding:11px 14px;margin:10px 0;background:var(--paper)}.permission-group summary{font-weight:700;cursor:pointer}.permission-row{display:grid;grid-template-columns:minmax(130px,1fr) minmax(145px,180px) minmax(100px,1fr);gap:10px;align-items:center;border-top:1px solid var(--line);padding:8px 0}.permission-row:first-of-type{margin-top:8px}.permission-row small{color:var(--muted);text-align:right}.notice-bad{border-color:#d88;color:#a33}.scene-panel .scene-list{display:block}.scene-detail .preset-grid{margin:12px 0}.scene-detail .preset-option{min-height:76px;text-align:left}.scene-detail .preset-option strong,.scene-detail .preset-option small{display:block}.scene-detail .preset-option small{font-size:10px;color:var(--muted)}.head-status{align-self:center}.form-card .form-label{margin-top:11px}.form-card .input{width:100%}.footer{margin-top:30px}
|
|
27
|
+
@media(max-width:650px){.permission-row{grid-template-columns:1fr 1fr}.permission-row small{grid-column:1 / -1;text-align:left}.scene-actions{flex-wrap:wrap}}
|
|
28
|
+
.global-deny-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:7px}.global-deny-option{display:flex;gap:7px;align-items:center;padding:8px;border:1px solid var(--line);border-radius:9px;font-size:11px;background:var(--soft)}.global-deny-option input{accent-color:var(--green)}@media(max-width:650px){.global-deny-grid{grid-template-columns:1fr}}
|
package/src/console/console.js
CHANGED
|
@@ -18,6 +18,7 @@ const modes = [
|
|
|
18
18
|
]
|
|
19
19
|
const groups = [
|
|
20
20
|
['聊天与媒体', ['qq.read', 'qq.send', 'qq.media.read', 'qq.reaction.write', 'qq.poke', 'qq.recall']],
|
|
21
|
+
['Amadeus Life', ['amadeus.life.read']],
|
|
21
22
|
['群管理', ['qq.group.essence', 'qq.group.notice', 'qq.group.card', 'qq.group.ban', 'qq.group.whole_ban', 'qq.group.kick', 'qq.group.name', 'qq.group.admin', 'qq.group.special_title']],
|
|
22
23
|
['Agent 与目录', ['dsh.search', 'qq.owner.workspace', 'qq.owner.tools', 'qq.friends.read', 'qq.groups.read']],
|
|
23
24
|
]
|
|
@@ -36,6 +37,7 @@ const labels = {
|
|
|
36
37
|
'qq.group.name': '群名称', 'qq.group.admin': '设置群管理员', 'qq.group.special_title': '群头衔',
|
|
37
38
|
'dsh.search': 'DSH 搜索', 'qq.owner.workspace': 'Owner 文件工作区',
|
|
38
39
|
'qq.owner.tools': 'Owner Host 工具', 'qq.friends.read': '好友目录', 'qq.groups.read': '群目录',
|
|
40
|
+
'amadeus.life.read': '读取本会话 Life 概况',
|
|
39
41
|
'qq.profile.write': '账号资料修改', 'qq.qzone.use': 'QQ 空间统一操作',
|
|
40
42
|
'qq.qzone.read': 'QQ 空间读取', 'qq.qzone.publish': 'QQ 空间发布',
|
|
41
43
|
}
|
|
@@ -536,3 +538,4 @@ $('add-form').addEventListener('submit', async event => {
|
|
|
536
538
|
} catch (error) { notice(`添加状态未确认:${error.message}`, true); await refresh() }
|
|
537
539
|
})
|
|
538
540
|
void refresh()
|
|
541
|
+
|
package/src/console/index.html
CHANGED
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="zh-CN" data-theme="light">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
-
<meta name="color-scheme" content="light dark">
|
|
7
|
-
<title>Amadeus QQ · 管理控制台</title>
|
|
8
|
-
<link rel="stylesheet" href="console.css">
|
|
9
|
-
</head>
|
|
10
|
-
<body>
|
|
11
|
-
<div class="app">
|
|
12
|
-
<aside class="sidebar">
|
|
13
|
-
<div class="brand"><div class="brand-logo">A</div><div><div class="brand-label">Amadeus QQ <span class="brand-tag">v1.2</span></div><div class="brand-sub">与世界一起聊天</div></div></div>
|
|
14
|
-
<div><div class="nav-label">CONSOLE · 管理控制台</div><nav class="nav" aria-label="主导航">
|
|
15
|
-
<button type="button" data-page="overview" class="active">总览首页</button>
|
|
16
|
-
<button type="button" data-page="scenes">会话管理</button>
|
|
17
|
-
<button type="button" data-page="features">功能中心</button>
|
|
18
|
-
<div class="nav-divider"></div>
|
|
19
|
-
<button type="button" data-page="account">账号与 QQ 空间</button>
|
|
20
|
-
<button type="button" data-page="global">全局设置</button>
|
|
21
|
-
<button type="button" data-page="diagnostics">运行与诊断</button>
|
|
22
|
-
</nav></div>
|
|
23
|
-
<div class="sidebar-bottom"><div class="plugin-status"><span class="micro">插件运行状态</span><strong id="side-status">正在读取</strong><p id="side-detail">等待 DSH Owner 鉴权</p><div class="idline"><span>Bot</span><b id="side-bot">—</b></div><div class="idline"><span>Owner</span><b id="side-owner">—</b></div></div></div>
|
|
24
|
-
</aside>
|
|
25
|
-
<main class="main"><div class="main-width">
|
|
26
|
-
<header class="head"><div class="page-lead"><div class="eyebrow">AMADEUS · QQ INTEGRATION</div><h1 id="page-title">总览首页</h1><p id="page-subtitle">连接状态、会话和首次配置。</p></div><div class="head-right"><div class="head-status" id="transport-status">NapCat:正在检查</div><button class="button" id="theme-toggle" type="button">切换主题</button></div></header>
|
|
27
|
-
<div id="notice" class="inline-notice hide" role="status" aria-live="polite"></div>
|
|
28
|
-
|
|
29
|
-
<section id="view-overview" class="view active" aria-label="总览首页">
|
|
30
|
-
<div class="stats-grid">
|
|
31
|
-
<div class="card stat-card"><div class="stat-top">插件状态</div><div class="stat-value" id="overview-plugin">—</div><div class="stat-caption" id="overview-transport">读取中</div></div>
|
|
32
|
-
<div class="card stat-card"><div class="stat-top">已授权会话</div><div class="stat-value" id="overview-scenes">0</div><div class="stat-caption">每个 QQ 场景独立绑定 DSH Session</div></div>
|
|
33
|
-
<div class="card stat-card"><div class="stat-top">实际 Session</div><div class="stat-value" id="overview-sessions">0</div><div class="stat-caption">授权后创建,重启后恢复</div></div>
|
|
34
|
-
<div class="card stat-card"><div class="stat-top">目标工作区</div><div class="stat-value" id="overview-workspace">未选择</div><div class="stat-caption">QQ 会话归属此 DSH Workspace</div></div>
|
|
35
|
-
</div>
|
|
36
|
-
<div class="two-columns"><div class="card padded"><h2>最近会话</h2><div id="overview-list" class="scene-list"></div><button class="button soft" type="button" data-page="scenes">管理会话</button></div><div class="card padded"><h2>首次设置</h2><p>选择 Workspace、配置本机 NapCat、指定唯一 Owner,然后授权群聊或私聊。</p><div id="onboarding" class="check-flow"></div><button class="button primary" type="button" data-page="global">打开全局设置</button></div></div>
|
|
37
|
-
<div class="inline-notice"><b>QQ 与 Life 的边界:</b>QQ 只处理当前聊天和同一 Session 内的等待续接。长期自主唤醒由可选的 Life 插件负责。</div>
|
|
38
|
-
</section>
|
|
39
|
-
|
|
40
|
-
<section id="view-scenes" class="view" aria-label="会话管理">
|
|
41
|
-
<div class="scene-layout"><div class="card scene-panel"><div class="sect-head"><h2>授权会话</h2><button class="button mini" id="add-scene" type="button">添加</button></div><input class="input" id="scene-filter" type="search" placeholder="筛选群号或 QQ 号" aria-label="筛选会话"><div id="scene-list" class="scene-list"></div></div>
|
|
42
|
-
<div class="card scene-detail" id="scene-detail"><h2>选择会话</h2><p>选择左侧 Scene 查看权限、Session 绑定和运行状态。</p></div></div>
|
|
43
|
-
</section>
|
|
44
|
-
|
|
45
|
-
<section id="view-features" class="view" aria-label="功能中心"><div class="callout"><div><b>按实际执行条件展示</b><p>源码路径、Provider 可用性和真实 QQ 验收是不同状态;这里的可用性以当前配置为准。</p></div></div><div id="feature-list" class="feature-grid"></div></section>
|
|
46
|
-
|
|
47
|
-
<section id="view-account" class="view" aria-label="账号与 QQ 空间"><div class="callout"><div><b>仅可信 Owner 私聊</b><p>账号资料和 QQ 空间不属于任何群聊预设;请先在 Owner 私聊 Scene 选择 Owner Agent。两组设置分别保存,避免其中一步失败后误以为全部生效。</p></div></div><form id="account-form"><div class="two-columns"><div class="card padded"><h2>账号资料</h2><p>昵称、签名、在线状态和头像均由 Owner 专用工具操作。</p><label class="form-label"><input id="account-profile" type="checkbox"> 允许 Owner 私聊修改账号资料</label><div id="account-status" class="inline-notice"></div></div><div class="card padded"><h2>QQ 空间</h2><p>Provider、账号级授权和 Scene 显式授权会逐层检查。</p><label class="form-label"><input id="account-qzone-enabled" type="checkbox"> 启用 QZone 工具</label><label class="form-label"><input id="account-qzone-publish" type="checkbox"> 授权此 Bot 发布空间内容</label><label class="form-label"><input id="account-qzone-use" type="checkbox"> 允许 Owner 私聊使用 QZone</label><label class="form-label" for="account-qzone-url">可选本机 QZone Provider 地址</label><input class="input" id="account-qzone-url" placeholder="http://127.0.0.1:端口"><label class="form-label" for="account-qzone-token-env">Provider Token 环境变量名</label><input class="input" id="account-qzone-token-env" placeholder="QZONE_ACCESS_TOKEN"><div id="qzone-status" class="inline-notice"></div></div></div><div class="detail-footer"><span id="account-state">当前设置</span><div class="detail-footer-actions"><button class="button" type="button" id="account-discard">撤销修改</button><button class="button primary" type="submit" data-account-save="scene">保存 Owner 授权</button><button class="button primary" type="submit" data-account-save="provider">保存空间配置</button></div></div></form></section>
|
|
48
|
-
|
|
49
|
-
<section id="view-global" class="view" aria-label="全局设置"><div class="callout"><div><b>由 DSH Owner 管理</b><p>配置保存到当前 DSH Profile,Token 不会回显。改动通过 DSH 配置服务应用;连接状态以运行诊断为准。</p></div></div>
|
|
50
|
-
<div class="card padded"><h2>QQ 接管</h2><p>同一个 NapCat 登录可轮流供 Amadeus QQ 和本地 AstrBot 使用。先暂停 Amadeus,看到“已暂停”后再启用 AstrBot;切回时先停用 AstrBot。</p><strong id="handoff-status" role="status">正在读取状态</strong><p class="form-hint" id="handoff-detail">切换不会删除 QQ Scene 或 DSH Session。暂停期间的消息不会自动补入 Amadeus;切换前已提交给 NapCat 的操作无法撤回。</p><button class="button" id="handoff-button" type="button" disabled>正在读取</button></div>
|
|
51
|
-
<form id="setup-form"><div class="form-grid">
|
|
52
|
-
<div class="card form-card"><h3>DSH Workspace</h3><p>所有新建 QQ Session 都会实际加入所选 Workspace。</p><label class="form-label" for="setup-workspace">工作区</label><select class="input" id="setup-workspace" required></select></div>
|
|
53
|
-
<div class="card form-card"><h3>Bot 与 Owner</h3><label class="form-label" for="setup-bot">Bot QQ 号</label><input class="input" id="setup-bot" inputmode="numeric" pattern="[1-9][0-9]*" required><label class="form-label" for="setup-owner">唯一 Owner QQ 号</label><input class="input" id="setup-owner" inputmode="numeric" pattern="[1-9][0-9]*" required></div>
|
|
54
|
-
<div class="card form-card"><h3>本机 NapCat / OneBot</h3><label class="form-label" for="setup-http">HTTP 地址</label><input class="input" id="setup-http" type="url" placeholder="http://127.0.0.1:3000" required><label class="form-label" for="setup-ws">WebSocket 地址</label><input class="input" id="setup-ws" placeholder="ws://127.0.0.1:3001" required><label class="form-label" for="setup-token">Access Token</label><input class="input" id="setup-token" type="password" autocomplete="new-password" placeholder="留空则保留现有 Token"><p class="form-hint" id="token-hint">当前未配置 Token</p></div>
|
|
55
|
-
<div class="card form-card"><h3>默认授权</h3><p>未知群聊和私聊始终拒绝。Owner 私聊会自动加入白名单。</p><label class="form-label" for="setup-groups">授权群号,逗号分隔</label><input class="input" id="setup-groups" placeholder="例如 123456789"><label class="form-label" for="setup-private">授权好友 QQ 号,逗号分隔</label><input class="input" id="setup-private"><label class="form-label"><input id="setup-connect" type="checkbox"> 启用 NapCat 连接</label></div>
|
|
56
|
-
<div class="card form-card"><h3>全局拒绝</h3><p>被勾选的能力对所有 Scene 生效,即使单个 Scene 请求允许也不能执行。此处由 DSH Owner 管理。</p><div id="setup-global-deny" class="global-deny-grid"></div></div>
|
|
57
|
-
</div><div class="detail-footer"><span id="setup-state">尚未修改</span><div class="detail-footer-actions"><button class="button" id="setup-discard" type="button">撤销修改</button><button class="button primary" type="submit">保存并应用</button></div></div></form>
|
|
58
|
-
</section>
|
|
59
|
-
|
|
60
|
-
<section id="view-diagnostics" class="view" aria-label="运行与诊断"><div class="stats-grid"><div class="card stat-card"><div class="stat-top">插件</div><div class="stat-value" id="diag-plugin">—</div></div><div class="card stat-card"><div class="stat-top">NapCat WebSocket</div><div class="stat-value" id="diag-transport">—</div></div><div class="card stat-card"><div class="stat-top">Workspace</div><div class="stat-value" id="diag-workspace">—</div></div><div class="card stat-card"><div class="stat-top">授权 Scene</div><div class="stat-value" id="diag-scenes">—</div></div></div><div class="card padded"><h2>配置检查</h2><div id="diagnostic-list" class="check-flow"></div><button class="button soft" id="refresh" type="button">重新检查</button></div></section>
|
|
61
|
-
<footer class="footer">Amadeus QQ v1.2.1 · 本地 DSH Owner 控制台</footer>
|
|
62
|
-
</div></main>
|
|
63
|
-
</div>
|
|
64
|
-
<dialog id="add-modal" class="modal" aria-labelledby="add-modal-title"><form id="add-form"><h2 id="add-modal-title">添加 QQ 会话</h2><p>新 Scene 默认安全聊天权限;可以在添加后选择“仅观察”。</p><div class="radio-pair"><label><input type="radio" name="kind" value="group" checked> 群聊</label><label><input type="radio" name="kind" value="private"> 私聊</label></div><label class="form-label" for="add-peer">群号 / QQ 号</label><input class="input" id="add-peer" inputmode="numeric" pattern="[1-9][0-9]*" required><div class="actions"><button class="button" id="add-cancel" type="button">取消</button><button class="button primary" type="submit">添加</button></div></form></dialog>
|
|
65
|
-
<script src="console.js"></script>
|
|
66
|
-
</body>
|
|
67
|
-
</html>
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN" data-theme="light">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<meta name="color-scheme" content="light dark">
|
|
7
|
+
<title>Amadeus QQ · 管理控制台</title>
|
|
8
|
+
<link rel="stylesheet" href="console.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="app">
|
|
12
|
+
<aside class="sidebar">
|
|
13
|
+
<div class="brand"><div class="brand-logo">A</div><div><div class="brand-label">Amadeus QQ <span class="brand-tag">v1.2</span></div><div class="brand-sub">与世界一起聊天</div></div></div>
|
|
14
|
+
<div><div class="nav-label">CONSOLE · 管理控制台</div><nav class="nav" aria-label="主导航">
|
|
15
|
+
<button type="button" data-page="overview" class="active">总览首页</button>
|
|
16
|
+
<button type="button" data-page="scenes">会话管理</button>
|
|
17
|
+
<button type="button" data-page="features">功能中心</button>
|
|
18
|
+
<div class="nav-divider"></div>
|
|
19
|
+
<button type="button" data-page="account">账号与 QQ 空间</button>
|
|
20
|
+
<button type="button" data-page="global">全局设置</button>
|
|
21
|
+
<button type="button" data-page="diagnostics">运行与诊断</button>
|
|
22
|
+
</nav></div>
|
|
23
|
+
<div class="sidebar-bottom"><div class="plugin-status"><span class="micro">插件运行状态</span><strong id="side-status">正在读取</strong><p id="side-detail">等待 DSH Owner 鉴权</p><div class="idline"><span>Bot</span><b id="side-bot">—</b></div><div class="idline"><span>Owner</span><b id="side-owner">—</b></div></div></div>
|
|
24
|
+
</aside>
|
|
25
|
+
<main class="main"><div class="main-width">
|
|
26
|
+
<header class="head"><div class="page-lead"><div class="eyebrow">AMADEUS · QQ INTEGRATION</div><h1 id="page-title">总览首页</h1><p id="page-subtitle">连接状态、会话和首次配置。</p></div><div class="head-right"><div class="head-status" id="transport-status">NapCat:正在检查</div><button class="button" id="theme-toggle" type="button">切换主题</button></div></header>
|
|
27
|
+
<div id="notice" class="inline-notice hide" role="status" aria-live="polite"></div>
|
|
28
|
+
|
|
29
|
+
<section id="view-overview" class="view active" aria-label="总览首页">
|
|
30
|
+
<div class="stats-grid">
|
|
31
|
+
<div class="card stat-card"><div class="stat-top">插件状态</div><div class="stat-value" id="overview-plugin">—</div><div class="stat-caption" id="overview-transport">读取中</div></div>
|
|
32
|
+
<div class="card stat-card"><div class="stat-top">已授权会话</div><div class="stat-value" id="overview-scenes">0</div><div class="stat-caption">每个 QQ 场景独立绑定 DSH Session</div></div>
|
|
33
|
+
<div class="card stat-card"><div class="stat-top">实际 Session</div><div class="stat-value" id="overview-sessions">0</div><div class="stat-caption">授权后创建,重启后恢复</div></div>
|
|
34
|
+
<div class="card stat-card"><div class="stat-top">目标工作区</div><div class="stat-value" id="overview-workspace">未选择</div><div class="stat-caption">QQ 会话归属此 DSH Workspace</div></div>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="two-columns"><div class="card padded"><h2>最近会话</h2><div id="overview-list" class="scene-list"></div><button class="button soft" type="button" data-page="scenes">管理会话</button></div><div class="card padded"><h2>首次设置</h2><p>选择 Workspace、配置本机 NapCat、指定唯一 Owner,然后授权群聊或私聊。</p><div id="onboarding" class="check-flow"></div><button class="button primary" type="button" data-page="global">打开全局设置</button></div></div>
|
|
37
|
+
<div class="inline-notice"><b>QQ 与 Life 的边界:</b>QQ 只处理当前聊天和同一 Session 内的等待续接。长期自主唤醒由可选的 Life 插件负责。</div>
|
|
38
|
+
</section>
|
|
39
|
+
|
|
40
|
+
<section id="view-scenes" class="view" aria-label="会话管理">
|
|
41
|
+
<div class="scene-layout"><div class="card scene-panel"><div class="sect-head"><h2>授权会话</h2><button class="button mini" id="add-scene" type="button">添加</button></div><input class="input" id="scene-filter" type="search" placeholder="筛选群号或 QQ 号" aria-label="筛选会话"><div id="scene-list" class="scene-list"></div></div>
|
|
42
|
+
<div class="card scene-detail" id="scene-detail"><h2>选择会话</h2><p>选择左侧 Scene 查看权限、Session 绑定和运行状态。</p></div></div>
|
|
43
|
+
</section>
|
|
44
|
+
|
|
45
|
+
<section id="view-features" class="view" aria-label="功能中心"><div class="callout"><div><b>按实际执行条件展示</b><p>源码路径、Provider 可用性和真实 QQ 验收是不同状态;这里的可用性以当前配置为准。</p></div></div><div id="feature-list" class="feature-grid"></div></section>
|
|
46
|
+
|
|
47
|
+
<section id="view-account" class="view" aria-label="账号与 QQ 空间"><div class="callout"><div><b>仅可信 Owner 私聊</b><p>账号资料和 QQ 空间不属于任何群聊预设;请先在 Owner 私聊 Scene 选择 Owner Agent。两组设置分别保存,避免其中一步失败后误以为全部生效。</p></div></div><form id="account-form"><div class="two-columns"><div class="card padded"><h2>账号资料</h2><p>昵称、签名、在线状态和头像均由 Owner 专用工具操作。</p><label class="form-label"><input id="account-profile" type="checkbox"> 允许 Owner 私聊修改账号资料</label><div id="account-status" class="inline-notice"></div></div><div class="card padded"><h2>QQ 空间</h2><p>Provider、账号级授权和 Scene 显式授权会逐层检查。</p><label class="form-label"><input id="account-qzone-enabled" type="checkbox"> 启用 QZone 工具</label><label class="form-label"><input id="account-qzone-publish" type="checkbox"> 授权此 Bot 发布空间内容</label><label class="form-label"><input id="account-qzone-use" type="checkbox"> 允许 Owner 私聊使用 QZone</label><label class="form-label" for="account-qzone-url">可选本机 QZone Provider 地址</label><input class="input" id="account-qzone-url" placeholder="http://127.0.0.1:端口"><label class="form-label" for="account-qzone-token-env">Provider Token 环境变量名</label><input class="input" id="account-qzone-token-env" placeholder="QZONE_ACCESS_TOKEN"><div id="qzone-status" class="inline-notice"></div></div></div><div class="detail-footer"><span id="account-state">当前设置</span><div class="detail-footer-actions"><button class="button" type="button" id="account-discard">撤销修改</button><button class="button primary" type="submit" data-account-save="scene">保存 Owner 授权</button><button class="button primary" type="submit" data-account-save="provider">保存空间配置</button></div></div></form></section>
|
|
48
|
+
|
|
49
|
+
<section id="view-global" class="view" aria-label="全局设置"><div class="callout"><div><b>由 DSH Owner 管理</b><p>配置保存到当前 DSH Profile,Token 不会回显。改动通过 DSH 配置服务应用;连接状态以运行诊断为准。</p></div></div>
|
|
50
|
+
<div class="card padded"><h2>QQ 接管</h2><p>同一个 NapCat 登录可轮流供 Amadeus QQ 和本地 AstrBot 使用。先暂停 Amadeus,看到“已暂停”后再启用 AstrBot;切回时先停用 AstrBot。</p><strong id="handoff-status" role="status">正在读取状态</strong><p class="form-hint" id="handoff-detail">切换不会删除 QQ Scene 或 DSH Session。暂停期间的消息不会自动补入 Amadeus;切换前已提交给 NapCat 的操作无法撤回。</p><button class="button" id="handoff-button" type="button" disabled>正在读取</button></div>
|
|
51
|
+
<form id="setup-form"><div class="form-grid">
|
|
52
|
+
<div class="card form-card"><h3>DSH Workspace</h3><p>所有新建 QQ Session 都会实际加入所选 Workspace。</p><label class="form-label" for="setup-workspace">工作区</label><select class="input" id="setup-workspace" required></select></div>
|
|
53
|
+
<div class="card form-card"><h3>Bot 与 Owner</h3><label class="form-label" for="setup-bot">Bot QQ 号</label><input class="input" id="setup-bot" inputmode="numeric" pattern="[1-9][0-9]*" required><label class="form-label" for="setup-owner">唯一 Owner QQ 号</label><input class="input" id="setup-owner" inputmode="numeric" pattern="[1-9][0-9]*" required></div>
|
|
54
|
+
<div class="card form-card"><h3>本机 NapCat / OneBot</h3><label class="form-label" for="setup-http">HTTP 地址</label><input class="input" id="setup-http" type="url" placeholder="http://127.0.0.1:3000" required><label class="form-label" for="setup-ws">WebSocket 地址</label><input class="input" id="setup-ws" placeholder="ws://127.0.0.1:3001" required><label class="form-label" for="setup-token">Access Token</label><input class="input" id="setup-token" type="password" autocomplete="new-password" placeholder="留空则保留现有 Token"><p class="form-hint" id="token-hint">当前未配置 Token</p></div>
|
|
55
|
+
<div class="card form-card"><h3>默认授权</h3><p>未知群聊和私聊始终拒绝。Owner 私聊会自动加入白名单。</p><label class="form-label" for="setup-groups">授权群号,逗号分隔</label><input class="input" id="setup-groups" placeholder="例如 123456789"><label class="form-label" for="setup-private">授权好友 QQ 号,逗号分隔</label><input class="input" id="setup-private"><label class="form-label"><input id="setup-connect" type="checkbox"> 启用 NapCat 连接</label></div>
|
|
56
|
+
<div class="card form-card"><h3>全局拒绝</h3><p>被勾选的能力对所有 Scene 生效,即使单个 Scene 请求允许也不能执行。此处由 DSH Owner 管理。</p><div id="setup-global-deny" class="global-deny-grid"></div></div>
|
|
57
|
+
</div><div class="detail-footer"><span id="setup-state">尚未修改</span><div class="detail-footer-actions"><button class="button" id="setup-discard" type="button">撤销修改</button><button class="button primary" type="submit">保存并应用</button></div></div></form>
|
|
58
|
+
</section>
|
|
59
|
+
|
|
60
|
+
<section id="view-diagnostics" class="view" aria-label="运行与诊断"><div class="stats-grid"><div class="card stat-card"><div class="stat-top">插件</div><div class="stat-value" id="diag-plugin">—</div></div><div class="card stat-card"><div class="stat-top">NapCat WebSocket</div><div class="stat-value" id="diag-transport">—</div></div><div class="card stat-card"><div class="stat-top">Workspace</div><div class="stat-value" id="diag-workspace">—</div></div><div class="card stat-card"><div class="stat-top">授权 Scene</div><div class="stat-value" id="diag-scenes">—</div></div></div><div class="card padded"><h2>配置检查</h2><div id="diagnostic-list" class="check-flow"></div><button class="button soft" id="refresh" type="button">重新检查</button></div></section>
|
|
61
|
+
<footer class="footer">Amadeus QQ v1.2.1 · 本地 DSH Owner 控制台</footer>
|
|
62
|
+
</div></main>
|
|
63
|
+
</div>
|
|
64
|
+
<dialog id="add-modal" class="modal" aria-labelledby="add-modal-title"><form id="add-form"><h2 id="add-modal-title">添加 QQ 会话</h2><p>新 Scene 默认安全聊天权限;可以在添加后选择“仅观察”。</p><div class="radio-pair"><label><input type="radio" name="kind" value="group" checked> 群聊</label><label><input type="radio" name="kind" value="private"> 私聊</label></div><label class="form-label" for="add-peer">群号 / QQ 号</label><input class="input" id="add-peer" inputmode="numeric" pattern="[1-9][0-9]*" required><div class="actions"><button class="button" id="add-cancel" type="button">取消</button><button class="button primary" type="submit">添加</button></div></form></dialog>
|
|
65
|
+
<script src="console.js"></script>
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
package/src/core.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { normalizeId, normalizeMessageId, sceneIdentity, sceneKey } from './storage.js'
|
|
4
4
|
import { normalizeOneBotMessage, sanitizeInboundSegments, validateOutgoingSegments } from './onebot.js'
|
|
5
|
-
import { CAPABILITY_CATALOG, PermissionEngine, validateScenePermissions } from './permissions.js'
|
|
5
|
+
import { CAPABILITY_CATALOG, LIFE_READ_CAPABILITY, PermissionEngine, validateScenePermissions } from './permissions.js'
|
|
6
6
|
|
|
7
7
|
const DEFAULT_WAIT_MS = 30_000
|
|
8
8
|
const MAX_WAIT_MS = 300_000
|
|
@@ -438,7 +438,20 @@ export class QQCore {
|
|
|
438
438
|
this.store.retireSession(scene, row.sessionId)
|
|
439
439
|
row = this.store.getScene(scene)
|
|
440
440
|
} else {
|
|
441
|
-
|
|
441
|
+
// A matching permission/workspace fingerprint does not prove the Host
|
|
442
|
+
// still knows this Session. Only an explicit false means missing; null
|
|
443
|
+
// (older Host mock without a lookup API) keeps prior behavior, while
|
|
444
|
+
// errors propagate and never trigger an identity rebuild.
|
|
445
|
+
const exists = typeof this.dsh.sessionExists === 'function'
|
|
446
|
+
? await this.dsh.sessionExists(row.sessionId)
|
|
447
|
+
: null
|
|
448
|
+
if (exists !== false) return row.sessionId
|
|
449
|
+
if (typeof this.dsh.cancelSceneSession !== 'function') throw new Error('QQ_SESSION_CANCEL_UNAVAILABLE')
|
|
450
|
+
const cancelled = await this.dsh.cancelSceneSession(row.sessionId)
|
|
451
|
+
if (cancelled?.accepted !== true) throw new Error('QQ_SESSION_CANCEL_FAILED')
|
|
452
|
+
this.#releaseWaiter(scene, row.sessionId)
|
|
453
|
+
this.store.retireSession(scene, row.sessionId)
|
|
454
|
+
row = this.store.getScene(scene)
|
|
442
455
|
}
|
|
443
456
|
}
|
|
444
457
|
const revision = this.#permissionRevision(row ?? {})
|
|
@@ -446,6 +459,7 @@ export class QQCore {
|
|
|
446
459
|
const created = await this.dsh.createSceneSession(scene, {
|
|
447
460
|
searchAllowed: this.#can(scene, 'dsh.search'),
|
|
448
461
|
mediaAllowed: this.#can(scene, 'qq.media.read'),
|
|
462
|
+
lifeAllowed: this.#can(scene, LIFE_READ_CAPABILITY),
|
|
449
463
|
ownerAgent: scene.kind === 'private' &&
|
|
450
464
|
this.permissions.ownerPrivateIds.has(scene.peerId) &&
|
|
451
465
|
this.permissions.evaluate(scene, this.store.getScenePermissions(scene), 'qq.read').mode === 'owner-agent',
|
|
@@ -622,8 +636,10 @@ export class QQCore {
|
|
|
622
636
|
const segments = validateOutgoingSegments(args.segments)
|
|
623
637
|
for (const segment of segments) {
|
|
624
638
|
if (segment.type === 'reply') {
|
|
625
|
-
const target = this.store.getScene(row).messages.
|
|
626
|
-
if (!target
|
|
639
|
+
const target = this.store.getScene(row).messages.some(item => item.messageId === segment.data.id)
|
|
640
|
+
if (!target && !this.store.hasDelivered(row, segment.data.id)) {
|
|
641
|
+
throw new Error('QQ_REPLY_SCOPE: reply target is not in this scene')
|
|
642
|
+
}
|
|
627
643
|
}
|
|
628
644
|
if (segment.type === 'at') {
|
|
629
645
|
if (row.kind !== 'group' || !this.store.getScene(row).messages.some(item => item.senderId === segment.data.qq)) {
|
|
@@ -890,3 +906,4 @@ export class QQCore {
|
|
|
890
906
|
this.transport.stop?.()
|
|
891
907
|
}
|
|
892
908
|
}
|
|
909
|
+
|