|
|
<template>
|
|
|
<div>
|
|
|
|
|
|
<xy-dialog title="打印预览" :is-show.sync="isShow" :width="90" ok-text="打印" @on-ok="printHtml">
|
|
|
<template v-slot:normalContent>
|
|
|
<div style="position: relative; margin-bottom: 16px; min-height: 40px;">
|
|
|
<div style="width: fit-content; margin: 0 auto;">
|
|
|
<RadioGroup v-model="currentForm" type="button">
|
|
|
<!-- <Radio label="pre" :disabled="!getBeforeForms">事前审批表格</Radio> -->
|
|
|
<!-- <Radio label="finance" :disabled="!fundLog">财务审核表</Radio> -->
|
|
|
<Radio label="post" :disabled="!getForms">事后支付表格</Radio>
|
|
|
</RadioGroup>
|
|
|
</div>
|
|
|
<div style="position: absolute; right: 0; top: 0;">
|
|
|
<label>打印方向:</label>
|
|
|
<select v-model="printOrientation" style="margin-right: 16px;">
|
|
|
<option value="portrait">纵向</option>
|
|
|
<option value="landscape">横向</option>
|
|
|
</select>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="white-container">
|
|
|
<div class="form-container">
|
|
|
<!-- Pre-payment Form -->
|
|
|
<div v-if="currentForm === 'pre'" class="payment-form">
|
|
|
<div v-if="getBeforeForms" v-html="getBeforeForms" />
|
|
|
<div v-else class="no-form-message">暂无事前审批表格内容</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- Post-payment Form -->
|
|
|
<div v-else-if="currentForm === 'post'" ref="printtable" class="payment-form">
|
|
|
<!-- 财务审核表内容放到事后支付表头部 -->
|
|
|
<table class="finance-review-table no-print">
|
|
|
<tr>
|
|
|
<th colspan="2" class="finance-header-row">合同信息</th>
|
|
|
<th colspan="5" class="finance-header-row">付款信息</th>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td class="sub-header">受款单位</td>
|
|
|
<td>{{ fundLog && fundLog.contract && fundLog.contract.supply || '-' }}</td>
|
|
|
<td class="sub-header">申请付款金额</td>
|
|
|
<td>{{ fundLog && fundLog.apply_money || '-' }}</td>
|
|
|
<td class="sub-header">实际支付金额</td>
|
|
|
<td>{{ fundLog && fundLog.act_money || '-' }}</td>
|
|
|
<td class="sub-header">款项类型</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td class="sub-header">合同名称</td>
|
|
|
<td>{{ fundLog && fundLog.contract && fundLog.contract.name || '-' }}</td>
|
|
|
<td class="sub-header">审计金额</td>
|
|
|
<td>{{ fundLog && fundLog.audit_money || '-' }}</td>
|
|
|
<td class="sub-header">本期扣款金额</td>
|
|
|
<td>{{ fundLog && fundLog.discount_money || '-' }}</td>
|
|
|
<td>{{ fundLog && fundLog.type || '-' }}</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td class="sub-header">合同金额</td>
|
|
|
<td>{{ fundLog && fundLog.contract && moneyFormat(fundLog.contract.money) || '-' }} (元)</td>
|
|
|
<td class="sub-header">是否为最后一笔</td>
|
|
|
<td>{{ fundLog && fundLog.is_end === 1 ? '是' : '否' }}</td>
|
|
|
<td class="sub-header">备注</td>
|
|
|
<td colspan="2">{{ fundLog && fundLog.remark || '-' }}</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
<div v-if="getForms" v-html="getForms" />
|
|
|
<div v-else class="no-form-message">暂无事后支付表格内容</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</xy-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { detailFundLog } from '@/api/paymentRegistration/fundLog'
|
|
|
import html2canvas from 'html2canvas'
|
|
|
import * as printJS from 'print-js'
|
|
|
|
|
|
// 添加金额转大写的工具函数
|
|
|
function numberToChinese(num) {
|
|
|
const units = ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿', '拾', '佰', '仟', '万']
|
|
|
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
|
|
|
const [integer, decimal] = num.toString().split('.')
|
|
|
let result = ''
|
|
|
let intNum = parseInt(integer)
|
|
|
if (intNum === 0) {
|
|
|
result = '零'
|
|
|
} else {
|
|
|
let i = 0
|
|
|
let lastDigit = null
|
|
|
let hasZero = false
|
|
|
while (intNum > 0) {
|
|
|
const digit = intNum % 10
|
|
|
if (digit === 0) {
|
|
|
if (!hasZero && lastDigit !== 0) {
|
|
|
result = '零' + result
|
|
|
hasZero = true
|
|
|
}
|
|
|
} else {
|
|
|
let unit = units[i]
|
|
|
if (i === 4 && result.startsWith('零')) {
|
|
|
unit = '万'
|
|
|
} else if (i === 8 && result.startsWith('零')) {
|
|
|
unit = '亿'
|
|
|
}
|
|
|
result = digits[digit] + unit + result
|
|
|
hasZero = false
|
|
|
}
|
|
|
lastDigit = digit
|
|
|
intNum = Math.floor(intNum / 10)
|
|
|
i++
|
|
|
}
|
|
|
result = result.replace(/零+$/, '')
|
|
|
result = result.replace(/零+/, '零')
|
|
|
}
|
|
|
if (decimal) {
|
|
|
const decimalNum = parseInt(decimal)
|
|
|
if (decimalNum > 0) {
|
|
|
result += '点'
|
|
|
for (let i = 0; i < decimal.length; i++) {
|
|
|
result += digits[parseInt(decimal[i])]
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (!decimal || parseInt(decimal) === 0) {
|
|
|
result += '整'
|
|
|
}
|
|
|
return result + '元'
|
|
|
}
|
|
|
|
|
|
export default {
|
|
|
name: 'PrintPaymentForm',
|
|
|
data() {
|
|
|
return {
|
|
|
isShow: false,
|
|
|
currentForm: 'post',
|
|
|
fundLog: null,
|
|
|
printOrientation: 'portrait' // 默认横向
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
getBeforeForms() {
|
|
|
return this.fundLog && this.fundLog.contract && this.fundLog.contract.before_forms
|
|
|
},
|
|
|
getForms() {
|
|
|
return this.fundLog && this.fundLog.contract && this.fundLog.contract.forms
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
getForms: {
|
|
|
handler(newVal) {
|
|
|
if (newVal) {
|
|
|
this.$nextTick(() => {
|
|
|
this.setupAmountListeners()
|
|
|
})
|
|
|
}
|
|
|
},
|
|
|
immediate: true
|
|
|
},
|
|
|
isShow: {
|
|
|
handler(newVal) {
|
|
|
if (newVal) {
|
|
|
this.$nextTick(() => {
|
|
|
this.setupAmountListeners()
|
|
|
})
|
|
|
}
|
|
|
},
|
|
|
immediate: true
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
async getDetailFundLog(id) {
|
|
|
try {
|
|
|
const res = await detailFundLog({ id })
|
|
|
this.fundLog = res
|
|
|
} catch (error) {
|
|
|
console.error('获取付款详情失败:', error)
|
|
|
this.$Message.error('获取付款详情失败')
|
|
|
}
|
|
|
},
|
|
|
setupAmountListeners() {
|
|
|
const dom = this.$refs.printtable
|
|
|
if (!dom) return
|
|
|
|
|
|
const sdateAmountInputs = dom.querySelectorAll('input[data-field^="sdate"]')
|
|
|
// 移除旧的监听器
|
|
|
sdateAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.caculateRoadDay)
|
|
|
input.removeEventListener('change', this.caculateRoadDay)
|
|
|
input.removeEventListener('blur', this.caculateRoadDay)
|
|
|
})
|
|
|
|
|
|
// 添加新的监听器
|
|
|
sdateAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.caculateRoadDay)
|
|
|
input.addEventListener('change', this.caculateRoadDay)
|
|
|
input.addEventListener('blur', this.caculateRoadDay)
|
|
|
})
|
|
|
|
|
|
const edateAmountInputs = dom.querySelectorAll('input[data-field^="edate"]')
|
|
|
// 移除旧的监听器
|
|
|
edateAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.caculateRoadDay)
|
|
|
input.removeEventListener('change', this.caculateRoadDay)
|
|
|
input.removeEventListener('blur', this.caculateRoadDay)
|
|
|
})
|
|
|
|
|
|
// 添加新的监听器
|
|
|
edateAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.caculateRoadDay)
|
|
|
input.addEventListener('change', this.caculateRoadDay)
|
|
|
input.addEventListener('blur', this.caculateRoadDay)
|
|
|
})
|
|
|
|
|
|
// 获取所有以 wan 开头的输入框
|
|
|
const wanAmountInputs = dom.querySelectorAll('input[data-field^="wan"]')
|
|
|
// 移除旧的监听器
|
|
|
wanAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.calculateTotal)
|
|
|
input.removeEventListener('change', this.calculateTotal)
|
|
|
input.removeEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 添加新的监听器
|
|
|
wanAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.calculateTotal)
|
|
|
input.addEventListener('change', this.calculateTotal)
|
|
|
input.addEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
|
|
|
// 获取所有以 qian 开头的输入框
|
|
|
const qianAmountInputs = dom.querySelectorAll('input[data-field^="qian"]')
|
|
|
// 移除旧的监听器
|
|
|
qianAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.calculateTotal)
|
|
|
input.removeEventListener('change', this.calculateTotal)
|
|
|
input.removeEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 添加新的监听器
|
|
|
qianAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.calculateTotal)
|
|
|
input.addEventListener('change', this.calculateTotal)
|
|
|
input.addEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 获取所有以 bai 开头的输入框
|
|
|
const baiAmountInputs = dom.querySelectorAll('input[data-field^="bai"]')
|
|
|
// 移除旧的监听器
|
|
|
baiAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.calculateTotal)
|
|
|
input.removeEventListener('change', this.calculateTotal)
|
|
|
input.removeEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 添加新的监听器
|
|
|
baiAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.calculateTotal)
|
|
|
input.addEventListener('change', this.calculateTotal)
|
|
|
input.addEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 获取所有以 shi 开头的输入框
|
|
|
const shiAmountInputs = dom.querySelectorAll('input[data-field^="shi"]')
|
|
|
// 移除旧的监听器
|
|
|
shiAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.calculateTotal)
|
|
|
input.removeEventListener('change', this.calculateTotal)
|
|
|
input.removeEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 添加新的监听器
|
|
|
shiAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.calculateTotal)
|
|
|
input.addEventListener('change', this.calculateTotal)
|
|
|
input.addEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 获取所有以 yuan 开头的输入框
|
|
|
const yuanAmountInputs = dom.querySelectorAll('input[data-field^="yuan"]')
|
|
|
// 移除旧的监听器
|
|
|
yuanAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.calculateTotal)
|
|
|
input.removeEventListener('change', this.calculateTotal)
|
|
|
input.removeEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
// 添加新的监听器
|
|
|
yuanAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.calculateTotal)
|
|
|
input.addEventListener('change', this.calculateTotal)
|
|
|
input.addEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 获取所有以 jiao 开头的输入框
|
|
|
const jiaoAmountInputs = dom.querySelectorAll('input[data-field^="jiao"]')
|
|
|
// 移除旧的监听器
|
|
|
jiaoAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.calculateTotal)
|
|
|
input.removeEventListener('change', this.calculateTotal)
|
|
|
input.removeEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
// 添加新的监听器
|
|
|
jiaoAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.calculateTotal)
|
|
|
input.addEventListener('change', this.calculateTotal)
|
|
|
input.addEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 获取所有以 fen 开头的输入框
|
|
|
const fenAmountInputs = dom.querySelectorAll('input[data-field^="fen"]')
|
|
|
// 移除旧的监听器
|
|
|
fenAmountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.calculateTotal)
|
|
|
input.removeEventListener('change', this.calculateTotal)
|
|
|
input.removeEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
// 添加新的监听器
|
|
|
fenAmountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.calculateTotal)
|
|
|
input.addEventListener('change', this.calculateTotal)
|
|
|
input.addEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 获取所有以 amount 开头的输入框
|
|
|
const amountInputs = dom.querySelectorAll('input[data-field^="amount"]')
|
|
|
console.log('找到的金额输入框:', amountInputs.length)
|
|
|
|
|
|
// 移除旧的监听器
|
|
|
amountInputs.forEach(input => {
|
|
|
input.removeEventListener('input', this.calculateTotal)
|
|
|
input.removeEventListener('change', this.calculateTotal)
|
|
|
input.removeEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 添加新的监听器
|
|
|
amountInputs.forEach(input => {
|
|
|
input.addEventListener('input', this.calculateTotal)
|
|
|
input.addEventListener('change', this.calculateTotal)
|
|
|
input.addEventListener('blur', this.calculateTotal)
|
|
|
})
|
|
|
|
|
|
// 监听 total 输入框的变化
|
|
|
const totalInput = dom.querySelector('input[data-field="total"]')
|
|
|
if (totalInput) {
|
|
|
totalInput.removeEventListener('input', this.updateUpperCaseFromTotal)
|
|
|
totalInput.removeEventListener('change', this.updateUpperCaseFromTotal)
|
|
|
totalInput.removeEventListener('blur', this.updateUpperCaseFromTotal)
|
|
|
|
|
|
totalInput.addEventListener('input', this.updateUpperCaseFromTotal)
|
|
|
totalInput.addEventListener('change', this.updateUpperCaseFromTotal)
|
|
|
totalInput.addEventListener('blur', this.updateUpperCaseFromTotal)
|
|
|
}
|
|
|
|
|
|
// 初始计算一次
|
|
|
this.calculateTotal()
|
|
|
},
|
|
|
caculateRoadDay() {
|
|
|
const sdateInput = this.$refs.printtable.querySelector('input[data-field^="sdate"]')
|
|
|
const edateInput = this.$refs.printtable.querySelector('input[data-field^="edate"]')
|
|
|
const sdate = sdateInput.value
|
|
|
const edate = edateInput.value
|
|
|
if (sdate && edate) {
|
|
|
const s = new Date(sdate)
|
|
|
const e = new Date(edate)
|
|
|
// 计算天数差
|
|
|
const roadDay = Math.floor((e - s) / (1000 * 60 * 60 * 24))
|
|
|
console.log('roadDay', sdate, edate, roadDay)
|
|
|
const roadDayInput = this.$refs.printtable.querySelector('input[data-field="roadDay"]')
|
|
|
if (roadDayInput) {
|
|
|
roadDayInput.value = roadDay
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
calculateTotal() {
|
|
|
const dom = this.$refs.printtable
|
|
|
if (!dom) return
|
|
|
let wanTotal = 0
|
|
|
const wanAmountInputs = dom.querySelectorAll('input[data-field^="wan"]')
|
|
|
wanAmountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
wanTotal += value
|
|
|
})
|
|
|
|
|
|
const wanInput = dom.querySelector('input[data-field="wTotal"]')
|
|
|
if (wanInput) {
|
|
|
wanInput.value = wanTotal===0?'':wanTotal
|
|
|
}
|
|
|
|
|
|
let qianTotal = 0
|
|
|
const qianAmountInputs = dom.querySelectorAll('input[data-field^="qian"]')
|
|
|
qianAmountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
qianTotal += value
|
|
|
})
|
|
|
|
|
|
const qianInput = dom.querySelector('input[data-field="qTotal"]')
|
|
|
if (qianInput) {
|
|
|
qianInput.value = qianTotal===0?'':qianTotal
|
|
|
}
|
|
|
|
|
|
let baiTotal = 0
|
|
|
const baiAmountInputs = dom.querySelectorAll('input[data-field^="bai"]')
|
|
|
baiAmountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
baiTotal += value
|
|
|
})
|
|
|
|
|
|
const baiInput = dom.querySelector('input[data-field="bTotal"]')
|
|
|
if (baiInput) {
|
|
|
baiInput.value = baiTotal===0?'':baiTotal
|
|
|
}
|
|
|
|
|
|
let shiTotal = 0
|
|
|
const shiAmountInputs = dom.querySelectorAll('input[data-field^="shi"]')
|
|
|
shiAmountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
shiTotal += value
|
|
|
})
|
|
|
|
|
|
const shiInput = dom.querySelector('input[data-field="sTotal"]')
|
|
|
if (shiInput) {
|
|
|
shiInput.value = shiTotal===0?'':shiTotal
|
|
|
}
|
|
|
|
|
|
let yuanTotal = 0
|
|
|
const yuanAmountInputs = dom.querySelectorAll('input[data-field^="yuan"]')
|
|
|
yuanAmountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
yuanTotal += value
|
|
|
})
|
|
|
|
|
|
const yuanInput = dom.querySelector('input[data-field="yTotal"]')
|
|
|
if (yuanInput) {
|
|
|
yuanInput.value = yuanTotal===0?'':yuanTotal
|
|
|
}
|
|
|
|
|
|
let jiaoTotal = 0
|
|
|
const jiaoAmountInputs = dom.querySelectorAll('input[data-field^="jiao"]')
|
|
|
jiaoAmountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
jiaoTotal += value
|
|
|
})
|
|
|
|
|
|
const jiaoInput = dom.querySelector('input[data-field="jTotal"]')
|
|
|
if (jiaoInput) {
|
|
|
jiaoInput.value = jiaoTotal===0?'':jiaoTotal
|
|
|
}
|
|
|
|
|
|
let fenTotal = 0
|
|
|
const fenAmountInputs = dom.querySelectorAll('input[data-field^="fen"]')
|
|
|
fenAmountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
fenTotal += value
|
|
|
})
|
|
|
|
|
|
const fenInput = dom.querySelector('input[data-field="fTotal"]')
|
|
|
if (fenInput) {
|
|
|
fenInput.value = fenTotal===0?'':fenTotal
|
|
|
}
|
|
|
|
|
|
let otherTotal = wanTotal * 10000 + qianTotal * 1000 + baiTotal * 100 + shiTotal * 10 + yuanTotal + jiaoTotal * 0.1 + fenTotal * 0.01
|
|
|
|
|
|
let total = 0
|
|
|
// 只计算以 amount 开头的输入框
|
|
|
const amountInputs = dom.querySelectorAll('input[data-field^="amount"]')
|
|
|
console.log('计算总金额,找到输入框数量:', amountInputs.length)
|
|
|
|
|
|
amountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
console.log('输入框值:', input.getAttribute('data-field'), value)
|
|
|
total += value
|
|
|
})
|
|
|
|
|
|
console.log('计算得到的总金额:', total)
|
|
|
|
|
|
// 更新总金额输入框
|
|
|
const totalInput = dom.querySelector('input[data-field="total"]')
|
|
|
if (totalInput) {
|
|
|
totalInput.value = total.toFixed(2)
|
|
|
console.log('更新总金额输入框:', totalInput.value)
|
|
|
}
|
|
|
|
|
|
// 更新大写金额
|
|
|
const upperCaseInput = dom.querySelector('input[data-field="upperCaseAmount"]')
|
|
|
if (upperCaseInput) {
|
|
|
upperCaseInput.value = numberToChinese(total)
|
|
|
console.log('更新大写金额:', upperCaseInput.value)
|
|
|
}
|
|
|
|
|
|
if (otherTotal !== 0) {
|
|
|
upperCaseInput.value = numberToChinese(otherTotal)
|
|
|
}
|
|
|
},
|
|
|
updateUpperCaseFromTotal() {
|
|
|
const dom = this.$refs.printtable
|
|
|
if (!dom) return
|
|
|
|
|
|
const totalInput = dom.querySelector('input[data-field="total"]')
|
|
|
const upperCaseInput = dom.querySelector('input[data-field="upperCaseAmount"]')
|
|
|
|
|
|
if (totalInput && upperCaseInput) {
|
|
|
const total = parseFloat(totalInput.value) || 0
|
|
|
upperCaseInput.value = numberToChinese(total)
|
|
|
console.log('从总金额更新大写金额:', total, upperCaseInput.value)
|
|
|
}
|
|
|
},
|
|
|
replaceControls(element) {
|
|
|
const inputs = element.getElementsByTagName('input')
|
|
|
Array.from(inputs).forEach(input => {
|
|
|
if (input.type === 'checkbox' || input.type === 'radio') {
|
|
|
// 跳过checkbox和radio,不替换,保持原样
|
|
|
return
|
|
|
}
|
|
|
const span = document.createElement('span')
|
|
|
let displayText = input.value || ''
|
|
|
if (input.type === 'date') {
|
|
|
displayText = input.value ? new Date(input.value).toLocaleDateString() : ''
|
|
|
}
|
|
|
span.textContent = displayText
|
|
|
const style = window.getComputedStyle(input)
|
|
|
span.style.cssText = style.cssText
|
|
|
;[
|
|
|
'width',
|
|
|
'height',
|
|
|
'padding',
|
|
|
'margin',
|
|
|
'font',
|
|
|
'fontSize',
|
|
|
'fontFamily',
|
|
|
'lineHeight',
|
|
|
'verticalAlign',
|
|
|
'border',
|
|
|
'background',
|
|
|
'color',
|
|
|
'boxSizing'
|
|
|
].forEach(key => {
|
|
|
span.style[key] = style[key]
|
|
|
})
|
|
|
span.style.width = '100%'
|
|
|
span.style.display = 'block'
|
|
|
span.style.textAlign = 'center'
|
|
|
input.parentNode.replaceChild(span, input)
|
|
|
})
|
|
|
|
|
|
const selects = element.getElementsByTagName('select')
|
|
|
Array.from(selects).forEach(select => {
|
|
|
const span = document.createElement('span')
|
|
|
span.textContent = select.options[select.selectedIndex]?.text || ''
|
|
|
const style = window.getComputedStyle(select)
|
|
|
span.style.cssText = style.cssText
|
|
|
;[
|
|
|
'width',
|
|
|
'height',
|
|
|
'padding',
|
|
|
'margin',
|
|
|
'font',
|
|
|
'fontSize',
|
|
|
'fontFamily',
|
|
|
'lineHeight',
|
|
|
'verticalAlign',
|
|
|
'border',
|
|
|
'background',
|
|
|
'color',
|
|
|
'boxSizing'
|
|
|
].forEach(key => {
|
|
|
span.style[key] = style[key]
|
|
|
})
|
|
|
span.style.width = '100%'
|
|
|
span.style.display = 'block'
|
|
|
span.style.textAlign = 'center'
|
|
|
select.parentNode.replaceChild(span, select)
|
|
|
})
|
|
|
|
|
|
const textareas = element.getElementsByTagName('textarea')
|
|
|
Array.from(textareas).forEach(textarea => {
|
|
|
const span = document.createElement('span')
|
|
|
span.textContent = textarea.value || ''
|
|
|
const style = window.getComputedStyle(textarea)
|
|
|
span.style.cssText = style.cssText
|
|
|
;[
|
|
|
'width',
|
|
|
'height',
|
|
|
'padding',
|
|
|
'margin',
|
|
|
'font',
|
|
|
'fontSize',
|
|
|
'fontFamily',
|
|
|
'lineHeight',
|
|
|
'verticalAlign',
|
|
|
'border',
|
|
|
'background',
|
|
|
'color',
|
|
|
'boxSizing'
|
|
|
].forEach(key => {
|
|
|
span.style[key] = style[key]
|
|
|
})
|
|
|
span.style.width = '100%'
|
|
|
span.style.display = 'block'
|
|
|
span.style.textAlign = 'center'
|
|
|
textarea.parentNode.replaceChild(span, textarea)
|
|
|
})
|
|
|
},
|
|
|
async print() {
|
|
|
try {
|
|
|
const tempContainer = document.createElement('div')
|
|
|
tempContainer.style.position = 'absolute'
|
|
|
tempContainer.style.left = '-9999px'
|
|
|
tempContainer.style.top = '-9999px'
|
|
|
document.body.appendChild(tempContainer)
|
|
|
|
|
|
const originalContent = this.$refs['printtable'].cloneNode(true)
|
|
|
tempContainer.appendChild(originalContent)
|
|
|
|
|
|
this.replaceControls(tempContainer)
|
|
|
|
|
|
const canvas = await html2canvas(tempContainer, {
|
|
|
backgroundColor: null,
|
|
|
useCORS: true
|
|
|
})
|
|
|
|
|
|
document.body.removeChild(tempContainer)
|
|
|
|
|
|
printJS({
|
|
|
printable: canvas.toDataURL(),
|
|
|
type: 'image',
|
|
|
documentTitle: `苏州市河道管理处${this.currentForm === 'pre' ? '事前审批表格' : this.currentForm === 'post' ? '事后支付表格' : '财务审核表'}`,
|
|
|
style: '@page{margin:auto;}'
|
|
|
})
|
|
|
} catch (error) {
|
|
|
console.error('打印失败:', error)
|
|
|
this.$Message.error('打印失败')
|
|
|
}
|
|
|
},
|
|
|
moneyFormat(val) {
|
|
|
if (!val && val !== 0) return '-'
|
|
|
return Number(val).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,')
|
|
|
},
|
|
|
printHtml() {
|
|
|
const printNode = this.$refs.printtable.cloneNode(true)
|
|
|
// 移除财务审核表
|
|
|
const financeTable = printNode.querySelector('.finance-review-table')
|
|
|
if (financeTable) {
|
|
|
financeTable.remove()
|
|
|
}
|
|
|
// 替换控件为纯文本(保留样式)
|
|
|
this.replaceControls(printNode)
|
|
|
|
|
|
// 计算并更新总金额
|
|
|
const amountInputs = printNode.querySelectorAll('input[data-field^="amount"]')
|
|
|
let total = 0
|
|
|
amountInputs.forEach(input => {
|
|
|
const value = parseFloat(input.value) || 0
|
|
|
total += value
|
|
|
})
|
|
|
|
|
|
// 更新总金额显示
|
|
|
const totalInput = printNode.querySelector('input[data-field="total"]')
|
|
|
if (totalInput) {
|
|
|
totalInput.value = total.toFixed(2)
|
|
|
}
|
|
|
|
|
|
// 更新大写金额显示
|
|
|
const upperCaseInput = printNode.querySelector('input[data-field="upperCaseAmount"]')
|
|
|
if (upperCaseInput) {
|
|
|
upperCaseInput.value = numberToChinese(total)
|
|
|
}
|
|
|
|
|
|
const orientation = this.printOrientation || 'portrait';
|
|
|
const margin = orientation === 'portrait'
|
|
|
? '2mm 10mm 10mm 2mm'
|
|
|
: '10mm 10mm 10mm 10mm';
|
|
|
const win = window.open('', '_blank')
|
|
|
win.document.write(`
|
|
|
<html>
|
|
|
<head>
|
|
|
<title>打印</title>
|
|
|
<style>
|
|
|
@page { size: A4 ${orientation}; margin: ${margin}; }
|
|
|
body {
|
|
|
margin: 0;
|
|
|
padding: 0;
|
|
|
}
|
|
|
.white-container {
|
|
|
width: 100% !important;
|
|
|
margin: 0 auto;
|
|
|
margin-left: 0px;
|
|
|
background: #fff;
|
|
|
padding: 0px;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
.form-container {
|
|
|
width: 100% !important;
|
|
|
margin: 0 auto;
|
|
|
}
|
|
|
table {
|
|
|
width: 100%;
|
|
|
border-collapse: collapse;
|
|
|
}
|
|
|
td {
|
|
|
border: 1px solid #000;
|
|
|
padding: 8px;
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
<div class="white-container">
|
|
|
<div class="form-container">
|
|
|
${printNode.innerHTML}
|
|
|
</div>
|
|
|
</div>
|
|
|
</body>
|
|
|
</html>
|
|
|
`)
|
|
|
win.document.close()
|
|
|
win.focus()
|
|
|
win.print()
|
|
|
win.close()
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.form-switch {
|
|
|
margin-bottom: 20px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.white-container {
|
|
|
background: #fff;
|
|
|
padding: 20px;
|
|
|
}
|
|
|
|
|
|
.form-container {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
padding: 20px;
|
|
|
font-family: SimSun, serif;
|
|
|
}
|
|
|
|
|
|
.payment-form {
|
|
|
border: 1px solid #000;
|
|
|
padding: 20px;
|
|
|
}
|
|
|
|
|
|
.no-form-message {
|
|
|
text-align: center;
|
|
|
padding: 40px;
|
|
|
color: #999;
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
|
|
|
.finance-review-table {
|
|
|
width: 100%;
|
|
|
border-collapse: collapse;
|
|
|
margin: 20px 0;
|
|
|
font-size: 15px;
|
|
|
background: #fff;
|
|
|
|
|
|
th, td {
|
|
|
border: 1px solid #e0e0e0;
|
|
|
padding: 10px 8px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
th.finance-header-row {
|
|
|
background: #eaf3ff;
|
|
|
color: #2d8cf0;
|
|
|
font-size: 16px;
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
|
|
|
.sub-header {
|
|
|
background: #f5f7fa;
|
|
|
color: #333;
|
|
|
font-weight: 600;
|
|
|
width: 120px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.finance-review-header {
|
|
|
margin-bottom: 16px;
|
|
|
}
|
|
|
|
|
|
.payment-registration-row {
|
|
|
display: flex;
|
|
|
margin-bottom: 4px;
|
|
|
}
|
|
|
|
|
|
.payment-registration-row-title {
|
|
|
width: 100px;
|
|
|
font-weight: bold;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.payment-registration-row-content {
|
|
|
flex: 1;
|
|
|
color: #666;
|
|
|
}
|
|
|
|
|
|
@media print {
|
|
|
.white-container {
|
|
|
padding: 0;
|
|
|
}
|
|
|
.form-container {
|
|
|
padding: 0;
|
|
|
}
|
|
|
.payment-form {
|
|
|
border: 1px solid #000;
|
|
|
}
|
|
|
.no-print {
|
|
|
display: none !important;
|
|
|
}
|
|
|
}
|
|
|
</style>
|