dsh-long-plugins 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/client/client.js +270 -65
- package/dsh.plugin.json +1 -1
- package/lib/index.js +36 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,6 +124,33 @@ MIT
|
|
|
124
124
|
|
|
125
125
|
## Changelog / 更新记录
|
|
126
126
|
|
|
127
|
+
### v2.2.1
|
|
128
|
+
|
|
129
|
+
修复输入框实底、浅色主题可读性问题,并为输入框、背景罩新增浅色/深色主题的分套设置。
|
|
130
|
+
|
|
131
|
+
🐛 Bug 修复
|
|
132
|
+
|
|
133
|
+
- 输入框实底跟随主题:此前用操作系统深色偏好判断,导致浅色主题下黑底黑字。改为读取 DSH 真实主题(`<html>` 上的 `color-scheme`),浅色 = 白底深字、深色 = 深底浅字,切换主题自动实时重算。
|
|
134
|
+
- 浅色主题可读性:统一桌面浅色下,气泡、工具调用名(Bash 等)、推理(think)标签、底部状态/统计行文字在背景图上过浅看不清。已按主题提高对比度并加描边;状态/统计行改用稳定的 `data-slot` 槽位定位(不再依赖会变的混淆类名),提高升级稳定性。
|
|
135
|
+
|
|
136
|
+
✨ 新增功能
|
|
137
|
+
|
|
138
|
+
- 输入框设置(设置面板新增"输入框"区):浅色主题、深色主题可分别设置背景颜色与不透明度,支持一键"恢复原生"。
|
|
139
|
+
- 背景罩设置(设置面板新增"背景罩"区):浅色主题、深色主题可分别设置罩色与罩强度,切换主题自动应用对应的一套。
|
|
140
|
+
|
|
141
|
+
🎨 视觉 / 交互
|
|
142
|
+
|
|
143
|
+
- 左栏「新会话」按钮去掉白/黑实底边框,文字改为跟随侧边栏的白字+描边,更好融入背景。
|
|
144
|
+
|
|
145
|
+
### v2.2.0
|
|
146
|
+
|
|
147
|
+
界面优化与重构
|
|
148
|
+
|
|
149
|
+
- 背景图独立层:背景图改为独立图层,新增「背景图模糊 / 背景图透明度」滑杆(单独一组,不影响磨砂卡),并新增「背景罩层颜色」色盘,背景图可模糊、可调透明度、罩色可选。
|
|
150
|
+
- 会话区:去掉会话区独立磨砂卡片,直接透出共享背景(背景图 + 罩层颜色 + 模糊),版面更通透。
|
|
151
|
+
- 输入区:整个输入区外围(composer 根/位置座)透明透出背景。
|
|
152
|
+
- 可读性:浅色主题下弱化标签/元信息文字加深,对比度更高。
|
|
153
|
+
|
|
127
154
|
### v2.1.0
|
|
128
155
|
- 增强:毛玻璃界面(玻璃拟态)进一步打磨。
|
|
129
156
|
- 主题感知磨砂:磨砂卡片颜色跟随系统深色/浅色主题自动反转(浅色=白磨砂深字 / 深色=深磨砂浅字)。
|
package/client/client.js
CHANGED
|
@@ -3053,22 +3053,38 @@ window.__ModuleLoader__.load({
|
|
|
3053
3053
|
backdrop-filter: none;
|
|
3054
3054
|
-webkit-backdrop-filter: none;
|
|
3055
3055
|
}
|
|
3056
|
+
/* 左栏顶部「新会话」按钮:去掉白/黑实底与边框,透出背景图;文字跟侧边栏一致(白+描边) */
|
|
3057
|
+
html[data-dsh-glass="on"] #root [class*="newSession"] {
|
|
3058
|
+
background-color: transparent !important;
|
|
3059
|
+
background-image: none !important;
|
|
3060
|
+
border: none !important;
|
|
3061
|
+
border-radius: 0 !important;
|
|
3062
|
+
box-shadow: none !important;
|
|
3063
|
+
backdrop-filter: none !important;
|
|
3064
|
+
-webkit-backdrop-filter: none !important;
|
|
3065
|
+
color: #ffffff !important;
|
|
3066
|
+
text-shadow: 0 1px 3px rgba(0,0,0,.85);
|
|
3067
|
+
}
|
|
3056
3068
|
/* 左栏内部根 / 底部容器也用透明(这些是 DSH 当前版本哈希类名;背景图要透到左栏与底部) */
|
|
3057
3069
|
html[data-dsh-glass="on"] #root [class*="hHd-Xa_root"],
|
|
3058
3070
|
html[data-dsh-glass="on"] #root [class*="FJxK0a_root"] {
|
|
3059
3071
|
background-color: transparent !important;
|
|
3060
3072
|
}
|
|
3061
|
-
/*
|
|
3073
|
+
/* 会话滚动区:去掉独立磨砂卡片,直接透出共享背景(背景图+罩层颜色+模糊) */
|
|
3062
3074
|
html[data-dsh-glass="on"] #root [class*="wSkVaW_scrollBody"] {
|
|
3063
|
-
background:
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3075
|
+
background-color: transparent !important;
|
|
3076
|
+
background-image: none !important;
|
|
3077
|
+
backdrop-filter: none !important;
|
|
3078
|
+
-webkit-backdrop-filter: none !important;
|
|
3079
|
+
border-radius: 0 !important;
|
|
3080
|
+
box-shadow: none !important;
|
|
3067
3081
|
overflow: auto;
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3082
|
+
width: 100% !important;
|
|
3083
|
+
max-width: none !important;
|
|
3084
|
+
margin: 0 !important;
|
|
3071
3085
|
}
|
|
3086
|
+
/* 背景图独立层:铺满整页、位于内容之下,可单独设背景图模糊与透明度,不影响内容清晰度 */
|
|
3087
|
+
.dsh-glass-bgimg{position:fixed;inset:0;z-index:-1;pointer-events:none;background-size:cover;background-position:center;background-repeat:no-repeat;display:none;}
|
|
3072
3088
|
/* 滚动条:细、半透明、圆角,且左移贴在内容区(不占卡片最右边缘),让右边缘过渡柔和 */
|
|
3073
3089
|
html[data-dsh-glass="on"] #root [class*="wSkVaW_scrollBody"]::-webkit-scrollbar { width: 8px; }
|
|
3074
3090
|
html[data-dsh-glass="on"] #root [class*="wSkVaW_scrollBody"]::-webkit-scrollbar-track { background: transparent; }
|
|
@@ -3083,22 +3099,66 @@ window.__ModuleLoader__.load({
|
|
|
3083
3099
|
border-radius: 0 !important;
|
|
3084
3100
|
box-shadow: none !important;
|
|
3085
3101
|
}
|
|
3086
|
-
/*
|
|
3087
|
-
html[data-dsh-glass="on"]
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
-
|
|
3102
|
+
/* 输入区外围(composerSeat/uV2eYG_root)透明,白块去掉、透出背景 */
|
|
3103
|
+
html[data-dsh-glass="on"] [class*="wSkVaW_composerSeat"],
|
|
3104
|
+
html[data-dsh-glass="on"] [class*="uV2eYG_root"] {
|
|
3105
|
+
background-color: transparent !important;
|
|
3106
|
+
background-image: none !important;
|
|
3107
|
+
box-shadow: none !important;
|
|
3108
|
+
backdrop-filter: none !important;
|
|
3109
|
+
-webkit-backdrop-filter: none !important;
|
|
3110
|
+
}
|
|
3111
|
+
/* 输入框盒子(uV2eYG_card):实底(浅色=白/深色=深)并在背景图之上,文字随主题,保证可读。
|
|
3112
|
+
加 #root 提高优先级,压过 DSH 自身把 card 背景设透明的规则 */
|
|
3113
|
+
html[data-dsh-glass="on"] #root [class*="uV2eYG_card"],
|
|
3114
|
+
html[data-dsh-glass="on"] [class*="uV2eYG_card"] {
|
|
3115
|
+
position: relative !important;
|
|
3116
|
+
z-index: 0 !important;
|
|
3117
|
+
background-color: #ffffff !important;
|
|
3118
|
+
background-image: none !important;
|
|
3119
|
+
color: #1a2332 !important;
|
|
3120
|
+
box-shadow: none !important;
|
|
3121
|
+
backdrop-filter: none !important;
|
|
3122
|
+
-webkit-backdrop-filter: none !important;
|
|
3123
|
+
}
|
|
3124
|
+
@media (prefers-color-scheme: dark) {
|
|
3125
|
+
html[data-dsh-glass="on"] #root [class*="uV2eYG_card"],
|
|
3126
|
+
html[data-dsh-glass="on"] [class*="uV2eYG_card"] { background: #1c2530 !important; color: #f5f7fa !important; }
|
|
3091
3127
|
}
|
|
3128
|
+
/* 轮次/历史提问预览:默认隐藏(点开才显示),并去掉头部底色,避免底部露出白条 */
|
|
3129
|
+
.dsh-turn-preview:not(.open){display:none !important;}
|
|
3130
|
+
.dsh-turn-preview-head{background:transparent !important;}
|
|
3092
3131
|
|
|
3093
3132
|
html[data-dsh-glass="off"] #root [class*="sidebarCol"],
|
|
3094
3133
|
html[data-dsh-glass="off"] #root [class*="header"],
|
|
3095
3134
|
html[data-dsh-glass="off"] #root [class*="centerCol"],
|
|
3096
3135
|
html[data-dsh-glass="off"] #root [class*="wSkVaW_root"],
|
|
3097
|
-
html[data-dsh-glass="off"] #root [class*="wSkVaW_scrollBody"]
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3136
|
+
html[data-dsh-glass="off"] #root [class*="wSkVaW_scrollBody"] { background-color: transparent !important; backdrop-filter: none; }
|
|
3137
|
+
/* 会话消息气泡:半透明底(随主题, 60%透明=40%不透明),与 AI 消息(透明/磨砂)区分、融入背景 */
|
|
3138
|
+
html[data-dsh-glass="on"] #root [class*="_bubble"]:not([class*="button"]) {
|
|
3139
|
+
background-color: color-mix(in srgb, var(--dsw-specific-input-major, #e8edf3) 40%, transparent) !important;
|
|
3140
|
+
}
|
|
3141
|
+
/* 统一桌面 + 浅色主题:DSH 的 secondary/tertiary 文字在浅色磨砂上太浅,统一加深,覆盖状态栏/工具标签等 */
|
|
3142
|
+
html[data-dsh-glass="on"][data-dsh-theme="light"] {
|
|
3143
|
+
--dsw-alias-label-secondary: #33414f !important;
|
|
3144
|
+
--dsw-alias-label-tertiary: #4a5866 !important;
|
|
3145
|
+
}
|
|
3146
|
+
/* 工具调用名(Bash/Shell等)与推理(think)标签:浅色下再显式压深,保证可读 */
|
|
3147
|
+
html[data-dsh-glass="on"][data-dsh-theme="light"] #root [class*="CY-8Ka_title"],
|
|
3148
|
+
html[data-dsh-glass="on"][data-dsh-theme="light"] #root [class*="QWLzLg_title"] {
|
|
3149
|
+
color: #2f3d4a !important;
|
|
3150
|
+
}
|
|
3151
|
+
/* 输入框下方状态/统计行(余额+步数/时长/速度等)都在 composer.dock 这个稳定 data 槽里:
|
|
3152
|
+
混淆类名会变, 改用 data 属性锁定, 按主题给高对比色+描边, 保证在背景图上可读 */
|
|
3153
|
+
html[data-dsh-glass="on"][data-dsh-theme="light"] [data-slot-conversation="conversation.composer.dock"],
|
|
3154
|
+
html[data-dsh-glass="on"][data-dsh-theme="light"] [data-slot-conversation="conversation.composer.dock"] * {
|
|
3155
|
+
color: #243240 !important;
|
|
3156
|
+
text-shadow: 0 1px 2px rgba(255,255,255,.5);
|
|
3157
|
+
}
|
|
3158
|
+
html[data-dsh-glass="on"][data-dsh-theme="dark"] [data-slot-conversation="conversation.composer.dock"],
|
|
3159
|
+
html[data-dsh-glass="on"][data-dsh-theme="dark"] [data-slot-conversation="conversation.composer.dock"] * {
|
|
3160
|
+
color: #e8edf3 !important;
|
|
3161
|
+
text-shadow: 0 1px 2px rgba(0,0,0,.6);
|
|
3102
3162
|
}
|
|
3103
3163
|
/* 会话区所有内容元素背景透明化:去掉"反底色"小块衬底,统一融入磨砂卡片 */
|
|
3104
3164
|
html[data-dsh-glass="on"] #root [class*="wSkVaW_scrollBody"] *:not([class*="button"]):not([class*="bubble"]):not([class*="_menu"]) {
|
|
@@ -3113,10 +3173,6 @@ window.__ModuleLoader__.load({
|
|
|
3113
3173
|
html[data-dsh-glass="on"] #root [class*="wSkVaW_scrollBody"] [class*="md-code-block"] {
|
|
3114
3174
|
background-color: transparent !important;
|
|
3115
3175
|
}
|
|
3116
|
-
/* uV2eYG_add: composer 里随内容变化的白色衬底,玻璃开启时透明化 */
|
|
3117
|
-
html[data-dsh-glass="on"] #root [class*="uV2eYG_add"] {
|
|
3118
|
-
background-color: transparent !important;
|
|
3119
|
-
}
|
|
3120
3176
|
/* 输入框下拉/悬浮菜单(如 / 命令、@ 提及):背景给不透明随主题色,避免叠在会话磨砂卡上重叠看不清 */
|
|
3121
3177
|
html[data-dsh-glass="on"] #root [class*="_menu"][class*="_menu"][class*="_menu"][class*="_menu"] {
|
|
3122
3178
|
background-color: var(--dsw-specific-input-major, #e8edf3) !important;
|
|
@@ -3137,6 +3193,14 @@ window.__ModuleLoader__.load({
|
|
|
3137
3193
|
backdrop-filter: none !important;
|
|
3138
3194
|
-webkit-backdrop-filter: none !important;
|
|
3139
3195
|
}
|
|
3196
|
+
/* 玻璃开启 + 浅色系统主题:加深弱化标签/元信息文字,避免浅灰字叠在浅磨砂卡上看不清 */
|
|
3197
|
+
@media (prefers-color-scheme: light) {
|
|
3198
|
+
html[data-dsh-glass="on"],
|
|
3199
|
+
html[data-dsh-glass="on"] * {
|
|
3200
|
+
--dsw-alias-label-secondary: #383d44 !important;
|
|
3201
|
+
--dsw-alias-label-tertiary: #50545b !important;
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3140
3204
|
.dsh-glass-section{display:flex;flex-direction:column;gap:16px;min-width:0;padding:4px 2px 24px;color:var(--dsw-alias-label-primary)}
|
|
3141
3205
|
.dsh-glass-head{display:flex;align-items:center;justify-content:space-between;gap:16px}
|
|
3142
3206
|
.dsh-glass-head h2{margin:0;font-size:20px;line-height:28px}
|
|
@@ -3145,6 +3209,9 @@ window.__ModuleLoader__.load({
|
|
|
3145
3209
|
.dsh-glass-switch input{width:34px;height:20px;accent-color:var(--dsw-alias-state-business-primary);cursor:pointer}
|
|
3146
3210
|
.dsh-glass-card{display:grid;gap:12px;padding:14px 16px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-specific-input-major)}
|
|
3147
3211
|
.dsh-glass-zone-title{font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary)}
|
|
3212
|
+
.dsh-glass-input-theme{border-top:1px dashed var(--dsw-alias-border-l2);padding-top:12px;display:grid;gap:12px}
|
|
3213
|
+
.dsh-glass-input-theme:first-of-type{border-top:none;padding-top:0}
|
|
3214
|
+
.dsh-glass-theme-label{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary)}
|
|
3148
3215
|
.dsh-glass-row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
|
|
3149
3216
|
.dsh-glass-row label{font-size:13px;color:var(--dsw-alias-label-primary);flex:none}
|
|
3150
3217
|
.dsh-glass-range{flex:1;min-width:160px;max-width:320px;accent-color:var(--dsw-alias-state-business-primary)}
|
|
@@ -3165,7 +3232,7 @@ window.__ModuleLoader__.load({
|
|
|
3165
3232
|
.dsh-glass-error{padding:10px 12px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);font-size:12px}
|
|
3166
3233
|
.dsh-glass-note{margin:0;font-size:12px;color:var(--dsw-alias-label-tertiary)}
|
|
3167
3234
|
`
|
|
3168
|
-
const GLASS_SWATCHES = ['#
|
|
3235
|
+
const GLASS_SWATCHES = ['#1a2332', '#0f1420', '#1e3a5f', '#1e5e46', '#5e2e5e', '#6e2323']
|
|
3169
3236
|
const glassText = (e) => (e && e.message) ? e.message : String(e)
|
|
3170
3237
|
function glassImageInput(value, onChange) {
|
|
3171
3238
|
return React.createElement('label', { className: 'dsh-glass-file' },
|
|
@@ -3222,16 +3289,37 @@ window.__ModuleLoader__.load({
|
|
|
3222
3289
|
React.useEffect(() => { load(); }, [load])
|
|
3223
3290
|
const patch = React.useCallback((p) => setState((s) => ({ ...s, cfg: { ...(s.cfg || {}), ...p } })), [])
|
|
3224
3291
|
const patchZone = React.useCallback((key, p) => setState((s) => ({ ...s, cfg: { ...(s.cfg || {}), [key]: p } })), [])
|
|
3292
|
+
// 输入框设置:按主题(theme)合并进 cfg.inputBox[theme](不整体覆盖、不丢另一主题)
|
|
3293
|
+
const patchInput = React.useCallback((theme, p) => setState((s) => {
|
|
3294
|
+
const box = { light: { color: '', opacity: 1 }, dark: { color: '', opacity: 1 }, ...((s.cfg && s.cfg.inputBox) || {}) }
|
|
3295
|
+
box[theme] = { ...((box[theme]) || { color: '', opacity: 1 }), ...p }
|
|
3296
|
+
return { ...s, cfg: { ...(s.cfg || {}), inputBox: box } }
|
|
3297
|
+
}), [])
|
|
3298
|
+
// 背景罩设置:按主题合并进 cfg.bgTint[theme]
|
|
3299
|
+
const patchBgTint = React.useCallback((theme, p) => setState((s) => {
|
|
3300
|
+
const box = { light: { color: '#1a2332', mask: 0.28 }, dark: { color: '#1a2332', mask: 0.28 }, ...((s.cfg && s.cfg.bgTint) || {}) }
|
|
3301
|
+
box[theme] = { ...((box[theme]) || { color: '#1a2332', mask: 0.28 }), ...p }
|
|
3302
|
+
return { ...s, cfg: { ...(s.cfg || {}), bgTint: box } }
|
|
3303
|
+
}), [])
|
|
3225
3304
|
const save = React.useCallback(async () => {
|
|
3226
3305
|
setState((s) => ({ ...s, saving: true, error: '' }))
|
|
3227
3306
|
try {
|
|
3228
3307
|
const cfg = state.cfg || {}
|
|
3308
|
+
const num = (v, fb) => ((typeof v === 'number' && Number.isFinite(v) && v >= 0) ? v : fb)
|
|
3229
3309
|
const payload = {
|
|
3230
|
-
enabled: !!cfg.enabled, blur:
|
|
3231
|
-
bgImage: state.bgImage || cfg.bgImage || '', bgMask:
|
|
3310
|
+
enabled: !!cfg.enabled, blur: num(cfg.blur, 0),
|
|
3311
|
+
bgImage: state.bgImage || cfg.bgImage || '', bgMask: num(cfg.bgMask, 0.28), bgColor: cfg.bgColor || '#1a2332', bgBlur: num(cfg.bgBlur, 0), bgOpacity: num(cfg.bgOpacity, 1),
|
|
3312
|
+
bgTint: {
|
|
3313
|
+
light: { color: (cfg.bgTint?.light?.color) || '#1a2332', mask: num(cfg.bgTint?.light?.mask, 0.28) },
|
|
3314
|
+
dark: { color: (cfg.bgTint?.dark?.color) || '#1a2332', mask: num(cfg.bgTint?.dark?.mask, 0.28) },
|
|
3315
|
+
},
|
|
3316
|
+
inputBox: {
|
|
3317
|
+
light: { color: (cfg.inputBox?.light?.color) || '', opacity: num(cfg.inputBox?.light?.opacity, 1) },
|
|
3318
|
+
dark: { color: (cfg.inputBox?.dark?.color) || '', opacity: num(cfg.inputBox?.dark?.opacity, 1) },
|
|
3319
|
+
},
|
|
3232
3320
|
zone: {
|
|
3233
|
-
session: { enabled: cfg.session && cfg.session.enabled !== false, color: (cfg.session && cfg.session.color) || '#1a2332', mask:
|
|
3234
|
-
input: { color: (cfg.input && cfg.input.color) || '#1a2332', mask:
|
|
3321
|
+
session: { enabled: cfg.session && cfg.session.enabled !== false, color: (cfg.session && cfg.session.color) || '#1a2332', mask: num(cfg.session && cfg.session.mask, 0.45), opacity: num(cfg.session && cfg.session.opacity, 0.5) },
|
|
3322
|
+
input: { color: (cfg.input && cfg.input.color) || '#1a2332', mask: num(cfg.input && cfg.input.mask, 0.6), opacity: num(cfg.input && cfg.input.opacity, 0.55) },
|
|
3235
3323
|
},
|
|
3236
3324
|
}
|
|
3237
3325
|
const r = await fetch('/api/dsh-uploads/glass-config', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(payload) })
|
|
@@ -3245,7 +3333,7 @@ window.__ModuleLoader__.load({
|
|
|
3245
3333
|
if (state.loading) return React.createElement('div', { className: 'dsh-glass-section' }, '加载中…')
|
|
3246
3334
|
return React.createElement('div', { className: 'dsh-glass-section' },
|
|
3247
3335
|
React.createElement('div', { className: 'dsh-glass-head' },
|
|
3248
|
-
React.createElement('div', null, React.createElement('h2', null, '
|
|
3336
|
+
React.createElement('div', null, React.createElement('h2', null, 'RA-Span'), React.createElement('p', null, '共用一张背景图铺满整页(RA-Span):背景图、背景罩层颜色、背景模糊/透明度可调;会话区/输入区按需透明或实底。')),
|
|
3249
3337
|
React.createElement('label', { className: 'dsh-glass-switch' }, React.createElement('input', { type: 'checkbox', checked: !!cfg.enabled, onChange: (e) => patch({ enabled: e.target.checked }) }), cfg.enabled ? '已开启' : '已关闭'),
|
|
3250
3338
|
),
|
|
3251
3339
|
state.error ? React.createElement('div', { className: 'dsh-glass-error' }, state.error) : null,
|
|
@@ -3255,18 +3343,60 @@ window.__ModuleLoader__.load({
|
|
|
3255
3343
|
React.createElement('input', { type: 'range', className: 'dsh-glass-range', min: 0, max: 80, value: cfg.blur ?? 20, onChange: (e) => patch({ blur: Number(e.target.value) }) }),
|
|
3256
3344
|
React.createElement('span', { className: 'dsh-glass-val' }, `${Number(cfg.blur ?? 20)} px`),
|
|
3257
3345
|
),
|
|
3258
|
-
React.createElement(GlassZoneCard, { title: '会话区', zone: cfg.session, onChange: (p) => patchZone('session', p), showGlassToggle: true }),
|
|
3259
|
-
React.createElement(GlassZoneCard, { title: '输入区', zone: cfg.input, onChange: (p) => patchZone('input', p) }),
|
|
3260
3346
|
React.createElement('div', { className: 'dsh-glass-row' },
|
|
3261
3347
|
React.createElement('label', null, '共用背景图'),
|
|
3262
3348
|
React.createElement('div', { className: 'dsh-glass-bg' }, glassImageInput(state.bgImage, (v) => setState((s) => ({ ...s, bgImage: v })))),
|
|
3263
3349
|
),
|
|
3350
|
+
React.createElement('div', { className: 'dsh-glass-card' },
|
|
3351
|
+
React.createElement('div', { className: 'dsh-glass-zone-title' }, '背景罩'),
|
|
3352
|
+
[['light', '浅色主题', '#1a2332'], ['dark', '深色主题', '#1a2332']].map(([t, label, native]) => {
|
|
3353
|
+
const bt = (cfg.bgTint && cfg.bgTint[t]) || { color: native, mask: 0.28 }
|
|
3354
|
+
return React.createElement('div', { key: t, className: 'dsh-glass-input-theme' },
|
|
3355
|
+
React.createElement('div', { className: 'dsh-glass-theme-label' }, label),
|
|
3356
|
+
React.createElement('div', { className: 'dsh-glass-row' },
|
|
3357
|
+
React.createElement('label', null, '罩色'),
|
|
3358
|
+
React.createElement('label', { className: 'dsh-glass-colorpicker' }, '色盘', React.createElement('input', { type: 'color', value: bt.color || native, onChange: (e) => patchBgTint(t, { color: e.target.value }) })),
|
|
3359
|
+
),
|
|
3360
|
+
React.createElement('div', { className: 'dsh-glass-row' },
|
|
3361
|
+
React.createElement('label', null, '罩强度'),
|
|
3362
|
+
React.createElement('input', { type: 'range', className: 'dsh-glass-range', min: 0, max: 0.95, step: 0.01, value: (typeof bt.mask === 'number') ? bt.mask : 0.28, onChange: (e) => patchBgTint(t, { mask: Number(e.target.value) }) }),
|
|
3363
|
+
React.createElement('span', { className: 'dsh-glass-val' }, `${Math.round((typeof bt.mask === 'number' ? bt.mask : 0.28) * 100)}%`),
|
|
3364
|
+
),
|
|
3365
|
+
)
|
|
3366
|
+
}),
|
|
3367
|
+
React.createElement('p', { className: 'dsh-glass-note' }, '浅色主题与深色主题可分别设置背景罩颜色与罩强度,切换主题时自动应用对应的一套。'),
|
|
3368
|
+
),
|
|
3264
3369
|
React.createElement('div', { className: 'dsh-glass-row' },
|
|
3265
|
-
React.createElement('label', null, '
|
|
3266
|
-
React.createElement('input', { type: 'range', className: 'dsh-glass-range', min: 0, max:
|
|
3267
|
-
React.createElement('span', { className: 'dsh-glass-val' }, `${
|
|
3370
|
+
React.createElement('label', null, '背景图模糊'),
|
|
3371
|
+
React.createElement('input', { type: 'range', className: 'dsh-glass-range', min: 0, max: 60, value: cfg.bgBlur ?? 0, onChange: (e) => patch({ bgBlur: Number(e.target.value) }) }),
|
|
3372
|
+
React.createElement('span', { className: 'dsh-glass-val' }, `${Number(cfg.bgBlur ?? 0)} px`),
|
|
3268
3373
|
),
|
|
3269
|
-
React.createElement('
|
|
3374
|
+
React.createElement('div', { className: 'dsh-glass-row' },
|
|
3375
|
+
React.createElement('label', null, '背景图透明度'),
|
|
3376
|
+
React.createElement('input', { type: 'range', className: 'dsh-glass-range', min: 0, max: 1, step: 0.01, value: cfg.bgOpacity ?? 1, onChange: (e) => patch({ bgOpacity: Number(e.target.value) }) }),
|
|
3377
|
+
React.createElement('span', { className: 'dsh-glass-val' }, `${Math.round((Number(cfg.bgOpacity ?? 1)) * 100)}%`),
|
|
3378
|
+
),
|
|
3379
|
+
React.createElement('div', { className: 'dsh-glass-card' },
|
|
3380
|
+
React.createElement('div', { className: 'dsh-glass-zone-title' }, '输入框'),
|
|
3381
|
+
[['light', '浅色主题', '#ffffff'], ['dark', '深色主题', '#1c2530']].map(([t, label, native]) => {
|
|
3382
|
+
const tb = (cfg.inputBox && cfg.inputBox[t]) || { color: '', opacity: 1 }
|
|
3383
|
+
return React.createElement('div', { key: t, className: 'dsh-glass-input-theme' },
|
|
3384
|
+
React.createElement('div', { className: 'dsh-glass-theme-label' }, label),
|
|
3385
|
+
React.createElement('div', { className: 'dsh-glass-row' },
|
|
3386
|
+
React.createElement('label', null, '输入框颜色'),
|
|
3387
|
+
React.createElement('label', { className: 'dsh-glass-colorpicker' }, '色盘', React.createElement('input', { type: 'color', value: tb.color || native, onChange: (e) => patchInput(t, { color: e.target.value }) })),
|
|
3388
|
+
React.createElement('button', { type: 'button', style: { marginLeft: 8, fontSize: 12 }, onClick: () => patchInput(t, { color: '', opacity: 1 }) }, '原生'),
|
|
3389
|
+
),
|
|
3390
|
+
React.createElement('div', { className: 'dsh-glass-row' },
|
|
3391
|
+
React.createElement('label', null, '不透明度'),
|
|
3392
|
+
React.createElement('input', { type: 'range', className: 'dsh-glass-range', min: 0, max: 1, step: 0.01, value: (typeof tb.opacity === 'number') ? tb.opacity : 1, onChange: (e) => patchInput(t, { opacity: Number(e.target.value) }) }),
|
|
3393
|
+
React.createElement('span', { className: 'dsh-glass-val' }, `${Math.round((typeof tb.opacity === 'number' ? tb.opacity : 1) * 100)}%`),
|
|
3394
|
+
),
|
|
3395
|
+
)
|
|
3396
|
+
}),
|
|
3397
|
+
React.createElement('p', { className: 'dsh-glass-note' }, '浅色主题与深色主题可分别设置。100% = 实底不透明,越低越透出背景图;"原生" = 跟随该主题的 DSH 原生色。文字颜色按背景亮度自动配深/浅,保证可读。'),
|
|
3398
|
+
),
|
|
3399
|
+
React.createElement('p', { className: 'dsh-glass-note' }, '提示:背景图铺满整页(可加背景图罩);背景图模糊/透明度单独可调;会话区使用自己的罩色、罩强度与透明度;左栏/顶部透出背景图;输入框颜色/不透明度可单独设置。'),
|
|
3270
3400
|
React.createElement('div', { className: 'dsh-glass-actions' },
|
|
3271
3401
|
React.createElement('button', { type: 'button', onClick: load }, '重置'),
|
|
3272
3402
|
React.createElement('button', { type: 'button', className: 'primary', disabled: state.saving, onClick: save }, state.saving ? '保存中…' : '保存生效'),
|
|
@@ -3302,6 +3432,15 @@ window.__ModuleLoader__.load({
|
|
|
3302
3432
|
}
|
|
3303
3433
|
window.addEventListener('resize', centerScroll)
|
|
3304
3434
|
window.__dshGlassCenter = centerScroll
|
|
3435
|
+
// 主题切换监听:观察 <html> 的 style/class;只创建一次(自触发的写入在 applyTheme 内先断开再重连,杜绝死循环)
|
|
3436
|
+
window.__dshGlassStyleObs = null
|
|
3437
|
+
if (!window.__dshGlassStyleObs) {
|
|
3438
|
+
window.__dshGlassStyleObs = new MutationObserver(() => window.__dshGlassApplyTheme && window.__dshGlassApplyTheme())
|
|
3439
|
+
window.__dshGlassStyleObs.observe(document.documentElement, { attributes: true, attributeFilter: ['style', 'class'] })
|
|
3440
|
+
}
|
|
3441
|
+
const themeMq = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)')
|
|
3442
|
+
const themeMqHandler = () => window.__dshGlassApplyTheme && window.__dshGlassApplyTheme()
|
|
3443
|
+
if (themeMq) themeMq.addEventListener('change', themeMqHandler)
|
|
3305
3444
|
// win 风格文字:给左栏/顶栏内的可见文字元素加白色+深色描边;跳过弹窗(modal/overlay/dialog/settings/panel)内元素。
|
|
3306
3445
|
|
|
3307
3446
|
window.__dshGlassApply = (cfg) => {
|
|
@@ -3318,60 +3457,126 @@ window.__ModuleLoader__.load({
|
|
|
3318
3457
|
b.style.backgroundImage = 'none'; b.style.backgroundSize = ''; b.style.backgroundPosition = ''; b.style.backgroundRepeat = ''
|
|
3319
3458
|
const fr = document.querySelector('#root > div > div') || document.querySelector('#root > div')
|
|
3320
3459
|
if (fr) { fr.style.backgroundColor = ''; fr.style.backgroundImage = 'none'; fr.style.backgroundSize = ''; fr.style.backgroundPosition = ''; fr.style.backgroundRepeat = '' }
|
|
3460
|
+
const bgEl = document.querySelector('.dsh-glass-bgimg'); if (bgEl) { bgEl.style.display = 'none' }
|
|
3321
3461
|
return
|
|
3322
3462
|
}
|
|
3463
|
+
// 读 DSH 真实主题(DSH 用 inline `color-scheme` 写在 <html style> 上,非 OS 偏好)
|
|
3464
|
+
const dshDark = () => /dark/i.test(getComputedStyle(document.documentElement).colorScheme)
|
|
3465
|
+
// 颜色亮度(0~1):用来自动决定文字用深色还是浅色,保证可读
|
|
3466
|
+
const relLum = (hex) => {
|
|
3467
|
+
const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(String(hex || ''))
|
|
3468
|
+
if (!m) return 0.5
|
|
3469
|
+
const map = (v) => { const s = parseInt(v, 16) / 255; return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4) }
|
|
3470
|
+
return 0.2126 * map(m[1]) + 0.7152 * map(m[2]) + 0.0722 * map(m[3])
|
|
3471
|
+
}
|
|
3323
3472
|
root.setAttribute('data-dsh-glass', c.enabled ? 'on' : 'off')
|
|
3324
3473
|
const sessOn = !(c.zone && c.zone.session && c.zone.session.enabled === false)
|
|
3325
3474
|
root.setAttribute('data-dsh-session-glass', sessOn ? 'on' : 'off')
|
|
3326
|
-
const
|
|
3475
|
+
const blurn = Number(c.blur); const blur = Math.max(0, Math.min(80, Number.isFinite(blurn) ? blurn : 16))
|
|
3327
3476
|
root.style.setProperty('--dsh-glass-blur', blur + 'px')
|
|
3328
3477
|
const zs = (c.zone && c.zone.session) || { color: '#1a2332', mask: 0.45, opacity: 0.5 }
|
|
3329
3478
|
const zi = (c.zone && c.zone.input) || { color: '#1a2332', mask: 0.6, opacity: 0.55 }
|
|
3330
|
-
|
|
3331
|
-
root.style.setProperty('--dsh-glass-
|
|
3332
|
-
const
|
|
3333
|
-
root.style.setProperty('--dsh-glass-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
const
|
|
3338
|
-
|
|
3339
|
-
|
|
3479
|
+
const smn = Number(zs.mask); const sm = Math.min(0.95, Math.max(0, Number.isFinite(smn) ? smn : 0.45))
|
|
3480
|
+
root.style.setProperty('--dsh-glass-session-bg', `rgba(${hexToRgb(zs.color)},${sm})`)
|
|
3481
|
+
const imn = Number(zi.mask); const im = Math.min(0.95, Math.max(0, Number.isFinite(imn) ? imn : 0.6))
|
|
3482
|
+
root.style.setProperty('--dsh-glass-input-bg', `rgba(${hexToRgb(zi.color)},${im})`)
|
|
3483
|
+
// 透明度=透明程度:越大越透明(100%=>雾面无填充,完全透出背景)
|
|
3484
|
+
const sop = Math.min(1, Math.max(0, Number.isFinite(Number(zs.opacity)) ? Number(zs.opacity) : 0.5))
|
|
3485
|
+
root.style.setProperty('--dsh-glass-session-white', `color-mix(in srgb, var(--dsw-specific-input-major, #e8edf3) ${Math.round((1 - sop) * 100)}%, transparent)`)
|
|
3486
|
+
const iop = Math.min(1, Math.max(0, Number.isFinite(Number(zi.opacity)) ? Number(zi.opacity) : 0.55))
|
|
3487
|
+
root.style.setProperty('--dsh-glass-input-white', `color-mix(in srgb, var(--dsw-specific-input-major, #e8edf3) ${Math.round((1 - iop) * 100)}%, transparent)`)
|
|
3488
|
+
|
|
3489
|
+
// 背景图罩(整页背景图上叠一层半透明罩色):浅/深主题各一套 color+mask;
|
|
3490
|
+
// 兼容旧版单套 bgColor/bgMask。
|
|
3491
|
+
const bgTint = (tk) => {
|
|
3492
|
+
const t = (c.bgTint && c.bgTint[tk]) || { color: c.bgColor || '#1a2332', mask: c.bgMask ?? 0.28 }
|
|
3493
|
+
const mask = Math.min(0.95, Math.max(0, Number.isFinite(Number(t && t.mask)) ? Number(t.mask) : 0.28))
|
|
3494
|
+
return { color: (t && t.color) || '#1a2332', mask }
|
|
3495
|
+
}
|
|
3496
|
+
// 给输入框卡片设内联实底+文字色,且用 !important,
|
|
3497
|
+
// 因为 DSH 核心样式用 background-color: transparent !important 压过普通内联样式;
|
|
3498
|
+
// 内联 !important 优先级最高,一定覆盖。颜色/不透明度来自配置 inputBox。
|
|
3499
|
+
const applyInputCard = () => {
|
|
3500
|
+
const inputCard = document.querySelector('#root [class*="uV2eYG_card"]')
|
|
3501
|
+
if (!inputCard) return
|
|
3502
|
+
const dark = dshDark()
|
|
3503
|
+
const ib = (c.inputBox && typeof c.inputBox === 'object') ? c.inputBox : {}
|
|
3504
|
+
// 浅色/深色各一套配置;兼容旧版单套 inputBox:{color,opacity}
|
|
3505
|
+
const tb = (ib.light && ib.dark) ? (dark ? ib.dark : ib.light) : ib
|
|
3506
|
+
const defBg = dark ? '#1c2530' : '#ffffff'
|
|
3507
|
+
// color: 空串/非法 => 用主题原生色;否则用用户指定的颜色
|
|
3508
|
+
const hasColor = tb && typeof tb.color === 'string' && /^#/.test(tb.color)
|
|
3509
|
+
const bgHex = hasColor ? tb.color : defBg
|
|
3510
|
+
const alpha = (tb && typeof tb.opacity === 'number' && Number.isFinite(tb.opacity)) ? Math.min(1, Math.max(0, tb.opacity)) : 1
|
|
3511
|
+
const bg = `rgba(${hexToRgb(bgHex)},${alpha})`
|
|
3512
|
+
const fg = relLum(bgHex) > 0.5 ? '#1a2332' : '#f5f7fa'
|
|
3513
|
+
inputCard.style.setProperty('background-color', bg, 'important')
|
|
3514
|
+
inputCard.style.setProperty('color', fg, 'important')
|
|
3515
|
+
// 子层(scroll/row)也是透明的,继承卡片文字色即可,确保可读
|
|
3516
|
+
inputCard.querySelectorAll('[class*="uV2eYG_scroll"],[class*="uV2eYG_row"]').forEach(el => {
|
|
3517
|
+
el.style.setProperty('color', fg, 'important')
|
|
3518
|
+
})
|
|
3519
|
+
}
|
|
3520
|
+
// 主题相关的东西统一重算:背景罩 + 输入框。切主题时由 observer/mq 触发。
|
|
3521
|
+
// 写入前先断开观察器,写完再重连,避免自触发造成死循环。
|
|
3522
|
+
const applyTheme = () => {
|
|
3523
|
+
const obs = window.__dshGlassStyleObs
|
|
3524
|
+
if (obs) obs.disconnect()
|
|
3525
|
+
try {
|
|
3526
|
+
const tk = dshDark() ? 'dark' : 'light'
|
|
3527
|
+
root.setAttribute('data-dsh-theme', tk)
|
|
3528
|
+
const bt = bgTint(tk)
|
|
3529
|
+
const v = `rgba(${hexToRgb(bt.color)},${bt.mask})`
|
|
3530
|
+
root.style.setProperty('--dsh-glass-bg-zone', v)
|
|
3531
|
+
applyInputCard()
|
|
3532
|
+
} finally {
|
|
3533
|
+
if (obs) obs.observe(document.documentElement, { attributes: true, attributeFilter: ['style', 'class'] })
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3340
3536
|
|
|
3341
3537
|
const body = document.body
|
|
3342
3538
|
const frame = document.querySelector('#root > div > div') || document.querySelector('#root > div')
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3539
|
+
// 背景图独立层:铺满整页、位于内容之下;背景图模糊/透明度单独可调(不影响内容清晰度)。
|
|
3540
|
+
// 背景罩用 CSS 变量 var(--dsh-glass-bg-zone),随主题切换自动刷新。
|
|
3541
|
+
let bgimg = document.querySelector('.dsh-glass-bgimg')
|
|
3542
|
+
if (!bgimg) { bgimg = document.createElement('div'); bgimg.className = 'dsh-glass-bgimg'; document.body.appendChild(bgimg) }
|
|
3543
|
+
const gzv = root.style.getPropertyValue('--dsh-glass-bg-zone') || 'rgba(26,35,50,0.28)'
|
|
3544
|
+
if (c.enabled && c.bgImage) {
|
|
3545
|
+
bgimg.style.display = 'block'
|
|
3546
|
+
bgimg.style.backgroundImage = `linear-gradient(var(--dsh-glass-bg-zone, ${gzv}), var(--dsh-glass-bg-zone, ${gzv})), url('${c.bgImage}')`
|
|
3547
|
+
bgimg.style.backgroundSize = 'cover'
|
|
3548
|
+
bgimg.style.backgroundPosition = 'center'
|
|
3549
|
+
bgimg.style.backgroundRepeat = 'no-repeat'
|
|
3550
|
+
const bblur = Math.max(0, Math.min(80, Number.isFinite(Number(c.bgBlur)) ? Number(c.bgBlur) : 0))
|
|
3551
|
+
bgimg.style.filter = bblur > 0 ? `blur(${bblur}px)` : 'none'
|
|
3552
|
+
const bop = Math.max(0, Math.min(1, Number.isFinite(Number(c.bgOpacity)) ? Number(c.bgOpacity) : 1))
|
|
3553
|
+
bgimg.style.opacity = String(bop)
|
|
3554
|
+
} else {
|
|
3555
|
+
bgimg.style.display = 'none'
|
|
3358
3556
|
}
|
|
3359
|
-
//
|
|
3557
|
+
// 移除 body/frame 上的锐利背景图(改由独立背景层显示),避免重复/遮盖
|
|
3558
|
+
body.style.backgroundImage = 'none'
|
|
3360
3559
|
if (c.enabled && c.bgImage) { body.style.backgroundColor = 'transparent' } else { body.style.backgroundColor = '' }
|
|
3361
|
-
|
|
3362
|
-
|
|
3560
|
+
if (frame) { frame.style.backgroundImage = 'none'; frame.style.backgroundColor = 'transparent' }
|
|
3561
|
+
|
|
3562
|
+
applyTheme()
|
|
3563
|
+
// 记录当前主题应用函数,供唯一观察器/mq 调用
|
|
3564
|
+
window.__dshGlassApplyTheme = applyTheme
|
|
3363
3565
|
centerScroll()
|
|
3364
3566
|
}
|
|
3365
3567
|
return () => {
|
|
3366
3568
|
window.__dshGlassApply = undefined
|
|
3367
3569
|
window.removeEventListener('resize', centerScroll)
|
|
3368
3570
|
window.__dshGlassCenter = undefined
|
|
3571
|
+
if (window.__dshGlassStyleObs) { window.__dshGlassStyleObs.disconnect(); window.__dshGlassStyleObs = null }
|
|
3572
|
+
if (themeMq) themeMq.removeEventListener('change', themeMqHandler)
|
|
3573
|
+
window.__dshGlassApplyTheme = undefined
|
|
3369
3574
|
}
|
|
3370
3575
|
}, 'dsh-long-plugins: glass applier')
|
|
3371
|
-
ctx.slots.inject('settings.section', () => ctx.slots.register({ name: 'settings.section', id: 'glass-ui', order: 40, label: '
|
|
3576
|
+
ctx.slots.inject('settings.section', () => ctx.slots.register({ name: 'settings.section', id: 'glass-ui', order: 40, label: 'RA-Span' }, GlassSettingsSection))
|
|
3372
3577
|
ctx.effect(() => {
|
|
3373
3578
|
fetch('/api/dsh-uploads/glass-config', { cache: 'no-store' }).then((r) => r.json()).then((b) => {
|
|
3374
|
-
if (b && b.cfg) { window.__dshGlassApply && window.__dshGlassApply({
|
|
3579
|
+
if (b && b.cfg) { window.__dshGlassApply && window.__dshGlassApply({ ...b.cfg, bgImage: b.bgImage }) }
|
|
3375
3580
|
}).catch(() => {})
|
|
3376
3581
|
}, 'dsh-long-plugins: glass boot')
|
|
3377
3582
|
},
|
package/dsh.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-long-plugins",
|
|
3
3
|
"description": "Merged DSH web plugins: upload manager (drag-and-drop attach any file to the message), workspace output files, skill docs, account balance, Markdown-to-Word (md2docx), and polished file preview (Word & PowerPoint real preview with zoom/pan, rendered Markdown), plus an auto-repair install for DSH core patches (reverse-proxy WebSocket heartbeat, upgrade relink). | 一个插件整合 DSH Web 的常用增强:上传管理(拖放上传:拖任意文件到会话框直接附加)、工作区「输出文件」面板、技能文档浏览、账户余额显示、Markdown 转 Word(md2docx)、Word/PowerPoint 真实预览(可缩放、翻页);并自带修复安装,自动重连 DSH 核心补丁(反代 WebSocket 心跳、升级重连)。",
|
|
4
|
-
"version": "2.1
|
|
4
|
+
"version": "2.2.1",
|
|
5
5
|
"entry": {
|
|
6
6
|
"name": "dsh-long-plugins",
|
|
7
7
|
"inject": [
|
package/lib/index.js
CHANGED
|
@@ -681,6 +681,38 @@ function sanitizeGlass(input) {
|
|
|
681
681
|
if ("bgImage" in input) out.bgImage = sanitizeUri(input.bgImage);
|
|
682
682
|
if ("bgColor" in input) out.bgColor = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(String(input.bgColor)) ? String(input.bgColor) : undefined;
|
|
683
683
|
if ("bgMask" in input) { const n = Number(input.bgMask); out.bgMask = Number.isFinite(n) ? Math.max(0, Math.min(0.95, n)) : undefined; }
|
|
684
|
+
if ("bgBlur" in input) { const n = Number(input.bgBlur); out.bgBlur = Number.isFinite(n) ? Math.max(0, Math.min(80, n)) : undefined; }
|
|
685
|
+
if ("bgOpacity" in input) { const n = Number(input.bgOpacity); out.bgOpacity = Number.isFinite(n) ? Math.max(0, Math.min(1, n)) : undefined; }
|
|
686
|
+
// 背景罩(整页背景图上叠的罩色):浅/深主题各一套 color + mask(罩强度)
|
|
687
|
+
if (input.bgTint && typeof input.bgTint === "object") {
|
|
688
|
+
const bt = {};
|
|
689
|
+
for (const key of ["light", "dark"]) {
|
|
690
|
+
const z = input.bgTint[key];
|
|
691
|
+
if (z && typeof z === "object") {
|
|
692
|
+
const o = {};
|
|
693
|
+
if ("color" in z) o.color = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(String(z.color)) ? String(z.color) : "#1a2332";
|
|
694
|
+
if ("mask" in z) { const n = Number(z.mask); o.mask = Number.isFinite(n) ? Math.max(0, Math.min(0.95, n)) : 0.28; }
|
|
695
|
+
bt[key] = Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined));
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
if (Object.keys(bt).length) out.bgTint = bt;
|
|
699
|
+
}
|
|
700
|
+
// 输入框(独立于 zone.input 的 DSH 玻璃变量):浅/深主题各一套 custom color + opacity(1=实底)。color 空串=用主题原生色
|
|
701
|
+
if (input.inputBox && typeof input.inputBox === "object") {
|
|
702
|
+
const ib = {};
|
|
703
|
+
for (const key of ["light", "dark"]) {
|
|
704
|
+
const z = input.inputBox[key];
|
|
705
|
+
if (z && typeof z === "object") {
|
|
706
|
+
const o = {};
|
|
707
|
+
const c = z.color;
|
|
708
|
+
if (c === "" || c === null || c === undefined) o.color = "";
|
|
709
|
+
else o.color = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(String(c)) ? String(c) : "";
|
|
710
|
+
if ("opacity" in z) { const n = Number(z.opacity); o.opacity = Number.isFinite(n) ? Math.max(0, Math.min(1, n)) : 1; }
|
|
711
|
+
ib[key] = Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
if (Object.keys(ib).length) out.inputBox = ib;
|
|
715
|
+
}
|
|
684
716
|
// 会话区/输入区各自独立罩色+罩强度
|
|
685
717
|
if (input.zone && typeof input.zone === "object") {
|
|
686
718
|
const zo = {};
|
|
@@ -1593,6 +1625,8 @@ window.addEventListener('resize',function(){ try{ if(fitMode) zoomFit(); else ap
|
|
|
1593
1625
|
// color=叠加/罩色;bgImage=共用背景图。顶栏/左栏的"罩"与整页共用 mask+color(不再单独存,简化)。
|
|
1594
1626
|
const GLASS_DEFAULTS = {
|
|
1595
1627
|
enabled: false, blur: 20, bgImage: "", bgColor: "#1a2332", bgMask: 0.28,
|
|
1628
|
+
bgTint: { light: { color: "#1a2332", mask: 0.28 }, dark: { color: "#1a2332", mask: 0.28 } },
|
|
1629
|
+
inputBox: { light: { color: "", opacity: 1 }, dark: { color: "", opacity: 1 } },
|
|
1596
1630
|
zone: { session: { color: "#1a2332", mask: 0.45, opacity: 0.5 }, input: { color: "#1a2332", mask: 0.6, opacity: 0.55 } },
|
|
1597
1631
|
};
|
|
1598
1632
|
const glassDir = resolve(homedir(), ".dsh-long-plugins");
|
|
@@ -1612,6 +1646,8 @@ window.addEventListener('resize',function(){ try{ if(fitMode) zoomFit(); else ap
|
|
|
1612
1646
|
enabled: cfg.enabled, blur: cfg.blur,
|
|
1613
1647
|
session: cfg.zone?.session || { enabled: true, color: "#1a2332", mask: 0.45, opacity: 0.5 },
|
|
1614
1648
|
input: cfg.zone?.input || { color: "#1a2332", mask: 0.6, opacity: 0.55 },
|
|
1649
|
+
inputBox: cfg.inputBox || { light: { color: "", opacity: 1 }, dark: { color: "", opacity: 1 } },
|
|
1650
|
+
bgTint: cfg.bgTint || { light: { color: "#1a2332", mask: 0.28 }, dark: { color: "#1a2332", mask: 0.28 } },
|
|
1615
1651
|
bgColor: cfg.bgColor || "#1a2332", bgMask: cfg.bgMask ?? 0.28,
|
|
1616
1652
|
bgImage: cfg.bgImage ? { present: true, bytes: Math.round((cfg.bgImage.length * 3) / 4) } : { present: false },
|
|
1617
1653
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-long-plugins",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Merged DSH web plugins: upload manager (drag-and-drop attach any file to the message), workspace output files, skill docs, account balance, Markdown-to-Word (md2docx), and polished file preview (Word & PowerPoint real preview with zoom/pan, rendered Markdown), plus an auto-repair install for DSH core patches (reverse-proxy WebSocket heartbeat, upgrade relink). | 一个插件整合 DSH Web 的常用增强:上传管理(拖放上传:拖任意文件到会话框直接附加)、工作区「输出文件」面板、技能文档浏览、账户余额显示、Markdown 转 Word(md2docx)、Word/PowerPoint 真实预览(可缩放、翻页);并自带修复安装,自动重连 DSH 核心补丁(反代 WebSocket 心跳、升级重连)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|