资讯动态

从零开始的 Claude Code 零代码生活 | 第四篇:把 JobLens 的 Mock 数据改到 TaoToken 后端接口

发布时间:2026/10/15 12:20:07 来源:尧图企业网站定制
1. 为什么 JobLens 的 Mock 数据必须换成真实接口JobLens 是一个面向校招生的岗位收集与投递进度管理工具核心动作就两个快速录入岗位、查看岗位列表。前几篇里前端页面已经能跑起来快速录入弹窗能填、岗位列表能显示但数据全是写死在mock/jobs.js里的假数据。你刷新页面新增的岗位没了你换台电脑数据还是那几条。这就是 Mock 数据的本质——它只是让 UI 看起来活着并没有真正存储任何东西。从 Mock 切到真实后端接口是零代码用户最容易卡住的一步。卡点不在“写代码”而在几个具体的位置前端请求的 Base URL 指向哪里、请求字段和后端是否对齐、响应结构怎么读、新增成功后列表为什么不刷新。这些问题在纯 Mock 阶段根本不会出现一旦接上真实接口就集中爆发。这篇要做的是把 JobLens 的前端请求从本地假数据切到一条统一的 API 通道上。后端用 FastAPI 写两个最小接口POST /api/jobs新增岗位、GET /api/jobs查询岗位列表。前端把请求的 Base URL 改到 TaoToken 统一 API 通道让所有模型调用和业务接口走同一个出口省得每个文件里散落一堆地址。适合谁看正在用 Claude Code 做小项目、前端已经能跑但数据还是假的、想搞明白“接口到底怎么接”的零代码用户。我试过最省事的做法是先把后端两个接口用 curl 跑通再动前端。顺序反了的话前端报错你根本分不清是接口没起来还是字段写错了。下面按这个顺序来先起 FastAPI 后端再把前端 Base URL 改到 TaoToken 通道然后逐个接新增和列表最后做连通性验证和排错。2. 接入前的准备TaoToken 通道与 FastAPI 后端骨架2.1 为什么统一走 TaoToken API 通道JobLens 后面会用到 JD 解析、岗位摘要这类模型能力如果每个功能各自配一套地址和 Key配置文件会越来越乱。TaoToken 提供统一 API 通道业务接口和模型调用可以走同一个 Base URLKey 也只维护一份。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 注意 API 地址不带 UTM 参数。你需要先拿到一个 API Key。进入控制台创建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 。生成后复制保存后面配置文件里要用。想先验证模型通道是否通可以去模型对话页试一句https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 。这里要强调一点TaoToken 是统一 API 通道不是让你绕过什么它就是把模型调用和业务请求收敛到一个出口方便管理和排错。你把它当成项目里的“统一网关地址”来理解就行。2.2 FastAPI 后端最小骨架后端只需要两个接口。先建目录mkdir -p joblens-backend/app joblens-backend/sql cd joblens-backend python -m venv venv source venv/bin/activate pip install fastapi uvicorn pydantic建一个app/main.py先写内存版方便快速验证接口逻辑不用一上来就折腾数据库from fastapi import FastAPI from pydantic import BaseModel from typing import Optional, List from datetime import datetime app FastAPI(titleJobLens API) class JobCreate(BaseModel): company_name: str job_title: str city: Optional[str] None job_direction: Optional[str] None tech_stack: Optional[str] None source_platform: Optional[str] None source_url: Optional[str] None jd_text: Optional[str] None status: str TODO_APPLY deadline: Optional[str] None notes: Optional[str] None JOBS: List[dict] [] _next_id 1 app.post(/api/jobs) def create_job(payload: JobCreate): global _next_id if not payload.company_name.strip(): return {code: 400, message: company_name is required, data: None} if not payload.job_title.strip(): return {code: 400, message: job_title is required, data: None} now datetime.now().strftime(%Y-%m-%d %H:%M:%S) job payload.model_dump() job[id] _next_id job[created_at] now job[updated_at] now JOBS.append(job) _next_id 1 return {code: 0, message: success, data: job} app.get(/api/jobs) def list_jobs(page: int 1, page_size: int 20): ordered sorted(JOBS, keylambda x: x[created_at], reverseTrue) start (page - 1) * page_size end start page_size return { code: 0, message: success, data: { list: ordered[start:end], total: len(ordered), page: page, page_size: page_size, }, }启动uvicorn app.main:app --reload --port 8000打开http://localhost:8000/docs能看到两个接口就说明后端起来了。这一步别急着接前端先用 curl 把两个接口各打一次确认返回结构和你预期一致。3. 可复制配置把前端 Base URL 改到 TaoToken 通道3.1 前端请求配置文件前端不要在每个组件里直接写fetch(http://localhost:8000/api/jobs)。建一个src/api/config.js把 Base URL 和 Key 集中管理// src/api/config.js export const API_BASE_URL https://taotoken.net/api; export const API_KEY sk-你的TaoToken密钥; export function buildHeaders() { return { Content-Type: application/json, Authorization: Bearer ${API_KEY}, }; }注意这里 Base URL 用的是 TaoToken 的 API 入口不带任何 UTM 参数。业务接口路径拼在后面比如/api/jobs。如果你本地后端还没部署到公网调试阶段可以先把API_BASE_URL临时指向http://localhost:8000等接口稳定了再切回 TaoToken 通道。切换只改这一行不用动组件。3.2 封装 jobApi.js建src/api/jobApi.js只放两个方法// src/api/jobApi.js import { API_BASE_URL, buildHeaders } from ./config; export async function createJob(payload) { const res await fetch(${API_BASE_URL}/api/jobs, { method: POST, headers: buildHeaders(), body: JSON.stringify(payload), }); const json await res.json(); if (json.code ! 0) { throw new Error(json.message || create job failed); } return json.data; } export async function getJobList(page 1, pageSize 20) { const res await fetch( ${API_BASE_URL}/api/jobs?page${page}page_size${pageSize}, { method: GET, headers: buildHeaders() } ); const json await res.json(); if (json.code ! 0) { throw new Error(json.message || load jobs failed); } return json.data; }字段名必须和后端一致用 snake_casecompany_name、job_title、source_platform、source_url、jd_text。如果前端表单里用的是companyName在提交前做一次映射别让后端收到驼峰字段。3.3 如果你用 Claude Code 的 settings 配置有些同学在 Claude Code 里跑项目会用到settings.json。把通道地址写进去路径和原文保持一致{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的TaoToken密钥, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }三件套要写全Base URL、Key、Model ID。少任何一个Claude Code 启动时都会报认证或模型找不到。如果你用的是 Codex对应的是auth.json{ base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥, model: claude-sonnet-4-20250514 }Cline 的 MCP 配置同理Base URL 填 TaoToken 通道Key 填生成的密钥Model ID 填你要用的模型。这三件套在任何一个客户端里都是固定结构换客户端只是文件名不同。4. 验证请求从 curl 到页面真实数据4.1 先用 curl 验证后端新增一条岗位curl -X POST http://localhost:8000/api/jobs \ -H Content-Type: application/json \ -d { company_name: 字节跳动, job_title: 后端开发实习生, city: 北京, job_direction: 后端, tech_stack: Python,FastAPI,MySQL, source_platform: 牛客, source_url: https://example.com/job/1, status: TODO_APPLY, deadline: 2026-06-30, notes: 朋友推荐优先投递 }预期返回{ code: 0, message: success, data: { id: 1, company_name: 字节跳动, job_title: 后端开发实习生, status: TODO_APPLY, created_at: 2026-05-24 10:00:00 } }再查列表curl http://localhost:8000/api/jobs?page1page_size20确认data.list里有刚才那条data.total是 1。如果list是空的先别动前端回去检查 POST 是否真的写进去了。4.2 前端接入新增岗位找到快速录入弹窗组件把原来的假保存逻辑替换成createJob。关键点有三个保存时按钮进 loading、成功后关闭弹窗并触发列表刷新、失败时展示错误提示。import { createJob } from ../api/jobApi; async function handleSave(form) { setLoading(true); try { await createJob({ company_name: form.companyName, job_title: form.jobTitle, city: form.city, job_direction: form.jobDirection, tech_stack: form.techStack, source_platform: form.sourcePlatform, source_url: form.sourceUrl, jd_text: form.jdText, status: TODO_APPLY, deadline: form.deadline, notes: form.notes, }); onClose(); onSuccess(); } catch (e) { setError(e.message); } finally { setLoading(false); } }onSuccess()里要重新调用getJobList()否则用户看不到刚新增的岗位会以为保存失败。4.3 前端接入岗位列表列表页面加载时调用getJobList用data.list渲染用data.total展示总数。补上 loading、empty、error 三个状态const [list, setList] useState([]); const [total, setTotal] useState(0); const [loading, setLoading] useState(true); const [error, setError] useState(); useEffect(() { loadJobs(); }, []); async function loadJobs() { setLoading(true); setError(); try { const data await getJobList(1, 20); setList(data.list); setTotal(data.total); } catch (e) { setError(e.message); } finally { setLoading(false); } }渲染时按状态分支loading 显示骨架或转圈error 显示错误文案加重试按钮list 为空显示空状态有数据才渲染卡片。这三个状态在 Mock 阶段可以偷懒接真实接口后必须补否则请求一失败页面就是一片空白你根本不知道发生了什么。4.4 成功结果长什么样打开岗位列表页自动请求接口新增一条岗位后弹窗关闭列表自动刷新新岗位出现在最上面刷新浏览器数据还在。这三条同时成立才算真正从 Mock 切到了真实数据。5. 常见报错排查401、local proxy failed、reading choices5.1 401 Unauthorized最常见的原因是 Key 没带或带错。检查buildHeaders()里Authorization是不是Bearer sk-xxx格式中间有没有多余空格。如果你把 Key 写在.env里确认前端构建时真的读到了别出现undefined。还有一种情况是 Key 复制时带了换行肉眼看不出来重新复制一次。5.2 local proxy failed这个报错通常出现在你本地起了代理类工具或者 Base URL 指向了一个本地端口但服务没起来。先确认API_BASE_URL指向的是https://taotoken.net/api还是http://localhost:8000。如果指向本地确认 uvicorn 在跑、端口没被占用。如果指向 TaoToken 通道确认网络能正常访问该地址别在请求里混入本地代理设置。5.3 reading choices 或 reading data这类报错是响应结构读错了。TaoToken 通道返回的是统一结构{code, message, data}模型类接口可能返回choices字段。如果你在业务接口里按choices去读就会报Cannot read properties of undefined (reading choices)。检查你的jobApi.js里读的是json.data还是json.choices业务接口只认data。5.4 OAuth 相关报错如果你在 Claude Code 里看到 OAuth 报错通常是认证方式冲突了。用 API Key 模式时确保settings.json里没有残留的 OAuth token 配置。三件套 Base URL、Key、Model ID 写全别只写 Key 不写 Base URL那样客户端会去默认地址认证自然失败。5.5 请求成功但列表为空接口返回code: 0但页面没数据。先看data.list是不是空数组如果是说明后端确实没数据回去用 curl 确认 POST 有没有写进去。如果data.list有数据但页面不显示检查前端读的是json.data.list还是json.list少一层就会拿到 undefined。还有一种情况是新增成功后没触发列表刷新用户看到的是旧数据。5.6 字段对不上后端返回company_name前端读companyName页面就是空白。联调阶段让 Claude Code 只做检查不做重构把字段映射问题单独列出来一次只修一处。别让它顺手“优化一下结构”联调问题往往很小一重构反而引入新问题。6. 继续往下走把通道用起来两个接口跑通之后JobLens 的最小数据链路就成立了用户填岗位、前端调新增、后端存数据、前端查列表、页面展示真实数据。这条链路是后面所有功能的地基。下一步如果继续扩展最小动作是接状态更新接口让岗位从 TODO_APPLY 流转到其他状态。再往后是 JD 解析这时候 TaoToken 通道的价值就体现出来了——业务接口和模型调用走同一个 Base URLKey 只维护一份不用在多个配置文件之间来回切。想先验证模型通道是否通去模型对话页发一句话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 。长期做编码和 Agent 类项目可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入过程中遇到认证或字段问题先查接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 再回 API Keys 页面确认密钥状态https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。最后留一个我踩过的坑切 Base URL 的时候只改了config.js里的常量忘了检查组件里有没有硬编码的地址。结果新增走的是新通道列表还在请求旧地址页面一半有数据一半没有。切通道时全局搜一遍http://和localhost把散落的地址都收敛到配置文件里后面换环境只改一行。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑