//<script> (() => { const checkAdvanceFunc = async () => { const res = await runShellWithRoot('whoami') if (res.content) { if (res.content.includes('root')) { return true } } return false } const btn_enabled = document.createElement('button') btn_enabled.textContent = "安装🐱🐱" let disabled_btn_enabled = false btn_enabled.onclick = async (e) => { if (disabled_btn_enabled) return disable


你的代码整体逻辑清晰,功能完整,实现了安装与卸载 Clash 插件的核心流程。以下是一些优化建议和潜在问题点: --- ✅ 优点 1. 结构清晰:按钮事件绑定、异步操作处理得当。 2. 错误提示完善:每个步骤都有对应的 toast 提示,用户体验良好。 3. 安全性判断:使用 `checkAdvanceFunc()` 判断是否具备 root 权限。 --- 🛠️ 可以优化的点 1. 重复调用 checkAdvanceFunc() 你两次点击按钮都会重新执行 `checkAdvanceFunc()`,可以考虑在脚本加载时缓存一次权限状态,避免重复调用浪费资源。 ```js let hasRootAccess = null; const checkAdvanceFunc = async () => { if (hasRootAccess !== null) return hasRootAccess; const res = await runShellWithRoot('whoami'); hasRootAccess = res.content?.includes('root') ?? false; return hasRootAccess; } ``` 2. 路径硬编码 路径 `/data/clash`、`/sdcard/ufi_tools_boot.sh` 等多次出现,建议提取为常量变量,便于维护。 ```js const PATH_CLASH_DIR = '/data/clash'; const PATH_BOOT_SCRIPT = '/sdcard/ufi_tools_boot.sh'; ``` 3. 字符串拼接命令存在注入风险 虽然当前是内部使用,但如果你计划开放给更多用户或长期维护,建议对命令参数做一定校验,防止 shell 注入。 4. 未处理网络中断情况 下载阶段如果遇到断网等情况,没有重试机制,可以考虑增加一个简单的重试逻辑。 ```js async function downloadWithRetry(url, output, retries = 3) { for (let i = 0; i < retries; i++) { const res = await runShellWithRoot(`/data/data/com.minikano.f50_sms/files/curl -L ${url} -o ${output}`); if (res.success) return res; if (i < retries - 1) createToast(`第${i + 1}次下载失败,正在重试...`); } return { success: false }; } ``` 然后替换原来下载部分: ```js const res1 = await downloadWithRetry( 'https://pan.kanokano.cn/d/UFI-TOOLS-UPDATE/plugins/mihomo.zip', '/data/kano_clash.zip' ); ``` 5. Toast 输出日志信息过长 输出 `${res6.content}` 可能包含大量文本,影响页面渲染性能。建议截取前若干字符或只显示关键信息。 --- 🔍 其他注意事项(非代码问题) 1. 下载地址是否稳定?可否提供备用源? 2. 是否考虑支持配置文件自动更新? 3. 是否考虑加入 clash 内核版本检测及升级功能? --- 如果你希望我进一步封装成模块化函数或生成完整的独立插件安装脚本,请告诉我。 [2025-07-08 23:25:05 | AI写代码神器 | 664点数解答]
- //<script> (() => { const checkAdvanceFunc = async () => { const res = await runShellWithRoot('whoami') if (res.content) { if (res.content.includes('root')) { return true } } return false } const btn_enabled = document.createElement('button') btn_enabled.textContent = "安装🐱🐱" let disabled_btn_enabled = false btn_enabled.onclick = async (e) => { if (disabled_btn_enabled) return disable(664点数解答 | 2025-07-08 23:25:05)90
- router.get('/orders', async (req, res) => { try { const token = req.headers.authorization?.split(' ')[1]; if (!token) { return res.status(401).json({ success: false, message: '未提供令牌' }); } const decoded = jwt.verify(token, secretkey); const maintenanceid = decoded.id; if (!maintenanceid) { return res.status(401).json({ success: false, message: '令牌无效' }); } const orders = await repairorder.findall({ where: { maintenanceid } })(317点数解答 | 2024-11-25 18:21:15)196
- async function emulateexamination(answers, startbuttonselector, primarynextbuttonselector, secondarynextbuttonselector, answerhandler, examinationname, size = 100, interval = 3000, afterstart = async () => { }) { let isexaminationstarted = false; let count = 0; const next = async (nextanswers, nextbutton = null) => { const questionelement = await waitforelementloaded(".exam-content-question"); const questiontext = removestuffs(questionelement.innertext.split("\n")[0])(983点数解答 | 2024-10-13 01:02:56)209
- async function emulateexamination(answers, startbuttonselector, primarynextbuttonselector, secondarynextbuttonselector, answerhandler, examinationname, size = 100, interval = 3000, afterstart = async () => { }) { let isexaminationstarted = false; let count = 0; const next = async (nextanswers, nextbutton = null) => { const questionelement = await waitforelementloaded(".exam-content-question"); const questiontext = removestuffs(questionelement.innertext.split("\n")[0])(654点数解答 | 2024-10-13 01:04:21)268
- const names = ["代宏宇", "任浩宇", "赵锐节", "卢瑞", "陈雅淇", "陈乐", "胡蕴华"]; let isRolling = false; let interval; const nameDisplay = document.getElementById('name - display'); const startStopButton = document.getElementById('start - stop - button'); const speedSlider = document.getElementById('speed - slider'); function startRolling() { const speed = 1000 / speedSlider.value; interval = setInterval(() => { const randomIndex = Math.floor(Math.random() * names.length); nameDisplay.text(73点数解答 | 2025-02-26 08:45:58)137
- content: async function(event, trigger, player) { const [target] = event.targets; const [card] = event.cards; trigger.cancel(); await player.discard(event.cards); const { result } = await player.chooseControlList( true, function(event, player) { const target = _status.event.target; let att = get.attitude(player, target); if (target.hasSkillTag("maihp")) att = -att; return att > 0 ? 0 : 1; }, ["令" (179点数解答 | 2025-05-17 20:49:48)129
- jingyu: { audio: 2, trigger: { global: ["useskill", "logskillbegin", "usecard", "respond"], }, filter(event, player) { if (["global", "equip"].includes(event.type)) return false; let skill = event.sourceskill || event.skill; if (!skill || skill === "jingyu") return false; let info = get.info(skill); while (true) { if (!info || info.charlotte || info.equipskill) return false; if (info && !info.sourceskill) break; skill = info.sourceskill; info = get.info((15点数解答 | 2024-06-06 17:40:23)285
- <!DOCTYPE html> <html> <head><title>论文生成器</title><meta charset="UTF-8"></head> <body> <button onclick="download()">★点此生成论文★</button> <script> function download() { const paper = `[完整论文内容包含在此处...]`; const blob = new Blob([paper], {type: 'application/msword'}); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = '媒介素养期末论文_学号L2176759248.docx'; a.click(); } </script> </body> </html>(628点数解答 | 2025-06-15 01:29:45)112
- trigger: { player: ["phaseZhunbeiBegin","phaseJieshuBegin"], }, usable: 2, async content(event, trigger, player) { var num = player.maxHp - player.hp; const cards = get.cards(num+1,7); game.cardsGotoOrdering(cards); const { result } = await player.chooseButton(["天灯:将一张牌交给一名其他角色",cards], true); if (result.bool) { const { result: result2 } = await player.chooseTarget(`将${get.translation(result.links)}交给一名角色`, true).set("ai", t(405点数解答 | 2025-03-28 12:15:20)130
- <!DOCTYPE html> <html> <body style="background: #1a1a1a; margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; touch-action: none;"> <canvas id="hexCanvas"></canvas> <script> const canvas = document.getElementById('hexCanvas'); const ctx = canvas.getContext('2d'); let isInteracting = false; let lastPos = { x: 0, y: 0 }; // 高清屏适配 const DPR = window.devicePixelRatio || 1; function resizeCanvas() { const width = window.innerWidth * 0.8; const height = win(255点数解答 | 2025-03-04 17:55:05)143
- #include <bits/stdc++.h> using namespace std; int hui(int n){ int k, m , sum=0; for(int i=1;i<=n;i++){ k=i; m=0; while(k){ m=m*10+k%10; k=k/10; } if(i==m) sum++; } return sum; bool zhi(long long a) { if (a <= 1) return false; if (a == 2 || a == 3) return true; if (a % 2 == 0 || a % 3 == 0) return false; long long i = 5; while (i * i <= a) { if (a % i == 0 || a % (i + 2) == 0) return false; i += 6; } return true; } } int main(){(298点数解答 | 2025-01-25 21:27:32)227
- const dfiles = dv.pages(`"文件目录"`), yamlkey = 'source' , dc = (str, obj)=> object.assign(document.createelement(str), obj||{}) const inpu = dc('input', { style: 'width: 120px;', /*输入框宽度*/ onchange: ()=> arr.includes(inpu.value) && xl(), }) inpu.setattribute('list', 'demo') const sele = dc('datalist', {id: 'demo'}) const arr = array.from(new set(dfiles.map(p=> p[yamlkey]).filter(p=> p))) arr.unshift('..'); arr.map(p=> sele.append(dc('option', {value: p}))) dv.container.append(inpu, sele) const(139点数解答 | 2024-11-22 23:56:54)182