news 2026/4/18 3:38:33

鸿蒙版“DeepSeek”客户端实战:基于 HarmonyOS 网络请求与 Markdown 渲染组件,手撸一个 AI 对话 App

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙版“DeepSeek”客户端实战:基于 HarmonyOS 网络请求与 Markdown 渲染组件,手撸一个 AI 对话 App

🚀 前言:当国产之光遇见国产之光

市面上全是 Web 版的套壳 AI,体验极其卡顿。
作为鸿蒙开发者,我们要做就做纯原生 (Native)的。
本教程将带你从零开始,使用ArkTS对接 DeepSeek 官方 API,并攻克最大的技术难点——在鸿蒙原生列表里完美渲染 Markdown 代码块


🏗️ 一、 架构设计:数据流转图

我们要实现的 App 包含三个核心层级:

  1. UI 层:基于List的聊天气泡界面。
  2. 渲染层:封装Web组件,通过loadData动态渲染 Markdown。
  3. 数据层:使用http模块发起 SSE (流式) 或普通 POST 请求。

系统架构 (Mermaid):

UI 渲染层

网络层

1. 点击发送
2. HTTP POST
3. 返回 JSON (Markdown)
4. 更新 @State 数组
5. 渲染数据
6. 注入 HTML

用户输入

ArkTS 业务逻辑

DeepSeek API

List 组件

聊天气泡

Web 组件 (Markdown 渲染器)


🛠️ 二、 核心实战:一步步手撸代码

1. 配置网络权限

首先,别忘了在module.json5中申请网络权限,否则 App 连网都连不上。

"requestPermissions":[{"name":"ohos.permission.INTERNET"}]
2. 封装 DeepSeek API 服务

DeepSeek 兼容 OpenAI 的 API 格式。我们封装一个简单的请求方法。

// DeepSeekService.etsimporthttpfrom'@ohos.net.http';exportclassDeepSeekService{privatestaticAPI_URL='https://api.deepseek.com/chat/completions';privatestaticAPI_KEY='你的_DEEPSEEK_API_KEY';// 记得替换!staticasyncchat(message:string):Promise<string>{lethttpRequest=http.createHttp();try{letresponse=awaithttpRequest.request(this.API_URL,{method:http.RequestMethod.POST,header:{'Content-Type':'application/json','Authorization':`Bearer${this.API_KEY}`},extraData:JSON.stringify({model:"deepseek-chat",messages:[{role:"system",content:"你是 DeepSeek,一个乐于助人的 AI 助手。"},{role:"user",content:message}],stream:false// 教程演示简单起见,暂不使用流式})});if(response.responseCode===200){// 解析返回结果constresult=JSON.parse(response.resultasstring);returnresult.choices[0].message.content;}else{return"网络请求失败: "+response.responseCode;}}catch(err){return"发生错误: "+JSON.stringify(err);}finally{httpRequest.destroy();}}}
3. 攻克难点:Markdown 渲染组件 (MarkdownView)

鸿蒙原生的RichText功能有限。为了支持代码高亮和表格,最稳妥的方案是使用 Web 组件加载本地 HTML 模板,并注入marked.jshighlight.js

// MarkdownView.etsimportweb_webviewfrom'@ohos.web.webview';@Componentexportstruct MarkdownView{@Propcontent:string;// 接收 Markdown 文本controller:web_webview.WebviewController=newweb_webview.WebviewController();// 构建一个包含 Markdown 解析库的 HTML 模板// 在真实项目中,建议将 marked.min.js 放进 rawfile 资源中读取privatehtmlTemplate(mdContent:string):string{return`<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown-light.min.css"> <style> body { padding: 10px; background-color: transparent; } </style> </head> <body> <div id="content" class="markdown-body"></div> <script> document.getElementById('content').innerHTML = marked.parse(\`${mdContent.replace(/`/g,'\\`')}\`); </script> </body> </html>`;}build(){// 关键:使用 Web 组件渲染 HTMLWeb({src:'',controller:this.controller}).onControllerAttached(()=>{// 当 Web 组件加载完成后,注入内容this.controller.loadData(this.htmlTemplate(this.content),"text/html","UTF-8");}).width('100%')// 根据内容动态高度是个大坑,这里简化处理,固定高度或使用 JS 交互算高度.height(300).backgroundColor(Color.Transparent)}}
4. 组装主界面 (Index.ets)

最后,把聊天列表、输入框和我们的MarkdownView组装起来。

import{DeepSeekService}from'./DeepSeekService';import{MarkdownView}from'./MarkdownView';// 定义消息模型classChatMessage{id:number;role:'user'|'ai';content:string;constructor(role:'user'|'ai',content:string){this.id=Date.now();this.role=role;this.content=content;}}@Entry@Componentstruct Index{@Statemessages:ChatMessage[]=[];@StateinputText:string="";@StateisLoading:boolean=false;scroller:Scroller=newScroller();asyncsendMessage(){if(this.inputText.trim()==="")return;// 1. 添加用户消息constuserMsg=this.inputText;this.messages.push(newChatMessage('user',userMsg));this.inputText="";this.isLoading=true;// 2. 调用 DeepSeek APIconstaiResponse=awaitDeepSeekService.chat(userMsg);// 3. 添加 AI 消息this.messages.push(newChatMessage('ai',aiResponse));this.isLoading=false;// 滚动到底部this.scroller.scrollEdge(Edge.Bottom);}build(){Column(){// 标题Text("DeepSeek Harmony").fontSize(20).fontWeight(FontWeight.Bold).height(50)// 聊天列表区List({scroller:this.scroller}){ForEach(this.messages,(msg:ChatMessage)=>{ListItem(){Row(){if(msg.role==='user'){// 用户消息 (右侧)Text(msg.content).backgroundColor('#95EC69').padding(10).borderRadius(8).margin({left:50})}else{// AI 消息 (左侧,支持 Markdown)Column(){MarkdownView({content:msg.content})}.backgroundColor('#FFFFFF').borderRadius(8).margin({right:20}).width('90%')}}.width('100%').justifyContent(msg.role==='user'?FlexAlign.End:FlexAlign.Start).padding(10)}})}.layoutWeight(1)// 占据剩余空间.backgroundColor('#F5F5F5')// 底部输入区Row(){TextInput({text:this.inputText,placeholder:"问点什么..."}).onChange((value)=>this.inputText=value).layoutWeight(1).backgroundColor(Color.White).margin({right:10})Button(this.isLoading?"思考中...":"发送").onClick(()=>this.sendMessage()).enabled(!this.isLoading)}.padding(10).backgroundColor('#EEEEEE')}.height('100%')}}

💡 三、 避坑指南与性能优化

  1. Web 组件高度自适应
    上面的代码为了演示给MarkdownView写死了高度。在生产环境中,你需要使用Web组件的onConsole或 JSBridge,在 HTML 渲染完成后将document.body.scrollHeight传回给 ArkTS,然后动态设置组件高度,否则长文会被截断。
  2. 流式响应 (Stream)
    DeepSeek 支持 Stream 模式(打字机效果)。在鸿蒙中,这需要使用http模块的on('headerReceive')on('dataReceive')监听事件,逐步拼接字符串并刷新 UI。这能极大提升用户体验。
  3. API Key 安全
    永远不要把 API Key 硬编码在客户端代码里上传到 Git!建议通过自己的后端服务器中转请求。

🎯 总结

通过不到 200 行代码,我们就在 HarmonyOS Next 上跑通了一个“DeepSeek”客户端。
这不仅验证了鸿蒙生态的开发效率,也展示了ArkTS + Web 组件混合开发的强大能力。

Next Step:
尝试给你的 App 加上“流式输出”功能,让 AI 的回复像打字机一样一个个蹦出来,体验瞬间提升 10 倍!

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

Nunchaku FLUX.1-Krea-dev量化模型:让AI绘画触手可及

在AI技术飞速发展的今天&#xff0c;高质量图像生成不再需要昂贵的专业显卡。Nunchaku Team推出的FLUX.1-Krea-dev量化模型&#xff0c;通过先进的SVDQuant技术&#xff0c;让普通用户也能轻松体验专业级AI绘画。 【免费下载链接】nunchaku-flux.1-krea-dev 项目地址: https…

作者头像 李华
网站建设 2026/4/18 2:21:41

SAP系统操作终极指南:从入门到精通的完整教程

SAP系统操作终极指南&#xff1a;从入门到精通的完整教程 【免费下载链接】SAP中文操作手册 探索SAP系统的强大功能&#xff0c;轻松掌握操作技巧&#xff01;本仓库提供《SAP 中文操作手册》电子书&#xff0c;内容详尽、结构清晰&#xff0c;适合初学者和进阶用户。通过这份实…

作者头像 李华
网站建设 2026/4/12 15:59:40

开源笔记神器Open-Notebook:如何用AI轻松管理你的知识库

开源笔记神器Open-Notebook&#xff1a;如何用AI轻松管理你的知识库 【免费下载链接】open-notebook An Open Source implementation of Notebook LM with more flexibility and features 项目地址: https://gitcode.com/GitHub_Trending/op/open-notebook 在信息爆炸的…

作者头像 李华
网站建设 2026/4/17 9:01:53

JPEG XL终极指南:从零构建高性能libjxl编解码环境

JPEG XL终极指南&#xff1a;从零构建高性能libjxl编解码环境 【免费下载链接】libjxl JPEG XL image format reference implementation 项目地址: https://gitcode.com/gh_mirrors/li/libjxl 在数字图像处理领域&#xff0c;JPEG XL作为下一代图像格式标准正迅速崛起。…

作者头像 李华
网站建设 2026/4/15 8:51:15

告别文件传输烦恼:croc如何用3行命令搞定跨设备文件互传?

还在为Windows、Mac、Linux之间的文件传输头疼吗&#xff1f;U盘容量不够、微信文件大小限制、云盘上传下载太慢&#xff1f;今天我要给你介绍一个革命性的工具——croc&#xff0c;它能让文件传输变得像聊天一样简单&#xff01;✨ 【免费下载链接】croc Easily and securely …

作者头像 李华
网站建设 2026/4/16 22:27:39

Fabric.js图像滤镜完全指南:从入门到精通

Fabric.js图像滤镜完全指南&#xff1a;从入门到精通 【免费下载链接】fabric.js Javascript Canvas Library, SVG-to-Canvas (& canvas-to-SVG) Parser 项目地址: https://gitcode.com/gh_mirrors/fa/fabric.js Fabric.js作为专业的JavaScript Canvas库&#xff0c…

作者头像 李华