news 2026/9/9 13:25:06

opencode:不绑定模型的AI编程Agent,免费模型也能玩得转

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
opencode:不绑定模型的AI编程Agent,免费模型也能玩得转

最近我把市面上的 AI 编程 Agent 基本都折腾了一遍:Claude Code、Codex CLI、Gemini CLI,还有一个以前被我忽略的开源选手——opencode。说实话,最早我对它没什么期待,终端里这类工具太多了,直到某天我把 Gemini Flash 这种免费模型接到 opencode 里,在一个老项目上当“临时工”完成了一次前端 Bug 排查,我才意识到这玩意儿可能是目前最“不挑食”的一个。

这篇不是官方文档的复读,而是我从安装到配置、从换模型到接 Skills、从命令行到桌面版的完整折腾记录。如果你正在纠结“该用哪个 AI Agent”,或者已经装了 opencode 却不知道怎么配才顺,那这篇应该能帮你少走不少弯路。

1. 它是什么:一个不绑定模型的终端 AI 同事

1.1 为什么我会从“试试看”变成“主力”

opencode 本质上是一个运行在终端里的 AI 编程助手,定位和 Claude Code 很像:你给它一个任务,它能自主读取项目文件、搜索代码、修改文件、执行命令,然后给你反馈。但和 Claude Code 这种深度绑定 Anthropic 模型的产品不同,opencode 从设计上就不想“站队”,它把大模型抽象成了可替换的 Provider,你可以自由选择 Anthropic、OpenAI、Google Gemini、DeepSeek、Ollama 本地模型,甚至任何兼容 OpenAI 协议的服务。

我之所以从“试试看”变成“主力”,就三个原因:

  1. 模型自由。我可以用 Claude 写复杂架构设计,用 Gemini Flash 跑日常修 Bug,用本地 Ollama 看看代码结构,不用为每个模型单独开一套工具。
  2. 全终端工作流。我本来就常驻终端,opencode 的 TUI 界面在 iTerm 里跑起来很顺手,开多个会话也不乱。
  3. 配置看得见摸得着。opencode 的配置就是一份 JSON 文件,改模型、改 baseURL、调权限,改完重启就能生效,不像某些闭源产品选项藏在设置深处。

如果你是一个需要同时对接多个模型、又不想被某个厂商锁死的开发者,opencode 大概率会戳中你。它特别适合这几类人:经常做 PoC、要在不同模型间横向对比效果的人;需要本地离线代码分析的人;以及看不惯图形 IDE 全家桶、坚持终端流的人。

1.2 横向对比:opencode / Claude Code / Codex CLI / Gemini CLI

为了避免引战,我尽量客观地列一下我用过的感受对比:

工具是否开源多模型支持免费模型接入终端体验生态扩展
opencode强,多 Provider支持TUI 完整,适合重度终端用户Skills、Memory、插件,社区活跃
Claude Code弱,主要是 Claude基本不支持好,会话管理成熟生态丰富,但封闭
Codex CLI弱,偏 OpenAI 系受限简洁但功能单薄刚起步,插件少
Gemini CLI弱,偏 Gemini 系支持自身免费额度简洁刚起步

单纯说“谁更好”其实不成立。我的选择是:需要深度工程能力、愿意为模型付费时用 Claude Code;需要快速白嫖、多模型对比、本地离线分析时用 opencode。Codex CLI 和 Gemini CLI 更像“厂商定制的专用客户端”,而 opencode 像“瑞士军刀”。

这里要特别提一句,opencode 对“免费模型”的支持是一个很实际的优势。很多人玩 AI 编程最先被卡住的就是 API 费用,opencode 能接 Gemini Flash、DeepSeek、Ollama 这类低成本或免费渠道,相当于把一个入门门槛直接踩平了。后面第 3 章我会给出具体搭配方案。

2. 安装与环境准备:别在第一步卡住

2.1 四种常见安装方式

opencode 的安装方式挺多,官方文档推荐优先用一键脚本,但我个人更建议根据系统选。

方式一:官方脚本(macOS / Linux)

curl -fsSL https://opencode.ai/install | bash

这个脚本默认把可执行文件装到用户目录下,不会污染系统级 PATH,也不要求 sudo,适合绝大多数人。安装完脚本会提示你把某个目录加入 PATH,我装完后的路径是~/.opencode/bin

方式二:npm 全局安装

npm i -g opencode-ai

这个方式适合已经有 Node.js 环境、且习惯用 npm 管理全局工具的人。注意 npm 全局安装的 bin 目录和系统自带目录不一定一致,如果你用的是 nvm,那 opencode 会装到当前 Node 版本的 bin 下面,换个 Node 版本就“消失”了。

方式三:Homebrew(macOS)

brew tap sst/tap brew install sst/tap/opencode

如果你是 Homebrew 的重度用户,这个方式最省心,后续升级直接用brew upgrade opencode就行。

方式四:Go 安装

go install github.com/sst/opencode/cmd/opencode@latest

热词里有人提到“opencode go 需要配合 cc switch 等工具”,指的就是这种方式。用go install装出来的二进制,默认只读取当前用户环境里的 API Key 配置,如果你在机器上同时维护了多套账号或模型 Provider,就需要配合 ccswitch 这类工具来切换身份,后面 3.4 我会展开。

装完之后先跑一下:

opencode --version

看到版本号就说明装成功了。

2.2 Windows 环境“无法识别‘opencode’项”的救法

如果你在 Windows PowerShell 里执行opencode报这个错:

opencode : 无法将“opencode”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

别慌,这八成是 PATH 没配上,不是软件坏了。我看好多人卡在这一步,其实就两个检查点:

  1. 确认安装目录。用一键脚本装的话,通常会在用户目录下生成.opencode/bin;用 npm 装的话,npm 全局 bin 目录一般在%APPDATA%\npm或你自定义的 prefix 目录。
  2. 把目录加进系统 PATH。按Win + R输入sysdm.cpl,打开“环境变量”,在用户变量里找到 Path,新增上面那个目录,然后重新打开一个终端窗口

注意:修改 PATH 后,已经打开的 PowerShell 或 CMD 窗口不会自动刷新,必须关闭重开。这个细节我踩过坑,搞了半天以为是安装问题,结果就是没重开窗口。

如果加了 PATH 仍不行,再检查一下是不是被 PowerShell 的执行策略拦了。可以临时执行:

Get-ExecutionPolicy

如果返回 Restricted,用下面这个命令放开当前用户(只是当前用户,不影响系统):

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

2.3 第一次启动:登录、选模型、跑一个任务

安装完成后,在项目目录里直接运行:

opencode

第一次启动会进入一个交互式引导。这个引导一般会问你用哪个 Provider、是否需要登录。opencode 支持两种身份建立方式:

  • opencode auth login:交互式登录,适合 Anthropic、OpenAI、Google 这类官方 API。
  • 直接设置环境变量:比如ANTHROPIC_API_KEYOPENAI_API_KEYGOOGLE_API_KEY,opencode 读到后会自动关联对应 Provider。

我自己的习惯是先不登录,先把一个免费模型配上,跑通整条链路再说。比如你有一个 Gemini API Key,可以先设置:

export GOOGLE_API_KEY=你的key opencode

进去之后输入一个最简单的任务,比如“请把当前目录下的文件列表和项目结构简要介绍给我”,看它能不能正确调用工具、返回结果。如果这一步通了,说明工具链没问题,后面再慢慢调模型和权限。

第一次运行命令时,opencode 通常会弹确认提示,问你是否允许执行某些操作。这个设计我觉得比某些工具“一声不吭直接跑命令”要安全得多,但也会让第一次使用的人觉得“怎么老问我”。习惯就好,后面可以配置自动批准白名单命令。

3. 模型配置与个性化:免费模型也能跑得很顺

3.1 API Key 的三种配法

opencode 读取模型密钥的方式主要有三种,从临时到持久:

第一种:环境变量(临时,适合单次会话)

export OPENAI_API_KEY=sk-xxxx export ANTHROPIC_API_KEY=sk-ant-xxxx export GOOGLE_API_KEY=xxxx opencode

第二种:opencode auth login(持久化,官方推荐)

执行后按提示选择 Provider,它会帮你把凭证写到系统钥匙串或本地配置文件里,之后每次启动自动读取。好处是安全,坏处是你想在同一台机器上切换不同账号时会有点麻烦。

第三种:配置文件opencode.json(持久化,可版本管理)

在项目根目录或用户配置目录(~/.config/opencode/)放一份 JSON,可以在里面显式指定要用哪个模型、哪个 Provider 地址。示例如下:

{ "$schema": "https://opencode.ai/config.json", "model": "google/gemini-2.5-flash", "provider": { "google": { "options": { "apiKey": "{env:GOOGLE_API_KEY}" } } } }

这个{env:GOOGLE_API_KEY}写法表示从环境变量读取,而不是把 Key 硬编码到仓库里。如果你是团队协作,强烈建议用这种方式,把opencode.json提交到仓库,但千万别把 Key 提交上去。

3.2 免费与低成本模型组合

很多人问 opencode 能不能不花钱用。能,但要降低预期。我实测下来比较顺的免费或低成本组合有三个:

组合 A:Google Gemini 系列(免费额度最香)

Gemini Flash 系列的免费额度对于个人日常开发非常够用,响应速度也快,适合做代码解释、重构建议、写单测。配合 opencode 的搜索和文件编辑能力,修 Bug 效率很高。

组合 B:DeepSeek(价格低,综合能力强)

DeepSeek 的 API 价格便宜,能力在线,尤其擅长中文场景下的代码理解。它不是免费,但量小时几乎是几分钱级别。如果你不想折腾免费模型,这是性价比很高的选择。

组合 C:Ollama 本地模型(完全离线、完全免费)

在本地启动 Ollama 后,opencode 里配置一个本地 Provider 即可。比如:

ollama run qwen2.5-coder

然后在 opencode 配置里把模型指向ollama/qwen2.5-coder或类似标识。这个适合敏感项目、离线环境,或者你只想用 AI 做“代码阅读器”的场景。

我的建议是:日常高频简单任务用 Gemini Flash,写复杂逻辑或架构分析时切到 Claude,预算敏感就 DeepSeek,完全离线就 Ollama。这就是 opencode 多 Provider 最大的价值——你不需要一个工具伺候一个模型。

3.3 opencode.json 示例:改模型、改 baseURL、调权限

除了模型选择,opencode.json最常用的是改 baseURL 和权限控制。

如果你用的是某个 OpenAI 协议兼容的网关或企业私有端点,就可以把 Provider 的 baseURL 指过去:

{ "provider": { "openai": { "options": { "baseURL": "https://your-gateway.example.com/v1" }, "models": { "my-custom-model": { "name": "My Custom Model" } } } } }

这个机制我很喜欢,等于把“用哪个模型”和“从哪访问模型”解耦了。很多公司内部有统一的大模型网关,opencode 通过 baseURL 直接对接,不用改业务代码。

权限控制方面,你可以在配置里声明哪些命令无需确认、哪些必须确认。比如允许 AI 直接运行npm testgit diff,但禁止直接执行rm -rf

{ "permissions": { "allow": ["npm test", "git diff", "git status"], "deny": ["rm -rf *"] } }

注意:权限配置不同版本字段名可能略有差异,以官方 schema 为准。我习惯先把deny写保守一点,尤其是自动模式下,AI 真的会执行命令,别等到把环境搞坏了才想起来设权限。

3.4 用 ccswitch 管理多个身份,配合 Go 版本

热词里那句“opencode go 需要配合 cc switch 等工具”我深有体会。用go install装的 opencode 是纯二进制,它不会像某些 GUI 应用那样帮你管理“多个登录身份”。当你有多个 API Key、多个 Provider 账号,或者一个模型对应多个网关时,手动改环境变量很容易乱。

ccswitch 在我理解里就是干这个的:你用命令行把一个“身份/配置组合”切换好,它会把对应的环境变量或凭据导出给当前 shell,opencode 启动时自然就读取到了。相当于把“切换模型身份”这件事,从“改配置文件 + 重启”变成了“一行命令”。

我的实操流程是:

# 先创建一个名为 work 的配置,绑定公司网关 key ccswitch create work --provider openai --base-url https://gw.example.com --key sk-xxx # 切换到 work 配置,并让环境变量生效 ccswitch use work # 在当前终端里启动 opencode opencode

这样 opencode 完全不用改任何配置,因为它读的是标准环境变量。好处是多个工具(opencode、Claude Code、Codex CLI)都能共享同一套身份管理,不会出现“这个工具能用那个工具不能用”的尴尬。

4. 实战场景:接手老项目、修前端 Bug、装 Skills 和 Memory

4.1 快速盘点一个陌生项目

实战是我最看重的部分。先拿“接手老项目”来说,这是 opencode 最典型的应用场景:丢给你一个 Git 仓库,几十个文件,没文档,没人带。

我的做法是,在项目根目录启动 opencode,然后给它一个非常具体的“盘点任务”:

请先阅读 README、package.json 和项目目录结构,然后告诉我: 1. 这个项目是做什么的,技术栈是什么; 2. 本地启动命令是什么; 3. 测试命令是什么; 4. 有没有明显的 TODO 或 FIXME 标记,集中在哪些文件里。

opencode 会调用文件搜索和读取工具,把关键文件都翻一遍,最后给你一份摘要。这一步能节省大量“人肉翻目录”的时间。而且因为有终端命令执行能力,它可以直接跑npm installnpm test来验证依赖是否完整,而不只是“纸上谈兵”。

不过要注意,老项目往往有坑,比如某个依赖装不上、某个本地服务没启动,opencode 的执行结果会和预期不一致。这种时候别急着让它继续改代码,先让它看日志、搜索报错信息,把环境问题解决了再说。

4.2 用 Playwright 复现并定位前端 Bug

“opencode playwright 怎么测试前端 bug”这个热词,说明很多人已经意识到:AI 写代码是一回事,AI 自己验证代码是另一回事。opencode 的一个实用姿势是:让它把 Playwright 当作自己的“眼睛”,去浏览器里复现问题。

具体流程我举一个真实场景:某个老项目里“购物车删除商品后数量不更新”。

我在 opencode 里的指令是这样下的:

项目已经启动了,跑在 http://localhost:5173。 请写一个 Playwright 脚本,完成以下操作: 1. 打开首页; 2. 搜索商品并加入购物车; 3. 进入购物车,点击第一个商品的删除按钮; 4. 等待页面刷新后,读取购物车角标数量; 5. 如果数量没有变化,把控制台所有报错截图并保存到 /tmp/opencode-debug。 然后运行这个脚本,告诉我失败原因。

opencode 会生成一个临时的 Node 脚本(也可能是 Python 脚本,取决于项目环境),然后通过终端执行。它可以根据执行结果反复调整选择器、等待条件,直到把 Bug 稳定复现出来。

比如最终跑出来的结果可能是:“删除接口返回 500,因为请求头里少了 CSRF token”。这时候再让 opencode 去看对应的请求封装代码,修复就是顺理成章的事了。

这个模式的核心价值在于:AI 不再“我觉得没问题”,而是“我用脚本证明有问题”。如果你写前端,强烈建议把 Playwright 脚本能力纳入你的 opencode 日常流程。

4.3 通过 Skills 扩展能力(安装 superpowers)

opencode 的 Skills 机制,简单理解就是给 AI 预装“工作手册”。它是一组结构化的提示词和工具说明,告诉 AI 在某类任务上应该按什么流程走。比如“代码审查 Skill”会要求 AI 先看 diff、再定位影响面、最后给出分级意见;“架构评审 Skill”会要求 AI 先画依赖关系、再分析循环依赖。

热词里的“opencode 安装 superpowers”就是指安装社区里很流行的一套 skills 集合——superpowers,里面包含了不少高质量的工作流。安装方式一般有两种:把仓库 clone 下来,然后将 skills 目录链接到 opencode 的配置目录;或者直接把 skill 文件复制进去。常见的目录位置是:

  • 全局:~/.config/opencode/skills/
  • 项目级:.opencode/skills/

我装上之后最直观的感受是,AI 处理问题的“套路感”变强了。比如让它做 Code Review,它不会只丢一句“看起来不错”,而是会按步骤检查错误处理、安全风险、性能隐患,并且给每条建议标注严重级别。这就是 Skills 的功劳。

如果你开发了内部规范,也可以把它们写成自定义 Skill,相当于把团队最佳实践固化到工具链里。

4.4 让 opencode 记住你的偏好(Memory)

热词里有“opencode memory”。这个功能解决的是“AI 每次对话都失忆”的问题。opencode 会在启动时自动读取一些项目内或用户级的上下文文件,作为“长期记忆”。

我自己的做法是在项目根目录放一个AGENTS.md(具体文件名和 opencode 版本有关,你可以看官方文档确认),里面写清楚:

  • 项目的技术栈、目录职责;
  • 启动和测试命令;
  • 代码风格要求,比如“组件用 TypeScript”“样式用 Tailwind”“禁止不写错误处理”;
  • 已知的坑,比如“这个项目不要执行npm run clean,会删掉本地数据库”。

这样每次 opencode 进入项目,都会先把这份“备忘录”读一遍,生成代码时更贴合项目实际。我实际测下来,它对生成内容的风格一致性有明显改善,尤其适合多人协作、代码规范多的团队。

个人用户也可以把通用偏好放在用户级 Memory 文件里,比如“提交信息用 Conventional Commits 格式”“测试文件放在 src/tests下”之类,这样所有项目都生效。

4.5 桌面版和 IDE 插件:换一个入口继续用

终端虽好,但不是所有人都喜欢。opencode 也提供了桌面版和 IDE 插件,我理解它们并不是“另一个产品”,而是同一套引擎的入口。

桌面版的好处是可以把会话、配置、日志都放到一个可视化的界面里,适合处理复杂任务时边看边操作。我还是习惯终端,但如果你给非命令行重度用户推荐 opencode,桌面版显然更容易上手。

VSCode 插件JetBrains IDEA 插件则是另一种形态:不用离开编辑器,直接在侧边栏打开 opencode 面板,选中代码发给 AI,AI 返回 diff 后可以快速接受或拒绝。在 IDEA 里用的时候,我主要拿它做“局部重构”,因为编辑器上下文就在眼前,改完马上能跑测试。“opencode vscode 插件”“opencode jetbrains idea 插件”这些热词说明大家确实需要这种无缝融入 IDE 的体验。

插件安装就和普通插件一样,在插件市场搜索 opencode 即可。装好后注意看它默认绑定的快捷键,我经常误触,后来直接改了快捷键。

5. 常见问题与排查手册

5.1 unexpected server error 的排查思路

热词里有一条非常具体:

c:\windows\system32>opencode error: unexpected server error. check server logs

这个报错我遇到过不止一次,而且原因五花八门。下面是我排查此类错误的一套固定套路:

  1. 先看日志。opencode 通常会在本地写日志文件,路径一般在~/.local/share/opencode/log/或用户配置目录下,按日期滚动。打开最新一份,重点找栈信息里的 HTTP 状态码,比如 401 是鉴权失败,429 是限流,500 是模型网关异常。
  2. 检查 Key 是否正确。先用echo $API_KEY确认环境变量没写错,再确认 Key 没有过期。很多“unexpected server error”其实就是 401,但被封装成了通用错误。
  3. 检查代理变量。如果你在终端里设置了HTTPS_PROXYHTTP_PROXY环境变量,opencode 的请求也会走代理。代理本身不可用或返回异常时,就会报这种模棱两可的错。可以试试临时unset HTTPS_PROXY HTTP_PROXY ALL_PROXY再跑一次,排除代理干扰。
  4. 切换一个 Provider 试试。比如原来用 OpenAI,切到 Gemini,如果问题消失,基本能锁定是上游模型服务的问题,而不是 opencode 本身的问题。

我的经验:遇到这个错误先别急着重装,90% 的情况要么是 Key 失效,要么是网络代理问题,要么是上游服务限流。按上面顺序排查,比盲目重装快得多。

5.2 Maven/Java 环境里执行命令失败:多半是子进程环境问题

热词里有个“opencode mvn配置”。我最初看到也愣了一下,后来反应过来,这多半是指在 Java/Maven 项目里用 opencode 时,AI 执行mvn testmvn package失败的情况。

opencode 执行命令时,子进程继承的是你启动 opencode 的那个 shell 环境。这意味着它不一定能拿到你在 GUI 应用里配置的 JAVA_HOME,或者你的 Maven 不在 PATH 里,又或者本地~/.m2/settings.xml里配了某个私服地址但当前网络不通。

遇到这种情况,建议先手动在终端里确认环境是好的:

mvn -v java -version

如果手动能跑而 opencode 跑不了,看看是不是你启动 opencode 的方式漏掉了环境变量,比如用 IDE 内置终端启动时没加载~/.zshrc。解决方案很简单:把必要环境变量写进opencode.json里,或者直接在项目根目录的 Memory 文件(比如 AGENTS.md)里写明“构建命令必须显式使用mvn -s /path/to/your/settings.xml”。

5.3 免费模型频繁限流,怎么办

免费模型用久了,最典型的问题就是限流。Gemini Flash 的免费额度虽然香,但同一时间段的请求太多会返回 429。opencode 遇到限流通常表现为:任务跑到一半,突然报错,然后整个会话卡住。

我的应对策略有两个:

一是opencode.json里把超时和重试参数调得激进一点,让它在限流时多等一会儿再重试(具体字段名看官方配置 schema,各版本略有差异)。

二是把模型分级使用:简单任务用免费模型,复杂任务手动切到付费模型。反正 opencode 切换模型很方便,我一般会在任务开始前想清楚“这个活值不值得用好模型”。比如改文案、补注释、整理目录结构,都用 Gemini Flash;涉及跨模块重构、性能优化、架构设计,再切 Claude 或 GPT。

5.4 opencode 2.0 升级后的注意点

热词里提到“opencode 2.0”。我升级后的第一感受是:权限确认更严格了,很多以前默认放行的操作现在会拦截,这是好事,但如果你升级后发现“AI 怎么变笨了,总是停下来问我”,多半不是模型变笨,而是权限策略变了。

遇到这种情况,先把配置里被拦的命令加进allow列表。另外 2.0 之后的一些底层命令格式也做了调整,如果你用旧版本的 prompt 写法,可能出现“调用工具失败”的情况,把 Skill 里的指令更新一下就好了。

升级利器:尽量把 opencode 的配置文件和 Skills 都纳入 Git 管理。这样每次升级后出现行为差异,你可以直接 diff 配置或回滚,而不是靠记忆力排查。

最后分享一点个人体会

用了这么久,我的整体感觉是:opencode 不是一个“花架子”工具,它的核心价值在“多模型自由”和“可编程的工程化能力”上。它不像某些闭源工具那样开箱即用、体验标准化,但恰恰是这个“不标准化”让它变得极其灵活。

如果你也想尝试,我建议第一天下来的目标就定三个:装上、跑通一个免费模型、用 Playwright 复现一个 bug。这三步做完,你对它到底适不适合自己,心里基本就有数了。踩过几次坑之后我最常做的事反而是:在 opencode 里同时开两个会话,一个用便宜模型读代码,一个用贵模型写核心逻辑,配合起来比任何单一工具都省心。这也算是它留给我的最大惊喜吧。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 13:24:43

STM32全双工网络语音实现:从I2S采集到UDP传输的完整方案

简介:STM32双工网络语音源代码是一套基于STM32微控制器与LwIP协议栈的嵌入式语音通信工程,面向需要实现双向实时语音传输的开发者,可作为相关课程设计与工程项目的起点。项目覆盖音频采集、PCM/G.711编解码、TCP连接管理及双工调度等关键环节…

作者头像 李华
网站建设 2026/9/9 13:23:06

使用 Polars GPUEngine 精细控制 GPU 查询执行

使用 Polars GPUEngine 精细控制 GPU 查询执行 【免费下载链接】polars Extremely fast Query Engine for DataFrames, written in Rust 项目地址: https://gitcode.com/GitHub_Trending/po/polars Polars 的 GPU 引擎(GPU engine)允许把 LazyFra…

作者头像 李华
网站建设 2026/9/9 13:22:05

基于S7-1200的升降横移式立体车库PLC控制方案

电梯房小区、医院停车场、老旧小区改造,这几年立体停车库的需求是真的大。我前前后后参与过几个升降横移式立体车库的项目,其中用西门子S7-1200系列做主控的方案占了大多数。说实话,立体车库在自动化项目里属于“麻雀虽小五脏俱全”的类型&am…

作者头像 李华