feat: 小票双版本对比展示与格式优化

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
zhangyan
2026-08-05 17:58:09 +08:00
co-authored by Claude Opus 4.6
parent d00208a33d
commit 6fc7b12d65
2 changed files with 157 additions and 96 deletions
@@ -217,6 +217,25 @@
}
.receipt-stage::-webkit-scrollbar { display: none; }
/* 双版本对比容器 */
.receipt-compare {
display: flex;
gap: 32px;
align-items: flex-start;
justify-content: center;
}
.receipt-compare__col {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.receipt-compare__label {
font-size: 12px;
color: rgba(255, 255, 255, 0.45);
letter-spacing: 0.5px;
}
/* 热敏小票纸 */
.receipt-paper {
width: 300px;
@@ -393,6 +412,9 @@
font-weight: 700;
color: #1a1a2e;
}
.receipt-score__value--text {
font-size: 12px;
}
/* 双二维码并排 */
.receipt-qr--dual {
@@ -576,7 +598,7 @@
id: 'CO-20260803-001',
mealType: 'lunch',
mealLabel: '午餐',
line: 'A 区 1 号餐线',
line: '一楼',
cashier: '张三',
time: '2026-08-03 12:15:30',
payTime: '2026-08-03 12:15:35',
@@ -596,7 +618,7 @@
id: 'CO-20260803-008',
mealType: 'breakfast',
mealLabel: '早餐',
line: 'A 区 1 号餐线',
line: '一楼',
cashier: '张三',
time: '2026-08-03 07:42:18',
payTime: '2026-08-03 07:42:23',
@@ -634,7 +656,7 @@
id: 'CO-20260803-022',
mealType: 'dinner',
mealLabel: '晚餐',
line: 'A 区 1 号餐线',
line: '一楼',
cashier: '王五',
time: '2026-08-03 18:15:20',
payTime: '2026-08-03 18:15:25',
@@ -688,8 +710,8 @@
/* 食堂抬头 */
var canteenInfo = {
name: 'CQ 能源公司员工食堂',
address: '重庆市渝北区星光大道 88 号',
name: '数味餐厅',
address: '陕西省西安市浐灞生态区欧亚大道3639号',
phone: '023-7788-XXXX'
};
@@ -745,109 +767,135 @@
return;
}
/* 按分区分组渲染 */
/* 按分区分组 */
var zoneOrder = ['营养秤', '档口秤'];
var zones = {};
order.items.forEach(function(it) {
if (!zones[it.zone]) zones[it.zone] = [];
zones[it.zone].push(it);
});
var itemsHtml = '';
zoneOrder.forEach(function(zoneName) {
var zoneItems = zones[zoneName];
if (!zoneItems || zoneItems.length === 0) return;
itemsHtml += '<tr class="receipt-zone-header"><td colspan="4">【' + zoneName + '】</td></tr>';
zoneItems.forEach(function(it) {
/* 小计 = 餐品克重 ÷ 100 × 单价(100g) */
var subtotal = it.weight / 100 * it.price;
itemsHtml += '<tr>'
+ '<td>' + it.name + '<span style="color:#999;font-size:10px;">' + it.weight + 'g</span></td>'
+ '<td>' + it.price.toFixed(2) + '</td>'
+ '<td>' + it.qty + '</td>'
+ '<td>' + subtotal.toFixed(2) + '</td>'
+ '</tr>';
/* 构建商品行HTML - 版本一:价格不含¥,重量不含g; 版本二:价格含¥,重量含g */
function buildItemsHtml(isV2) {
var html = '';
zoneOrder.forEach(function(zoneName) {
var zoneItems = zones[zoneName];
if (!zoneItems || zoneItems.length === 0) return;
/* 分区名称映射: 营养秤→餐线, 档口秤→档口 */
var zoneLabel = zoneName === '营养秤' ? '餐线' : (zoneName === '档口秤' ? '档口' : zoneName);
html += '<tr class="receipt-zone-header"><td colspan="4">' + zoneLabel + '】</td></tr>';
zoneItems.forEach(function(it) {
/* 小计 = 餐品克重 ÷ 100 × 100克单价 */
var subtotal = it.weight / 100 * it.price;
html += '<tr>'
+ '<td>' + it.name + '</td>'
+ '<td>' + (isV2 ? '¥' : '') + it.price.toFixed(2) + '</td>'
+ '<td>' + it.weight + (isV2 ? 'g' : '') + '</td>'
+ '<td>' + (isV2 ? '¥' : '') + subtotal.toFixed(2) + '</td>'
+ '</tr>';
});
});
});
return html;
}
var discountRow = order.discount > 0
? '<div class="receipt-row"><span class="receipt-row__label">优惠</span><span class="receipt-row__value">-' + order.discount.toFixed(2) + '</span></div>'
: '';
/* 构建完整小票纸张HTML */
function buildReceiptPaper(isV2) {
var itemsHtml = buildItemsHtml(isV2);
var discountRow = order.discount > 0
? '<div class="receipt-row"><span class="receipt-row__label">优惠</span><span class="receipt-row__value">-¥' + order.discount.toFixed(2) + '</span></div>'
: '';
/* 营养得分: 82分统一显示为"继续努力" */
var scoreText = order.nutrition.score === 82 ? '继续努力' : order.nutrition.score;
return ''
+ '<div class="receipt-paper">'
/* 食堂抬头 */
+ '<div class="receipt-header">'
+ '<div class="receipt-name">' + canteenInfo.name + '</div>'
+ '<div class="receipt-sub">' + canteenInfo.address + '</div>'
+ '<div class="receipt-sub">电话:' + canteenInfo.phone + '</div>'
+ '</div>'
+ '<div class="receipt-divider receipt-divider--double"></div>'
/* 订单信息 */
+ '<div class="receipt-info">'
+ '<div class="receipt-row"><span class="receipt-row__label">订单号</span><span class="receipt-row__value">' + order.id + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">餐线</span><span class="receipt-row__value">' + order.line + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">收银员</span><span class="receipt-row__value">' + order.cashier + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">就餐时间</span><span class="receipt-row__value">' + order.time + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">付款时间</span><span class="receipt-row__value">' + order.payTime + '</span></div>'
+ '</div>'
+ '<div class="receipt-divider"></div>'
/* 消费明细表 */
+ '<table class="receipt-table">'
+ '<thead><tr><th>餐品</th><th>单价/100g' + (isV2 ? '' : '(元)') + '</th><th>取用量(g)</th><th>小计</th></tr></thead>'
+ '<tbody>' + itemsHtml + '</tbody>'
+ '</table>'
+ '<div class="receipt-divider"></div>'
/* 金额汇总 */
+ '<div class="receipt-amount">'
+ '<div class="receipt-row"><span class="receipt-row__label">合计</span><span class="receipt-row__value">¥' + order.total.toFixed(2) + '</span></div>'
+ discountRow
+ '<div class="receipt-row receipt-amount__payable"><span class="receipt-row__label">应付</span><span>¥' + order.payable.toFixed(2) + '</span></div>'
+ '<div class="receipt-row receipt-amount__paid"><span class="receipt-row__label">实付</span><span>¥' + order.paid.toFixed(2) + '</span></div>'
+ '</div>'
+ '<div class="receipt-divider"></div>'
/* 支付信息 */
+ '<div class="receipt-info">'
+ '<div class="receipt-row"><span class="receipt-row__label">支付类型</span><span class="receipt-row__value">' + order.payType + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">支付方式</span><span class="receipt-row__value">' + order.payMethod + '</span></div>'
/* 仅会员支付订单展示餐卡余额 */
+ (order.payType === '会员支付'
? '<div class="receipt-row"><span class="receipt-row__label">餐卡余额</span><span class="receipt-row__value">¥' + order.balance.toFixed(2) + '</span></div>'
: '')
+ '</div>'
+ '<div class="receipt-divider"></div>'
/* 营养摄入摘要 */
+ '<div class="receipt-nutrition-title">- - - ' + (isV2 ? '营养素摄入量 / 餐' : '营养摄入摘要') + ' - - -</div>'
+ '<div class="receipt-nutrition-grid">'
+ '<div class="nutrition-item"><div class="nutrition-item__label">热量</div><div class="nutrition-item__value">' + order.nutrition.calories + '<small>kcal</small></div></div>'
+ '<div class="nutrition-item"><div class="nutrition-item__label">蛋白质</div><div class="nutrition-item__value">' + order.nutrition.protein + '<small>g</small></div></div>'
+ '<div class="nutrition-item"><div class="nutrition-item__label">脂肪</div><div class="nutrition-item__value">' + order.nutrition.fat + '<small>g</small></div></div>'
+ '<div class="nutrition-item"><div class="nutrition-item__label">碳水</div><div class="nutrition-item__value">' + order.nutrition.carb + '<small>g</small></div></div>'
+ '</div>'
+ '<div class="receipt-score">'
+ '<span class="receipt-score__label">营养得分</span>'
+ '<span class="receipt-score__value' + (scoreText === '继续努力' ? ' receipt-score__value--text' : '') + '">' + scoreText + '</span>'
+ '</div>'
+ '<div class="receipt-divider"></div>'
/* 二维码 */
+ '<div class="receipt-qr--dual">'
+ '<div class="receipt-qr">'
+ getQRCodeEnterpriseSVG()
+ '<div class="receipt-qr__text">扫码加入企业微信群</div>'
+ '<div class="receipt-qr__sub">获取营养知识与优惠活动</div>'
+ '</div>'
+ '<div class="receipt-qr">'
+ getQRCodeMiniProgramSVG()
+ '<div class="receipt-qr__text">扫码进入小程序</div>'
+ '<div class="receipt-qr__sub">查看详细营养分析报告</div>'
+ '</div>'
+ '</div>'
+ '<div class="receipt-divider receipt-divider--double"></div>'
/* 底部提示 */
+ '<div class="receipt-footer">'
+ '<div class="receipt-footer__line1">合理膳食 均衡营养</div>'
+ '<div class="receipt-footer__line2">谢谢惠顾,欢迎下次光临</div>'
+ '</div>'
+ '</div>';
}
/* 并排展示两个版本 */
var html = ''
+ '<div class="receipt-paper">'
/* 食堂抬头 */
+ '<div class="receipt-header">'
+ '<div class="receipt-name">' + canteenInfo.name + '</div>'
+ '<div class="receipt-sub">' + canteenInfo.address + '</div>'
+ '<div class="receipt-sub">电话:' + canteenInfo.phone + '</div>'
+ '</div>'
+ '<div class="receipt-divider receipt-divider--double"></div>'
/* 订单信息 */
+ '<div class="receipt-info">'
+ '<div class="receipt-row"><span class="receipt-row__label">订单号</span><span class="receipt-row__value">' + order.id + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">餐线</span><span class="receipt-row__value">' + order.line + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">收银员</span><span class="receipt-row__value">' + order.cashier + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">就餐时间</span><span class="receipt-row__value">' + order.time + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">付款时间</span><span class="receipt-row__value">' + order.payTime + '</span></div>'
+ '</div>'
+ '<div class="receipt-divider"></div>'
/* 消费明细表 */
+ '<table class="receipt-table">'
+ '<thead><tr><th>餐品</th><th>单价(100g)</th><th>份数</th><th>小计</th></tr></thead>'
+ '<tbody>' + itemsHtml + '</tbody>'
+ '</table>'
+ '<div class="receipt-divider"></div>'
/* 金额汇总 */
+ '<div class="receipt-amount">'
+ '<div class="receipt-row"><span class="receipt-row__label">合计</span><span class="receipt-row__value">' + order.total.toFixed(2) + '</span></div>'
+ discountRow
+ '<div class="receipt-row receipt-amount__payable"><span class="receipt-row__label">应付</span><span>¥' + order.payable.toFixed(2) + '</span></div>'
+ '<div class="receipt-row receipt-amount__paid"><span class="receipt-row__label">实付</span><span>¥' + order.paid.toFixed(2) + '</span></div>'
+ '</div>'
+ '<div class="receipt-divider"></div>'
/* 支付信息 */
+ '<div class="receipt-info">'
+ '<div class="receipt-row"><span class="receipt-row__label">支付类型</span><span class="receipt-row__value">' + order.payType + '</span></div>'
+ '<div class="receipt-row"><span class="receipt-row__label">支付方式</span><span class="receipt-row__value">' + order.payMethod + '</span></div>'
/* 仅会员支付订单展示餐卡余额 */
+ (order.payType === '会员支付'
? '<div class="receipt-row"><span class="receipt-row__label">餐卡余额</span><span class="receipt-row__value">¥' + order.balance.toFixed(2) + '</span></div>'
: '')
+ '</div>'
+ '<div class="receipt-divider"></div>'
/* 营养摄入摘要 */
+ '<div class="receipt-nutrition-title">- - - 营养摄入摘要 - - -</div>'
+ '<div class="receipt-nutrition-grid">'
+ '<div class="nutrition-item"><div class="nutrition-item__label">热量</div><div class="nutrition-item__value">' + order.nutrition.calories + '<small>kcal</small></div></div>'
+ '<div class="nutrition-item"><div class="nutrition-item__label">蛋白质</div><div class="nutrition-item__value">' + order.nutrition.protein + '<small>g</small></div></div>'
+ '<div class="nutrition-item"><div class="nutrition-item__label">脂肪</div><div class="nutrition-item__value">' + order.nutrition.fat + '<small>g</small></div></div>'
+ '<div class="nutrition-item"><div class="nutrition-item__label">碳水</div><div class="nutrition-item__value">' + order.nutrition.carb + '<small>g</small></div></div>'
+ '</div>'
+ '<div class="receipt-score">'
+ '<span class="receipt-score__label">营养得分</span>'
+ '<span class="receipt-score__value">' + order.nutrition.score + '</span>'
+ '</div>'
+ '<div class="receipt-divider"></div>'
/* 二维码 */
+ '<div class="receipt-qr--dual">'
+ '<div class="receipt-qr">'
+ getQRCodeEnterpriseSVG()
+ '<div class="receipt-qr__text">扫码加入企业微信群</div>'
+ '<div class="receipt-qr__sub">获取营养知识与优惠活动</div>'
+ '<div class="receipt-compare">'
+ '<div class="receipt-compare__col">'
+ '<div class="receipt-compare__label">版本一(价格不含¥ · 重量不含g)</div>'
+ buildReceiptPaper(false)
+ '</div>'
+ '<div class="receipt-qr">'
+ getQRCodeMiniProgramSVG()
+ '<div class="receipt-qr__text">扫码进入小程序</div>'
+ '<div class="receipt-qr__sub">查看详细营养分析报告</div>'
+ '<div class="receipt-compare__col">'
+ '<div class="receipt-compare__label">版本二(价格含¥ · 重量含g</div>'
+ buildReceiptPaper(true)
+ '</div>'
+ '</div>'
+ '<div class="receipt-divider receipt-divider--double"></div>'
/* 底部提示 */
+ '<div class="receipt-footer">'
+ '<div class="receipt-footer__line1">合理膳食 均衡营养</div>'
+ '<div class="receipt-footer__line2">谢谢惠顾,欢迎下次光临</div>'
+ '</div>'
+ '</div>';
+ '</div>';
document.getElementById('receiptStage').innerHTML = html;
updatePrintBtn();
@@ -1,5 +1,18 @@
# 结算设备 CHANGELOG
## 2026-08-05 | 小票双版本对比展示与格式优化
### 变更
- `02-print-receipt.html` 小票预览改为双版本并排对比展示
- **版本一**:价格不含 ¥,重量不含 g,表头显示"单价/100g(元)"
- **版本二**:价格含 ¥,重量含 g,小计含 ¥,表头显示"单价/100g"
- 分区名称映射:营养秤→餐线、档口秤→档口
- 餐厅名称改为"数味餐厅",地址改为陕西省西安市浐灞生态区欧亚大道3639号
- 餐线名称改为"一楼"
- 营养得分 82 分统一显示为"继续努力"(字号缩小至 12px)
- 合计/优惠金额全局加 ¥ 符号
- 版本二营养标题改为"营养素摄入量 / 餐"
## 2026-08-04 | 小票金额计算与支付信息优化
### 变更