Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f400459497 | |||
| 64ac17d6b5 |
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.0.42] - 2026-06-15
|
||||
|
||||
### 修复
|
||||
- 修复商品二维码扫码页报"index.html not found"的错误
|
||||
|
||||
## [1.0.41] - 2026-06-15
|
||||
|
||||
### 改进
|
||||
- 标签打印布局优化:编号字体与度数/日期统一大小,内容整体下移并填满标签底部,店名适当放大
|
||||
- 标签度数与规格之间加宽间距,两个字段更易区分
|
||||
|
||||
## [1.0.40] - 2026-06-15
|
||||
|
||||
### 新功能
|
||||
|
||||
@@ -80,7 +80,7 @@ func Load() {
|
||||
viper.SetDefault("storage.upload_dir", "./uploads/images")
|
||||
viper.SetDefault("storage.base_url", "http://localhost:8080/images")
|
||||
viper.SetDefault("storage.public_url", "http://localhost:8081")
|
||||
viper.SetDefault("storage.web_dir", "./client/build/web")
|
||||
viper.SetDefault("storage.web_dir", "./web")
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Println("[config] no config file found, using defaults and env vars")
|
||||
|
||||
@@ -224,26 +224,38 @@ Future<ui.Image> _renderLabelBitmap({
|
||||
// 扫码溯源:居中于二维码正下方
|
||||
_drawText(canvas, '扫码溯源', qrLeft, qrTop + qrS + 2, 14, qrS, center: true);
|
||||
|
||||
// 左侧文字(无字段名标签):按行等比分配高度铺满,字号自适应填充
|
||||
// 左侧文字:固定字号 + 自适应行间距(与二维码上下对齐,行距均匀分配剩余空间)
|
||||
const lx = 22.0;
|
||||
const textMaxW = qrLeft - lx - 6; // 164
|
||||
|
||||
// 字号固定:只有商品名按宽度自适应,其余行均固定,杜绝自动放大
|
||||
const double kShopSize = 17.0; // 酒行名,粗体
|
||||
const double kSmallSize = 13.0; // 编号 / 度数 / 日期,统一小字
|
||||
// 商品名:仅按宽度适配,上限 26px,下限 14px
|
||||
final double nameSize = _fitFont(name, textMaxW, 1000, true, 26.0).clamp(14.0, 26.0);
|
||||
|
||||
final codeText = code.isNotEmpty ? '编号:$code' : '';
|
||||
final rows = <(String, double, bool)>[
|
||||
(shop, 0.9, true),
|
||||
(name, 1.5, true),
|
||||
if (codeText.isNotEmpty) (codeText, 1.0, false),
|
||||
if (degSpec.isNotEmpty) (degSpec, 1.05, false),
|
||||
if (date.isNotEmpty) (date, 1.0, false),
|
||||
if (shop.isNotEmpty) (shop, kShopSize, true),
|
||||
if (name.isNotEmpty) (name, nameSize, true),
|
||||
if (codeText.isNotEmpty) (codeText, kSmallSize, false),
|
||||
if (degSpec.isNotEmpty) (degSpec, kSmallSize, false),
|
||||
if (date.isNotEmpty) (date, kSmallSize, false),
|
||||
];
|
||||
const topY = 4.0, botY = 156.0;
|
||||
final totalWeight = rows.fold<double>(0, (a, r) => a + r.$2);
|
||||
double yy = topY;
|
||||
|
||||
// 文字区域:整体略低于二维码顶部,底部延伸至扫码溯源文字下方
|
||||
const double kTextTop = 16.0; // 比二维码顶部(8)低一些,整体下移
|
||||
const double kTextBot = 150.0; // 延伸至底部,减少留白
|
||||
const double kLineH = 1.35; // 行高倍数(字号 × 行高 = 该行占用高度)
|
||||
final double totalTextH = rows.fold(0.0, (s, r) => s + r.$2 * kLineH);
|
||||
final int n = rows.length;
|
||||
final double rawGap = n > 0 ? (kTextBot - kTextTop - totalTextH) / (n + 1) : 4.0;
|
||||
final double gap = rawGap < 1.5 ? 1.5 : rawGap;
|
||||
|
||||
double yy = kTextTop + gap;
|
||||
for (final r in rows) {
|
||||
final rowH = (botY - topY) * r.$2 / totalWeight;
|
||||
final fs = _fitFont(r.$1, textMaxW, rowH * 0.84, r.$3, 30);
|
||||
final ty = yy + (rowH - fs * 1.25) / 2;
|
||||
_drawText(canvas, r.$1, lx, ty < yy ? yy : ty, fs, textMaxW, bold: r.$3);
|
||||
yy += rowH;
|
||||
_drawText(canvas, r.$1, lx, yy, r.$2, textMaxW, bold: r.$3);
|
||||
yy += r.$2 * kLineH + gap;
|
||||
}
|
||||
|
||||
return recorder.endRecording().toImage(w, h);
|
||||
|
||||
Reference in New Issue
Block a user