)
1. 为什么我用 Codex 搭数据可视化大屏而不是手写 ECharts数据可视化大屏这个东西做过一次你就知道它有多“碎”。一个 1920×1080 的深色科技风大屏通常要塞进数字翻牌器、折线图、柱状图、饼图、雷达图、地图热力图、3D 柱状图、排行榜还要 WebSocket 实时刷新、图表联动、自适应缩放、全屏轮播。如果纯手写光是 ECharts 的 option 配置就能写到你怀疑人生更别说每个图表的主题色、发光边框、渐变填充都要统一。我这次的做法是把整个大屏拆成“可描述的模块”然后用 Codex 逐块生成。Codex 在这里的价值不是帮你写一个console.log而是能理解“深色科技风 发光边框 渐变填充 1920×1080 设计稿”这种视觉描述直接产出可运行的 Vue 3 ECharts 组件。你要做的是把需求描述得足够具体然后逐项验证渲染结果。这篇内容适合三类人一是前端想快速交付大屏项目的同学二是需要给老板/客户做汇报演示的运营或产品三是想用 AI 辅助编码但不知道怎么下提示词的开发者。核心检索词就是 Codex、AI、数据可视化大屏、ECharts、WebSocket全文围绕“从零生成 可复制配置 逐项验证”展开。我试过直接让 AI 一次性生成整个项目结果组件之间 props 对不上、地图 GeoJSON 加载失败、WebSocket 降级逻辑缺失。后来改成“先定结构再逐组件生成最后联调”的节奏才稳定下来。下面把我实际跑通的流程完整拆给你。2. TaoToken 前置准备让 Codex 稳定产出可运行代码在开始写大屏之前先把 Codex 的调用环境准备好。我这边用的是 TaoToken 提供的 API 接入方式官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。注意 API 地址后面不加 UTM 参数直接用于配置 Base URL。为什么要在这一步单独讲因为很多人卡在“Codex 能对话但生成不了完整项目”上本质是模型调用不稳定或者上下文被截断。TaoToken 的接入方式兼容常见的 OpenAI 风格配置你只需要拿到 Key然后把 Base URL 指向 https://taotoken.net/api 即可。如果你还没建 Key可以去控制台页面 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建模型对话调试可以用 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 先验证模型是否正常返回。这里给一个我实际使用的配置片段以 Codex CLI 的auth.json为例路径通常在~/.codex/auth.json不同版本可能略有差异以你本地实际路径为准{ base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥, model: gpt-5-codex }三件套必须齐全Base URL、Key、Model ID。少一个都会出现 401 或者模型找不到。如果你用的是 Cline 或 CC Switch 这类工具配置逻辑一样把 Base URL 填https://taotoken.net/apiKey 填你创建的密钥Model ID 填你实际可用的模型名。我踩过的坑是只填了 Key 没改 Base URL结果请求打到了默认地址一直报local proxy failed。后来把 Base URL 显式写成https://taotoken.net/api就正常了。另外如果你要做长期编码或者 Agent 类任务可以考虑 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 适合需要持续调用、上下文较长的场景。环境检查命令如下建议先跑一遍node -v # 需要 v20 以上 pnpm -v # 需要 9 以上 codex --version # 确认 Codex CLI 可用如果codex --version报错说明 CLI 没装好先解决这个再往下走。模型对话验证可以用 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 发一条测试消息确认返回正常。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到参数问题可以对照查。3. 可复制配置Codex 提示词模板 ECharts 配置片段这一节是全文的核心我把我实际用的 Codex 提示词模板和关键配置片段都贴出来你可以直接复制修改。整个大屏项目我拆成了 8 个步骤每个步骤对应一段提示词。3.1 项目初始化提示词codex 用 Vue 3 Vite TypeScript 创建一个名为>data-dashboard/ ├── public/ │ └── china.json # 中国地图 GeoJSON ├── src/ │ ├── assets/styles/ │ │ ├── reset.css │ │ ├── theme.scss # 深色主题变量 │ │ └── dashboard.scss # 大屏布局样式 │ ├── components/ │ │ ├── HeaderPanel.vue │ │ ├── NumberFlip.vue │ │ ├── LineChart.vue │ │ ├── BarChart.vue │ │ ├── PieChart.vue │ │ ├── MapChart.vue │ │ ├── RadarChart.vue │ │ ├── Bar3DChart.vue │ │ └── RankList.vue │ ├── composables/ │ │ ├── useECharts.ts │ │ ├── useWebSocket.ts │ │ └── useAutoResize.ts │ ├── mock/dashboardData.ts │ ├── App.vue │ └── main.ts ├── index.html ├── vite.config.ts └── package.json3.2 深色主题变量配置提示词codex 编写 src/assets/styles/theme.scss定义数据大屏的深色科技风主题变量 - 背景色系深蓝到深黑渐变 - 边框发光边框效果 - 文字白色/青色/金色 - 图表配色蓝、青、绿、橙、紫 - 卡片效果毛玻璃 发光描边 注释用中文生成的theme.scss关键片段// 背景色系 $bg-primary: #0a0e27; $bg-secondary: #0d1137; $bg-card: rgba(13, 17, 55, 0.8); $bg-gradient: linear-gradient(180deg, #0a0e27 0%, #0d1137 50%, #131852 100%); // 边框色系 $border-primary: rgba(45, 130, 255, 0.3); $border-glow: rgba(0, 200, 255, 0.6); $border-radius: 8px; // 文字色系 $text-primary: #ffffff; $text-secondary: #8b9fc5; $text-highlight: #00e5ff; $text-gold: #ffd700; // 图表配色方案 $chart-colors: ( #2d82ff, #00e5ff, #00e676, #ffa726, #ab47bc, #ef5350, #ffee58, #26c6da ); // 发光效果 $glow-blue: 0 0 10px rgba(45, 130, 255, 0.5), 0 0 20px rgba(45, 130, 255, 0.3); $glow-cyan: 0 0 10px rgba(0, 229, 255, 0.5), 0 0 20px rgba(0, 229, 255, 0.3); // 卡片样式 Mixin mixin card-glass { background: $bg-card; backdrop-filter: blur(10px); border: 1px solid $border-primary; border-radius: $border-radius; box-shadow: $glow-blue; transition: box-shadow 0.3s ease; :hover { box-shadow: $glow-cyan; border-color: $border-glow; } }3.3 大屏 Grid 布局配置提示词codex 编写 src/assets/styles/dashboard.scss使用 CSS Grid 实现 1920x1080 的大屏布局 - 顶部标题栏高 80px - 左侧3 个图表卡片纵向排列 - 中间地图占最大面积 底部数字面板 - 右侧3 个图表卡片纵向排列 - 每个卡片间距 12px - 整体内边距 16px 注释用中文生成的布局核心.dashboard-container { width: 1920px; height: 1080px; position: absolute; top: 50%; left: 50%; transform-origin: center center; display: grid; padding: 16px; gap: 12px; grid-template-columns: 450px 1fr 450px; grid-template-rows: 80px 1fr 1fr 1fr 120px; grid-template-areas: header header header left-1 center right-1 left-2 center right-2 left-3 center right-3 left-3 bottom right-3; }3.4 ECharts 通用 Hook 配置提示词codex 编写 src/composables/useECharts.ts一个 Vue 3 组合式函数封装 ECharts 的通用逻辑 1. 自动初始化和销毁 ECharts 实例 2. 监听容器尺寸变化自动 resize 3. 支持主题切换 4. 支持设置和更新 option 5. 暴露 ECharts 实例供高级操作 注释用中文生成的useECharts.ts关键部分import { ref, onMounted, onUnmounted, shallowRef } from vue import * as echarts from echarts import type { ECharts, EChartsOption } from echarts export function useECharts( chartRef: RefHTMLElement | undefined, initOption?: EChartsOption ) { const chartInstance shallowRefECharts | null(null) const darkTheme { backgroundColor: transparent, textStyle: { color: #8b9fc5 }, color: [#2d82ff, #00e5ff, #00e676, #ffa726, #ab47bc, #ef5350], } const initChart () { if (!chartRef.value) return echarts.registerTheme(dark-dashboard, darkTheme) chartInstance.value echarts.init(chartRef.value, dark-dashboard, { renderer: canvas, }) if (initOption) chartInstance.value.setOption(initOption) } const setOption (option: EChartsOption, notMerge false) { chartInstance.value?.setOption(option, notMerge) } const handleResize () { chartInstance.value?.resize({ animation: { duration: 300 } }) } onMounted(() { initChart() window.addEventListener(resize, handleResize) }) onUnmounted(() { window.removeEventListener(resize, handleResize) chartInstance.value?.dispose() }) return { chartInstance, setOption, handleResize } }3.5 WebSocket 实时数据 Hook提示词codex 编写 src/composables/useWebSocket.ts一个 WebSocket 组合式函数 1. 自动连接和断线重连 2. 心跳检测保活 3. 消息解析JSON 4. 支持回调函数处理消息 5. 如果没有 WebSocket 服务使用定时器模拟数据推送 注释用中文生成的useWebSocket.ts核心逻辑export function useWebSocket( onMessage: (data: any) void, options: WebSocketOptions {} ) { const { url ws://localhost:8080/ws/dashboard, reconnectInterval 3000, heartbeatInterval 30000, maxReconnectCount 10, useMock true, mockInterval 5000, } options const isConnected ref(false) let ws: WebSocket | null null let mockTimer: ReturnTypetypeof setInterval | null null const startMockData () { mockTimer setInterval(() { const mockData { type: dashboard_update, timestamp: Date.now(), data: { totalSales: Math.round(1200000 Math.random() * 100000), orderCount: Math.round(8500 Math.random() * 1000), onlineUsers: Math.round(20000 Math.random() * 8000), conversionRate: (10 Math.random() * 5).toFixed(1), }, } onMessage(mockData) }, mockInterval) } onMounted(() { if (useMock) startMockData() else connect() }) onUnmounted(() { disconnect() }) return { isConnected, connect, disconnect } }3.6 地图热力图配置片段提示词codex 编写 src/components/MapChart.vue使用 ECharts 实现中国省份销售数据热力图 1. 注册中国地图 GeoJSON 2. 按销售额着色深浅表示多少 3. 鼠标悬停显示省份数据 4. 点击省份时触发事件联动刷新其他图表 5. 散点标注 TOP 城市 6. 深色主题配色 注释用中文地图核心配置onMounted(async () { const response await fetch(/china.json) const chinaJson await response.json() echarts.registerMap(china, chinaJson) setOption({ visualMap: { min: 0, max: 15000, inRange: { color: [ rgba(45, 130, 255, 0.1), rgba(45, 130, 255, 0.3), rgba(0, 229, 255, 0.5), rgba(0, 229, 255, 0.8), #00e5ff, ], }, calculable: true, }, geo: { map: china, roam: false, zoom: 1.2, center: [105, 36], itemStyle: { areaColor: rgba(13, 17, 55, 0.8), borderColor: rgba(45, 130, 255, 0.4), }, }, series: [ { type: map, map: china, geoIndex: 0, data: salesData }, { type: effectScatter, coordinateSystem: geo, data: cityData, rippleEffect: { brushType: stroke, scale: 4, period: 4 }, }, ], }) bindEvent(click, (params: any) { if (params.name) emit(province-click, params.name) }) })3.7 3D 柱状图配置片段提示词codex 编写 src/components/Bar3DChart.vue使用 echarts-gl 实现 3D 柱状图 1. 展示四个季度、六个品类的销售数据 2. 3D 透视效果可旋转 3. 柱体渐变色 4. 自动旋转动画 注释用中文3D 柱状图核心import echarts-gl setOption({ grid3D: { boxWidth: 150, boxHeight: 80, boxDepth: 100, viewControl: { autoRotate: true, autoRotateSpeed: 10, distance: 220, alpha: 25, beta: 30, }, light: { main: { intensity: 1.2, shadow: true }, ambient: { intensity: 0.3 }, }, }, series: [{ type: bar3D, data: generateData(), shading: lambert, barSize: 15, itemStyle: { color: (params: any) { const colors [#2d82ff, #00e5ff, #00e676, #ffa726, #ab47bc, #ef5350] return colors[params.data[1] % colors.length] }, opacity: 0.85, }, }], })3.8 自适应缩放 Hookexport function useAutoResize( containerRef: RefHTMLElement | undefined, designWidth: number 1920, designHeight: number 1080 ) { const updateScale () { if (!containerRef.value) return const scaleX window.innerWidth / designWidth const scaleY window.innerHeight / designHeight const scale Math.min(scaleX, scaleY) containerRef.value.style.transform translate(-50%, -50%) scale(${scale}) } onMounted(() { updateScale() window.addEventListener(resize, updateScale) }) onUnmounted(() { window.removeEventListener(resize, updateScale) }) }以上配置片段全部可复制路径和原文一致。你按顺序生成基本不会出现组件对不上的问题。4. 验证请求与成功结果本地启动后逐项检查配置写完之后最关键的一步是验证。很多人生成完代码直接pnpm dev看到白屏就慌了。我建议按下面的顺序逐项检查每一步都有明确的成功标志。4.1 启动项目cd>VITE v5.x.x ready in 800 ms ➜ Local: http://localhost:3000/ ➜ Network: http://192.168.x.x:3000/浏览器打开http://localhost:3000/如果看到深色背景和顶部标题栏说明基础布局生效。4.2 检查图表渲染打开浏览器控制台逐个确认第一折线图是否显示两条曲线今年/去年并且有渐变面积填充。如果只显示坐标轴没有曲线检查series的data是否为空。第二柱状图是否显示六个品类的柱子柱子顶部是否有圆角。如果柱子是纯色没有渐变检查itemStyle.color的colorStops配置。第三饼图是否显示环形效果并且有六个扇区。如果饼图变成实心圆检查radius: [35%, 65%]是否生效。第四地图是否显示中国轮廓并且省份有深浅着色。如果地图区域是空白大概率是china.json没加载成功检查public/china.json是否存在以及fetch(/china.json)的路径是否正确。第五3D 柱状图是否显示立体柱子并且自动旋转。如果显示 2D 平面检查是否引入了echarts-gl以及grid3D配置是否生效。4.3 检查 WebSocket 数据刷新在App.vue中我配置的是模拟数据模式每 5 秒刷新一次。验证方法打开控制台观察数字翻牌器的数值是否每 5 秒变化一次。如果数值一直不动检查useWebSocket的useMock是否为true以及mockInterval是否设置正确。如果你想接真实 WebSocket把useMock改成false并把url改成你的 WebSocket 服务地址。连接成功后控制台会输出 WebSocket 已连接。如果连接失败会看到 WebSocket 已断开然后自动重连重连 10 次后降级到模拟数据。4.4 检查图表联动点击地图上的任意省份观察左侧折线图和柱状图是否刷新。成功标志是折线图的数值发生明显变化柱状图的柱子高度也同步变化。如果点击没反应检查MapChart.vue的emit(province-click, params.name)是否触发以及App.vue中handleMapClick是否正确接收并传递selectedProvince。4.5 检查自适应缩放把浏览器窗口从全屏拖到半屏观察大屏是否整体等比缩放而不是出现滚动条或者内容被裁切。成功标志是大屏始终居中内容完整可见。如果出现滚动条检查html, body, #app是否设置了overflow: hidden以及.dashboard-container的transform-origin是否为center center。4.6 检查全屏和轮播按 F11 键观察是否进入全屏模式。如果浏览器拦截了 F11可以手动点击全屏按钮。轮播功能默认每 30 秒切换一次数据面板鼠标悬停时暂停轮播。成功结果汇总7 个核心图表组件全部渲染数字翻牌器每 5 秒刷新地图点击联动折线图和柱状图窗口缩放时大屏等比适配F11 全屏正常。首屏加载时间在代码分割优化后小于 3 秒打包体积约 800KBgzip 后。5. 本篇常见错误排查401、local proxy failed、reading choices、OAuth这一节把我实际遇到过的报错和排查过程整理出来你对照着看。5.1 401 Unauthorized报错原文Error: 401 Unauthorized {error:{message:Invalid API key,type:invalid_request_error}}原因Key 填错、Key 过期、或者 Base URL 没配对。排查步骤第一确认auth.json中的api_key是完整的没有多余空格第二确认base_url是https://taotoken.net/api注意结尾没有多余的斜杠第三去控制台重新创建一个 Key 试试。如果还是 401检查 Model ID 是否写错有些模型名大小写敏感。5.2 local proxy failed报错原文Error: local proxy failed: dial tcp 127.0.0.1:7890: connect: connection refused原因本地配置了代理但代理服务没启动。排查步骤第一检查环境变量HTTP_PROXY和HTTPS_PROXY是否指向了一个不可用的地址第二如果不需要代理直接清空这两个变量第三确认 Codex CLI 的配置文件里没有硬编码代理地址。这个报错和 TaoToken 本身无关是本地网络环境问题。5.3 reading choices of undefined报错原文TypeError: Cannot read properties of undefined (reading choices)原因API 返回结构不符合预期通常是 Base URL 配错导致返回了 HTML 错误页或者 Model ID 不存在导致返回了错误对象。排查步骤第一用 curl 直接请求一次看返回的 JSON 结构curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的密钥 \ -H Content-Type: application/json \ -d {model:gpt-5-codex,messages:[{role:user,content:hi}]}如果返回的是{choices:[...]}说明接口正常问题在客户端解析如果返回的是错误信息按错误信息修正 Base URL 或 Model ID。5.4 OAuth 相关报错报错原文Error: OAuth token expired, please re-authenticate原因如果你用的是需要 OAuth 的客户端比如某些 Claude Code 接入场景token 过期了。排查步骤第一重新走一遍授权流程第二确认auth.json中的 token 字段是最新的第三如果用的是 TaoToken 的 API Key 模式不需要 OAuth直接检查 Key 是否有效即可。5.5 地图加载失败报错原文GET http://localhost:3000/china.json 404 (Not Found)原因china.json没有放到public目录或者路径写错。排查步骤第一确认文件在public/china.json第二确认fetch(/china.json)的路径以斜杠开头第三如果部署到子目录需要把路径改成fetch(/dashboard/china.json)。5.6 图表不显示或显示不全现象容器有高度但图表空白。原因ECharts 初始化时容器高度为 0。排查步骤第一确认.card-content设置了flex: 1和min-height: 0第二确认chartRef绑定的 div 有明确的宽高第三在onMounted之后加一个nextTick再初始化。对照这些报错基本能覆盖 90% 的接入问题。如果遇到其他报错优先检查 Base URL、Key、Model ID 三件套是否齐全。6. 语义一致 CTA继续用 Codex 把大屏做成可交付项目大屏跑通之后下一步就是把它变成可交付的东西。我自己的习惯是先用模型对话把每个图表的 option 调到自己满意再用 Coding Plan 做长期迭代最后把接入文档存下来方便团队复用。如果你在排障或者接入阶段卡住了优先看 API Keys 和接入文档。API Keys 入口在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。这两个页面能解决大部分配置问题。如果你想先验证模型返回是否正常用模型对话页面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 发一条测试消息确认链路通了再写代码。如果你打算长期用 Codex 做编码和 Agent 任务比如持续迭代这个大屏项目、接入更多数据源、做自动化部署可以考虑 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。它更适合上下文长、调用频繁的场景。最后说一个实用技巧把这篇里的提示词模板存成一个prompts.md文件放在项目根目录。下次做新大屏时直接改改颜色和图表类型让 Codex 按模板重新生成效率会高很多。大屏项目最怕的不是写代码而是需求反复改有了模板之后改需求就是改提示词的事。