拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

layui 全屏功能实现:TaoToken 统一 Key 接入与配置验证

layui 全屏功能实现:TaoToken 统一 Key 接入与配置验证 1. layui 全屏功能为什么总在真实项目里翻车layui 全屏功能实现这件事表面看只是调一个requestFullscreen()但真放到后台管理系统里问题会一个接一个冒出来按钮点一次进全屏、再点一次退不出去按 ESC 退出后图标状态没同步刷新页面后全屏状态丢失横向导航栏里按钮位置被挤歪更麻烦的是当你想把 AI 能力接进这个 layui 页面时Key 散落在各个 JS 文件里换个模型就要全局搜一遍。这篇就围绕「layui 全屏功能实现 TaoToken 统一 Key 接入与配置验证」这条线走。前半段把全屏交互做扎实后半段把 AI 通道的 Key 收敛到一处最后用一次真实请求验证通道是否打通。适合正在维护 layui 后台、又想把 AI 工具接进来的前端同学。全屏 API 本身不复杂难的是状态同步和跨浏览器兼容Key 接入本身也不复杂难的是统一管理和切换。两件事凑一起正好是一套可复制的落地骨架。我试过把全屏按钮塞进 layui 的layui-nav里结果position: absolute的定位基准变成了导航容器而不是视口按钮直接飘到屏幕外。后来改成挂在layui-layout-admin的侧边结构上用固定定位才稳。下面按步骤拆。2. TaoToken 前置把统一 Key 和 API 通道准备好在写全屏逻辑之前先把 AI 通道的前置工作做完这样后面验证请求时不会卡在鉴权上。TaoToken 在这里扮演的是统一 Key 与 API 通道的角色你只需要维护一份 Key就能在 layui 页面里调用模型对话、编码辅助等能力不用为每个模型单独记一套凭证。第一步打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册并登录。登录后进入控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在左侧找到 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 创建一个新的 Key。创建时建议按项目命名比如layui-admin-fullscreen方便以后区分。第二步确认你要用的模型通道。如果你只是想在 layui 页面里做一次对话验证用模型对话入口 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 先手动试一条消息确认 Key 有效。如果你打算长期在编辑器或 Agent 里用走 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 更合适。接入细节看文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite Claude Code 相关配置参考 https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecode-anthropicutm_campaignrewrite 。第三步把 API 基地址记下来https://taotoken.net/api 。注意这个地址不带任何查询参数配置里直接写它就行。Key 只在服务端或本地配置文件中出现不要硬编码进前端 JS 里后面我会用 config.toml 和 settings.json 两种骨架演示怎么隔离。注意Key 属于敏感凭证提交到 Git 前务必确认配置文件已在.gitignore中。前端页面只调用你自己的后端接口由后端转发到 TaoToken避免 Key 暴露在浏览器里。3. 可复制配置config.toml 与 settings.json 骨架这一节给你两份可直接抄的配置骨架。config.toml 适合放在后端服务或本地工具目录settings.json 适合放在编辑器或 Agent 的配置目录。两份都指向同一个 API 基地址Key 用占位符你替换成自己创建的那串即可。先看 config.toml# TaoToken 统一通道配置骨架 # 放置位置项目根目录或 ~/.config/taotoken/config.toml # 注意此文件不要提交到公开仓库 [provider] name taotoken base_url https://taotoken.net/api api_key sk-替换成你在控制台创建的Key timeout_seconds 60 [model] # 按你实际开通的通道填写先用对话模型验证 default claude-sonnet fallback gpt-4o-mini [request] max_retries 2 retry_backoff_ms 800 stream true [log] level info # 日志里不要打印完整 Key mask_key true再看 settings.json适合编辑器或 Agent 读取{ taotoken: { baseUrl: https://taotoken.net/api, apiKey: sk-替换成你在控制台创建的Key, defaultModel: claude-sonnet, timeout: 60000, stream: true, retry: { max: 2, backoffMs: 800 } }, layui: { fullscreenStorageKey: fullscreen_info, fullscreenTip: 按 ESC 退出全屏 } }两份配置里我都留了layui相关字段目的是把全屏状态存储的 key 也统一管理避免 JS 里到处写魔法字符串。CC Switch 切换步骤很简单如果你用 CC Switch 管理多套通道把上面 config.toml 的[provider]段作为一个 profile 导入切换时选中taotoken这个 profile 即可不用改代码。切换后建议重启一次工具进程确保配置重新加载。提示config.toml 和 settings.json 二选一即可取决于你的工具链读哪种格式。两者不要同时维护同一份 Key容易改漏。4. layui 全屏 API 调用与状态同步实现配置就绪后回到 layui 页面本身。全屏功能的核心是三个动作进入全屏、退出全屏、同步图标状态。原始写法里entryFullScreen和exitFullScreen分开定义没问题但状态判断依赖document.fullscreenElement系列属性容易在 ESC 退出时漏掉监听。先给出改进后的 HTML 结构按钮挂在侧边栏用固定定位避免被导航容器影响!-- layui 布局中的全屏按钮 -- div classadmin-side-full idfullScreen title切换全屏 i classlayui-icon layui-icon-screen-full/i /div对应的 CSS注意用position: fixed而不是absolutez-index给足.admin-side-full { position: fixed; cursor: pointer; z-index: 19940201; left: 200px; top: 25%; width: 30px; height: 30px; line-height: 30px; text-align: center; color: #eeeeee; background-color: #1AA094; border-radius: 4px; transition: background-color 0.2s; } .admin-side-full:hover { background-color: #168f83; }JS 部分做三件事封装进入/退出、监听fullscreenchange同步图标、用 localStorage 记住用户偏好。这里我把存储 key 从配置里读保持和 settings.json 一致layui.use([jquery, layer, form], function () { var $ layui.jquery; var layer layui.layer; var form layui.form; var STORAGE_KEY fullscreen_info; function getFullscreenElement() { return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement; } function entryFullScreen() { var docE document.documentElement; if (docE.requestFullscreen) { docE.requestFullscreen(); } else if (docE.mozRequestFullScreen) { docE.mozRequestFullScreen(); } else if (docE.webkitRequestFullscreen) { docE.webkitRequestFullscreen(); } else if (docE.msRequestFullscreen) { docE.msRequestFullscreen(); } } function exitFullScreen() { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.webkitCancelFullScreen) { document.webkitCancelFullScreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } function syncIcon() { var isFull getFullscreenElement() ! null; $(#fullScreen).html( isFull ? i classlayui-icon layui-icon-screen-restore/i : i classlayui-icon layui-icon-screen-full/i ); } // 关键监听全屏变化覆盖 ESC 退出场景 [fullscreenchange, mozfullscreenchange, webkitfullscreenchange, msfullscreenchange].forEach(function (evt) { document.addEventListener(evt, syncIcon); }); $(#fullScreen).on(click, function () { if (getFullscreenElement() null) { entryFullScreen(); localStorage.setItem(STORAGE_KEY, true); } else { exitFullScreen(); localStorage.setItem(STORAGE_KEY, false); } }); // 页面加载时恢复偏好 var saved localStorage.getItem(STORAGE_KEY); if (saved true) { layer.alert(按 ESC 退出全屏, { title: 进入全屏提示, skin: layui-layer-lan, closeBtn: 0, anim: 4, offset: 100px }, function (index) { entryFullScreen(); layer.close(index); }); } syncIcon(); });这里和原始 excerpt 最大的差别是加了fullscreenchange监听。没有它用户按 ESC 退出后图标还停留在「退出全屏」状态再点一次逻辑就反了。加上监听后无论通过按钮还是 ESC图标都能自动同步。5. 验证请求确认 TaoToken 通道真的通了全屏交互做完接下来验证 AI 通道。不要跳过这一步很多「配置看起来对但请求 401」的问题都是这里暴露的。用 curl 发一条最小请求确认 Key 和基地址都正确curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-替换成你的Key \ -d { model: claude-sonnet, messages: [ {role: user, content: 只回复两个字通了} ], stream: false }成功时你会看到类似这样的返回结构{ id: chatcmpl-xxxx, object: chat.completion, model: claude-sonnet, choices: [ { index: 0, message: { role: assistant, content: 通了 }, finish_reason: stop } ], usage: { prompt_tokens: 12, completion_tokens: 2, total_tokens: 14 } }看到choices[0].message.content有内容说明通道打通。如果返回 401检查 Key 是否复制完整、有没有多余空格返回 404检查 base_url 是不是写成了带路径的地址正确写法就是https://taotoken.net/api路径部分由具体接口补全。在 layui 页面里调用时建议走你自己的后端转发前端只请求本地接口// 前端调用本地后端由后端携带 Key 转发到 TaoToken $.ajax({ url: /api/ai/chat, type: POST, contentType: application/json, data: JSON.stringify({ model: claude-sonnet, messages: [{ role: user, content: 帮我总结当前页面功能 }] }), success: function (res) { layer.msg(res.content || 请求成功); }, error: function (xhr) { layer.msg(通道异常 xhr.status); } });后端转发时读取 config.toml 里的base_url和api_key这样前端永远拿不到 Key。验证通过后你可以在模型对话入口再手动发一条消息交叉确认确保不是单点偶然成功。6. 本篇常见错排查全屏按钮点了没反应。先看浏览器控制台有没有报错多数是requestFullscreen被浏览器策略拦截比如页面处于 iframe 中且没加allowfullscreen。layui 后台常嵌在 iframe 里给 iframe 标签补上allowfullscreen和allowfullscreen属性即可。ESC 退出后图标不同步。检查有没有注册fullscreenchange系列监听。只写点击逻辑不写监听是这类问题最常见的原因。四个前缀事件都注册一遍覆盖不同内核。刷新后自动进全屏弹窗不出现。确认 localStorage 的 key 和读取时一致。原始代码里出现过funnscreen_info和fullscreen_info拼写不一致的情况一个字母之差就导致状态读不到。建议像本文一样把 key 抽成常量。请求返回 401 或 403。Key 无效或未带上。检查Authorization头格式是否为Bearer sk-xxx中间有一个空格。另外确认 Key 没有过期必要时去 API Keys 页面重新生成。请求返回 404。base_url 写错。正确值是https://taotoken.net/api不要在后面多加/v1或/chat具体路径由接口拼接。如果你在 settings.json 里写成了带路径的地址改回纯基地址。CC Switch 切换后不生效。切换 profile 后工具进程可能缓存了旧配置重启一次即可。同时确认 config.toml 里没有残留旧 provider 段。全屏后布局错位。全屏状态下视口尺寸变化layui 的固定宽度侧边栏可能溢出。给侧边栏加overflow-y: auto或者在全屏变化时触发一次layui.table.resize()之类的重绘。排障时如果怀疑是通道问题而不是代码问题直接回到 API Keys 页面确认 Key 状态再对照接入文档核对请求格式。文档里对请求头和路径有明确说明比反复试错快得多。7. 把全屏和统一 Key 收进同一套骨架到这里layui 全屏功能和 TaoToken 统一 Key 接入就串成了一条线。全屏部分的关键是fullscreenchange监听加 localStorage 偏好按钮定位用 fixed 避免被导航容器带偏Key 部分的关键是 config.toml 或 settings.json 二选一前端只调本地后端Key 不进浏览器。如果你后面要在 layui 页面里接更多 AI 能力比如表格智能填充、表单自动校验直接复用这套配置骨架就行新增功能只需要在后端加一个转发接口前端不用再碰 Key。长期在编辑器或 Agent 里做编码辅助的话Coding Plan 那条通道更省心配置一次到处能用。最后留一个实用习惯每次改完 config.toml 或 settings.json先跑一遍第 5 节的 curl 验证再动前端代码。通道确认通了前端问题就只剩前端问题排查范围直接砍一半。
返回列表