feat: 单据收起汇总明细,CDN改新地址并升至1.1.18
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="summary-title">{{ title }}</view>
|
||||
<slot name="before-list" />
|
||||
<view class="summary-wrap">
|
||||
<scroll-view scroll-x class="summary-scroll">
|
||||
<view class="summary-table" :style="{ width: tableWidth }">
|
||||
<view class="summary-row summary-head">
|
||||
<view
|
||||
v-for="col in columns"
|
||||
:key="col.key"
|
||||
class="summary-cell"
|
||||
:style="cellStyle(col)"
|
||||
>{{ col.label }}</view>
|
||||
</view>
|
||||
<view v-if="!rows.length" class="summary-empty">{{ emptyText }}</view>
|
||||
<view
|
||||
v-for="row in rows"
|
||||
:key="row.group_key"
|
||||
class="summary-row"
|
||||
:class="{ 'summary-row--open': expandedKey === row.group_key }"
|
||||
@click="toggleRow(row.group_key)"
|
||||
>
|
||||
<view
|
||||
v-for="col in columns"
|
||||
:key="col.key"
|
||||
class="summary-cell"
|
||||
:style="cellStyle(col)"
|
||||
>{{ formatCell(row, col.key) }}</view>
|
||||
</view>
|
||||
<view v-if="rows.length" class="summary-row summary-total">
|
||||
<view
|
||||
v-for="col in columns"
|
||||
:key="col.key"
|
||||
class="summary-cell"
|
||||
:style="cellStyle(col)"
|
||||
>{{ totalCell(col.key) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view v-if="expandedRow" class="summary-fine">
|
||||
<view class="summary-fineTitle">
|
||||
细码({{ expandedRow.fine_codes.length }})
|
||||
<text class="summary-fineHint">{{ expandedKey ? '点击行收起' : '' }}</text>
|
||||
</view>
|
||||
<view v-if="!expandedRow.fine_codes.length" class="summary-empty">暂无细码</view>
|
||||
<scroll-view v-else scroll-x class="summary-scroll">
|
||||
<view class="summary-table" :style="{ width: fineTableWidth }">
|
||||
<view class="summary-row summary-head">
|
||||
<view
|
||||
v-for="col in fineCols"
|
||||
:key="col.key"
|
||||
class="summary-cell"
|
||||
:style="cellStyle(col)"
|
||||
>{{ col.label }}</view>
|
||||
</view>
|
||||
<view
|
||||
v-for="(fc, fcIndex) in expandedRow.fine_codes"
|
||||
:key="fc.id || fcIndex"
|
||||
class="summary-row"
|
||||
>
|
||||
<view
|
||||
v-for="col in fineCols"
|
||||
:key="col.key"
|
||||
class="summary-cell"
|
||||
:class="{ 'summary-action': col.key === 'action' }"
|
||||
:style="cellStyle(col)"
|
||||
@click="onFineCellTap(col.key, fc)"
|
||||
>{{ formatFineCell(fc, col.key) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view v-if="deletable && expandedRow.fine_codes.length" class="summary-tip">
|
||||
点击「删除」移除对应细码
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const SUMMARY_COLUMNS = [
|
||||
{ label: '成品编号', key: 'product_code', width: 260 },
|
||||
{ label: '色号', key: 'product_color_code', width: 220 },
|
||||
{ label: '匹数', key: 'roll', width: 140 },
|
||||
{ label: '数量', key: 'weight', width: 160 },
|
||||
{ label: '染整单', key: 'quote_order_no', width: 260 },
|
||||
{ label: '缸号', key: 'dye_factory_dyelot_number', width: 220 },
|
||||
];
|
||||
|
||||
const FINE_COLUMNS = [
|
||||
{ label: '卷号', key: 'volume_number', width: 140 },
|
||||
{ label: '外部卷号', key: 'extern_volume_number', width: 180 },
|
||||
{ label: '匹数', key: 'roll', width: 120 },
|
||||
{ label: '数量', key: 'weight', width: 150 },
|
||||
{ label: '仓位', key: 'warehouse_bin_name', width: 180 },
|
||||
{ label: '缸号', key: 'dye_factory_dyelot_number', width: 200 },
|
||||
];
|
||||
|
||||
const TARE_COLUMNS = [
|
||||
{ label: '纸筒重量', key: 'paper_tube_weight', width: 180 },
|
||||
{ label: '包装重量', key: 'package_weight', width: 180 },
|
||||
];
|
||||
|
||||
export default {
|
||||
props: {
|
||||
groups: { type: Array, default: () => [] },
|
||||
title: { type: String, default: '明细' },
|
||||
emptyText: { type: String, default: '暂无明细' },
|
||||
rollKey: { type: String, default: 'in_roll' },
|
||||
weightKey: { type: String, default: 'in_weight' },
|
||||
deletable: { type: Boolean, default: false },
|
||||
showTareColumns: { type: Boolean, default: false },
|
||||
showBarCode: { type: Boolean, default: false },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expandedKey: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
columns() {
|
||||
return SUMMARY_COLUMNS;
|
||||
},
|
||||
rows() {
|
||||
const rows = [];
|
||||
(this.groups || []).forEach((product) => {
|
||||
(product.colors || []).forEach((color) => {
|
||||
rows.push({
|
||||
group_key: color.group_key,
|
||||
product_code: product.product_code || '',
|
||||
product_name: product.product_name || '',
|
||||
product_color_code: color.product_color_code || '',
|
||||
product_color_name: color.product_color_name || '',
|
||||
quote_order_no: color.quote_order_no || '',
|
||||
dye_factory_dyelot_number: color.dye_factory_dyelot_number || '',
|
||||
roll: color[this.rollKey],
|
||||
weight: color[this.weightKey],
|
||||
fine_codes: color.fine_codes || [],
|
||||
});
|
||||
});
|
||||
});
|
||||
return rows;
|
||||
},
|
||||
expandedRow() {
|
||||
return this.rows.find((row) => row.group_key === this.expandedKey) || null;
|
||||
},
|
||||
fineCols() {
|
||||
const cols = [...FINE_COLUMNS];
|
||||
if (this.showBarCode) {
|
||||
const idx = cols.findIndex((col) => col.key === 'weight');
|
||||
cols.splice(idx + 1, 0, { label: '条码', key: 'bar_code', width: 280 });
|
||||
}
|
||||
if (this.showTareColumns) {
|
||||
const idx = cols.findIndex((col) => col.key === 'weight');
|
||||
cols.splice(idx + 1, 0, ...TARE_COLUMNS);
|
||||
}
|
||||
if (this.deletable) {
|
||||
cols.push({ label: '操作', key: 'action', width: 120 });
|
||||
}
|
||||
return cols;
|
||||
},
|
||||
tableWidth() {
|
||||
return this.sumWidth(this.columns);
|
||||
},
|
||||
fineTableWidth() {
|
||||
return this.sumWidth(this.fineCols);
|
||||
},
|
||||
totalRoll() {
|
||||
return this.sumField('roll');
|
||||
},
|
||||
totalWeight() {
|
||||
return this.sumField('weight');
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
rows() {
|
||||
if (this.expandedKey && !this.rows.some((row) => row.group_key === this.expandedKey)) {
|
||||
this.expandedKey = '';
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
sumWidth(cols) {
|
||||
const total = cols.reduce((sum, col) => sum + (col.width || 120), 0);
|
||||
return `${total}rpx`;
|
||||
},
|
||||
sumField(key) {
|
||||
const total = this.rows.reduce((sum, row) => sum + Number(row[key] || 0), 0);
|
||||
return Number(total.toFixed(2));
|
||||
},
|
||||
cellStyle(col) {
|
||||
return {
|
||||
width: `${col.width}rpx`,
|
||||
minWidth: `${col.width}rpx`,
|
||||
maxWidth: `${col.width}rpx`,
|
||||
};
|
||||
},
|
||||
joinName(code, name) {
|
||||
const main = code || '-';
|
||||
return name ? `${main} ${name}` : main;
|
||||
},
|
||||
formatCell(row, key) {
|
||||
if (key === 'product_code') return this.joinName(row.product_code, row.product_name);
|
||||
if (key === 'product_color_code') return this.joinName(row.product_color_code, row.product_color_name);
|
||||
if (key === 'roll' || key === 'weight') {
|
||||
const val = row[key];
|
||||
if (val === 0) return '0';
|
||||
return val != null && val !== '' ? val : '-';
|
||||
}
|
||||
const val = row[key];
|
||||
if (val === 0) return '0';
|
||||
return val != null && val !== '' ? val : '-';
|
||||
},
|
||||
totalCell(key) {
|
||||
if (key === 'product_code') return '合计';
|
||||
if (key === 'roll') return this.totalRoll;
|
||||
if (key === 'weight') return this.totalWeight;
|
||||
return '';
|
||||
},
|
||||
toggleRow(key) {
|
||||
this.expandedKey = this.expandedKey === key ? '' : key;
|
||||
},
|
||||
formatFineCell(fc, key) {
|
||||
if (key === 'action') return '删除';
|
||||
const val = fc[key];
|
||||
if (val === 0) return '0';
|
||||
return val != null && val !== '' ? val : '-';
|
||||
},
|
||||
onFineCellTap(key, fc) {
|
||||
if (!this.deletable || key !== 'action') return;
|
||||
this.$emit('delete', fc);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/common/pda-typography.scss';
|
||||
|
||||
.summary-title {
|
||||
font-size: $pda-font-body;
|
||||
font-weight: bold;
|
||||
padding: 24rpx 26rpx 12rpx;
|
||||
border-left: 6rpx solid #007AFF;
|
||||
margin: 20rpx 26rpx 0;
|
||||
}
|
||||
.summary-wrap {
|
||||
margin: 0 26rpx 16rpx;
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.summary-scroll {
|
||||
width: 100%;
|
||||
}
|
||||
.summary-table {
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
.summary-row {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
.summary-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.summary-head {
|
||||
background: #f7f8fa;
|
||||
}
|
||||
.summary-row--open {
|
||||
background: #f0f7ff;
|
||||
}
|
||||
.summary-total {
|
||||
background: #fff7e6;
|
||||
}
|
||||
.summary-cell {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: $pda-row-min-height;
|
||||
padding: 12rpx 16rpx;
|
||||
font-size: $pda-font-body;
|
||||
color: #333;
|
||||
border-right: 1rpx solid #f0f0f0;
|
||||
word-break: break-all;
|
||||
}
|
||||
.summary-head .summary-cell {
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
}
|
||||
.summary-total .summary-cell {
|
||||
font-weight: bold;
|
||||
}
|
||||
.summary-cell:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
.summary-empty {
|
||||
padding: 28rpx 16rpx;
|
||||
font-size: $pda-font-placeholder;
|
||||
color: #999;
|
||||
}
|
||||
.summary-fine {
|
||||
padding: 8rpx 0 16rpx;
|
||||
}
|
||||
.summary-fineTitle {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 12rpx 16rpx 8rpx;
|
||||
font-size: $pda-font-action;
|
||||
color: #2979ff;
|
||||
}
|
||||
.summary-fineHint {
|
||||
color: #999;
|
||||
font-size: $pda-font-popup-sub;
|
||||
}
|
||||
.summary-action {
|
||||
color: #f5222d;
|
||||
}
|
||||
.summary-tip {
|
||||
padding: 8rpx 16rpx 0;
|
||||
font-size: $pda-font-popup-sub;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user