需求描述
一个小课设,需要制作一个食品的二维码,扫描一下可以展示对应食品的详细信息。记录一下二维码扫描跳转功能的开发,这方面的文章还挺少的。
手机微信扫描后
原理简单说明
使用QRcode这个插件生成二维码,生成二维码的时候往二维码里面写上目标地址和参数
比如我这里的内容是这么写的:就是把http路径和请求参数写进去就行,扫描后浏览器会自动跳转到该地址的页面请求的。
CodeContent := fmt.Sprintf("http://172.22.232.142:3000/TraceSearch?id=%d", foodCount.Int64())
环境说明
我做的是go的后端(用的gin框架),前端是react。
二维码制作
用到的依赖
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
"github.com/google/uuid" //二维码图片随机命名用
安装依赖,直接终端执行 go get github.com/skip2/go-qrcode
qrcode将会内置命令行工具$GOPATH/bin/。
建议学习这个视频来写QRcode生成方法:https://www.bilibili.com/video/BV1NM4y1K7VG/
二维码生成方法封装:
func GenerateQRCode(fileName string, content string, w int, h int) {
qrCode, err := qr.Encode(content, qr.M, qr.Auto) //创建二维码,参数分别为:内容、中等纠错级别(就是容忍二维码一定程度的破坏也能识别)、自动采用二维码自适应最佳编码方式(一般都默认这个)
if err != nil {
log.Printf("qr.Encode failed, err: %v", err)
return
}
qrCode, err = barcode.Scale(qrCode, w, h)//设置二维码的宽高
if err != nil {
fmt.Println(err)
}
//创建完整的二维码保存路径
fullFilePath := fmt.Sprintf("%s/%s", "QRcode", fileName) //对于go项目而言构建项目后的所在目录为根目录,所以直接写根目录下的QRcode了
fmt.Println("输出拼接后的路径:", fullFilePath)
file, err := os.Create(fullFilePath)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
png.Encode(file, qrCode)
//路径返回
}```
二维码生成实际调用案例:
```go
func init(){
foodCount, err := FoodInstance.FoodItemCount(FoodClient.GetCallOpts())
fmt.Println(foodCount)
CodeContent := fmt.Sprintf("http://172.22.232.142:3000/TraceSearch?id=%d", foodCount.Int64()) //192.168.31.188
fmt.Printf("二维码内容:%s", CodeContent)
//使用uuid生成唯一的二维码文件名
uuidObj, err := uuid.NewRandom()//使用uuid对二维码命名避免重复
fileName := uuidObj.String() + ".png"
QRcodePath := fmt.Sprintf("%s/%s", "http://127.0.0.1:8080/QRcode", fileName)
fmt.Println("二维码路径:", QRcodePath) //输出二维码路径
//将fooddetail生成二维码信息
GenerateQRCode(fileName, CodeContent, 300, 300)//准备工作完成调用生成二维码方法
}
如果foodCount为3,那么至此就生成了写有http://172.22.232.142:3000/TraceSearch?id=3的二维码。扫描后会自动带着id=3的参数跳转到这个页面。
跳转后的页面展示
可以参考原生js获取地址参数进行渲染的js
<!DOCTYPE html>
<html>
<head>
<title>QR Code Example</title>
<script>
[window](https://wenku.csdn.net/doc/6412b47ebe7fbd1778d3fc75?spm=1055.2569.3001.10083&kwd=window).onload = [function](https://wenku.csdn.net/doc/6452013cea0840391e738cc4?spm=1055.2569.3001.10083&kwd=function)() {
// 获取 URL 中的参数
var params = new URL[search](https://wenku.csdn.net/doc/wdpg71tad9?spm=1055.2569.3001.10083&kwd=search)Params(window.location.search);
var name = params.get('name');
var age = params.get('age');
// 在页面中展示数据
document.get[element](https://wenku.csdn.net/doc/z7c28mgs2i?spm=1055.2569.3001.10083&kwd=element)ById('name').innerText = name;
document.getElementById('age').innerText = age;
}
</script>
</head>
<body>
<h1>Welcome</h1>
<p>Your name is <span id="name"></span></p>
<p>Your age is <span id="age"></span></p>
</body>
</html>
本项目当中react的实现
使用 const { id } = router.query;获取跳转地址的参数
const TraceSearch = () => {
const router = useRouter();
const [foodData, setFoodData] = useState({});
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
// const [isLoading, setIsLoading] = useState(true); // 初始加载状态为 true
// 获取URL参数并请求数据[7,8](@ref)
useEffect(() => {
const fetchData = async () => {
try {
// setIsLoading(true);
const { id } = router.query;//注意这里,使用react的路由获取参数
if (!id) return;
const response = await axios.get('http://172.22.232.142:8080/getFoodInfo', { params: { id } });//拿到id参数后进行查询渲染
const data = response.data;
setFoodData(data);
console.log('请求结果:', data); // 直接打印响应数据
Toast.info(`食品名称: ${data.foodName}, 物流状态: ${data.isLogistics}`);
} catch (err) {
const message = err.response?.data?.error || err.message;
Toast.error(`加载失败: ${message}`);
} finally {
setLoading(false);
}
};
if (router.isReady) fetchData(); // 确保路由参数已就绪
}, [router.isReady, router.query.id]); // 依赖项优化