feat: 实现二维码高级渲染功能,支持自定义颜色、形状和 Logo 嵌入
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
use crate::error::{AppError, AppResult};
|
||||
use crate::models::qrcode::{QrConfig, QrResult};
|
||||
use crate::utils::qrcode_renderer::{image_to_base64, render_basic_qr};
|
||||
use crate::utils::qrcode_renderer::{image_to_base64, render_qr};
|
||||
|
||||
/// 二维码生成服务
|
||||
pub struct QrCodeService;
|
||||
@@ -39,8 +39,17 @@ impl QrCodeService {
|
||||
return Err(AppError::InvalidData("边距不能超过 50".to_string()));
|
||||
}
|
||||
|
||||
// 验证 Logo 缩放比例
|
||||
if let Some(logo) = &config.logo {
|
||||
if logo.scale < 0.05 || logo.scale > 0.3 {
|
||||
return Err(AppError::InvalidData(
|
||||
"Logo 缩放比例必须在 0.05 到 0.3 之间".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染二维码
|
||||
let img = render_basic_qr(config)?;
|
||||
let img = render_qr(config)?;
|
||||
|
||||
// 转换为 Base64
|
||||
let base64_data = image_to_base64(&img)?;
|
||||
@@ -76,8 +85,22 @@ impl QrCodeService {
|
||||
));
|
||||
}
|
||||
|
||||
// 验证边距
|
||||
if config.margin > 50 {
|
||||
return Err(AppError::InvalidData("边距不能超过 50".to_string()));
|
||||
}
|
||||
|
||||
// 验证 Logo 缩放比例
|
||||
if let Some(logo) = &config.logo {
|
||||
if logo.scale < 0.05 || logo.scale > 0.3 {
|
||||
return Err(AppError::InvalidData(
|
||||
"Logo 缩放比例必须在 0.05 到 0.3 之间".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染二维码
|
||||
let img = render_basic_qr(config)?;
|
||||
let img = render_qr(config)?;
|
||||
|
||||
// 保存到文件
|
||||
img.save(output_path)
|
||||
@@ -90,6 +113,7 @@ impl QrCodeService {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::models::qrcode::{QrStyle};
|
||||
|
||||
#[test]
|
||||
fn test_generate_preview() {
|
||||
@@ -98,6 +122,8 @@ mod tests {
|
||||
size: 512,
|
||||
margin: 4,
|
||||
error_correction: "M".to_string(),
|
||||
style: None,
|
||||
logo: None,
|
||||
};
|
||||
|
||||
let result = QrCodeService::generate_preview(&config);
|
||||
@@ -108,6 +134,30 @@ mod tests {
|
||||
assert_eq!(qr_result.format, "png");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_preview_with_style() {
|
||||
let style = QrStyle {
|
||||
dot_shape: "circle".to_string(),
|
||||
eye_shape: "square".to_string(),
|
||||
foreground_color: "#FF0000".to_string(),
|
||||
background_color: "#FFFFFF".to_string(),
|
||||
is_gradient: false,
|
||||
gradient_colors: None,
|
||||
};
|
||||
|
||||
let config = QrConfig {
|
||||
content: "https://example.com".to_string(),
|
||||
size: 512,
|
||||
margin: 4,
|
||||
error_correction: "M".to_string(),
|
||||
style: Some(style),
|
||||
logo: None,
|
||||
};
|
||||
|
||||
let result = QrCodeService::generate_preview(&config);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_preview_invalid_size() {
|
||||
let config = QrConfig {
|
||||
@@ -115,6 +165,8 @@ mod tests {
|
||||
size: 50, // 太小
|
||||
margin: 4,
|
||||
error_correction: "M".to_string(),
|
||||
style: None,
|
||||
logo: None,
|
||||
};
|
||||
|
||||
let result = QrCodeService::generate_preview(&config);
|
||||
@@ -128,6 +180,8 @@ mod tests {
|
||||
size: 512,
|
||||
margin: 100, // 太大
|
||||
error_correction: "M".to_string(),
|
||||
style: None,
|
||||
logo: None,
|
||||
};
|
||||
|
||||
let result = QrCodeService::generate_preview(&config);
|
||||
|
||||
Reference in New Issue
Block a user