Webiny SDK 实战指南:在 Next.js / Vue / Node.js 外部应用中读写 Headless CMS 内容
CMS后端前端【免费下载链接】webiny-jsOpen-source, self-hosted CMS platform on AWS serverless (Lambda, DynamoDB, S3). TypeScript framework with multi-tenancy, lifecycle hooks, GraphQL API, and AI-assisted development via MCP server. Built for developers at large organizations.项目地址https://gitcode.com/gh_mirrors/we/webiny-js点击查看免费下载Webiny 的webiny/sdk是一个面向外部应用Next.js、Vue、Node.js 等的 TypeScript 客户端库让你可以在 Webiny 之外读取、写入、发布 Headless CMS 内容条目操作 File Manager 文件、查询语言列表、触发后台任务等。本文以仓库中的官方技能文档为基础结合packages/sdk的真实源码实现完整讲解 SDK 的安装、初始化、Result 模式、fields必传参数、预览模式、类型安全泛型、增删改查与发布流程、后台任务管理以及常见的 API Key 权限与 Content model not found 报错排查。TL;DRSDK 能做什么webiny/sdk为外部应用提供与 Webiny Headless CMS、File Manager 交互的 TypeScript 接口。所有方法统一返回Result对象用isOk()判断成败支持条目的列表、获取、创建、更新、发布、取消发布内置过滤、排序、分页与 TypeScript 泛型类型安全。其源码位于仓库 packages/sdk入口类Webiny在 Webiny.ts 中定义构造时一次性初始化cms、tenantManager、fileManager、languages、tasks、webhooks六个模块并复用同一个配置。安装与初始化npm install webiny/sdk初始化一次并全局复用例如放在lib/webiny.ts// lib/webiny.ts import { Webiny } from webiny/sdk; export const webiny new Webiny({ token: process.env.WEBINY_API_TOKEN!, endpoint: process.env.WEBINY_API_ENDPOINT!, tenant: process.env.WEBINY_API_TENANT || root });三个核心配置项token—— 在 Webiny AdminSettings API Keys生成的 API Key tokenendpoint—— 基础 API URL末尾不能带斜杠。在 Webiny 项目中运行yarn webiny info可找到 API URLWebsite Builder 项目使用NEXT_PUBLIC_WEBSITE_BUILDER_API_HOSTtenant—— 租户 ID默认root。IMPORTANT:千万不要给endpoint加尾部斜杠。SDK 内部会自动把/graphql拼到 endpoint 之后https://xxx.cloudfront.net/这种写法会让所有请求失败。从源码看WebinyConfig还支持两个进阶选项见 types.tsheaders?: Recordstring, string—— 自定义 HTTP 请求头可覆盖或补充默认头fetch?: typeof fetch—— 自定义 fetch 实现便于在非浏览器环境如老版 Node、测试环境注入自己的 HTTP 客户端。token的类型是TokenProvidertypes.ts既可以传字符串也可以传() string | Promisestring函数——后者适合 token 动态刷新/轮换的场景。SDK 底层对x-tenant和Authorization: Bearer token头的组装逻辑见 executeGraphQL.ts注意若自定义 headers 里已设置AuthorizationSDK 不会覆盖它。fields参数必传每个 SDK 方法都必须传fields数组来指定要返回哪些字段省略会直接报运行时错误。Zod 校验 schema 中规定fields必须包含至少一个非空字符串schemas.ts因此漏传fields会在发起网络请求之前就被本地校验拦截返回ValidationError。内容字段用values.fieldId前缀values.name、values.price元数据用顶层字段名id、entryId、createdOn、status嵌套字段用点号values.author.name// 最小 fields —— 只要 ID fields: [id, entryId]; // 内容字段 fields: [id, entryId, values.name, values.price, values.description]; // 嵌套引用字段 fields: [id, values.title, values.author.name, values.author.email];除了values.*和顶层元数据CmsEntryData类型cmsTypes.ts还暴露了meta对象通过meta.status、meta.version等字段前缀访问包含status、modelId、version、locked、title、description、image以及高级发布工作流数据data此外还有createdOn/savedOn/modifiedOn及createdBy等审计字段、firstPublishedOn/lastPublishedOn等发布记录以及location.folderId等 ACO 文件夹位置信息。CMS读取模式 vs 预览模式webiny.cms.listEntries和webiny.cms.getEntry接受preview参数控制返回哪个版本的 revisionpreview返回内容适用场景false默认仅已发布条目面向公众的应用、SSG 静态生成true最新 revision草稿或已发布均可内容预览、编辑工具写操作createEntry、updateEntryRevision等不受preview影响。从源码看preview是可选布尔值最终作为 GraphQL 变量$preview: Boolean传给cms.listEntries/cms.getEntry见 listEntries.ts 与 getEntry.ts。Result 模式永不抛异常的 API每个 SDK 方法都返回Result对象——它从不 throwconst result await webiny.cms.listEntries({ modelId: product, fields: [id, values.name] }); if (result.isOk()) { console.log(result.value.data); // 成功 —— 类型化数据 } else { console.error(result.error.message); // 失败 —— 错误信息 }Result类的实现位于 Result.ts是受函数式编程中Either/Result启发的容器类型除isOk()/isFail()类型守卫外还提供map(fn)—— 成功时转换值失败时原样传递错误mapError(fn)—— 失败时转换错误flatMap(fn)—— 链式组合返回Result的函数match({ ok, fail })—— 模式匹配统一处理两种分支get value/get error—— 直接取值对错误取值、对成功取错会抛出异常谨慎使用。配套的错误体系定义在 errors.ts统一继承BaseError并带有稳定 codeHttpErrorHTTP_ERROR—— 非 2xx 的 HTTP 状态码error.data.status携带状态码ApiErrorAPI_ERROR—— GraphQL 层错误error.data.code携带服务端错误码NetworkErrorNETWORK_ERROR—— fetch 失败或响应 JSON 解析失败ValidationErrorVALIDATION_ERROR—— 参数未通过 Zod schema 校验在发起任何网络请求之前就返回校验机制见 createMethod.ts。TypeScript 泛型为values提供完整类型安全传入类型参数即可让values获得完整类型import type { CmsEntryData } from webiny/sdk; interface Product { name: string; price: number; sku: string; description: string; category?: CmsEntryDataProductCategory; } interface ProductCategory { name: string; slug: string; } const result await webiny.cms.listEntriesProduct({ modelId: product, fields: [id, entryId, values.name, values.price, values.sku] }); if (result.isOk()) { // result.value.data 的类型是 CmsEntryDataProduct[] const products result.value.data; // products[0].values.name —— 完全类型化 }引用字段如category被类型化为CmsEntryDataT它包装了被引用条目携带id、entryId和values。这些类型都从包入口统一导出index.tsCmsEntryDataTValues的具体字段定义见 cmsTypes.ts。读取数据列出条目const result await webiny.cms.listEntriesProduct({ modelId: product, fields: [id, entryId, values.name, values.price], sort: { values.name: asc }, limit: 10 });listEntries的返回结构listEntries.ts为{ data, meta }其中meta包含cursor: string | null、hasMoreItems: boolean、totalCount: number配合after参数即可实现游标分页limit默认为 10。带过滤条件列出const result await webiny.cms.listEntriesProduct({ modelId: product, fields: [id, entryId, values.name, values.price], where: { values.price_gte: 100, values.name_contains: Pro }, sort: { values.price: desc } });过滤操作符操作符说明示例_eq等于默认values.status: active_not不等于values.status_not: archived_contains包含子串values.name_contains: Pro_startsWith以某字符串开头values.name_startsWith: Web_gt/_gte大于 / 大于等于values.price_gte: 100_lt/_lte小于 / 小于等于values.price_lt: 500_in在数组中values.status_in: [active, featured]排序格式sort是一个Recordstring, asc | desc对象sort: { values.name: asc } // 字母序 sort: { values.price: desc } // 价格从高到低 sort: { values.createdOn: desc } // 最新在前schema层对sort的校验限定值只能是字面量asc或descschemas.ts这解释了为什么sort: [values.name_ASC]这类写法会失败。获取单条条目用where传idrevision ID或entryId// 按 revision ID const result await webiny.cms.getEntryProduct({ modelId: product, where: { id: abc123#0001 }, fields: [id, entryId, values.name, values.price] }); // 按 entry ID获取最新已发布 revision const result await webiny.cms.getEntryProduct({ modelId: product, where: { entryId: abc123 }, fields: [id, entryId, values.name] });GetEntryWhere除了id/entryId还支持values按内容字段值过滤见 getEntry.ts。注意getEntry的where是必传项位置在where内而不是方法级参数。预览模式草稿内容给listEntries或getEntry传preview: true即可访问未发布/草稿内容const result await webiny.cms.listEntriesProduct({ modelId: product, fields: [id, entryId, values.name], preview: true // 返回草稿 已发布 });写入数据CRITICAL:内容字段必须包在data对象的values键里。直接平铺字段不带values会得到空条目或畸形条目。创建条目const result await webiny.cms.createEntry({ modelId: contactSubmission, data: { values: { // ← 必填所有内容字段都要包在 values 里 name: John Doe, email: johnexample.com, message: Hello from the contact form! } }, fields: [id, entryId] });更新条目 revision方法名是updateEntryRevision不是updateEntry。使用revisionId完整的entryId#revisionNumber如abc123#0001const result await webiny.cms.updateEntryRevision({ modelId: product, revisionId: abc123#0001, // ← 注意revisionId不是 id data: { values: { // ← 必填字段包在 values 里 price: 29.99 } }, fields: [id, entryId, values.price] });发布 / 取消发布方法名是publishEntryRevision和unpublishEntryRevision不是publishEntry/unpublishEntry。两者都要求revisionId和fieldsawait webiny.cms.publishEntryRevision({ modelId: product, revisionId: abc123#0001, fields: [id, entryId, status] }); await webiny.cms.unpublishEntryRevision({ modelId: product, revisionId: abc123#0001, fields: [id, entryId, status] });删除条目 revisionawait webiny.cms.deleteEntryRevision({ modelId: product, revisionId: abc123#0001, fields: [] });从 schema 看deleteEntryRevision还支持permanent: boolean可选参数schemas.ts传true可永久删除而不是移入回收站。全部 CMS 写方法在 CmsSdk.ts 中统一暴露返回类型均为Result..., HttpError | ApiError | NetworkError | ValidationError。语言列表webiny.languages.listLanguages()返回所有已启用的语言——被禁用的语言总是被服务端过滤掉因此不需要传过滤参数import type { Language } from webiny/sdk; const result await webiny.languages.listLanguages(); if (result.isOk()) { const languages: Language[] result.value; // languages[0].code, .name, .direction, .isDefault }Language类型interface Language { id: string; code: string; // 例如 en-US name: string; // 例如 English (US) direction?: ltr | rtl; isDefault?: boolean; }该方法的实际 GraphQL 查询见 listLanguages.ts直接请求languages.listLanguages字段集并返回Language[]。File Manager// 列出文件 const files await webiny.fileManager.listFiles({ limit: 20, fields: [id, key, name, size, type, src] }); // 上传文件返回用于直传 S3 的预签名 URL const uploaded await webiny.fileManager.uploadFile({ file: myFile });fileManager模块远比表面看到的丰富。从 methods/fileManager 目录看它提供了listFiles、getFile、createFile(s)、updateFile、deleteFile、listTags、预签名上传getPresignedPostPayload(s)、分片上传createMultiPartUpload/completeMultiPartUpload以及图片元数据提取、文件类型嗅探等工具函数。listFiles返回结构与 CMS 一致{ data: FmFile[], meta: { cursor, hasMoreItems, totalCount } }listFiles.ts支持search、where、limit、after、sort参数fields会通过buildFieldsSelection动态生成 GraphQL 字段选择。通过代码创建 API Key需要编程式访问时可以以扩展extension的方式创建 API Key// extensions/MyApiKey.ts import { ApiKeyFactory } from webiny/api/security; class MyApiKeyImpl implements ApiKeyFactory.Interface { execute(): ApiKeyFactory.Return { return [ { name: Universal API Key, slug: universal-key, token: wat_12345678, permissions: [{ name: * }] } ]; } } export default ApiKeyFactory.createImplementation({ implementation: MyApiKeyImpl, dependencies: [] });注册扩展时src属性里必须包含.ts文件扩展名——省略会导致构建失败Api.Extension src{/extensions/MyApiKey.ts} /仓库中 extensions/MyApiKey.ts 即此类扩展的既有示例。后台任务Background Taskswebiny.tasks封装了 Background Tasks 的 GraphQL API。所有方法都返回Result且永不抛异常。相关类型定义TaskStatus、TaskDefinition、TaskRun、TaskLog、TaskLogItem见 taskTypes.ts。列出任务定义返回所有已注册的任务定义——在触发任务之前用它发现合法的definitionIDconst result await webiny.tasks.listDefinitions(); if (result.isOk()) { // result.value: TaskDefinition[] for (const def of result.value) { console.log(def.id, def.title, def.description); } }列出任务运行记录const result await webiny.tasks.listTasks(); if (result.isOk()) { // result.value: TaskRun[] for (const task of result.value) { console.log(task.id, task.taskStatus, task.definitionId); } }列出任务日志可选用任务运行 ID 过滤// 全部日志 const result await webiny.tasks.listLogs(); // 某个任务运行的日志 const result await webiny.tasks.listLogs({ where: { task: yourTaskRunId } }); if (result.isOk()) { for (const log of result.value) { for (const item of log.items) { console.log([${item.type}] ${item.message}); } } }触发任务const result await webiny.tasks.triggerTask({ definition: myTaskDefinitionId, input: { someVariable: someValue, anotherVariable: 42 } }); if (result.isOk()) { const task result.value; // TaskRun console.log(task.id, task.taskStatus, task.executionName); }TaskRun的完整字段taskTypes.ts还包括startedOn、finishedOn、iterations、parentId、eventResponse等可用于监控与编排。中止任务任务会在下一个安全检查点停止const result await webiny.tasks.abortTask({ id: yourTaskRunId, message: Stopped by user request // 可选 }); if (result.isOk()) { console.log(result.value.taskStatus); // aborted }后台任务类型import type { TaskDefinition, TaskRun, TaskLog, TaskLogItem, TaskStatus } from webiny/sdk; type TaskStatus pending | running | completed | failed | aborted | stopped; interface TaskDefinition { id: string; title: string; description?: string; } interface TaskRun { id: string; definitionId: string; taskStatus: TaskStatus; input?: unknown; output?: unknown; startedOn?: string; finishedOn?: string; executionName?: string; iterations?: number; parentId?: string; }SDK 模块总览模块Webiny 应用你可以做什么webiny.cmsHeadless CMS列出、获取、创建、更新、发布、取消发布、删除条目 revisionwebiny.fileManagerFile Manager列出、上传、管理文件与文件夹webiny.tenantManager多租户创建、安装、启用、禁用租户webiny.languages语言列出已启用语言id、code、name、direction、isDefaultwebiny.tasks后台任务触发、中止任务列出任务运行、定义与日志另外Webiny构造函数同时挂载了webhooks模块见 Webiny.ts覆盖 Webhook 的创建、更新、删除、投递记录查询、重发、验签等能力模块名采用Webiny与Sdk双向导出保持向后兼容Webiny.ts。常见错误对照表错误写法正确写法data: { name: ... }data: { values: { name: ... } }updateEntry(...)updateEntryRevision(...)publishEntry(...)publishEntryRevision(...)unpublishEntry(...)unpublishEntryRevision(...)sort: [values.name_ASC]sort: { values.name: asc }getEntry({ id: ... })getEntry({ where: { id: ... } })省略fields始终提供fields: [...]endpoint 尾部带斜杠去掉 endpoint URL 的尾部斜杠用未知definition字符串触发任务使用listDefinitions()返回的 ID —— GQL schema 会用它校验WebinyBackgroundTaskDefinitionEnum!快速参考Install: npm install webiny/sdk Import: import { Webiny } from webiny/sdk; Type import: import type { CmsEntryData, TaskRun } from webiny/sdk; Initialize: new Webiny({ token, endpoint, tenant }) Result check: result.isOk() - result.value / result.error.message API endpoint: yarn webiny info (in your Webiny project) -- NO trailing slash Preview mode: pass preview: true to listEntries / getEntry fields required: every CMS method needs a fields: string[] array values wrapper: createEntry/updateEntryRevision data must use { values: { ... } } Background tasks: webiny.tasks.triggerTask({ definition, input }) Abort task: webiny.tasks.abortTask({ id, message? }) Filter logs by task: webiny.tasks.listLogs({ where: { task: id } })故障排查SDK 的错误信息描述的是服务端视角的世界有时会掩盖真正的原因。下面这些模式都真实咬过实际项目——遇到这些错误时先按清单排查再怀疑 schema 或框架本身。Content model modelName not found.这个错误字面意思是当前已认证的主体看不到该 ID 的模型——不一定代表模型不存在。按顺序检查三件事模型是否真的存在打开 Webiny Admin → Headless CMS → Models确认modelId完全一致区分大小写——是productCategory不是ProductCategory或product-category。模型是否已发布 / 不是私有只在代码中创建但尚未部署的模型或定义为.private(...)而不是.public(...)的模型不会通过公开 Read API 可见。API Key 是否有读取该模型的权限这是模型明明存在时最常见的原因。CMS 故意返回 not found 而不是 forbidden防止攻击者用未授权 key 探测 schema。打开 Settings → API Keys → 你的 key确认至少具备Headless CMS访问权限cms.contentEntry、cms.contentModel等选择了相关的模型分组或 All groups对私有模型匹配的read权限 scope修复方式给 key 补上缺失权限保存后重试无需改代码。用错了 API Key用 Website Builder key 做 Headless CMS 读取Website Builder starter 自带NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY。这个 key 是为 WB 编辑器本身存在的默认只有 Website Builder 权限——没有任何 Headless CMS 模型的访问权。在 Server Component 里复用它调webiny.cms.listEntries(...)是 WB 项目里 Content model not found 最常见的原因——对 CMS 来说这个请求看起来就是一个未授权请求。两种修复方式推荐——使用独立的、CMS 作用域的 API Key。在 Webiny AdminSettings → API Keys生成新 key只授予公开站点所需的 CMS 权限通常是相关模型分组的读取权限用不同的环境变量暴露并传给 SDK# .env NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY... # 仅供 WB 编辑器使用 WEBINY_CMS_READ_TOKEN... # 供 Server Component 中的 SDK 调用// lib/webiny.ts import { Webiny } from webiny/sdk; export const webiny new Webiny({ token: process.env.WEBINY_CMS_READ_TOKEN!, // ← 不是 WB key endpoint: process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_HOST!, tenant: process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_TENANT || root });把读取和编辑器权限放在不同 key 上也便于吊销和遵循最小权限原则。不太推荐——给现有 WB key 扩展 CMS 权限。在 Settings → API Keys 打开 WB key给它加上所需的 Headless CMS 权限。能用但同一个 token 同时控制编辑器和公开读取后续的作用域隔离和密钥轮换会更麻烦。提醒NEXT_PUBLIC_*环境变量会被 Next.js 内联进客户端 bundle。放在该前缀后面的任何内容都是公开可见的。只读、且 scope 到公开内容的 CMS token 暴露出去没问题编辑器或可写 token 则不行——这类 token 请用非NEXT_PUBLIC_环境变量并且只在 Server Component 或 Route Handler 里读取。其他快速排查项endpoint带尾部斜杠。SDK 会自己拼接/graphql尾部斜杠会产生畸形 URL导致所有调用失败。去掉即可拼接逻辑见 executeGraphQL.ts。tenant不对。多租户环境下默认的root租户看不到其他租户下定义的模型。确认 tenant ID 与拥有该模型的租户一致。endpoint host 错误。WB 项目有时有独立的 Admin 和 Read API 域名。SDK 应该始终指向ReadAPI公开的 CloudFront URL而不是 Admin host。漏传fields参数。这会在请求时以不同消息抛出但如果你看到数据返回之前就有 schema 级错误请复查每个调用是否都传了非空fields: [...]。相关技能webiny-api-cms-content-models—— 定义你用 SDK 查询的那些模型webiny-website-builder—— 在 Website Builder 组件内使用 SDK 拉取 CMS 数据。更多实现细节可深入阅读 packages/sdk/src 目录尤其关注 Webiny.ts、Result.ts、executeGraphQL.ts 与 CmsSdk.ts 这几个核心文件它们定义了 SDK 的模块装配、错误语义与 GraphQL 调用管线。赞分享CMS后端前端【免费下载链接】webiny-jsOpen-source, self-hosted CMS platform on AWS serverless (Lambda, DynamoDB, S3). TypeScript framework with multi-tenancy, lifecycle hooks, GraphQL API, and AI-assisted development via MCP server. Built for developers at large organizations.项目地址https://gitcode.com/gh_mirrors/we/webiny-js点击查看免费下载相关推荐Webiny 6.5 集成 AI Power Ups 生成 Headless CMS 条目内容CmsGenerateEntryContentUseCase 实战指南Webiny 6.5 集成 AI Power Ups 生成 Headless CMS 条目内容CmsGenerateEntryContentUseCaseCMS后端前端Webiny Headless CMS GraphQL Schema 生成与快照测试实战指南Webiny Headless CMS GraphQL Schema 生成与快照测试实战指南 导读 本文围绕 Webiny 开源项目 api headlessCMS后端前端Webiny api-headless-cms 内容条目数据工厂Entry Data FactoriesDI 重构内联逻辑与工厂注入实战指南Webiny api headless cms 内容条目数据工厂Entry Data FactoriesDI 重构内联逻辑与工厂注入实战指南 本文基于仓库CMS后端前端上一篇Sequoia 高而窄旗形策略实战3 层过滤管道如何锁定机构重仓强势股下一篇魔兽争霸3高清重制版卡顿修复指南三步解决帧率不稳与显示异常难题创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

游戏引擎架构解析:对象生命周期与资源管理实战

游戏引擎架构解析:对象生命周期与资源管理实战

写游戏引擎的人都知道,对象和资源这两个词,看起来各管各的,实际上纠缠得比想象中深得多。这一篇是“游戏引擎架构深度解析”系列的第四篇,重点拆解游戏对象(Game Object/Entity)与资源管理(Asse…

2026/10/9 2:02:21 阅读更多 →
用户能编辑自己的资料,能否编辑自己的权限?Payload 多租户字段授权复盘

用户能编辑自己的资料,能否编辑自己的权限?Payload 多租户字段授权复盘

用户能编辑自己的资料,能否编辑自己的权限?Payload 多租户字段授权复盘 背景与最新进展 本篇时效依据是近72小时 GitHub 已审核漏洞库的新收录记录。项目披露早于数据库收录,不能将收录时间当作攻击发生时间。安全公告提供版本与触发条件&a…

2026/10/9 2:02:21 阅读更多 →
Apache Beam 2.36.0 版本深度解析:Kafka 停止读取时间、cloudpickle 序列化与破坏性变更全指南

Apache Beam 2.36.0 版本深度解析:Kafka 停止读取时间、cloudpickle 序列化与破坏性变更全指南

大数据批处理流处理数据工程 【免费下载链接】beam Apache Beam is a unified programming model for Batch and Streaming data processing. 项目地址: https://gitcode.com/gh_mirrors/beam4/beam 点击查看 免费下载 Apache Beam 2.36.0(2022-02-07 发…

2026/10/9 2:01:20 阅读更多 →

最新新闻

餐饮连锁销量预测实战:DeepSeek+POS数据落地避坑指南

餐饮连锁销量预测实战:DeepSeek+POS数据落地避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 4:33:54 阅读更多 →
软件测试自动化面试题拆解:从答题思路到项目实战

软件测试自动化面试题拆解:从答题思路到项目实战

先别去背那些零碎的软件测试自动化面试题答案,背答案是最亏的准备方式。你真正该解决的问题是“面试官为什么会问这道题”,以及“他期待听到什么样的回答逻辑”。今天这篇东西,我不会给你列一长串题目然后往下一贴答案就完事,我会…

2026/10/9 4:33:54 阅读更多 →
X平台自动回复工具设计:规则引擎与AI分层处理实战

X平台自动回复工具设计:规则引擎与AI分层处理实战

1. 从一条推文说起:为什么自动回复值得认真做做社媒运营的人都有一个共同的痛:消息太多,回不过来。尤其是X平台上的创作者、独立开发者、小团队运营者,每天面对的是私信、评论区提问、提及,内容高度重复——“价格多少…

2026/10/9 4:33:54 阅读更多 →
国产工业IDE适配鸿蒙:嵌入式测试工具的技术突破与实践

国产工业IDE适配鸿蒙:嵌入式测试工具的技术突破与实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 4:33:54 阅读更多 →
claude-mem:给AI对话加装长期记忆,告别跨会话失忆

claude-mem:给AI对话加装长期记忆,告别跨会话失忆

如果你平时经常跟AI对话工具打交道,大概率遇到过这种场景:同一个项目,上一轮会话已经把背景、目标、约束都交代得清清楚楚,新开一个会话,对面就像失忆了一样,还得再把技术栈、方案结论、待办事项从头说一遍…

2026/10/9 4:33:54 阅读更多 →
DeepSeek工具调用与多模态扩展实战指南

DeepSeek工具调用与多模态扩展实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 4:32:53 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →