diff --git a/gear-oa/src/main/java/com/gear/oa/controller/GearStockIoOrderController.java b/gear-oa/src/main/java/com/gear/oa/controller/GearStockIoOrderController.java index c25ac14..27e6097 100644 --- a/gear-oa/src/main/java/com/gear/oa/controller/GearStockIoOrderController.java +++ b/gear-oa/src/main/java/com/gear/oa/controller/GearStockIoOrderController.java @@ -22,7 +22,9 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import org.springframework.format.annotation.DateTimeFormat; import java.util.Arrays; +import java.util.Date; import java.util.List; import java.util.Map; @@ -46,6 +48,13 @@ public class GearStockIoOrderController extends BaseController { ExcelUtil.exportExcel(list, "出入库单据", GearStockIoOrderVo.class, response); } + @GetMapping("/materialFlow") + public R materialFlow(@NotNull(message = "物料ID不能为空") @RequestParam Long itemId, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime) { + return R.ok(stockIoOrderService.queryMaterialFlow(itemId, startTime, endTime)); + } + @GetMapping("/{orderId}") public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long orderId) { return R.ok(stockIoOrderService.queryById(orderId)); diff --git a/gear-oa/src/main/java/com/gear/oa/service/IGearStockIoOrderService.java b/gear-oa/src/main/java/com/gear/oa/service/IGearStockIoOrderService.java index 613b152..ae52026 100644 --- a/gear-oa/src/main/java/com/gear/oa/service/IGearStockIoOrderService.java +++ b/gear-oa/src/main/java/com/gear/oa/service/IGearStockIoOrderService.java @@ -6,8 +6,11 @@ import com.gear.oa.domain.bo.GearStockIoOrderBo; import com.gear.oa.domain.bo.GearStockIoOrderWithDetailBo; import com.gear.oa.domain.vo.GearStockIoOrderVo; import com.gear.oa.domain.vo.GearStockIoOrderWithDetailVo; +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; import java.util.Collection; +import java.util.Date; import java.util.List; public interface IGearStockIoOrderService { @@ -29,4 +32,31 @@ public interface IGearStockIoOrderService { void confirmIn(Long orderId); void revoke(Long orderId, String reason); + + MaterialFlowResp queryMaterialFlow(Long itemId, Date startTime, Date endTime); + + @lombok.Data + class MaterialFlowResp { + private Long itemId; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date startTime; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + private BigDecimal confirmInQty; + private BigDecimal outQty; + private BigDecimal revokeInQty; + private BigDecimal revokeOutQty; + private BigDecimal netQty; + private List rows; + } + + @lombok.Data + class MaterialFlowRow { + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date time; + private String action; + private String orderCode; + private String ioType; + private BigDecimal qtyChange; + } } diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/GearStockIoOrderServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/GearStockIoOrderServiceImpl.java index c486c48..1e13555 100644 --- a/gear-oa/src/main/java/com/gear/oa/service/impl/GearStockIoOrderServiceImpl.java +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/GearStockIoOrderServiceImpl.java @@ -20,6 +20,8 @@ import com.gear.oa.domain.vo.GearStockIoOrderVo; import com.gear.oa.domain.vo.GearStockIoOrderWithDetailVo; import com.gear.oa.mapper.*; import com.gear.oa.service.IGearStockIoOrderService; +import com.gear.oa.service.IGearStockIoOrderService.MaterialFlowResp; +import com.gear.oa.service.IGearStockIoOrderService.MaterialFlowRow; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -355,6 +357,129 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService { baseMapper.updateById(update); } + @Override + public MaterialFlowResp queryMaterialFlow(Long itemId, Date startTime, Date endTime) { + if (itemId == null) { + throw new ServiceException("物料ID不能为空"); + } + List confirmOrders = baseMapper.selectList(Wrappers.lambdaQuery() + .eq(GearStockIoOrder::getIoType, "I") + .eq(GearStockIoOrder::getConfirmInFlag, "1") + .isNotNull(GearStockIoOrder::getConfirmInTime) + .ge(startTime != null, GearStockIoOrder::getConfirmInTime, startTime) + .le(endTime != null, GearStockIoOrder::getConfirmInTime, endTime) + .eq(GearStockIoOrder::getDelFlag, "0")); + + List outOrders = baseMapper.selectList(Wrappers.lambdaQuery() + .eq(GearStockIoOrder::getIoType, "O") + .isNotNull(GearStockIoOrder::getExecuteTime) + .ge(startTime != null, GearStockIoOrder::getExecuteTime, startTime) + .le(endTime != null, GearStockIoOrder::getExecuteTime, endTime) + .eq(GearStockIoOrder::getDelFlag, "0")); + + List revokeOrders = baseMapper.selectList(Wrappers.lambdaQuery() + .eq(GearStockIoOrder::getRevokeFlag, "1") + .isNotNull(GearStockIoOrder::getRevokeTime) + .ge(startTime != null, GearStockIoOrder::getRevokeTime, startTime) + .le(endTime != null, GearStockIoOrder::getRevokeTime, endTime) + .eq(GearStockIoOrder::getDelFlag, "0")); + + Set orderIds = new HashSet<>(); + for (GearStockIoOrder o : confirmOrders) { + if (o != null && o.getOrderId() != null) orderIds.add(o.getOrderId()); + } + for (GearStockIoOrder o : outOrders) { + if (o != null && o.getOrderId() != null) orderIds.add(o.getOrderId()); + } + for (GearStockIoOrder o : revokeOrders) { + if (o != null && o.getOrderId() != null) orderIds.add(o.getOrderId()); + } + + Map qtyMap = new HashMap<>(); + if (!orderIds.isEmpty()) { + List details = detailMapper.selectList(Wrappers.lambdaQuery() + .in(GearStockIoOrderDetail::getOrderId, orderIds) + .eq(GearStockIoOrderDetail::getItemType, "material") + .eq(GearStockIoOrderDetail::getItemId, itemId) + .eq(GearStockIoOrderDetail::getDelFlag, "0")); + for (GearStockIoOrderDetail d : details) { + if (d == null || d.getOrderId() == null) continue; + BigDecimal q = d.getQuantity() == null ? BigDecimal.ZERO : d.getQuantity(); + qtyMap.merge(d.getOrderId(), q, BigDecimal::add); + } + } + + BigDecimal confirmInQty = BigDecimal.ZERO; + BigDecimal outQty = BigDecimal.ZERO; + BigDecimal revokeInQty = BigDecimal.ZERO; + BigDecimal revokeOutQty = BigDecimal.ZERO; + List rows = new ArrayList<>(); + + for (GearStockIoOrder o : confirmOrders) { + if (o == null || o.getOrderId() == null || o.getConfirmInTime() == null) continue; + BigDecimal qty = qtyMap.getOrDefault(o.getOrderId(), BigDecimal.ZERO); + if (qty.compareTo(BigDecimal.ZERO) <= 0) continue; + MaterialFlowRow r = new MaterialFlowRow(); + r.setTime(o.getConfirmInTime()); + r.setAction("确认入库"); + r.setOrderCode(o.getOrderCode()); + r.setIoType(o.getIoType()); + r.setQtyChange(qty); + rows.add(r); + confirmInQty = confirmInQty.add(qty); + } + + for (GearStockIoOrder o : outOrders) { + if (o == null || o.getOrderId() == null || o.getExecuteTime() == null) continue; + BigDecimal qty = qtyMap.getOrDefault(o.getOrderId(), BigDecimal.ZERO); + if (qty.compareTo(BigDecimal.ZERO) <= 0) continue; + MaterialFlowRow r = new MaterialFlowRow(); + r.setTime(o.getExecuteTime()); + r.setAction("出库"); + r.setOrderCode(o.getOrderCode()); + r.setIoType(o.getIoType()); + r.setQtyChange(qty.negate()); + rows.add(r); + outQty = outQty.add(qty); + } + + for (GearStockIoOrder o : revokeOrders) { + if (o == null || o.getOrderId() == null || o.getRevokeTime() == null) continue; + BigDecimal qty = qtyMap.getOrDefault(o.getOrderId(), BigDecimal.ZERO); + if (qty.compareTo(BigDecimal.ZERO) <= 0) continue; + MaterialFlowRow r = new MaterialFlowRow(); + r.setTime(o.getRevokeTime()); + r.setAction("撤回"); + r.setOrderCode(o.getOrderCode()); + r.setIoType(o.getIoType()); + if ("O".equalsIgnoreCase(o.getIoType())) { + r.setQtyChange(qty); + revokeOutQty = revokeOutQty.add(qty); + } else if ("I".equalsIgnoreCase(o.getIoType())) { + r.setQtyChange(qty.negate()); + revokeInQty = revokeInQty.add(qty); + } else { + continue; + } + rows.add(r); + } + + rows.sort(Comparator.comparing(MaterialFlowRow::getTime)); + BigDecimal net = confirmInQty.subtract(outQty).add(revokeOutQty).subtract(revokeInQty); + + MaterialFlowResp resp = new MaterialFlowResp(); + resp.setItemId(itemId); + resp.setStartTime(startTime); + resp.setEndTime(endTime); + resp.setConfirmInQty(confirmInQty); + resp.setOutQty(outQty); + resp.setRevokeInQty(revokeInQty); + resp.setRevokeOutQty(revokeOutQty); + resp.setNetQty(net); + resp.setRows(rows); + return resp; + } + private GearStockIoOrder requireOrder(Long orderId) { if (orderId == null) { throw new ServiceException("单据ID不能为空"); diff --git a/gear-ui3/src/api/wms/stockIoOrder.js b/gear-ui3/src/api/wms/stockIoOrder.js index 366448d..0ac1652 100644 --- a/gear-ui3/src/api/wms/stockIoOrder.js +++ b/gear-ui3/src/api/wms/stockIoOrder.js @@ -59,3 +59,11 @@ export function revokeStockIoOrder(orderId, reason) { data: { reason: reason || '' } }) } + +export function getMaterialFlow(params) { + return request({ + url: '/gear/stockIoOrder/materialFlow', + method: 'get', + params + }) +} diff --git a/gear-ui3/src/views/wms/stockIoOrder/in.vue b/gear-ui3/src/views/wms/stockIoOrder/in.vue index 6ca5194..bb2407c 100644 --- a/gear-ui3/src/views/wms/stockIoOrder/in.vue +++ b/gear-ui3/src/views/wms/stockIoOrder/in.vue @@ -29,12 +29,16 @@ 导出 + + 统计/打印 + + + + + + + + + + + + + 查询 + + + +
+
+
+ 物料出入库统计 +
+
+ 物料:{{ flowItemName || '-' }} + 时间: + {{ (flowForm.timeRange && flowForm.timeRange[0]) || '-' }} + + {{ (flowForm.timeRange && flowForm.timeRange[1]) || '-' }} +
+ + + +
确认入库
+
{{ flowResult ? flowResult.confirmInQty : '-' }}
+
+
+ + +
出库
+
{{ flowResult ? flowResult.outQty : '-' }}
+
+
+ + +
撤回入库
+
{{ flowResult ? flowResult.revokeInQty : '-' }}
+
+
+ + +
撤回出库
+
{{ flowResult ? flowResult.revokeOutQty : '-' }}
+
+
+
+ + + +
净变动
+
{{ flowResult ? flowResult.netQty : '-' }}
+
+
+
+ + + + + + + +
+
+ + +
@@ -215,7 +310,8 @@ import { getStockIoOrderWithDetail, addStockIoOrderWithDetail, confirmInStockIoOrder, - revokeStockIoOrder + revokeStockIoOrder, + getMaterialFlow } from '@/api/wms/stockIoOrder' export default { @@ -250,7 +346,15 @@ export default { bizType: [{ required: true, message: '业务类型不能为空', trigger: 'blur' }] }, detailOpen: false, - detailData: null + detailData: null, + flowOpen: false, + flowLoading: false, + flowForm: { + itemId: undefined, + timeRange: [] + }, + flowItemName: '', + flowResult: null } }, computed: { @@ -267,6 +371,30 @@ export default { const n = Number(val) return Number.isFinite(n) ? n : 0 }, + operationRows(order) { + const rows = [] + if (!order) return rows + rows.push({ + action: '创建单据', + user: order.createBy || '-', + time: order.createTime || '-' + }) + if (order.confirmInTime) { + rows.push({ + action: '确认入库', + user: order.confirmInBy || '-', + time: order.confirmInTime || '-' + }) + } + if (order.revokeTime) { + rows.push({ + action: '撤回', + user: order.revokeBy || '-', + time: order.revokeTime || '-' + }) + } + return rows + }, getList() { this.loading = true listStockIoOrder(this.queryParams) @@ -366,6 +494,75 @@ export default { this.buttonLoading = false }) }, + openFlow() { + this.flowOpen = true + this.flowResult = null + if (!this.flowForm.timeRange || this.flowForm.timeRange.length !== 2) { + const end = new Date() + const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000) + this.flowForm.timeRange = [this.formatDateTime(start), this.formatDateTime(end)] + } + }, + formatDateTime(d) { + const pad = (n) => (n < 10 ? '0' + n : String(n)) + const yyyy = d.getFullYear() + const MM = pad(d.getMonth() + 1) + const dd = pad(d.getDate()) + const HH = pad(d.getHours()) + const mm = pad(d.getMinutes()) + const ss = pad(d.getSeconds()) + return `${yyyy}-${MM}-${dd} ${HH}:${mm}:${ss}` + }, + onFlowMaterialChange(material) { + this.flowItemName = material && material.materialName ? material.materialName : '' + }, + fetchFlow() { + if (!this.flowForm.itemId) { + this.$modal.msgError('请选择物料') + return + } + if (!this.flowForm.timeRange || this.flowForm.timeRange.length !== 2) { + this.$modal.msgError('请选择时间范围') + return + } + this.flowLoading = true + this.flowResult = null + getMaterialFlow({ + itemId: this.flowForm.itemId, + startTime: this.flowForm.timeRange[0], + endTime: this.flowForm.timeRange[1] + }) + .then((res) => { + this.flowResult = res.data || null + }) + .finally(() => { + this.flowLoading = false + }) + }, + printFlow() { + const el = this.$refs.flowPrintContent + if (!el) return + const w = window.open('', '_blank') + if (!w) return + const html = ` + + + 物料出入库统计 + + + ${el.innerHTML} + ` + w.document.open() + w.document.write(html) + w.document.close() + w.focus() + w.print() + w.close() + }, submitEdit() { this.$refs.editFormRef.validate((valid) => { if (!valid) return diff --git a/gear-ui3/src/views/wms/stockIoOrder/out.vue b/gear-ui3/src/views/wms/stockIoOrder/out.vue index 0518669..8bf248e 100644 --- a/gear-ui3/src/views/wms/stockIoOrder/out.vue +++ b/gear-ui3/src/views/wms/stockIoOrder/out.vue @@ -26,12 +26,16 @@ 导出 + + 统计/打印 + + + + + + + + + + + + + 查询 + + + +
+
+
+ 物料出入库统计 +
+
+ 物料:{{ flowItemName || '-' }} + 时间: + {{ (flowForm.timeRange && flowForm.timeRange[0]) || '-' }} + + {{ (flowForm.timeRange && flowForm.timeRange[1]) || '-' }} +
+ + + +
确认入库
+
{{ flowResult ? flowResult.confirmInQty : '-' }}
+
+
+ + +
出库
+
{{ flowResult ? flowResult.outQty : '-' }}
+
+
+ + +
撤回入库
+
{{ flowResult ? flowResult.revokeInQty : '-' }}
+
+
+ + +
撤回出库
+
{{ flowResult ? flowResult.revokeOutQty : '-' }}
+
+
+
+ + + +
净变动
+
{{ flowResult ? flowResult.netQty : '-' }}
+
+
+
+ + + + + + + +
+
+ + +
@@ -195,7 +290,8 @@ import { listStockIoOrder, getStockIoOrderWithDetail, addStockIoOrderWithDetail, - revokeStockIoOrder + revokeStockIoOrder, + getMaterialFlow } from '@/api/wms/stockIoOrder' export default { @@ -229,7 +325,15 @@ export default { bizType: [{ required: true, message: '业务类型不能为空', trigger: 'blur' }] }, detailOpen: false, - detailData: null + detailData: null, + flowOpen: false, + flowLoading: false, + flowForm: { + itemId: undefined, + timeRange: [] + }, + flowItemName: '', + flowResult: null } }, computed: { @@ -246,6 +350,30 @@ export default { const n = Number(val) return Number.isFinite(n) ? n : 0 }, + operationRows(order) { + const rows = [] + if (!order) return rows + rows.push({ + action: '创建单据', + user: order.createBy || '-', + time: order.createTime || '-' + }) + if (order.executeTime) { + rows.push({ + action: '出库', + user: order.executeBy || '-', + time: order.executeTime || '-' + }) + } + if (order.revokeTime) { + rows.push({ + action: '撤回', + user: order.revokeBy || '-', + time: order.revokeTime || '-' + }) + } + return rows + }, getList() { this.loading = true listStockIoOrder(this.queryParams) @@ -324,6 +452,75 @@ export default { this.buttonLoading = false }) }, + openFlow() { + this.flowOpen = true + this.flowResult = null + if (!this.flowForm.timeRange || this.flowForm.timeRange.length !== 2) { + const end = new Date() + const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000) + this.flowForm.timeRange = [this.formatDateTime(start), this.formatDateTime(end)] + } + }, + formatDateTime(d) { + const pad = (n) => (n < 10 ? '0' + n : String(n)) + const yyyy = d.getFullYear() + const MM = pad(d.getMonth() + 1) + const dd = pad(d.getDate()) + const HH = pad(d.getHours()) + const mm = pad(d.getMinutes()) + const ss = pad(d.getSeconds()) + return `${yyyy}-${MM}-${dd} ${HH}:${mm}:${ss}` + }, + onFlowMaterialChange(material) { + this.flowItemName = material && material.materialName ? material.materialName : '' + }, + fetchFlow() { + if (!this.flowForm.itemId) { + this.$modal.msgError('请选择物料') + return + } + if (!this.flowForm.timeRange || this.flowForm.timeRange.length !== 2) { + this.$modal.msgError('请选择时间范围') + return + } + this.flowLoading = true + this.flowResult = null + getMaterialFlow({ + itemId: this.flowForm.itemId, + startTime: this.flowForm.timeRange[0], + endTime: this.flowForm.timeRange[1] + }) + .then((res) => { + this.flowResult = res.data || null + }) + .finally(() => { + this.flowLoading = false + }) + }, + printFlow() { + const el = this.$refs.flowPrintContent + if (!el) return + const w = window.open('', '_blank') + if (!w) return + const html = ` + + + 物料出入库统计 + + + ${el.innerHTML} + ` + w.document.open() + w.document.write(html) + w.document.close() + w.focus() + w.print() + w.close() + }, submitEdit() { this.$refs.editFormRef.validate((valid) => { if (!valid) return diff --git a/gear-ui3/src/views/wms/stockIoOrder/panels/stockIoOrderPage.vue b/gear-ui3/src/views/wms/stockIoOrder/panels/stockIoOrderPage.vue index 9925e3e..f23e5c9 100644 --- a/gear-ui3/src/views/wms/stockIoOrder/panels/stockIoOrderPage.vue +++ b/gear-ui3/src/views/wms/stockIoOrder/panels/stockIoOrderPage.vue @@ -49,6 +49,9 @@ 导出 + + 统计/打印 + @@ -56,6 +59,7 @@ + + + + + + + + + + + + 查询 + + + +
+
+
+ 物料出入库统计 +
+
+ 物料:{{ flowItemName || '-' }} + 时间: + {{ (flowForm.timeRange && flowForm.timeRange[0]) || '-' }} + + {{ (flowForm.timeRange && flowForm.timeRange[1]) || '-' }} +
+ + + +
确认入库
+
{{ flowResult ? flowResult.confirmInQty : '-' }}
+
+
+ + +
出库
+
{{ flowResult ? flowResult.outQty : '-' }}
+
+
+ + +
撤回入库
+
{{ flowResult ? flowResult.revokeInQty : '-' }}
+
+
+ + +
撤回出库
+
{{ flowResult ? flowResult.revokeOutQty : '-' }}
+
+
+
+ + + +
净变动
+
{{ flowResult ? flowResult.netQty : '-' }}
+
+
+
+ + + + + + + +
+
+ + +
@@ -292,7 +387,8 @@ import { getStockIoOrderWithDetail, addStockIoOrderWithDetail, updateStockIoOrderWithDetail, - delStockIoOrder + delStockIoOrder, + getMaterialFlow } from '@/api/wms/stockIoOrder' export default { @@ -355,7 +451,15 @@ export default { bizType: [{ required: true, message: '业务类型不能为空', trigger: 'blur' }] }, detailOpen: false, - detailData: null + detailData: null, + flowOpen: false, + flowLoading: false, + flowForm: { + itemId: undefined, + timeRange: [] + }, + flowItemName: '', + flowResult: null } }, computed: { @@ -397,6 +501,37 @@ export default { if (v === '2') return 'success' return 'info' }, + operationRows(order) { + const rows = [] + if (!order) return rows + rows.push({ + action: '创建单据', + user: order.createBy || '-', + time: order.createTime || '-' + }) + if (order.ioType === 'O' && order.executeTime) { + rows.push({ + action: '出库', + user: order.executeBy || '-', + time: order.executeTime || '-' + }) + } + if (order.ioType === 'I' && order.confirmInTime) { + rows.push({ + action: '确认入库', + user: order.confirmInBy || '-', + time: order.confirmInTime || '-' + }) + } + if (order.revokeTime) { + rows.push({ + action: '撤回', + user: order.revokeBy || '-', + time: order.revokeTime || '-' + }) + } + return rows + }, getList() { this.loading = true listStockIoOrder(this.queryParams) @@ -514,6 +649,75 @@ export default { `stockIoOrder_${type}_${new Date().getTime()}.xlsx` ) }, + openFlow() { + this.flowOpen = true + this.flowResult = null + if (!this.flowForm.timeRange || this.flowForm.timeRange.length !== 2) { + const end = new Date() + const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000) + this.flowForm.timeRange = [this.formatDateTime(start), this.formatDateTime(end)] + } + }, + formatDateTime(d) { + const pad = (n) => (n < 10 ? '0' + n : String(n)) + const yyyy = d.getFullYear() + const MM = pad(d.getMonth() + 1) + const dd = pad(d.getDate()) + const HH = pad(d.getHours()) + const mm = pad(d.getMinutes()) + const ss = pad(d.getSeconds()) + return `${yyyy}-${MM}-${dd} ${HH}:${mm}:${ss}` + }, + onFlowMaterialChange(material) { + this.flowItemName = material && material.materialName ? material.materialName : '' + }, + fetchFlow() { + if (!this.flowForm.itemId) { + this.$modal.msgError('请选择物料') + return + } + if (!this.flowForm.timeRange || this.flowForm.timeRange.length !== 2) { + this.$modal.msgError('请选择时间范围') + return + } + this.flowLoading = true + this.flowResult = null + getMaterialFlow({ + itemId: this.flowForm.itemId, + startTime: this.flowForm.timeRange[0], + endTime: this.flowForm.timeRange[1] + }) + .then((res) => { + this.flowResult = res.data || null + }) + .finally(() => { + this.flowLoading = false + }) + }, + printFlow() { + const el = this.$refs.flowPrintContent + if (!el) return + const w = window.open('', '_blank') + if (!w) return + const html = ` + + + 物料出入库统计 + + + ${el.innerHTML} + ` + w.document.open() + w.document.write(html) + w.document.close() + w.focus() + w.print() + w.close() + }, showDetail(row) { this.detailOpen = true this.detailData = null