vue+java实现简易AI问答组件(基于百度文心大模型)
一、需求
公司想要在页面中加入AI智能对话功能,故查找免费gpt接口,最终决定百度千帆大模型(进入官网、官方文档中心);
二、主要功能列举
- AI智能对话;
- 记录上下文回答环境;
- 折叠/展开窗口;
- 可提前中止回答;
- 回答内容逐字展示并语音播报;
三、效果图
四、技术选型
1、前端环境
- node(14.21.3)
- VueCli 2
- element-ui(^2.15.14)
- axios
- node-sass(^4.14.1)
- sass-loader(^7.3.1)
- js-md5(^0.8.3)
2、后端环境
- JDK8
- springboot
五、声明
- 本文章以及源码纯粹自己写着玩,等于是个demo,有许多需要完善和优化的地方,仅供大家参考,有错误的地方欢迎大家批评指正~~
- 由于作者其实是java,所以前端代码中如果看到神奇的地方,希望大家包涵,哈哈哈哈
四、百度千帆大模型应用创建
1、访问官网,注册账号并登录;
2、选择“应用接入”-“创建应用”
进去填一个应用名及描述即可,服务默认全勾选上;
3、保存后返回应用列表,获取api key和secret key
PS:
百度提供的大模型服务有好多种,我此处是白嫖的其中一个免费的,如下图:
其中ERNIE开头的是百度自己的,文心一言用的就是这种,其他有些是三方大模型;
具体不同服务之间有什么区别可以看官方介绍,个人觉得免费的几个主要在于轻量等级、响应速度、回答内容复杂程度、可保存的上下文大小等几个方面;
五、部分后台代码
1、官网下载java sdk或者引入百度千帆pom
官放文档地址:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/7ltgucw50
java SDK地址:https://github.com/baidubce/bce-qianfan-sdk/tree/main/java
maven仓库地址:https://mvnrepository.com/artifact/com.baidubce/qianfan
POM:
<!-- https://mvnrepository.com/artifact/com.baidubce/qianfan -->
<dependency><groupId>com.baidubce</groupId><artifactId>qianfan</artifactId><version>0.0.4</version>
</dependency>
2、创建springboot项目,并导入sdk或引入千帆pom
此处是把sdk导入到工程中;
3、项目代码结构如下
pom.xml :
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.baidu</groupId><artifactId>aichat</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><name>aichat</name><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.9</version></parent><dependencies><!-- SpringBoot的依赖配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.2.13.RELEASE</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.10.1</version></dependency><dependency><groupId>org.apache.httpcomponents.client5</groupId><artifactId>httpclient5</artifactId><version>5.3.1</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.1.1.RELEASE</version><configuration><fork>true</fork> <!-- 如果没有该配置,devtools不会生效 --></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>3.1.0</version><configuration><failOnMissingWebXml>false</failOnMissingWebXml><warName>${project.artifactId}</warName></configuration></plugin></plugins><finalName>${project.artifactId}</finalName></build></project>
AiChatController.java:
package com.baidubce.controller;import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import com.baidubce.qianfan.Qianfan;
import com.baidubce.qianfan.core.builder.ChatBuilder;
import com.baidubce.qianfan.model.chat.ChatResponse;
import com.baidubce.qianfan.model.chat.Message;
import com.baidubce.utils.JsonUtils;
import com.baidubce.utils.SecUtils;@RestController
public class AiChatController {private static final String accessKey = "你创建的应用的API Key";private static final String secretKey = "你创建的应用的Secret Key";private static Qianfan qianfan = new Qianfan("OAuth", accessKey, secretKey);/*** 参数:* messages: 对话记录,role:user是用户,assistant是AI,如:[{"role":"user","content":"1"},{"role":"assistant","content":"“1”是一个数字。"},{"role":"user","content":"你是"},{"role":"assistant","content":""}]* timestamp:请求毫秒值,1717742825695* signature: 签名,4bc9c3b8dbe4de5bc924b6fa0506c606* @author x轩* @version 2024年6月7日 下午2:46:32*/@PostMapping("/sendMsg")public String sendMsg(@RequestBody Map<String, Object> params) {// 验签,我自己加的,防止恶意调用,作用不大,提高门槛而已if(!checkSign(params)) {return "签名不正确!";}String result = null;try {result = chat(String.valueOf(params.get("messages")));} catch (Exception e) {e.printStackTrace();return "接口繁忙,请稍后再试!";}return result;}/*** 参数:* messages: 业务参数* timestamp:请求毫秒值* signature: 签名* * 加签规则:* 要求1:timestamp和当前系统时间不能超过5秒钟* 要求2:MYCHAT|timestamp|messages拼接后MD53次加密** @author x轩* @version 2024年6月6日 下午4:13:03*/private boolean checkSign(Map<String, Object> params) {String timestamp = String.valueOf(params.get("timestamp"));String messages = String.valueOf(params.get("messages"));String signature = String.valueOf(params.get("signature"));if(StringUtils.isAnyBlank(timestamp, messages, signature)) {return false;}// 1.判断时间if((System.currentTimeMillis()- Long.valueOf(timestamp))>5000) {// 过期return false;}// 2.验签String p = "MYCHAT|"+timestamp+"|"+messages;String md5of3 = SecUtils.encoderByMd5With32Bit(SecUtils.encoderByMd5With32Bit(SecUtils.encoderByMd5With32Bit(p)));if(!signature.equalsIgnoreCase(md5of3)) {return false;}return true;}public static void main(String[] args) {
// chat("对于调休你怎么看");chatStream("介绍一下自己");}private static String chat(String messages) {ChatBuilder bulder = qianfan.chatCompletion()
// .model("ERNIE-Speed-128K")
// .model("ERNIE-Speed-8K").model("ERNIE-Tiny-8K");List<Message> messageList = JsonUtils.readValues(messages, Message.class);// 过滤一下,去除空内容对象messageList = messageList.stream().filter(m->{return StringUtils.isNotBlank(m.getContent());}).collect(Collectors.toList());for(Message m : messageList) {bulder.addMessage(m);}ChatResponse response = bulder.execute();return response.getResult();}private static void chatStream(String message) {Iterator<ChatResponse> stream = qianfan.chatCompletion()
// .model("ERNIE-Speed-128K")
// .model("ERNIE-Speed-8K").model("ERNIE-Tiny-8K").addMessage("user", message).executeStream();while(stream.hasNext()) {System.out.println(stream.next().getResult());}}
}
六、 Vue部分代码
1、vue.config.js
const port = process.env.port || process.env.npm_config_port || 80 // 端口module.exports = {lintOnSave: false,publicPath: "/aichat-front",assetsDir: 'static',// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。productionSourceMap: false,devServer: {host: '0.0.0.0',port: port,open: true,proxy: {['/aichat']: {target: `http://127.0.0.1:8080/aichat`,changeOrigin: true,pathRewrite: {['^/aichat']: ''}},},},
}
2、App.vue
<template><div id="app"><qian-fan-chat/></div>
</template><script>
import QianFanChat from './components/QianFanChat'export default {name: 'App',components: {QianFanChat}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
</style>
3、@/components/QianFanChat组件
<template><div class="chat-div"><div v-show="showChatBox" class="chat-main"><div id="messagediv" class="messagediv"><div class="item"><img class="avatar" :src="aiAvatar" ><div class="answerDiv"><p>我是AI智能小助手,有问题请咨询我吧!</p></div></div><div v-for="(item, index) in messageList" class="item"><img v-if="item.role=='assistant'" class="avatar" :src="aiAvatar" ><img v-if="item.role=='user'" class="avatar" :src="userAvatar" ><div class="answerDiv"><p v-if="!item.loading" v-html="item.content"></p><p v-else>思考中 <i class="el-icon-loading"></i></p><a v-if="index==messageList.length-1 &&item.role=='assistant' && (loading || speaking)" href="#" @click="stopAnswer">停止回答</a></div></div></div><div class="sendDiv"><el-input @keyup.enter.native="getAnswer" v-model="question" placeholder="输入中医药相关内容搜一搜"></el-input><el-button @click="getAnswer"><i class="el-icon-s-promotion"></i></el-button></div></div><div v-show="showChatBox" class="close-btn" @click="showChatBox=false"><i class="el-icon-close"></i></div><div v-show="!showChatBox" class="small-window" @click="showChatBox=true">AI问答</div></div>
</template>
<script>
const msg = new SpeechSynthesisUtterance();import { sendMsg } from '@/api/aichat';
import { sign } from '@/utils/securityUtil'
import aiAvatar from '@/assets/images/ai-avatar.jpg';
import userAvatar from '@/assets/images/user-avatar.jpg';export default {name: 'QianFanChat',data(){return {showChatBox: false,loading: false,speaking: false,aiAvatar,userAvatar,question:'',messageList:[],// 逐字输出 STARTtimer: null,length: 0,index: 0,// 逐字输出 END}},mounted(){},methods: {getAnswer(){if(this.loading){this.$message({type: 'warning', message:'正在回答,请耐心等待!'});return;}if(!this.question.trim()){this.$message({type: 'warning', message:'请输入内容!'});return;}this.loading = true;let tmpQustion = this.question;this.question = '';this.messageList.push({ role:'user', content: tmpQustion, loading: false });this.messageList.push({ role:'assistant', content: '' , loading: true});this.$nextTick(()=>{this.scroll();})let params = {messages: JSON.stringify(this.messageList)};params.timestamp = new Date().getTime();params.signature = sign(params);sendMsg(params).then(res=>{// 判断loading是否被中断(停止回答可中断)if(!this.loading){// 点击了“停止回答”return;}// 接口请求完毕,替换最后一条内容this.messageList[this.messageList.length-1].loading = false;this.index = 0;this.length = res.length;this.handleSpeak(res);// 一个字一个字给我蹦this.timer = setInterval(()=>{if(this.index<=this.length-1){let word = res.charAt(this.index);if(word=='\n'){word = '<br>'}this.messageList[this.messageList.length-1].content += word;this.index++;}else{// 结束this.loading = false;clearInterval(this.timer);}this.scroll();}, 30);})},scroll(){messagediv.scrollTo({top: messagediv.scrollHeight,})},stopAnswer(){this.handleStop();clearInterval(this.timer);this.length = 0;this.index = 0;this.loading = false;// 判断最后一条内容是不是空,是则给上默认输出let lastMsg = this.messageList[this.messageList.length-1];if(!lastMsg.content){lastMsg.loading = false;lastMsg.content = '请继续向我提问吧!';}},// 语音播报的函数handleSpeak(text) {this.handleStop();this.speaking = true;// 处理多音字msg.text = text; // 朗读内容msg.lang = "zh-CN"; // 使用的语言:中文 msg.volume = 0.5; // 声音音量:1 设置将在其中发言的音量。区间范围是0到1,默认是1msg.rate = 1.6; // 语速:1 设置说话的速度。默认值是1,范围是0.1到10,表示语速的倍数,例如2表示正常语速的两倍msg.pitch = 1.5; // 音高:2 设置说话的音调(音高)。范围从0(最小)到2(最大)。默认值为1// msg.voiceURI = 'Google 普通话(中国大陆)';msg.onstart = (e)=>{};msg.onend = (e)=>{this.speaking = false;};msg.onboundary = (e) => {}speechSynthesis.speak(msg); // 播放},// 语音停止handleStop(e) {this.speaking = false;msg.text = e;msg.lang = "zh-CN";speechSynthesis.cancel(msg);},}
}
</script>
<style lang="scss" scoped>::v-deep {.el-input {width: 270px;input {background-color: rgba(0,0,0,.5);border: none;color: white;}}.el-button {background-color: rgba(0,0,0,.5);border: none;margin-left: 10px;padding: 0 20px;i {font-size: 20px;color: white;}&:focus {background-color: rgba(0,0,0,.5);}&:hover {background-color: white;i {color: black;}}}}.chat-div {position: absolute;top: 0;left: 0;display: flex;z-index: 99;cursor: pointer;.close-btn {margin-top: 18px;color: white;background-color: rgba(0, 0, 0, .6);height: 30px;width: 30px;text-align: center;line-height: 30px;border-radius: 50%;}.small-window {color: white;margin-top: 18px;padding: 10px;background-color: rgba(16, 168, 129, .8);width: 26px;font-size: 20px;border-top-right-radius: 10px;border-bottom-right-radius: 10px;}}.chat-main {border-radius: 4px;margin: 10px 0;padding: .1rem .1rem;width: 374px;.messagediv {overflow: auto;max-height: 60vh;.item {display: flex;margin-bottom: .1rem;.avatar {width: 40px;height: 40px;}.answerDiv {p {color: white;background-color: rgba(0, 0, 0, .6);padding: 10px;margin: 0 10px;font-size: 16px;border-radius: 6px;text-align: left;}a {cursor: pointer;font-size: 15px;color: red;text-decoration: underline;margin-left: 10px;font-weight: bold;}}}&::-webkit-scrollbar {width: 0;}}.sendDiv {display: flex;justify-content: end;margin: 10px 10px 0 0;}}
</style>
4、@/utils/request.js
import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({// axios中请求配置有baseURL选项,表示请求URL公共部分baseURL: process.env.VUE_APP_BASE_API,// 超时timeout: 50000
})
// request拦截器
service.interceptors.request.use(config => {// get请求映射params参数if (config.method === 'get' && config.params) {let url = config.url + '?';for (const propName of Object.keys(config.params)) {const value = config.params[propName];var part = encodeURIComponent(propName) + "=";if (value !== null && typeof (value) !== "undefined") {if (typeof value === 'object') {for (const key of Object.keys(value)) {if (value[key] !== null && typeof (value[key]) !== 'undefined') {let params = propName + '[' + key + ']';let subPart = encodeURIComponent(params) + '=';url += subPart + encodeURIComponent(value[key]) + '&';}}} else {url += part + encodeURIComponent(value) + "&";}}}url = url.slice(0, -1);config.params = {};config.url = url;}return config
}, error => {console.log(error)Promise.reject(error)
})// 响应拦截器
service.interceptors.response.use(res => {return res.data;},error => {console.log('err' + error)let { message } = error;if (message == "Network Error") {message = "后端接口连接异常";}else if (message.includes("timeout")) {message = "系统接口请求超时";}else if (message.includes("Request failed with status code")) {message = "系统接口" + message.substr(message.length - 3) + "异常";}Message({message: message,type: 'error',duration: 5 * 1000})return Promise.reject(error)}
)export default service
5、@/utils/securityUtil.js
PS: 由于这个项目不需要登录,我又怕接口泄露导致别人恶意调用,所以给接口加了个签名,具体策略大家可以自定义(讲真的,没什么用,前台加签别人打开调试模式照样可以看到加签策略。。。为了应对这个情况,我把前台加签JS给做了个混淆,算是增加一下门槛吧;还可以禁止用户点击F12和右键事件【具体代码见此篇文章】)
// 加签方法,方法接收两个参数: timestamp和messages(消息JSON字符串),返回签名;已混淆,以下代码具体签名策略如下:固定字符串"MYCHAT"、时间戳、消息体用|拼接后进行3次MD5加密:如MYCHAT|1718181053994|[{"role":"user","content":"1"},{"role":"assistant","content":"“1”是一个数字。"}]
const _0x4e66=['MYCHAT','timestamp'];const _0x3524=function(_0x4e6602,_0x35247b){_0x4e6602=_0x4e6602-0x0;let _0x2ee47d=_0x4e66[_0x4e6602];return _0x2ee47d;};import _0x50d0de from'js-md5';export function sign(_0x5c789a){let _0x1bf721='|'+_0x5c789a[_0x3524('0x1')];let _0x202f97='|'+_0x5c789a['messages'];let _0x74f806=_0x3524('0x0')+_0x1bf721+_0x202f97;_0x74f806=_0x50d0de(_0x74f806);_0x74f806=_0x50d0de(_0x74f806);_0x74f806=_0x50d0de(_0x74f806);return _0x74f806;}
6、@/api/aichat.js
import request from '@/utils/request'export function sendMsg(data) {return request({url: '/sendMsg',method: 'post',data: data})}
有问题或者需要完整项目源码的话私聊吧,关机下班底薪到手~
相关文章:
vue+java实现简易AI问答组件(基于百度文心大模型)
一、需求 公司想要在页面中加入AI智能对话功能,故查找免费gpt接口,最终决定百度千帆大模型(进入官网、官方文档中心); 二、主要功能列举 AI智能对话;记录上下文回答环境;折叠/展开窗口&#…...
刷代码随想有感(104):动态规划——01背包问题/二维dp数组
题干: 代码: #include<bits/stdc.h> using namespace std; int n,bagweight; void solve(){vector<int>weight(n, 0);vector<int>value(n, 0);for(int i 0; i < n; i){cin>>weight[i];}for(int j 0; j < n; j){cin>…...
Docker-Portainer可视化管理工具
Docker-Portainer可视化管理工具 文章目录 Docker-Portainer可视化管理工具介绍资源列表基础环境一、安装Docker二、配置Docker加速器三、拉取Portainer汉化版本镜像四、运行容器五、访问可视化界面 介绍 Portainer是一款开源的容器管理平台,它提供了一个直观易用的…...
SqlSugar 集成
1 关于 SqlSugar SqlSugar 是 .NET/C# 平台非常优秀的 ORM 框架,目前 Nuget 总下载突破 700K,Github 关注量也高达 3.2K,是目前当之无愧的国产优秀 ORM 框架之一。 SqlSugar 官方地址:果糖网 ( SqlSugar 官网 &#…...
MySQL Connector/C++ 和 MySQL Connector/ODBC 的区别
MySQL Connector/C++ 和 MySQL Connector/ODBC 是两种不同的数据库连接工具,它们各自有不同的特点和用途。以下是它们之间的一些主要区别: 1. **编程接口**: - MySQL Connector/C++ 提供了面向对象的编程接口,它是用C++编写的,提供了C++特有的类和对象来与MySQL数据库…...
Weevil-Optimizer象鼻虫优化算法的matlab仿真实现
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 Weevil-Optimizer象鼻虫优化算法的matlab仿真实现,仿真输出算法的优化收敛曲线,对比不同的适应度函数。 2.测试软件版本以及运行结果展示…...
Web前端项目-交互式3D魔方【附源码】
交互式3D魔方 3D魔方游戏是一款基于网页技术的三维魔方游戏。它利用HTML、CSS和JavaScript前端技术来实现3D效果,并在网页上呈现出逼真的魔方操作体验。 运行效果: 一:index.html <!DOCTYPE html> <html><head><…...
视频格式转换avi格式怎么弄?分享视频转换方法
视频格式转换avi格式怎么弄?AVI作为一种广泛支持的视频格式,能够在多种设备和播放器上顺畅播放,确保我们的视频内容能够无障碍地分享给朋友或上传至各大平台。其次,AVI格式通常具有较好的兼容性,能够避免格式转换过程中…...
UniRx 入门
Reactive X 是 Reactive Extensions 的缩写,一般简写为 Rx,最初是 LINQ 的一个扩展,由微软的团队开发,Rx 是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流,支持大部…...
简单游戏制作——飞行棋
控制台初始化 int w 50; int h 50; ConsoleInit(w, h); static void ConsoleInit(int w, int h) {//基础设置//光标的隐藏Console.CursorVisible false;//舞台的大小Console.SetWindowSize(w, h);Console.SetBufferSize(w, h); } 场景选择相关 #region 场景选择相关 //声…...
等保一体机
等保一体机是面向等保场景推出的合规型安全防护产品。基于“一个中心,三重防护”的设计理念,通过内置全面、多样的安全能力,为政府、医疗、教育、企业等中小型客户提供快速合规、按需赋能的一站式等保合规解决方案。 等保一体机要求管理网络和…...
什么是寄存器文件(Register File)?
寄存器文件(Register File)是计算机系统中用于存储处理器操作数的小型、快速的存储单元集。它在 CPU 内部,提供极高的访问速度,通常用于存储临时数据、操作数和指令执行过程中的中间结果。 寄存器文件的组成和特点 寄存器集&…...
6月15号作业
使用手动连接,将登录框中的取消按钮使用第二中连接方式,右击转到槽,在该槽函数中,调用关闭函数 将登录按钮使用qt4版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin"࿰…...
零基础入门学用Arduino 第三部分(三)
重要的内容写在前面: 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。个人把这个教程学完之后,整体感觉是很好的,如果有条件的可以先学习一些相关课程,学起来会更加轻松,相关课程有数字电路…...
Trusty qemu + android环境搭建详细步骤
下载源码 mkdir trusty cd trusty repo init -u https://android.googlesource.com/trusty/manifest -b master repo sync -j32 编译 ./trusty/vendor/google/aosp/scripts/build.py generic-arm64 查看编译结果 ls build-root/build-generic-arm64/lk.bin 安装运行依赖 …...
杀戮尖塔游戏
Java 你正在玩策略卡牌杀戮尖塔游戏,轮到你出牌,手里N张攻击卡,每张都需要花金币coust[i]和获得伤害dmager[i]。 最多花3金币能造成的最大伤害是多少? class Solution{public int calc(int[] cost, int[] dmager, N){int[][] db …...
Kubernetes (K8s) 和 Spring Cloud 的区别
Kubernetes (K8s) 和 Spring Cloud 是两种常用的云原生技术,它们在微服务架构和云计算领域中扮演着重要的角色。尽管两者都有助于开发和部署微服务,但它们的功能和目标存在显著差异。本文将详细讨论 Kubernetes 和 Spring Cloud 的区别,从它们…...
定个小目标之刷LeetCode热题(21)
这是道技巧题,利用了 (num - 1)% n 计算下标的形式来将数组元素与数组索引产生映射关系,代码如下,可以看下注释 class Solution {public List<Integer> findDisappearedNumbers(int[] nums) {int n nums.lengt…...
Oracle 打开钱包 ORA-28368: cannot auto-create wallet
ORA-28368: cannot auto-create wallet 开启钱包抱错,看下钱包信息 SQL> select * from v$encryption_wallet;WRL_TYPE -------------------- WRL_PARAMETER -------------------------------------------------------------------------------- STATUS ------…...
【麒麟虚拟机】NetworkManager没有运行
麒麟V10 建linux麒麟虚拟机,发现,网络没有配置 提示,NetworkManager没有运行。编辑联接也不能配置 解决方法,在终端输入命令: sudo systemctl start NetworkManager 启动以后,编辑连接选自动以太网&…...
vue之一键部署的shell脚本和它的点.bat文件、海螺AI、ChatGPT
MENU 前言vite.config.ts的配置deploy文件夹的其他内容remote.shpwd.txtdeploy.bat 前言 1、在src同级新建deploy.bat文件; 2、在src同级新建deploy文件夹,文件夹中新建pwd.txt和remote.sh文件; 3、配置好后,直接双击deploy.bat文…...
pg和oracle的区别
1、从功能上来说pg要比oracle数据库弱。 2、pg不支持索引组织表。 pg和oracle的相似之处: 1、使用共享内存的进程结构,客户端与数据库服务器建立一个连接后,数据库服务器就启动一个进程为这个连接服务。这与mysql的线程模型不一样。 2、p…...
Docker:在DockerHub上创建私有仓库
文章目录 Busybox创建仓库推送镜像到仓库 本篇开始要学习在DockerHub上搭建一个自己的私有仓库 Busybox Busybox是一个集成了三百多个最常用Linux命令和工具的软件,BusyBox包含了很多工具,这里拉取该镜像推送到仓库中: 安装 apt install …...
框架的使用
什么是框架? 盖房子,框架结构 框架结构就是房子主体,基本功能 把很多基础功能已经实现(封装了) 框架:在基础语言之上,对各种基础功能进行封装,方便开发者,提高开发效…...
Autosar-DEM诊断事件管理流程
文章目录 前言一、故障事件监控二、故障信息上报三、故障信息处理Event的使能条件四、故障信息存储五、故障系统降级关联文章:Autosar实践——DEM配置 前言 DEM全称“Diagnostic Event Management”,该模块是AUTOSAR架构中的BSW模块之一。谈到故障,我们首先会想到如何去监控…...
LabVIEW输送机动态特性参数监测系统
开发了一套基于LabVIEW软件和STM32F103ZET6单片机的带式输送机动态特性参数监测系统。该系统通过电阻应变式压力传感器和光电编码器实时采集输送带的张力和带速信息,通过5G模块将数据传输至上位机,实现数据的可视化处理与实时预警,有效提高输…...
绿色版DirectoryOpus功能强大且高度可定制的Windows文件管理器
Directory Opus(通常简称为DOpus)是一款功能强大且高度可定制的Windows文件管理器。它提供了许多超越Windows默认文件资源管理器(Explorer)的功能,使得文件和文件夹的管理变得更加高效和直观。以下是对Directory Opus的…...
Cocos Creator,Youtube 小游戏!
YouTube 官方前段时间发布了一则重磅通知,宣布平台旗下小游戏功能 Youtube Playables 正式登录全平台(安卓、iOS、网页),并内置了数十款精选小游戏。 Youtube Playables 入口: https://www.youtube.com/playables Coco…...
分层解耦
三层架构 controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据, service:业务逻辑层,处理具体的业务逻辑。 dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数…...
GenICam标准(六)
系列文章目录 GenICam标准(一) GenICam标准(二) GenICam标准(三) GenICam标准(四) GenICam标准(五) GenICam标准(六) 文章目录 系列文…...
多说评论插件对网站优化/yy直播
文/苏格兰折耳猫 图片来源于网络Social Listening可以帮助企业实现如下图所示的几个商业目标,这引起了一些新媒体、咨询从业者浓厚的兴趣,他们强烈要求笔者继续对Social Listening的分析方法和应用场景做进一步的阐述。作为回应,笔者将在本文…...
网站开发 ssh 菜鸟/seo课程培训机构
介绍 在Kubernetes集群上运行多个服务和应用程序时,集中式集群级日志记录可以帮助您快速排序和分析Pod生成的大量日志数据。 一种流行的集中式日志记录解决方案是Elasticsearch, F luentd和K ibana(EFK)。 Elasticsearch是一个实…...
淄博logo设计公司/淘宝优化
详细解答与dp序列初始化请见Carl大佬:点击链接 动态规划序列含义: dp[持有股票][不持股票] 持有股票: 应该为最便宜的股票,(积累问题→\rightarrow→)或者是在上一次(不一定刚刚就是上一支就…...
做公司网站棋牌/购买友情链接
今天说说以***者的角度去谈谈服务器被干掉后,我们该做的哪些防护和检查工作,高手的话都比较熟悉系统加固和安全的问题,对于我等初学者来说,没有做过从事过安全方面工作,所以只能从***者的角度去说说相对立的工作。因为…...
主题网站设计模板/百度模拟搜索点击软件
准备好滚滚的JOE – Java on Everything吗? Java on Everything掌握了如何在几乎所有内容上运行Java的关键。 没有操作系统? 没问题。 JOE无需操作系统即可工作。 放弃操作系统的好处是什么? Java on Everything是由约瑟夫库里格(…...
怎么能自己做网站/百度seo排名优化价格
使用Z-偏移量 在一个三维场景中,我们可以对共面的多边形使用z-偏移量来使它们不再共面。这项技术通常用于在场景中正确的显示阴影。例如,一堵墙上的阴影与这堵墙的深度值是相同的,如果我们先渲染了墙再来渲染阴影,那么阴影就有可能…...