mirror of
https://github.com/foxhui/WebAI2API.git
synced 2026-06-16 21:03:59 +08:00
feat: 增加 CSS 注入关闭动画,模糊滤镜等
This commit is contained in:
+11
-1
@@ -5,7 +5,17 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [3.4.6] - 2026-01-11
|
||||
## [3.4.7] - 2026-01-14
|
||||
|
||||
### ✨ Added
|
||||
- **CSS注入**
|
||||
- 增加 CSS 注入,支持禁用动画,禁用模糊滤镜,降低字体渲染精度
|
||||
|
||||
### 🔄 Changed
|
||||
- **超时优化**
|
||||
- 增长 Google Flow 适配器的控件等待超时时间,防止在低配设备上因操作过慢而超时
|
||||
|
||||
## [3.4.6] - 2026-01-13
|
||||
|
||||
### 🔄 Changed
|
||||
- **优化速度**
|
||||
|
||||
+22
-1
@@ -156,7 +156,28 @@ browser:
|
||||
# ⚠️ 风险提示: 正常 Firefox 用户默认开启 Fission,虽然关闭它不会泄露常规指纹,
|
||||
# 但极高阶的反爬系统可能会通过检测“单进程模型”或“跨进程通信延迟”来识别自动化特征!
|
||||
fission: true
|
||||
|
||||
|
||||
# CSS 性能优化注入
|
||||
# 通过禁用网页特效在无显卡环境下降低 CPU 压力
|
||||
cssInject:
|
||||
# 禁用网页动画
|
||||
# 作用:移除 transition 和 animation
|
||||
# 收益:显著降低 CPU 持续占用
|
||||
# 风险:极低。几乎不影响浏览器指纹
|
||||
animation: false
|
||||
|
||||
# 禁用滤镜和阴影
|
||||
# 作用:移除 blur(模糊)、box-shadow(阴影) 等复杂渲染
|
||||
# 收益:在无显卡环境下,能避免 CPU 占用 100% 导致卡顿
|
||||
# 风险:中。界面会变得难看,少数反爬可能会检测样式计算结果
|
||||
filter: false
|
||||
|
||||
# 降低字体渲染质量
|
||||
# 作用:关闭字体抗锯齿,强制使用极速渲染模式
|
||||
# 收益:微量减少 CPU 绘图压力
|
||||
# ⚠️ 风险:高。会导致文字边缘有锯齿,且可能导致字体指纹与标准浏览器不符(易被高级反爬识别)
|
||||
font: false
|
||||
|
||||
# [全局代理] 如果 Instance 没有独立配置代理,将使用此配置
|
||||
proxy:
|
||||
# 是否启用代理
|
||||
|
||||
@@ -352,6 +352,75 @@ export async function initBrowserBase(config, options = {}) {
|
||||
const screenHeight = myFingerprint.screen?.availHeight || 768;
|
||||
await page.setViewportSize({ width: screenWidth, height: screenHeight });
|
||||
|
||||
// CSS 性能优化注入
|
||||
const cssInjectConfig = browserConfig.cssInject || {};
|
||||
const cssToInject = [];
|
||||
|
||||
if (cssInjectConfig.animation) {
|
||||
cssToInject.push(`
|
||||
*, *::before, *::after {
|
||||
/* 过渡和关键帧动画 */
|
||||
transition: none !important;
|
||||
animation: none !important;
|
||||
transition-property: none !important;
|
||||
|
||||
/* 平滑滚动 */
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
|
||||
/* transform 动画 */
|
||||
*:not(dummy-selector) {
|
||||
transition-duration: 0s !important;
|
||||
animation-duration: 0s !important;
|
||||
transition-delay: 0s !important;
|
||||
animation-delay: 0s !important;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
if (cssInjectConfig.filter) {
|
||||
cssToInject.push(`
|
||||
*, *::before, *::after {
|
||||
filter: none !important;
|
||||
backdrop-filter: none !important;
|
||||
box-shadow: none !important;
|
||||
text-shadow: none !important;
|
||||
mix-blend-mode: normal !important;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
if (cssInjectConfig.font) {
|
||||
cssToInject.push(`
|
||||
html, body {
|
||||
text-rendering: optimizeSpeed !important;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
// 只有当至少一个开关启用时才进行注入,防止影响浏览器指纹
|
||||
if (cssToInject.length > 0) {
|
||||
const cssString = cssToInject.join('\n');
|
||||
await context.addInitScript(`
|
||||
(function() {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = ${JSON.stringify(cssString)};
|
||||
if (document.head) {
|
||||
document.head.appendChild(style);
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.head.appendChild(style);
|
||||
});
|
||||
}
|
||||
})();
|
||||
`);
|
||||
const enabledFeatures = [];
|
||||
if (cssInjectConfig.animation) enabledFeatures.push('动画禁用');
|
||||
if (cssInjectConfig.filter) enabledFeatures.push('滤镜禁用');
|
||||
if (cssInjectConfig.font) enabledFeatures.push('字体优化');
|
||||
logger.info('浏览器', `[${markLabel}] CSS 注入已启用: ${enabledFeatures.join(', ')}`);
|
||||
}
|
||||
|
||||
// 返回 context 和 page(导航、预热、cursor 初始化由工作池负责)
|
||||
return {
|
||||
context,
|
||||
|
||||
@@ -77,11 +77,17 @@ export function getBrowserConfig() {
|
||||
const config = readRawConfig();
|
||||
const browser = config.browser || {};
|
||||
const proxy = browser.proxy || {};
|
||||
const cssInject = browser.cssInject || {};
|
||||
|
||||
return {
|
||||
path: browser.path || '',
|
||||
headless: browser.headless || false,
|
||||
fission: browser.fission !== false, // 默认 true
|
||||
cssInject: {
|
||||
animation: cssInject.animation || false,
|
||||
filter: cssInject.filter || false,
|
||||
font: cssInject.font || false
|
||||
},
|
||||
proxy: {
|
||||
enable: proxy.enable || false,
|
||||
type: proxy.type || 'http',
|
||||
@@ -107,6 +113,15 @@ export function saveBrowserConfig(data) {
|
||||
if (data.headless !== undefined) config.browser.headless = data.headless;
|
||||
if (data.fission !== undefined) config.browser.fission = data.fission;
|
||||
|
||||
// CSS 性能优化配置
|
||||
if (data.cssInject) {
|
||||
if (!config.browser.cssInject) config.browser.cssInject = {};
|
||||
const css = data.cssInject;
|
||||
if (css.animation !== undefined) config.browser.cssInject.animation = css.animation;
|
||||
if (css.filter !== undefined) config.browser.cssInject.filter = css.filter;
|
||||
if (css.font !== undefined) config.browser.cssInject.font = css.font;
|
||||
}
|
||||
|
||||
if (data.proxy) {
|
||||
if (!config.browser.proxy) config.browser.proxy = {};
|
||||
const p = data.proxy;
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{c as i,I as u}from"./index-DopB6Sc2.js";var l={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M928 140H96c-17.7 0-32 14.3-32 32v496c0 17.7 14.3 32 32 32h380v112H304c-8.8 0-16 7.2-16 16v48c0 4.4 3.6 8 8 8h432c4.4 0 8-3.6 8-8v-48c0-8.8-7.2-16-16-16H548V700h380c17.7 0 32-14.3 32-32V172c0-17.7-14.3-32-32-32zm-40 488H136V212h752v416z"}}]},name:"desktop",theme:"outlined"};function c(r){for(var t=1;t<arguments.length;t++){var e=arguments[t]!=null?Object(arguments[t]):{},n=Object.keys(e);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(e).filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),n.forEach(function(a){s(r,a,e[a])})}return r}function s(r,t,e){return t in r?Object.defineProperty(r,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):r[t]=e,r}var o=function(t,e){var n=c({},t,e.attrs);return i(u,c({},n,{icon:l}),null)};o.displayName="DesktopOutlined";o.inheritAttrs=!1;export{o as D};
|
||||
import{c as i,I as u}from"./index-BgSomuu7.js";var l={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M928 140H96c-17.7 0-32 14.3-32 32v496c0 17.7 14.3 32 32 32h380v112H304c-8.8 0-16 7.2-16 16v48c0 4.4 3.6 8 8 8h432c4.4 0 8-3.6 8-8v-48c0-8.8-7.2-16-16-16H548V700h380c17.7 0 32-14.3 32-32V172c0-17.7-14.3-32-32-32zm-40 488H136V212h752v416z"}}]},name:"desktop",theme:"outlined"};function c(r){for(var t=1;t<arguments.length;t++){var e=arguments[t]!=null?Object(arguments[t]):{},n=Object.keys(e);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(e).filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),n.forEach(function(a){s(r,a,e[a])})}return r}function s(r,t,e){return t in r?Object.defineProperty(r,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):r[t]=e,r}var o=function(t,e){var n=c({},t,e.attrs);return i(u,c({},n,{icon:l}),null)};o.displayName="DesktopOutlined";o.inheritAttrs=!1;export{o as D};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{_ as b,k as w,l as k,o as c,b as C,d as S,w as n,c as o,g as e,f as a,h as i}from"./index-DopB6Sc2.js";const B={style:{"margin-bottom":"8px"}},T={style:{"margin-bottom":"8px"}},z={style:{"margin-bottom":"8px"}},U={style:{display:"flex","justify-content":"flex-end","margin-top":"24px"}},M={style:{"margin-bottom":"8px"}},j={style:{"margin-bottom":"8px"}},q={style:{display:"flex","justify-content":"flex-end","margin-top":"24px"}},L={__name:"server",setup(N){const d=w(),s=k({port:5173,authToken:"",keepaliveMode:"comment",queueBuffer:2,imageLimit:5});c(async()=>{await d.fetchServerConfig(),Object.assign(s,d.serverConfig)});const m=async()=>{await d.saveServerConfig(s)};return(V,t)=>{const p=a("a-input-number"),r=a("a-col"),y=a("a-input-password"),u=a("a-select-option"),g=a("a-select"),f=a("a-row"),v=a("a-button"),x=a("a-card"),_=a("a-layout");return S(),C(_,{style:{background:"transparent"}},{default:n(()=>[o(x,{title:"服务器设置",bordered:!1,style:{width:"100%"}},{default:n(()=>[o(f,{gutter:[16,16]},{default:n(()=>[o(r,{xs:24,md:12},{default:n(()=>[e("div",B,[t[5]||(t[5]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"监听端口",-1)),t[6]||(t[6]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 设置服务器监听的端口号,默认为 5173 ",-1)),o(p,{value:s.port,"onUpdate:value":t[0]||(t[0]=l=>s.port=l),min:1,max:65535,placeholder:"请输入端口号",style:{width:"100%"}},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",T,[t[7]||(t[7]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"鉴权 Token",-1)),t[8]||(t[8]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 用于 API 请求鉴权的密钥,留空则不启用鉴权 ",-1)),o(y,{value:s.authToken,"onUpdate:value":t[1]||(t[1]=l=>s.authToken=l),placeholder:"请输入 Token",type:"password"},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",z,[t[11]||(t[11]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"心跳包类型",-1)),t[12]||(t[12]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 选择 SSE 流式响应的心跳包格式 ",-1)),o(g,{value:s.keepaliveMode,"onUpdate:value":t[2]||(t[2]=l=>s.keepaliveMode=l),style:{width:"100%"},placeholder:"请选择心跳包类型"},{default:n(()=>[o(u,{value:"comment"},{default:n(()=>[...t[9]||(t[9]=[i("Comment - 注释格式",-1)])]),_:1}),o(u,{value:"content"},{default:n(()=>[...t[10]||(t[10]=[i("Content - 内容格式",-1)])]),_:1})]),_:1},8,["value"])])]),_:1})]),_:1}),e("div",U,[o(v,{type:"primary",onClick:m},{default:n(()=>[...t[13]||(t[13]=[i(" 保存设置 ",-1)])]),_:1})])]),_:1}),o(x,{title:"队列设置",bordered:!1,style:{width:"100%","margin-top":"10px"}},{default:n(()=>[o(f,{gutter:[16,16]},{default:n(()=>[o(r,{xs:24,md:12},{default:n(()=>[e("div",M,[t[14]||(t[14]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"队列缓冲区大小",-1)),t[15]||(t[15]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}},[i(" 非流式请求的额外排队数(设为 0 则不限制非流式请求数量)"),e("br"),i(" 实际队列上限 = Workers数量 + 缓冲区大小 ")],-1)),o(p,{value:s.queueBuffer,"onUpdate:value":t[3]||(t[3]=l=>s.queueBuffer=l),min:0,max:100,placeholder:"默认为 2",style:{width:"100%"}},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",j,[t[16]||(t[16]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"图片数量上限",-1)),t[17]||(t[17]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}},[i(" 单次请求最多支持的图片附件数量"),e("br"),i(" 网页最多支持10个附件,超出会被丢弃 ")],-1)),o(p,{value:s.imageLimit,"onUpdate:value":t[4]||(t[4]=l=>s.imageLimit=l),min:1,max:10,placeholder:"默认为 5",style:{width:"100%"}},null,8,["value"])])]),_:1})]),_:1}),e("div",q,[o(v,{type:"primary",onClick:m},{default:n(()=>[...t[18]||(t[18]=[i(" 保存设置 ",-1)])]),_:1})])]),_:1})]),_:1})}}},A=b(L,[["__scopeId","data-v-bd32923f"]]);export{A as default};
|
||||
import{_ as b,k as w,l as k,o as c,b as C,d as S,w as n,c as o,g as e,f as a,h as i}from"./index-BgSomuu7.js";const B={style:{"margin-bottom":"8px"}},T={style:{"margin-bottom":"8px"}},z={style:{"margin-bottom":"8px"}},U={style:{display:"flex","justify-content":"flex-end","margin-top":"24px"}},M={style:{"margin-bottom":"8px"}},j={style:{"margin-bottom":"8px"}},q={style:{display:"flex","justify-content":"flex-end","margin-top":"24px"}},L={__name:"server",setup(N){const d=w(),s=k({port:5173,authToken:"",keepaliveMode:"comment",queueBuffer:2,imageLimit:5});c(async()=>{await d.fetchServerConfig(),Object.assign(s,d.serverConfig)});const m=async()=>{await d.saveServerConfig(s)};return(V,t)=>{const p=a("a-input-number"),r=a("a-col"),y=a("a-input-password"),u=a("a-select-option"),g=a("a-select"),f=a("a-row"),v=a("a-button"),x=a("a-card"),_=a("a-layout");return S(),C(_,{style:{background:"transparent"}},{default:n(()=>[o(x,{title:"服务器设置",bordered:!1,style:{width:"100%"}},{default:n(()=>[o(f,{gutter:[16,16]},{default:n(()=>[o(r,{xs:24,md:12},{default:n(()=>[e("div",B,[t[5]||(t[5]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"监听端口",-1)),t[6]||(t[6]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 设置服务器监听的端口号,默认为 5173 ",-1)),o(p,{value:s.port,"onUpdate:value":t[0]||(t[0]=l=>s.port=l),min:1,max:65535,placeholder:"请输入端口号",style:{width:"100%"}},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",T,[t[7]||(t[7]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"鉴权 Token",-1)),t[8]||(t[8]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 用于 API 请求鉴权的密钥,留空则不启用鉴权 ",-1)),o(y,{value:s.authToken,"onUpdate:value":t[1]||(t[1]=l=>s.authToken=l),placeholder:"请输入 Token",type:"password"},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",z,[t[11]||(t[11]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"心跳包类型",-1)),t[12]||(t[12]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 选择 SSE 流式响应的心跳包格式 ",-1)),o(g,{value:s.keepaliveMode,"onUpdate:value":t[2]||(t[2]=l=>s.keepaliveMode=l),style:{width:"100%"},placeholder:"请选择心跳包类型"},{default:n(()=>[o(u,{value:"comment"},{default:n(()=>[...t[9]||(t[9]=[i("Comment - 注释格式",-1)])]),_:1}),o(u,{value:"content"},{default:n(()=>[...t[10]||(t[10]=[i("Content - 内容格式",-1)])]),_:1})]),_:1},8,["value"])])]),_:1})]),_:1}),e("div",U,[o(v,{type:"primary",onClick:m},{default:n(()=>[...t[13]||(t[13]=[i(" 保存设置 ",-1)])]),_:1})])]),_:1}),o(x,{title:"队列设置",bordered:!1,style:{width:"100%","margin-top":"10px"}},{default:n(()=>[o(f,{gutter:[16,16]},{default:n(()=>[o(r,{xs:24,md:12},{default:n(()=>[e("div",M,[t[14]||(t[14]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"队列缓冲区大小",-1)),t[15]||(t[15]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}},[i(" 非流式请求的额外排队数(设为 0 则不限制非流式请求数量)"),e("br"),i(" 实际队列上限 = Workers数量 + 缓冲区大小 ")],-1)),o(p,{value:s.queueBuffer,"onUpdate:value":t[3]||(t[3]=l=>s.queueBuffer=l),min:0,max:100,placeholder:"默认为 2",style:{width:"100%"}},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",j,[t[16]||(t[16]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"图片数量上限",-1)),t[17]||(t[17]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}},[i(" 单次请求最多支持的图片附件数量"),e("br"),i(" 网页最多支持10个附件,超出会被丢弃 ")],-1)),o(p,{value:s.imageLimit,"onUpdate:value":t[4]||(t[4]=l=>s.imageLimit=l),min:1,max:10,placeholder:"默认为 5",style:{width:"100%"}},null,8,["value"])])]),_:1})]),_:1}),e("div",q,[o(v,{type:"primary",onClick:m},{default:n(()=>[...t[18]||(t[18]=[i(" 保存设置 ",-1)])]),_:1})])]),_:1})]),_:1})}}},A=b(L,[["__scopeId","data-v-bd32923f"]]);export{A as default};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{y as i,k as a,v as r}from"./index-DopB6Sc2.js";const u=i("system",{state:()=>({status:"",version:"1.0.0",systemVersion:"",uptime:0,cpuUsage:0,memoryUsage:{total:0,used:0,free:0},safeMode:{enabled:!1,reason:null},stats:{totalRequests:0,successRate:0,activeWorkers:0,totalWorkers:0,avgResponseTime:0,success:0,failed:0}}),actions:{async fetchStatus(){const t=a();try{const e=await fetch("/admin/status",{headers:t.getHeaders()});if(e.ok){const s=await e.json();this.$patch(s)}}catch(e){console.error("Failed to fetch system status:",e)}},async fetchStats(){const t=a();try{const e=await fetch("/admin/stats",{headers:t.getHeaders()});if(e.ok){const s=await e.json();this.stats=s}}catch(e){console.error("Failed to fetch stats:",e)}},async restartService(t={}){const e=a(),{loginMode:s,workerName:n}=t;try{const o=await(await fetch("/admin/restart",{method:"POST",headers:{...e.getHeaders(),"Content-Type":"application/json"},body:JSON.stringify({loginMode:s,workerName:n})})).json();return o.success?(r.success(o.message||"服务重启中..."),!0):(r.error("重启失败"),!1)}catch{return r.error("重启请求失败"),!1}},async stopService(){const t=a();try{const s=await(await fetch("/admin/stop",{method:"POST",headers:t.getHeaders()})).json();return s.success?(r.success(s.message||"服务停止中..."),!0):(r.error("停止失败"),!1)}catch{return r.error("停止请求失败"),!1}}}});export{u};
|
||||
import{y as i,k as a,v as r}from"./index-BgSomuu7.js";const u=i("system",{state:()=>({status:"",version:"1.0.0",systemVersion:"",uptime:0,cpuUsage:0,memoryUsage:{total:0,used:0,free:0},safeMode:{enabled:!1,reason:null},stats:{totalRequests:0,successRate:0,activeWorkers:0,totalWorkers:0,avgResponseTime:0,success:0,failed:0}}),actions:{async fetchStatus(){const t=a();try{const e=await fetch("/admin/status",{headers:t.getHeaders()});if(e.ok){const s=await e.json();this.$patch(s)}}catch(e){console.error("Failed to fetch system status:",e)}},async fetchStats(){const t=a();try{const e=await fetch("/admin/stats",{headers:t.getHeaders()});if(e.ok){const s=await e.json();this.stats=s}}catch(e){console.error("Failed to fetch stats:",e)}},async restartService(t={}){const e=a(),{loginMode:s,workerName:n}=t;try{const o=await(await fetch("/admin/restart",{method:"POST",headers:{...e.getHeaders(),"Content-Type":"application/json"},body:JSON.stringify({loginMode:s,workerName:n})})).json();return o.success?(r.success(o.message||"服务重启中..."),!0):(r.error("重启失败"),!1)}catch{return r.error("重启请求失败"),!1}},async stopService(){const t=a();try{const s=await(await fetch("/admin/stop",{method:"POST",headers:t.getHeaders()})).json();return s.success?(r.success(s.message||"服务停止中..."),!0):(r.error("停止失败"),!1)}catch{return r.error("停止请求失败"),!1}}}});export{u};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -6,7 +6,7 @@
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>WebAI2API</title>
|
||||
<script type="module" crossorigin src="/assets/index-DopB6Sc2.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-BgSomuu7.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BVr8U7Bl.css">
|
||||
</head>
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ const formData = reactive({
|
||||
path: '',
|
||||
headless: false,
|
||||
fission: true,
|
||||
// CSS 性能优化
|
||||
cssAnimation: false,
|
||||
cssFilter: false,
|
||||
cssFont: false,
|
||||
// 全局代理
|
||||
proxyEnable: false,
|
||||
proxyType: 'http',
|
||||
@@ -26,6 +30,13 @@ onMounted(async () => {
|
||||
formData.headless = cfg.headless || false;
|
||||
formData.fission = cfg.fission !== false; // 默认 true
|
||||
|
||||
// CSS 性能优化
|
||||
if (cfg.cssInject) {
|
||||
formData.cssAnimation = cfg.cssInject.animation || false;
|
||||
formData.cssFilter = cfg.cssInject.filter || false;
|
||||
formData.cssFont = cfg.cssInject.font || false;
|
||||
}
|
||||
|
||||
if (cfg.proxy) {
|
||||
formData.proxyEnable = cfg.proxy.enable || false;
|
||||
formData.proxyType = cfg.proxy.type || 'http';
|
||||
@@ -42,6 +53,11 @@ const handleSave = async () => {
|
||||
const config = {
|
||||
path: formData.path,
|
||||
headless: formData.headless,
|
||||
cssInject: {
|
||||
animation: formData.cssAnimation,
|
||||
filter: formData.cssFilter,
|
||||
font: formData.cssFont
|
||||
},
|
||||
fission: formData.fission,
|
||||
proxy: {
|
||||
enable: formData.proxyEnable,
|
||||
@@ -177,6 +193,64 @@ const handleSave = async () => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-collapse-panel>
|
||||
|
||||
<!-- CSS 性能优化 -->
|
||||
<a-collapse-panel key="cssInject" header="CSS 性能优化注入">
|
||||
<a-alert
|
||||
message="⚡ 适用于无 GPU 的服务器环境,通过禁用网页特效来降低 CPU 压力"
|
||||
type="info"
|
||||
show-icon
|
||||
style="margin-bottom: 16px;"
|
||||
/>
|
||||
|
||||
<!-- 禁用动画 -->
|
||||
<div style="margin-bottom: 16px; padding: 12px; background: #fafafa; border-radius: 6px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<div>
|
||||
<div style="font-weight: 600; margin-bottom: 4px;">禁用网页动画</div>
|
||||
<div style="font-size: 12px; color: #8c8c8c;">
|
||||
移除 transition 和 animation,显著降低 CPU 持续占用
|
||||
</div>
|
||||
<a-tag color="green" style="margin-top: 6px;">风险:极低</a-tag>
|
||||
</div>
|
||||
<a-switch v-model:checked="formData.cssAnimation" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 禁用滤镜 -->
|
||||
<div style="margin-bottom: 16px; padding: 12px; background: #fafafa; border-radius: 6px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<div>
|
||||
<div style="font-weight: 600; margin-bottom: 4px;">禁用滤镜和阴影</div>
|
||||
<div style="font-size: 12px; color: #8c8c8c;">
|
||||
移除 blur(模糊)、box-shadow(阴影) 等复杂渲染
|
||||
</div>
|
||||
<a-tag color="orange" style="margin-top: 6px;">风险:中</a-tag>
|
||||
<span style="font-size: 11px; color: #faad14; margin-left: 8px;">
|
||||
界面会变丑,少数反爬可能检测样式计算结果
|
||||
</span>
|
||||
</div>
|
||||
<a-switch v-model:checked="formData.cssFilter" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 降低字体渲染 -->
|
||||
<div style="padding: 12px; background: #fff2f0; border-radius: 6px; border: 1px solid #ffccc7;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<div>
|
||||
<div style="font-weight: 600; margin-bottom: 4px;">降低字体渲染质量</div>
|
||||
<div style="font-size: 12px; color: #8c8c8c;">
|
||||
强制使用极速渲染模式,微量减少 CPU 绘图压力
|
||||
</div>
|
||||
<a-tag color="red" style="margin-top: 6px;">⚠️ 风险:高</a-tag>
|
||||
<div style="font-size: 11px; color: #cf1322; margin-top: 4px;">
|
||||
会导致文字边缘有锯齿,且可能导致字体指纹与标准浏览器不符,易被高级反爬识别
|
||||
</div>
|
||||
</div>
|
||||
<a-switch v-model:checked="formData.cssFont" />
|
||||
</div>
|
||||
</div>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user