自己的网页加一个搜索框,调用deepseek的API

ops/2025/3/11 22:42:47/

一切源于一个学习黑马程序员视频的突发奇想
在网页悬浮一个搜索按钮,点击可以实现调用deepseek文本模型回答你的问题

前端实现

前端使用vue实现的

首先是整体页面:AIWidget.vue

javascript"><template><div><!-- 悬浮 AI 按钮 --><el-button class="floating-button" @click="dialogVisible = true"><el-icon><Search /></el-icon></el-button><!-- AI 搜索框 --><el-dialog v-model="dialogVisible" title="AI 搜索" width="400px"><el-inputv-model="query"placeholder="请输入搜索内容..."@keyup.enter="handleSearch"/><el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button><el-divider /><el-scrollbar height="200px"><ul v-if="results.length"><li v-for="(item, index) in results" :key="index">{{ item }}</li></ul><p v-else class="no-result">暂无搜索结果</p></el-scrollbar></el-dialog></div>
</template><script>
import { ref, watch } from "vue";
import { Search } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { aiSearch } from "@/api/aiSearch";
import { debounce } from "lodash-es";export default {components: { Search },setup() {const dialogVisible = ref(false);const query = ref("");const results = ref([]);const loading = ref(false);const handleSearch = debounce(async () => {const cleanQuery = query.value.trim().replace(/<[^>]*>?/gm, "");if (!cleanQuery) return;loading.value = true;try {const response = await aiSearch(cleanQuery);results.value = response.data || [];} catch (error) {ElMessage.error("搜索失败:" + error.message);results.value = [];} finally {loading.value = false;}}, 500);watch(dialogVisible, (val) => {if (!val) {query.value = "";results.value = [];}});return { dialogVisible, query, results, loading, handleSearch };},
};
</script><style scoped>
.floating-button {position: fixed;bottom: 20px;right: 20px;width: 50px;height: 50px;font-size: 20px;border-radius: 50%;background-color: #409eff;color: white;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);cursor: pointer;transition: background-color 0.3s;
}.floating-button:hover {background-color: #66b1ff;
}.search-btn {margin-top: 10px;width: 100%;
}.no-result {text-align: center;color: gray;
}
</style>

直接放在src/commpoents
接下来是JS文件,直接放在 src/api/
aiSearch.js

javascript">import request from '@/utils/request';// AI 搜索 API 请求
export function aiSearch(query) {return request({url: '/ai-search',method: 'get',params: { q: query }});
}

为了在每个页面的右下角都显示这个搜索框,我们直接导入组件到App.vue
App.vue

javascript"><template><div><router-view /><AIWidget /> <!-- 悬浮 AI 按钮 --></div></template><script setup>
import useSettingsStore from '@/store/modules/settings'
import { handleThemeStyle } from '@/utils/theme'
import AIWidget from "@/components/AIWidget.vue"; // 导入 AI 搜索组件onMounted(() => {nextTick(() => {// 初始化主题样式handleThemeStyle(useSettingsStore().theme)})
})</script>

后端实现

首先在 application.yml 添加配置:

siliconflow:api:url: https://api.siliconflow.cn/v1/chat/completionstoken: your_token_here  # 替换为实际tokenmodel: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B

创建请求/响应 DTO 对象:
AiSearchReq.java

java">package com.dkd.manage.controller.AI;import com.dkd.common.core.domain.R;
import com.dkd.manage.service.AI.IAiSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/ai-search")
public class AiSearchController {@Autowiredprivate IAiSearchService aiSearchService;@GetMapping("")public R<List<String>> search(@RequestParam String q) {return R.ok(aiSearchService.searchAI(q));}
}

ChatCompletionReq.java

java">package com.dkd.manage.domain.dto.AI;import lombok.AllArgsConstructor;
import lombok.Data;import java.util.ArrayList;
import java.util.List;@Data
public class ChatCompletionReq {private String model;private List<Message> messages;private boolean stream = false;private int max_tokens = 512;private double temperature = 0.7;private double top_p = 0.7;private int top_k = 50;private double frequency_penalty = 0.5;private int n = 1;private ResponseFormat response_format = new ResponseFormat("text");//private List<Tool> tools = new ArrayList<>();@Data@AllArgsConstructorpublic static class Message {private String role;private String content;}@Data@AllArgsConstructorpublic static class ResponseFormat {private String type;}@Datapublic static class Tool {private String type = "function";private ToolFunction function = new ToolFunction();}@Datapublic static class ToolFunction {private String description = "";private String name = "";private Object parameters = new Object();private boolean strict = false;}
}

ChatCompletionResp.java

java">package com.dkd.manage.domain.dto.AI;import lombok.Data;import java.util.List;@Data
public class ChatCompletionResp {private List<Choice> choices;@Datapublic static class Choice {private Message message;}@Datapublic static class Message {private String content;}
}

Controller 层:
AiSearchController.java

java">package com.dkd.manage.controller.AI;import com.dkd.common.core.domain.R;
import com.dkd.manage.service.AI.IAiSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/ai-search")
public class AiSearchController {@Autowiredprivate IAiSearchService aiSearchService;@GetMapping("")public R<List<String>> search(@RequestParam String q) {return R.ok(aiSearchService.searchAI(q));}
}

Service 接口:
IAiSearchService.java

java">package com.dkd.manage.service.AI;import java.util.List;public interface IAiSearchService {List<String> searchAI(String query);
}

Service 实现:
AiSearchServiceImpl.java

java">package com.dkd.manage.service.impl;import com.dkd.common.exception.ServiceException;
import com.dkd.manage.domain.dto.AI.ChatCompletionReq;
import com.dkd.manage.domain.dto.AI.ChatCompletionResp;
import com.dkd.manage.service.AI.IAiSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.util.Arrays;
import java.util.Collections;
import java.util.List;@Service
public class IAiSearchServiceImpl implements IAiSearchService {@Value("${siliconflow.api.url}")private String apiUrl;@Value("${siliconflow.api.token}")private String apiToken;@Value("${siliconflow.api.model}")private String model;@Autowiredprivate RestTemplate restTemplate;@Overridepublic List<String> searchAI(String query) {// 1. 构建请求头HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);headers.setBearerAuth(apiToken);// 2. 构建请求体ChatCompletionReq request = new ChatCompletionReq();request.setModel(model);request.setMessages(Collections.singletonList(new ChatCompletionReq.Message("user", query)));// 3. 发送请求HttpEntity<ChatCompletionReq> entity = new HttpEntity<>(request, headers);ResponseEntity<ChatCompletionResp> response = restTemplate.exchange(apiUrl,HttpMethod.POST,entity,ChatCompletionResp.class);// 4. 处理响应if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {String content = response.getBody().getChoices().get(0).getMessage().getContent();return Arrays.asList(content.split("\\n"));}throw new ServiceException("AI 服务调用失败");}
}

配置 RestTemplate(如果尚未配置):
RestTemplateConfig.java

放在framework/src/main/<a class=java/com/" />

java">package com.dkd.framework.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}

http://www.ppmy.cn/ops/165037.html

相关文章

golang从入门到做牛马:第八篇-Go语言运算符-数学与逻辑的“魔法棒”

在Go语言中,运算符就像是数学与逻辑的“魔法棒”,它们可以在程序运行时执行各种操作。Go语言提供了丰富的运算符,包括算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符和其他运算符。接下来,让我们一起探索这些运算符的奥秘。 算术运算符:数字的“加减乘除” 算…

[Java]使用java进行JDBC编程

首先要从中央仓库下载api(类似驱动程序)&#xff0c;为了链接java和mysql 下载jar包&#xff0c;需要注意的是jar包的版本要和mysql保持一致 下面是新建文件夹lib&#xff0c;把jar包放进去&#xff0c;并添加为库 sql固定的情况下运行 import com.mysql.cj.jdbc.MysqlDataSo…

Uniapp项目运行到微信小程序、H5、APP等多个平台教程

摘要&#xff1a;Uniapp作为一款基于Vue.js的跨平台开发框架&#xff0c;支持“一次开发&#xff0c;多端部署”。本文将手把手教你如何将Uniapp项目运行到微信小程序、H5、APP等多个平台&#xff0c;并解析常见问题。 一、环境准备 在开始前&#xff0c;请确保已安装以下工具…

MySQL环境安装详细教程(Windows/macOS/Linux)

摘要&#xff1a;本文详细介绍了在Windows、macOS和Linux三大操作系统下安装MySQL数据库的完整流程&#xff0c;帮助开发者快速搭建本地MySQL环境。 一、MySQL安装前准备 官网下载 访问MySQL官网 → 选择"Downloads" → 选择"MySQL Community (GPL) Downloads&…

DeepSeek V3 源码:从入门到放弃!

从入门到放弃 花了几天时间&#xff0c;看懂了DeepSeek V3 源码的逻辑。源码的逻辑是不难的&#xff0c;但为什么模型结构需要这样设计&#xff0c;为什么参数需要这样设置呢&#xff1f;知其然&#xff0c;但不知其所以然。除了模型结构以外&#xff0c;模型的训练数据、训练…

GStreamer —— 2.9、Windows下Qt加载GStreamer库后运行 - “教程9:媒体信息收集“(附:完整源码)

简介 上一个教程演示了多线程和 Pad 可用性。本教程介绍媒体信息收集。有时&#xff0c;您可能希望快速找出文件的媒体类型 &#xff08;或 URI&#xff09;包含媒体&#xff0c;或者您是否能够播放媒体。你 可以构建一个管道&#xff0c;将其设置为 Run&#xff0c;并监视总线…

C#实现高性能异步文件下载器(支持进度显示/断点续传)

一、应用场景分析 异步文件下载器用处很大&#xff0c;当我们需要实现以下功能时可以用的上&#xff1a; 大文件下载&#xff08;如4K视频/安装包&#xff09; 避免UI线程阻塞&#xff0c;保证界面流畅响应多任务并行下载 支持同时下载多个文件&#xff0c;提升带宽利用率后台…

引领变革!北京爱悦诗科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!

在2025年“GAS消费电子科创奖”评选中&#xff0c;北京爱悦诗科技有限公司提交的“aigo爱国者GS06”&#xff0c;在技术创新性、设计创新性、工艺创新性、智能化创新性及原创性五大维度均获得评委的高度认可&#xff0c;荣获“产品创新奖”。 这一奖项不仅是对爱悦诗在消费电子…