商品管理幻灯图片更换实现
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.mapper.ProductMapper"><resultMap id="productResult" type="com.java1234.entity.Product"><association property="type" column="typeId" select="com.java1234.mapper.SmallTypeMapper.findById"></association></resultMap><select id="list" parameterType="Map" resultMap="productResult">select * from t_product<where><if test="name!=null and name!='' ">and name like concat('%',#{name},'%')</if></where><if test="start!=null and pageSize!=null ">limit #{start},#{pageSize}</if></select><select id="getTotal" parameterType="Map" resultType="Long">select count(*) from t_product<where><if test="name!=null and name!='' ">and name like concat('%',#{name},'%')</if></where></select><insert id="add" parameterType="com.java1234.entity.Product">insert into t_product values(null,#{name},#{price},#{stock},#{proPic},#{hot},#{swiper},#{swiperPic},#{swiperSort},#{type.id},null,#{productIntroImgs},#{productParaImgs},#{description});</insert><update id="update" parameterType="com.java1234.entity.Product">update t_product<set><if test="name!=null and name!=''">name=#{name},</if><if test="price!=null">price=#{price},</if><if test="stock!=null">stock=#{stock},</if><if test="type!=null and type.id!=null">typeId=#{type.id},</if><if test="proPic!=null and proPic!=''">proPic=#{proPic},</if><if test="description!=null and description!=''">description=#{description},</if><if test="productIntroImgs!=null and productIntroImgs!=''">productIntroImgs=#{productIntroImgs},</if><if test="productParaImgs!=null and productParaImgs!=''">productParaImgs=#{productParaImgs},</if><if test="swiperPic!=null and swiperPic!=''">swiperPic=#{swiperPic},</if><if test="swiperSort!=null">swiperSort=#{swiperSort},</if></set>where id=#{id}</update><select id="findById" parameterType="Integer" resultMap="productResult">select * from t_product where id=#{id}</select></mapper>
package com.java1234.controller.admin;import com.java1234.entity.*;
import com.java1234.service.IProductService;
import com.java1234.util.DateUtil;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 管理端-商品Controller控制器* @author java1234_小锋* @site www.java1234.com* @company 南通小锋网络科技有限公司* @create 2022-02-14 6:54*/
@RestController
@RequestMapping("/admin/product")
public class AdminProductController {@Autowiredprivate IProductService productService;@Value("${productImagesFilePath}")private String productImagesFilePath;@Value("${swiperImagesFilePath}")private String swiperImagesFilePath;/*** 根据条件分页查询* @param pageBean* @return*/@RequestMapping("/list")public R list(@RequestBody PageBean pageBean){System.out.println(pageBean);Map<String,Object> map=new HashMap<>();map.put("name",pageBean.getQuery().trim());map.put("start",pageBean.getStart());map.put("pageSize",pageBean.getPageSize());List<Product> productList = productService.list(map);Long total = productService.getTotal(map);Map<String,Object> resultMap=new HashMap<>();resultMap.put("productList",productList);resultMap.put("total",total);return R.ok(resultMap);}/*** 更新热门状态* @param id* @param hot* @return*/@GetMapping("/updateHot/{id}/state/{hot}")public R updateHot(@PathVariable(value = "id")Integer id,@PathVariable(value = "hot")boolean hot){Product product=productService.getById(id);product.setHot(hot);if(hot){product.setHotDateTime(new Date());}else{product.setHotDateTime(null);}productService.saveOrUpdate(product);return R.ok();}/*** 更新swiper状态* @param id* @param swiper* @return*/@GetMapping("/updateSwiper/{id}/state/{swiper}")public R updateSwiper(@PathVariable(value = "id")Integer id,@PathVariable(value = "swiper")boolean swiper){Product product=productService.getById(id);product.setSwiper(swiper);productService.saveOrUpdate(product);return R.ok();}/*** 删除* @param id* @return*/@GetMapping("/delete/{id}")public R delete(@PathVariable(value = "id")Integer id){productService.removeById(id);return R.ok();}/*** 添加或修改* @param product* @return*/@RequestMapping("/save")public R save(@RequestBody Product product){System.out.println("product"+product);if(product.getId()==null || product.getId() == -1){productService.add(product);}else{productService.update(product);}return R.ok();}/*** 上传商品大类图片* @param file* @return* @throws Exception*/@RequestMapping("/uploadImage")public Map<String,Object> uploadImage(MultipartFile file)throws Exception{Map<String,Object> resultMap=new HashMap<>();if(!file.isEmpty()){//获取文件名String originalFilename = file.getOriginalFilename();String suffixName=originalFilename.substring(originalFilename.lastIndexOf("."));String newFileName= DateUtil.getCurrentDateStr() + suffixName;FileUtils.copyInputStreamToFile(file.getInputStream(),new File(productImagesFilePath+newFileName));resultMap.put("code",0);resultMap.put("msg","上传成功");Map<String,Object> dataMap=new HashMap<>();dataMap.put("title",newFileName);dataMap.put("src","/image/product/"+newFileName);resultMap.put("data",dataMap);}return resultMap;}/*** 上传swiper幻灯图片* @param file* @return* @throws Exception*/@RequestMapping("/uploadSwiperImage")public Map<String,Object> uploadSwiperImage(MultipartFile file)throws Exception{Map<String,Object> resultMap=new HashMap<>();if(!file.isEmpty()){//获取文件名String originalFilename = file.getOriginalFilename();String suffixName=originalFilename.substring(originalFilename.lastIndexOf("."));String newFileName= DateUtil.getCurrentDateStr() + suffixName;FileUtils.copyInputStreamToFile(file.getInputStream(),new File(swiperImagesFilePath+newFileName));resultMap.put("code",0);resultMap.put("msg","上传成功");Map<String,Object> dataMap=new HashMap<>();dataMap.put("title",newFileName);dataMap.put("src","/image/swiper/"+newFileName);resultMap.put("data",dataMap);}return resultMap;}
}
server:port: 8080servlet:context-path: /spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_java1234_mall_v3?serverTimezone=Asia/Shanghaiusername: rootpassword: 123456mybatis-plus:global-config:db-config:id-type: auto #id生成规则:数据库id自增configuration:map-underscore-to-camel-case: false # 开启驼峰功能auto-mapping-behavior: full # 自动映射任何复杂的结果log-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath:mybatis/mapper/*.xmlweixin:jscode2sessionUrl: https://api.weixin.qq.com/sns/jscode2sessionappid: wx8a1b5168c6b661afsecret: 56cd2d8dbc9d5ebcc759e48a62131be0#微信支付配置# appid# mch_id 商户号# key 商户的key【API密匙】# url api请求地址# notify_url 服务器异步通知页面路径weixinpayconfig:appid: wx8a1b5168c6b661afmch_id: 换成你的key: jrBXpy1VPNY0FCFI42EBShLom7KMaRBaurl: https://api.mch.weixin.qq.com/pay/unifiedordernotify_url: https://2c23-222-184-165-54.ngrok.io/weixinpay/notifyUrlbigTypeImagesFilePath: D://java1234-mall-v3/bigTypeImgs/productImagesFilePath: D://java1234-mall-v3/productImgs/swiperImagesFilePath: D://java1234-mall-v3/swiperImgs/
<template><el-dialogmodel-value="swiperImageDialogVisible"title="幻灯设置"width="30%"@close="handleClose"center><el-formref="formRef":model="form"label-width="100px"style="text-align: center":rules="rules"><el-form-item label="排列序号" prop="swiperSort"><el-input v-model="form.swiperSort" style="width: 100px"/></el-form-item><el-upload:headers="headers"class="avatar-uploader":action="getServerUrl()+'/admin/product/uploadSwiperImage'":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload"><img v-if="imageUrl" :src="imageUrl" class="avatar" /><el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon></el-upload></el-form><template #footer><span class="dialog-footer"><el-button type="primary" @click="handleConfirm">确认更换</el-button></span></template></el-dialog>
</template><script setup>import {defineEmits, defineProps, ref, watch} from "vue";
import axios,{getServerUrl} from "@/util/axios";
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'const tableData=ref([])const props=defineProps({imageDialogValue:{type:Object,default:()=>{},required:true}}
)const headers=ref({token:window.sessionStorage.getItem("token")
})const rules=ref({swiperSort:[{required: true,message:'请输入排列序号'},{type:'number',message: '排序序号必须是数值类型',transform: (value) => Number(value)}]
})const form=ref({id:-1,swiperPic:'',swiperSort:0
})const formRef=ref(null)const imageUrl=ref("")watch(()=>props.imageDialogValue,()=>{form.value=props.imageDialogValue;imageUrl.value=getServerUrl()+'/image/swiper/'+form.value.swiperPic},{deep:true,immediate:true}
)const emits=defineEmits(['update:modelValue','initProductList'])const handleClose=()=>{emits('update:modelValue',false)
}const handleAvatarSuccess=(res)=>{imageUrl.value=getServerUrl()+res.data.srcform.value.swiperPic=res.data.title;
}const beforeAvatarUpload = (file) => {const isJPG = file.type === 'image/jpeg'const isLt2M = file.size / 1024 / 1024 < 2if (!isJPG) {ElMessage.error('图片必须是jpg格式')}if (!isLt2M) {ElMessage.error('图片大小不能超过2M!')}return isJPG && isLt2M
}const handleConfirm=async()=>{formRef.value.validate(async(valid)=>{if(valid){let result=await axios.post("admin/product/save",form.value);let data=result.data;if(data.code==0){ElMessage.success("执行成功!")formRef.value.resetFields();emits("initProductList")handleClose();}else{ElMessage.error(data.msg);}}});}</script><style>.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;
}
.avatar-uploader .el-upload:hover {border-color: #409eff;
}
.el-icon.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 178px;height: 178px;text-align: center;
}
.avatar {width: 178px;height: 178px;display: block;
}</style>
<template><el-card><el-row :gutter="20" class="header"><el-col :span="7"><el-input placeholder="请输入商品名称..." clearable v-model="queryForm.query"></el-input></el-col><el-button type="primary" :icon="Search" @click="initProductList">搜索</el-button><el-button type="primary" @click="handleDialogValue()">添加商品</el-button></el-row><el-table :data="tableData" stripe style="width: 100%"><el-table-column prop="name" label="商品名称" width="200" fixed/><el-table-column prop="image" label="商品图片" width="150" align="center"><template v-slot="scope"><img :src="getServerUrl()+'/image/product/'+scope.row.proPic" width="80" height="80"/></template></el-table-column><el-table-column prop="price" label="商品价格" width="100" /><el-table-column prop="stock" label="商品库存" width="200" /><el-table-column prop="type" label="商品类别" width="200" :formatter="typeNameFormatter"/><el-table-column prop="hot" label="热卖?" width="100" align="center"><template v-slot="{row}"><el-switch v-model="row.hot" @change="hotChangeHandle(row)"></el-switch></template></el-table-column><el-table-column prop="swiper" label="首页幻灯?" width="100" align="center"><template v-slot="{row}"><el-switch v-model="row.swiper" @change="swiperChangeHandle(row)"></el-switch></template></el-table-column><el-table-column prop="swiperPic" label="幻灯图片" width="150" align="center"><template v-slot="scope"><img :src="getServerUrl()+'/image/swiper/'+scope.row.swiperPic" width="150" height="75"/></template></el-table-column><el-table-column prop="swiperSort" label="幻灯排序" width="150" align="center"/><el-table-column prop="description" label="商品描述" width="400"/><el-table-column prop="action" label="操作" width="500" fixed="right"><template v-slot="scope"><el-button type="success" @click="handleImageDialogValue(scope.row)">更换图片</el-button><el-button type="primary" @click="handleSwiperImageDialogValue(scope.row)">幻灯设置</el-button><el-button type="primary" :icon="Edit" @click="handleDialogValue(scope.row)"></el-button><el-button type="danger" :icon="Delete" @click="handleDelete(scope.row.id)"></el-button><el-button type="primary" :icon="Edit" @click="handleDialogValue(scope.row)">轮播图设置</el-button></template></el-table-column></el-table><el-paginationv-model:currentPage="queryForm.pageNum":page-sizes="[10, 20, 30, 40,50]":page-size="queryForm.pageSize":small="small":disabled="disabled":background="background"layout="total, sizes, prev, pager, next, jumper":total="total"@size-change="handleSizeChange"@current-change="handleCurrentChange"></el-pagination></el-card><Dialog v-model="dialogVisible" :dialogTitle="dialogTitle" @initProductList="initProductList" :dialogValue="dialogValue"/><ImageDialog v-model="imageDialogVisible" :imageDialogValue="imageDialogValue" @initProductList="initProductList"></ImageDialog><SwiperImageDialog v-model="swiperImageDialogVisible" :imageDialogValue="imageDialogValue" @initProductList="initProductList"></SwiperImageDialog>
</template><script setup>import {Search,Edit,Delete } from '@element-plus/icons-vue'
import { ref } from 'vue'
import axios,{ getServerUrl } from '@/util/axios'
import Dialog from './components/dialog'
import ImageDialog from './components/imageDialog'
import SwiperImageDialog from './components/swiperImageDialog'
import {ElMessageBox,ElMessage} from 'element-plus'const queryForm=ref({query:'',pageNum:1,pageSize:10
})const total=ref(0)const tableData=ref([
])const dialogValue=ref({})
const dialogVisible=ref(false)
const dialogTitle=ref('')const imageDialogVisible=ref(false)const imageDialogValue=ref({})const swiperImageDialogVisible=ref(false)const initProductList=async()=>{console.log('xxx')const res=await axios.post("admin/product/list",queryForm.value);tableData.value=res.data.productList;total.value=res.data.total;
}initProductList();const handleSizeChange=(pageSize)=>{queryForm.value.pageNum=1;queryForm.value.pageSize=pageSize;initProductList();
}const handleCurrentChange=(pageNum)=>{queryForm.value.pageNum=pageNum;initProductList();
}const handleImageDialogValue=(row)=>{imageDialogValue.value=JSON.parse(JSON.stringify(row))imageDialogVisible.value=true
}const handleSwiperImageDialogValue=(row)=>{imageDialogValue.value=JSON.parse(JSON.stringify(row))swiperImageDialogVisible.value=true
}const handleDialogValue = (row) => {if(row){dialogValue.value=JSON.parse(JSON.stringify(row));dialogTitle.value="商品修改"}else{dialogValue.value={bigType:{id:""}}dialogTitle.value="商品添加"}dialogVisible.value=true;
}const handleDelete = (id) => {ElMessageBox.confirm('您确定要删除这条记录吗?','系统提示',{confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning',}).then(async() => {console.log("id="+id)let res=await axios.get("admin/product/delete/"+id);if(res.data.code==0){ElMessage({type: 'success',message: '删除成功!',});initProductList();}else{ElMessage({type: 'error',message: res.data.msg,});}}).catch(() => {})
}const typeNameFormatter=(row)=>{return row.type.name
}const hotChangeHandle=async(row)=>{let res = await axios.get("admin/product/updateHot/"+row.id+"/state/"+row.hot);if(res.data.code==0){ElMessage({type:'success',message:'执行成功!',})}else{ElMessage({type: 'error',message: res.data.msg,})initProductList();}
}const swiperChangeHandle=async(row)=>{let res = await axios.get("admin/product/updateSwiper/"+row.id+"/state/"+row.swiper);if(res.data.code==0){ElMessage({type:'success',message:'执行成功!',})}else{ElMessage({type: 'error',message: res.data.msg,})initProductList();}
}</script><style lang="scss" scoped>.header{padding-bottom: 16px;box-sizing: border-box;
}.el-pagination{padding-top: 15px;box-sizing: border-box;
}</style>
相关文章:
商品管理幻灯图片更换实现
<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace"com.java1234.mapper.ProductMappe…...
tomcat下载与使用教程
1. tomcat下载 官网:https://tomcat.apache.org/ 镜像地址:https://mirrors.huaweicloud.com/apache/tomcat/ 1、选择一个版本下载,官网下载速度缓慢,推荐镜像 2、对压缩包进行解压,无需进行安装,解压放…...
通过 Elasticsearch 和 Go 使用混合搜索进行地鼠狩猎
作者:CARLY RICHMOND,LAURENT SAINT-FLIX 就像动物和编程语言一样,搜索也经历了不同实践的演变,很难在其中做出选择。 在本系列的最后一篇博客中,Carly Richmond 和 Laurent Saint-Flix 将关键字搜索和向量搜索结合起…...
【LIUNX】配置缓存DNS服务
配置缓存DNS服务 A.安装bind bind-utils1.尝试修改named.conf配置文件2.测试nslookup B.修改named.conf配置文件1.配置文件2.再次测试 缓存DNS服务器:只提供域名解析结果的缓存功能,目的在于提高数据查询速度和效率,但是没有自己控制的区域地…...
Arduino驱动A01NYUB防水超声波传感器(超声波传感器)
目录 1、传感器特性 2、控制器和传感器连线图 3、通信协议 4、驱动程序 A01NYUB超声波测距传感器是一款通过发射和接收机械波来感应物体距离的电子传感器。该款产品具有监测距离远、范围广、防水等优点,且具有一定的穿透能力(烟雾、粉尘等)。该产品带有可拆卸式喇叭口,安…...
curl(八)时间和环境变量以及配置
一 时间 ① --connect-timeout 连接超时时间 ② -m | --max-time 数据最大传输时间 -m: 限制curl 完成时间(overall time limit)-m,--max-time <seconds> 整个交互完成的超时时间场景: 通过设置-m参数,可以避免请求时间过长而导致的超时错误…...
K8S知识点(十)
(1)Pod详解-启动命令 创建Pod,里面的两个容器都正常运行 (2)Pod详解-环境变量 (3)Pod详解-端口设置 (4)Pod详解-资源配额 修改:memory 不满足条件是不能正常…...
Netty实现通信框架
一、LengthFieldBasedFrameDecoder的参数解释 1、LengthFieldBasedFrameDecoder的构造方法参数 看下最多参数的构造方法 /*** Creates a new instance.** param byteOrder* the {link ByteOrder} of the length field* param maxFrameLength* the maximum len…...
【OpenCV实现图像:用OpenCV图像处理技巧之白平衡算法】
文章目录 概要加载样例图像统计数据分析White Patch Algorithm小结 概要 白平衡技术在摄影和图像处理中扮演着至关重要的角色。在不同的光照条件下,相机可能无法准确地捕捉到物体的真实颜色,导致图像呈现出暗淡、色调不自然或者褪色的效果。为了解决这个…...
文件包含 [ZJCTF 2019]NiZhuanSiWei1
打开题目 代码审计 if(isset($text)&&(file_get_contents($text,r)"welcome to the zjctf")){ 首先isset函数检查text参数是否存在且不为空 用file_get_contents函数读取text制定的文件内容并与welcome to the zjctf进行强比较 echo "<br><h…...
Java网络编程基础内容
IP地址 域名解析: 本机访问域名时,会从本地的DNS上解析数据(每个电脑都有),如果有,获取其对应的IP,通过IP访问服务器。如果本地没有,会去网络提供商的DNS找域名对应的IP࿰…...
DevChat:开发者专属的基于IDE插件化编程协助工具
DevChat:开发者专属的基于IDE插件化编程协助工具 一、DevChat 的介绍1.1 DevChat 简介1.2 DevChat 优势 二、DevChat 在 VSCode 上的使用2.1 安装 DevChat2.2 注册 DevChat2.3 使用 DevChat 三、DevChat 的实战四、总结 一、DevChat 的介绍 在AI浪潮的席卷下&#x…...
Python数据容器之[列表]
Python数据容器 Python中的数据容器: 一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素 每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。 数据容器根据特点的不同,如: 是否支…...
大咖直播间”系列直播课第一期——如何抓住HarmonyOS带来的机遇?
想了解#HarmonyOS#背后隐藏着怎样的商业机遇? 想成功搭上万物互联快车,与HarmonyOS一起发展壮大? 想知道开发者应该怎样把握时代机遇,实现高质高效就业? 答案尽在#华为开发者学堂#《大咖直播间》第一期课程,…...
跨域:利用JSONP、WebSocket实现跨域访问
跨域基础知识点:跨域知识点 iframe实现跨域的四种方式:iframe实现跨域的四种方式 注:本篇中使用到的虚拟主机也是上面iframe中配置的 目录 JSONP跨域 JSONP介绍 跨域实验: WebSocket跨域 websocket介绍 跨域实验 JSONP跨域 …...
java项目之戒烟网站(ssm+vue)
项目简介 戒烟网站实现了以下功能: 用户可以对首页,用户分享,论坛交流,公告文章,个人中心,后台管理等功能进行操作。 管理员可以对网站所有功能进行管理,包括管理用户的基本信息。 Ǵ…...
Redis集群,你真的学会了吗?
目录 1、为什么引入集群 1.1、先来了解集群是什么 1.2、哨兵模式的缺陷 引入集群解决了什么问题 1.3、使用集群,如何存储数据 2、三种主流的分片方式【经典面试题】 2.1、哈希求余算法 2.1.1、哈希求余算法的介绍 2.1.2、哈希求余算法如何扩容 2.2、一致性…...
手机地磁传感器与常见问题
在手机中,存在不少传感器,例如光距感,陀螺仪,重力加速度,地磁等。关于各传感器,虽功能作用大家都有所了解,但是在研发设计debug过程中,却总是会遇到很多头疼的问题。关于传感器&…...
EF Core 数据库映射成实体类
首先在 NuGet 包管理器中安装三个包 Microsoft.EntityFrameworkCore.SqlServer 是一个用于与 SQL Server 数据库进行交互的实体框架核心包。这个包提供了方便的方法和工具,用于在 .NET Core 应用程序中操作 SQL Server 数据库。 Microsoft.EntityFrameworkCore.Too…...
【算法优选】 动态规划之斐波那契数列模型
文章目录 🎋前言🍀[第 N 个泰波那契数](https://leetcode.cn/problems/n-th-tribonacci-number/)🚩题目描述🚩算法流程🚩代码实现 🎄[使用最小花费爬楼梯](https://leetcode.cn/problems/min-cost-climbing…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
