7 changed files with 525 additions and 2 deletions
@ -0,0 +1,454 @@
|
||||
<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> |
Loading…
Reference in new issue