feat: 小票双版本对比展示与格式优化
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
d00208a33d
commit
6fc7b12d65
@@ -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 | 小票金额计算与支付信息优化
|
||||
|
||||
### 变更
|
||||
|
||||
Reference in New Issue
Block a user