1. 准备工作
-
注册 DeepSeek 账号
- 前往 DeepSeek 官网 注册账号并获取 API Key。
-
创建 UniApp 项目
- 使用 HBuilderX 创建一个新的 UniApp 项目(选择 Vue3 或 Vue2 模板)。
-
安装依赖
- 如果需要在 UniApp 中使用 HTTP 请求,推荐使用
uni.request
(UniApp 内置)或axios
(需额外安装)。
- 如果需要在 UniApp 中使用 HTTP 请求,推荐使用
2. 实现代码
2.1 在 pages/index/index.vue
中实现问诊功能
javascript
<template>
<view class="container">
<!-- <view class="nav">
<image src="../../static/images/back.png" @tap="toMenu"></image>
<text>问医生</text>
</view> -->
<statement ref="dialog"></statement>
<view class="chat_area" id="test" ref="chatbox">
<view class="current_time" v-show="chatList.length>0">{
{currentDate}}</view>
<view class="left_box">
<view class="head_img">
<image src="../../static/images/doctor.png"></image>
</view>
<view class="content_box">
<view class="content post">
<view>我是您的AI医生小迦,很高兴为您解答。</view>
<view>您可以这样问我:</view>
<view class="post_request">
<view v-for="(item,index) in postRequest" :key="index">
<text class="active" @click="tapQuestion(item)">{
{item.id}}.{
{item.text}}</text>
</view>
</view>
<!-- <u-read-more showHeight="200">
<rich-text :nodes="item.msg"></rich-text>
</u-read-more> -->
<!-- {
{item.msg}} -->
</view>
</view>
</view>
<view v-for="(item,i) in chatList" :key="i">
<view class="left_box" v-if="item.role == 'assistant'">
<view class="head_img">
<image src="../../static/images/doctor.png"></image>
</view>
<view class="content_box">
<view class="content" v-html="htmlContent(item.content)">
<!-- <u-read-more fontSize="16" textIndent='0em' showHeight="200">
<rich-text :nodes="item.msg"></rich-text>
</u-read-more> -->
</view>
</view>
</view>
<view class="right_box" v-if="item.role == 'user'">
<view class="content_box">
<view class="content" >
{
{item.content}}
</view>
</view>
<view class="head_img">
<image :src="userImg==''?nullImg:userImg"></image>
</view>
</view>
</view>
<u-loading-icon text="小迦正在思考中..." textSize="16" :show="showLoading"></u-loading-icon>
</view>
<view class="input_tab">
<view class="statement">成都XXXX科技有限责任公司©<text @tap="exemptStatement">免责声明</text></view>
<view class="input_com">
<view class="left">
<image src="../../static/images/HOT.png"></image>
<input placeholder="请输入问题" v-model.trim="userQuesion" cursor-spacing="30rpx"></input>
</view>
<view class="send_btn" @tap="sendMsg">发送</view>
</view>
</view>
</view>
</template>
<script>
import statement from "../../components/askForComponents/statement.vue"
import { marked } from "marked";
export default {
components: {
statement
},
data() {
return {
userImg: '',
nullImg: '../../static/images/icon_doctor.png',
showLoading: false,
postRequest: [{
id: 1,
text: '乳腺BIRADS分级是什么?',
},
{
id: 2,
text: '乳房胀痛怎么办?',
},
{
id: 3,
text: '乳腺癌有没有征兆?'
}
],
chatList: [],
userQuesion: '',
robotAnswer: '',
currentDate: '',
domHeight: 0,
messages: [
{
role: "system",
content: "你是一名专业的全科医生对医疗面面俱到的AI医生小迦,请无论什么时候都不要忘了自己的身份,你是AI医生小迦,不是AI辅助;当患者询问你问题的时候,能全面细致并且礼貌的回答或为患者解决问题,当患者询问你任何与无关医疗的问题时,你会礼貌的拒绝回答。",
},
],
}
},
onLoad(option) {
let userInfo = getApp().globalData.userInfo;
// console.log("userInfo",userInfo)
this.userImg = userInfo.personInfo.avatar;
//获取热门问题并自动发送
// console.log("option=======>", option)
if (!option.questionText) return
this.userQuesion = option.questionText
this.sendMsg()
},
watch: {
'chatList.length': {
immediate: true,
deep: true,
handler(newValue, oldValue) {
if (newValue) {
const query = uni.createSelectorQuery().in(this)
query.select('#test').boundingClientRect(data => {
// console.log("data", data)
this.domHeight = data.height
}).exec()
}
}
},
domHeight(newVal, oldVal) {
if (newVal) {
uni.pageScrollTo({
scrollTop: this.domHeight,
duration: 100
})
}
}
},
mounted() {
this.$refs.dialog.open('center')
let myDate = new Date()
this.currentDate = (myDate.getHours() + '').padStart(2, '0') + ':' + (myDate.getMinutes() + '').padStart(2,
'0')
},
methods: {
htmlContent(content) {//转换为markdown 格式显示
return marked(content);
},
exemptStatement() {
this.$refs.dialog.open('center')
},
tapQuestion(item) {
this.send(item.text)
},
// 新对话
async send(val) {
this.showLoading = true
let messages = {
role: 'user',
content: val
}
this.chatList.push(messages)
this.messages.push(messages)
var that = this
console.log('==========开始诊断=======');
await uni.request({
url: "https://api.deepseek.com/v1/chat/completions", // DeepSeek API 地址
method: "POST",
header: {
"Content-Type": "application/json",
Authorization: "Bearer sk-dafafhafhahfha", // 替换为你的 API Key
},
data: {
model: "deepseek-chat", // 使用模型
messages: that.messages
},
success: (res) => {
messages = {
role: 'assistant',
content: res.data.choices[0].message.content
}
that.chatList.push(messages)
that.messages.push(messages)
that.showLoading = false
console.log('诊断结果:', res.data);
},
fail: (err) => {
console.error('请求失败:', err);
messages = {
role: 'assistant',
content: '服务器繁忙,请稍后再试。'
}
that.chatList.push(messages)
that.messages.push(messages)
that.showLoading = false
}
});
},
sendMsg() {
this.send(this.userQuesion)
this.userQuesion = null
this.robotAnswer = null
}
}
}
</script>
<style lang="scss">
.container {
padding: 28rpx;
}
.nav {
height: 80rpx;
width: 100%;
background-color: #ffffff;
display: flex;
align-items: center;
position: fixed;
top: 0;
left: 0;
z-index: 999;
image {
margin: 0 20rpx;
width: 40rpx;
height: 40rpx;
}
text {
color: #838383;
font-size: 40rpx;
}
}
.chat_area {
padding-bottom: 200rpx;
// padding-top: 60rpx;
.current_time {
display: flex;
justify-content: center;
font-size: 20rpx;
color: #9d9d9d;
}
.left_box,
.right_box {
display: flex;
.head_img {
width: 90rpx;
height: 90rpx;
margin: 20rpx 0;
image {
width: 90rpx;
height: 90rpx;
border-radius: 50%;
}
}
.content_box {
margin: 20rpx;
color: #5a5a5a;
background-color: #e5e5e5;
padding: 20rpx;
border-radius: 8rpx;
.post {}
.content {
text-align: justify;
font-size: 30rpx;
max-width: 460rpx;
white-space: normal;
word-wrap: break-word;
.post_request {
// text-indent: 2em;
color: #996699;
display: flex;
flex-direction: column;
.active:active {
width: 100%;
background-color: #FFFFFF;
opacity: 0.6;
}
}
}
}
}
.right_box {
display: flex;
justify-content: flex-end;
}
.right_box>.content_box {
background-color: #1b1263;
color: #FFFFFF;
}
}
.input_tab {
background-color: #ffffff;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
.statement {
margin: 0 auto;
font-size: 20rpx;
color: #838383;
text {
color: #1b1263;
text-decoration: underline;
}
}
.input_com {
display: flex;
justify-content: space-between;
padding: 20rpx;
margin: 20rpx;
.left {
width: 500rpx;
max-width: 500rpx;
border: 2rpx solid #e3e3e3;
display: flex;
align-items: center;
image {
width: 20rpx;
height: 20rpx;
margin: 0 20rpx;
}
input {
width: 100%;
font-size: 24rpx;
}
}
.send_btn {
padding: 20rpx 40rpx;
color: #FFFFFF;
border-radius: 8rpx;
background-color: #1b1263;
}
}
}
</style>
2.2 实现效果
![](https://i-blog.csdnimg.cn/direct/f7f39758bed244b2a5dc557a669187d4.jpeg)
3. 示例说明
3.1 单轮对话(仅 user
角色)
如果不需要设置系统指令,可以只传递 user
角色的消息:
javascript
messages: [
{
role: "user",
content: "我最近三天持续发烧38.5度,伴有咳嗽",
},
];
3.2 多轮对话(包含 system
和 user
角色)
如果需要设置系统指令,可以包含 system
角色:
javascript
messages: [
{
role: "system",
content: "你是一名专业的全科医生,请根据患者描述进行问诊。",
},
{
role: "user",
content: "我最近三天持续发烧38.5度,伴有咳嗽",
},
];
3.3 多轮对话(包含历史记录)
如果需要支持多轮对话,可以将历史记录添加到 messages
中:
javascript
messages: [
{
role: "system",
content: "你是一名专业的全科医生,请根据患者描述进行问诊。",
},
{
role: "user",
content: "我最近三天持续发烧38.5度,伴有咳嗽",
},
{
role: "assistant",
content: "请问您是否有其他症状,如喉咙痛或头痛?",
},
{
role: "user",
content: "还有喉咙痛,但没有头痛。",
},
];
4. 代码示例
4.1 单轮对话
javascript
methods: {
async getDiagnosis() {
const response = await uni.request({
url: "https://api.deepseek.com/v1/chat/completions",
method: "POST",
header: {
"Content-Type": "application/json",
Authorization: "Bearer your_api_key_here",
},
data: {
model: "medical-model-1.0",
messages: [
{
role: "user",
content: this.userInput,
},
],
},
});
if (response.statusCode === 200) {
this.diagnosisResponse = response.data.choices[0].message.content;
}
},
},
4.2 多轮对话
javascript
data() {
return {
conversationHistory: [], // 对话历史
};
},
methods: {
async getDiagnosis() {
// 添加用户输入到对话历史
this.conversationHistory.push({
role: "user",
content: this.userInput,
});
const response = await uni.request({
url: "https://api.deepseek.com/v1/chat/completions",
method: "POST",
header: {
"Content-Type": "application/json",
Authorization: "Bearer your_api_key_here",
},
data: {
model: "medical-model-1.0",
messages: this.conversationHistory,
},
});
if (response.statusCode === 200) {
const assistantReply = response.data.choices[0].message.content;
// 添加助手回复到对话历史
this.conversationHistory.push({
role: "assistant",
content: assistantReply,
});
this.diagnosisResponse = assistantReply;
}
},
},
5. 注意事项
-
system
角色的作用-
用于设置对话的背景或指令。
-
如果不需要,可以省略。
-
-
user
角色的必要性- 必须包含
user
角色的消息,否则 API 无法生成回复。
- 必须包含
-
对话历史长度
-
每次请求都会消耗 token,因此需要控制对话历史的长度。
-
可以通过截断历史记录或设置最大 token 数来优化。
-
-
多轮对话的实现
-
将每次的用户输入和助手回复添加到
messages
中。 -
确保对话历史的顺序正确。
-
6. 总结
-
必须包含
user
角色,用于传递用户输入。 -
system
角色可选,用于设置对话背景。 -
多轮对话 需要将历史记录添加到
messages
中。