|
|
|
<template>
|
|
|
|
<div>
|
|
|
|
<el-dialog
|
|
|
|
v-model="details.popUpShow.visible"
|
|
|
|
destroy-on-close
|
|
|
|
align-center
|
|
|
|
:title="props.title"
|
|
|
|
:width="props.width"
|
|
|
|
:fullscreen="props.isFullscreen && details.isFullscreen"
|
|
|
|
:show-close="!props.isFullscreen"
|
|
|
|
>
|
|
|
|
<!-- 标题 -- 头部控件区 -->
|
|
|
|
<template v-if="props.isFullscreen" #header="{ close, titleId, titleClass }">
|
|
|
|
<div class="my-header flex-c-sb">
|
|
|
|
<div class="fwb" :id="titleId" :class="titleClass">{{ props.title }}</div>
|
|
|
|
<div class="flex-c-c">
|
|
|
|
<!-- 全屏显示按钮 -->
|
|
|
|
<el-button type="text" @click="handleFullScrean()" v-if="!details.isFullscreen">
|
|
|
|
<el-icon class=""><FullScreen /></el-icon>
|
|
|
|
</el-button>
|
|
|
|
<el-button type="text" @click="handleFullScrean()" v-else>
|
|
|
|
<el-icon class=""><CopyDocument /></el-icon>
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
<!-- 弹窗关闭按钮 -->
|
|
|
|
<el-button type="text">
|
|
|
|
<el-icon class="" @click="close"><Close /></el-icon>
|
|
|
|
</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<div class="printCode" ref="printNodeRef">
|
|
|
|
<template v-if="details.html">
|
|
|
|
<div v-html="details.html"></div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<slot></slot>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="flex-c-c mt10">
|
|
|
|
<el-button @click="handleClose" icon="CircleClose"> 关 闭 </el-button>
|
|
|
|
<el-button type="primary" v-if="props.isShowExport" @click="handleExport" icon="Download">
|
|
|
|
导 出
|
|
|
|
</el-button>
|
|
|
|
<el-button
|
|
|
|
type="primary"
|
|
|
|
@click="printTemplate"
|
|
|
|
icon="Printer"
|
|
|
|
:disabled="details.printLoading"
|
|
|
|
:loading="details.printLoading"
|
|
|
|
>
|
|
|
|
打 印
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
<el-button
|
|
|
|
type="primary"
|
|
|
|
@click="handleShowEdit"
|
|
|
|
icon="Edit"
|
|
|
|
:disabled="details.printLoading"
|
|
|
|
:loading="details.printLoading"
|
|
|
|
>
|
|
|
|
编辑打印机
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
<!-- <el-select
|
|
|
|
v-model="activeIndex"
|
|
|
|
placeholder="打印机"
|
|
|
|
style="width: 200px; margin-left: 10px"
|
|
|
|
>
|
|
|
|
<el-option
|
|
|
|
v-for="item in $store.state.print.printList"
|
|
|
|
:label="item.label"
|
|
|
|
:value="item.value"
|
|
|
|
:key="item.label"
|
|
|
|
/>
|
|
|
|
</el-select> -->
|
|
|
|
</div>
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
<!-- 确认打印机 -->
|
|
|
|
<el-dialog v-model="isShow" title="确认打印机" align-center width="fit-content">
|
|
|
|
<div style="margin-bottom: 40px" class="flex-c-c">
|
|
|
|
<div class="flex-none">编辑打印机:</div>
|
|
|
|
<el-select
|
|
|
|
v-model="activeIndex"
|
|
|
|
placeholder="打印机"
|
|
|
|
style="width: 200px; margin-left: 10px"
|
|
|
|
>
|
|
|
|
<el-option
|
|
|
|
v-for="item in $store.state.print.printList"
|
|
|
|
:label="item.label"
|
|
|
|
:value="item.value"
|
|
|
|
:key="item.label"
|
|
|
|
/>
|
|
|
|
</el-select>
|
|
|
|
</div>
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
<el-dialog
|
|
|
|
v-model="details.popUpShow.setNum"
|
|
|
|
title="确认打印标签数"
|
|
|
|
align-center
|
|
|
|
width="50%"
|
|
|
|
destroy-on-close
|
|
|
|
>
|
|
|
|
<template v-for="item in details.waybillInfo.detailList">
|
|
|
|
<div class="fwb">品类名:{{ item.productName }}</div>
|
|
|
|
<div class="flex mt10 mb20">
|
|
|
|
<div class="flex1 align-center mr20">
|
|
|
|
<div class="mr10">开始索引</div>
|
|
|
|
<el-input-number
|
|
|
|
class="flex1"
|
|
|
|
v-model="item.start"
|
|
|
|
:min="1"
|
|
|
|
:max="item.num"
|
|
|
|
></el-input-number>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="flex1 align-center">
|
|
|
|
<div class="mr10">结束索引</div>
|
|
|
|
<el-input-number
|
|
|
|
class="flex1"
|
|
|
|
v-model="item.end"
|
|
|
|
:min="isNumber(item.start > 1) ? item.start : 0"
|
|
|
|
:max="item.num"
|
|
|
|
></el-input-number>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<div class="flex-c-sb">
|
|
|
|
<div></div>
|
|
|
|
<div>
|
|
|
|
<el-button @click="details.popUpShow.setNum = false">取消</el-button>
|
|
|
|
<el-button type="primary" @click="handleShowPrint" icon="Printer">确认</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</el-dialog>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { defineProps, computed, ref, nextTick, reactive, watch } from 'vue';
|
|
|
|
import print from '@/utils/print';
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
|
import { getObjType } from '@/utils/util';
|
|
|
|
import * as XLSX from 'xlsx';
|
|
|
|
import { exportExcelByDom } from '@/utils/export';
|
|
|
|
import { dateNow } from '@/utils/date';
|
|
|
|
import { postFindZeroWaybillLabelInfo } from '@/api/waybill/WaybillOrderList.js';
|
|
|
|
import { useStore } from 'vuex';
|
|
|
|
import { isNumber } from '@antfu/utils';
|
|
|
|
|
|
|
|
const $store = useStore();
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
/** 弹窗宽度 */
|
|
|
|
width: {
|
|
|
|
type: String,
|
|
|
|
default: '780px',
|
|
|
|
},
|
|
|
|
/** 标题 */
|
|
|
|
title: {
|
|
|
|
type: String,
|
|
|
|
default: '二维码',
|
|
|
|
},
|
|
|
|
/** 是否显示导出按钮 */
|
|
|
|
isShowExport: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true,
|
|
|
|
},
|
|
|
|
/** 打印函数 */
|
|
|
|
printFn: {
|
|
|
|
type: Function,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
/** 打印类型 */
|
|
|
|
type: {
|
|
|
|
type: String,
|
|
|
|
default: 'titlePrint',
|
|
|
|
},
|
|
|
|
/** 导出名称 */
|
|
|
|
exportName: {
|
|
|
|
type: String,
|
|
|
|
default: '导出',
|
|
|
|
},
|
|
|
|
/** 是否开启全屏按钮 */
|
|
|
|
isFullscreen: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const $emit = defineEmits(['update:modelValue']);
|
|
|
|
|
|
|
|
const isShow = ref(false);
|
|
|
|
|
|
|
|
const activeIndex = computed({
|
|
|
|
get() {
|
|
|
|
return $store.state.print[props.type + 'ActiveIndex'];
|
|
|
|
},
|
|
|
|
set(activeIndex) {
|
|
|
|
// 设置打印机
|
|
|
|
$store.commit('SET_PRINT_ACTIVE', { activeIndex, type: props.type });
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const details = reactive({
|
|
|
|
/** 打印loading */
|
|
|
|
printLoading: false,
|
|
|
|
/** 是否全屏 */
|
|
|
|
isFullscreen: false,
|
|
|
|
/** 运单信息 */
|
|
|
|
waybillInfo: {} as any,
|
|
|
|
popUpShow: {
|
|
|
|
/** 打印 */
|
|
|
|
visible: false,
|
|
|
|
setNum: false,
|
|
|
|
},
|
|
|
|
html: '',
|
|
|
|
waybillNo: '',
|
|
|
|
});
|
|
|
|
|
|
|
|
const handleClose = () => {
|
|
|
|
details.popUpShow.visible = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
const printNodeRef = ref();
|
|
|
|
|
|
|
|
/** 生成Excel */
|
|
|
|
const createExcel = () => {
|
|
|
|
// const table = this.$refs.tableRef;
|
|
|
|
|
|
|
|
/* 将表格转换为 Workbook 对象 */
|
|
|
|
const wb = XLSX.utils.table_to_book(printNodeRef.value);
|
|
|
|
|
|
|
|
console.log('wb :>> ', wb);
|
|
|
|
|
|
|
|
wb.Sheets.Sheet1;
|
|
|
|
|
|
|
|
//单元格外侧框线
|
|
|
|
const borderAll = {
|
|
|
|
top: {
|
|
|
|
style: 'thin',
|
|
|
|
},
|
|
|
|
bottom: {
|
|
|
|
style: 'thin',
|
|
|
|
},
|
|
|
|
left: {
|
|
|
|
style: 'thin',
|
|
|
|
},
|
|
|
|
right: {
|
|
|
|
style: 'thin',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const key in wb.Sheets.Sheet1) {
|
|
|
|
const item = wb.Sheets.Sheet1[key];
|
|
|
|
|
|
|
|
const type = getObjType(item);
|
|
|
|
|
|
|
|
console.log('type :>> ', type);
|
|
|
|
|
|
|
|
if (type !== 'object') continue;
|
|
|
|
|
|
|
|
item.s = {
|
|
|
|
border: borderAll,
|
|
|
|
font: {
|
|
|
|
// name: "微软雅黑",
|
|
|
|
// sz: 16,
|
|
|
|
color: { rgb: '000000' },
|
|
|
|
bold: true,
|
|
|
|
italic: false,
|
|
|
|
underline: false,
|
|
|
|
},
|
|
|
|
fill: {
|
|
|
|
fgColor: { rgb: 'C5D9F1' },
|
|
|
|
},
|
|
|
|
alignment: {
|
|
|
|
horizontal: 'center',
|
|
|
|
vertical: 'center',
|
|
|
|
wrapText: false, // 自动换行
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
item.t = 's';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 导出 Workbook 到 Excel 文件 */
|
|
|
|
XLSX.writeFile(wb, 'data.xlsx');
|
|
|
|
};
|
|
|
|
|
|
|
|
/** 导出 */
|
|
|
|
const handleExport = () => {
|
|
|
|
if (!printNodeRef.value) return ElMessage.warning('数据暂未请求完成, 请稍等');
|
|
|
|
|
|
|
|
ElMessageBox.confirm('确认导出?', '', {
|
|
|
|
confirmButtonText: '确认',
|
|
|
|
cancelButtonText: '关闭',
|
|
|
|
type: 'warning',
|
|
|
|
}).then(() => {
|
|
|
|
console.log('printNodeRef.value :>> ', printNodeRef.value);
|
|
|
|
|
|
|
|
props.type === 'titlePrint'
|
|
|
|
? createExcel()
|
|
|
|
: exportExcelByDom(printNodeRef.value, props.exportName + ' - ' + dateNow() + '.xlsx');
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/** 打印 */
|
|
|
|
const printTemplate = () => {
|
|
|
|
if (props.printFn) return props.printFn();
|
|
|
|
|
|
|
|
details.printLoading = true;
|
|
|
|
|
|
|
|
const nodeArr = document.querySelectorAll('.printSmallText');
|
|
|
|
|
|
|
|
for (let i = 0; i < nodeArr.length; i++) {
|
|
|
|
const val = nodeArr[i] as any;
|
|
|
|
val.style.fontSize = '0.5rem';
|
|
|
|
val.style.lineHeight = '0.7rem';
|
|
|
|
}
|
|
|
|
|
|
|
|
const timer = setTimeout(() => {
|
|
|
|
const printNode = document.querySelectorAll('.printCode > div > div');
|
|
|
|
console.log('printNode :>> ', printNode);
|
|
|
|
print(printNode, props.type);
|
|
|
|
handleClose();
|
|
|
|
details.printLoading = false;
|
|
|
|
clearTimeout(timer);
|
|
|
|
}, 500);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 是否开启床车明细全屏
|
|
|
|
* @params(_type) 开启或关闭
|
|
|
|
*/
|
|
|
|
const handleFullScrean = () => {
|
|
|
|
details.isFullscreen = !details.isFullscreen;
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleGetWaybillInfo = async (waybillNo, loading, loadingKey = 'pageLoading') => {
|
|
|
|
try {
|
|
|
|
loading[loadingKey] = true;
|
|
|
|
details.waybillNo = waybillNo;
|
|
|
|
|
|
|
|
const res = await postFindZeroWaybillLabelInfo({ waybillNo });
|
|
|
|
|
|
|
|
const { code, data } = res.data;
|
|
|
|
|
|
|
|
if (code !== 200) return;
|
|
|
|
if (getObjType(data) !== 'object') return;
|
|
|
|
|
|
|
|
details.waybillInfo = data;
|
|
|
|
|
|
|
|
if (getObjType(details.waybillInfo.detailList) !== 'array') details.waybillInfo.detailList = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < details.waybillInfo.detailList.length; i++) {
|
|
|
|
const value = details.waybillInfo.detailList[i];
|
|
|
|
|
|
|
|
value.start = value.num > 1 ? 1 : 0;
|
|
|
|
value.end = value.num >= 1 ? value.num : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
details.popUpShow.setNum = true;
|
|
|
|
} catch (error) {
|
|
|
|
console.log('error :>> ', error);
|
|
|
|
} finally {
|
|
|
|
loading[loadingKey] = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleShowPrint = () => {
|
|
|
|
let flag = true;
|
|
|
|
|
|
|
|
let html = '';
|
|
|
|
let waybillProductName = '';
|
|
|
|
|
|
|
|
for (let i = 0; i < details.waybillInfo.detailList.length; i++) {
|
|
|
|
const value = details.waybillInfo.detailList[i];
|
|
|
|
|
|
|
|
waybillProductName += value.productName + ' - ' + value.num + '<br />';
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < details.waybillInfo.detailList.length; i++) {
|
|
|
|
const value = details.waybillInfo.detailList[i];
|
|
|
|
|
|
|
|
if (value.end <= 0) continue;
|
|
|
|
|
|
|
|
flag = false;
|
|
|
|
|
|
|
|
for (let index = value.start; index <= value.end; index++) {
|
|
|
|
let template = details.waybillInfo.template;
|
|
|
|
|
|
|
|
template = template.replace('发站仓信息', details.waybillInfo.destinationWarehouseName);
|
|
|
|
template = template.replace('目的仓信息', details.waybillInfo.departureWarehouseName);
|
|
|
|
template = template.replace('发站信息', details.waybillInfo.destination);
|
|
|
|
template = template.replace('到站信息', details.waybillInfo.departure);
|
|
|
|
template = template.replace('运单号', details.waybillNo);
|
|
|
|
template = template.replace('订单号', details.waybillInfo.orderNo);
|
|
|
|
template = template.replace('运单地址', details.waybillInfo.waybillNoCode);
|
|
|
|
template = template.replace('总件数值', details.waybillInfo.totalCount);
|
|
|
|
template = template.replace('总重量值', details.waybillInfo.totalWeight);
|
|
|
|
template = template.replace('总方数值', details.waybillInfo.total_volume);
|
|
|
|
template = template.replace('货物单项信息', value.productName + ' - ' + index);
|
|
|
|
template = template.replace(
|
|
|
|
'寄件人信息',
|
|
|
|
details.waybillInfo.shipperName +
|
|
|
|
details.waybillInfo.shipperMobile +
|
|
|
|
details.waybillInfo.shipperAddress
|
|
|
|
);
|
|
|
|
template = template.replace('货物信息', waybillProductName);
|
|
|
|
template = template.replace(
|
|
|
|
'收件人信息',
|
|
|
|
details.waybillInfo.consigneeName +
|
|
|
|
details.waybillInfo.consigneeMobile +
|
|
|
|
details.waybillInfo.consigneeAddress
|
|
|
|
);
|
|
|
|
template = template.replace('送货方式值', details.waybillInfo.delivery_way);
|
|
|
|
template = template.replace('送货时间值', details.waybillInfo.createDate.split(' ')[0]);
|
|
|
|
|
|
|
|
html += template;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag) return ElMessage.warning('请输入需要打印的范围');
|
|
|
|
|
|
|
|
details.html = html;
|
|
|
|
details.popUpShow.visible = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleShowEdit = () => {
|
|
|
|
$store.commit('GET_PRINT_LIST');
|
|
|
|
isShow.value = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
defineExpose({ handleGetWaybillInfo });
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.printCode {
|
|
|
|
max-height: 80vh;
|
|
|
|
overflow-y: scroll;
|
|
|
|
}
|
|
|
|
|
|
|
|
.my-header {
|
|
|
|
:deep(.el-icon) {
|
|
|
|
font-size: 20px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|