560 lines
20 KiB
Plaintext
560 lines
20 KiB
Plaintext
<template>
|
||
<div class="app-container monthly-paymentDetail">
|
||
<div class="filter-container">
|
||
<el-form :inline="true" :model="basicInfo" class="demo-form-inline" size="small">
|
||
<el-form-item label="Name:">
|
||
<el-input v-model="basicInfo.Name" style="width:160px;" readonly />
|
||
</el-form-item>
|
||
<el-form-item label="ID:">
|
||
<el-input v-model="basicInfo.Code" style="width:100px;" readonly />
|
||
</el-form-item>
|
||
<el-form-item label="Rank:">
|
||
<el-input v-model="basicInfo.RankName" style="width:180px;" readonly />
|
||
</el-form-item>
|
||
<el-form-item label="Month:">
|
||
<el-input v-model="basicInfo.YearMonth" readonly style="width:100px;" />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="Exchange Rate:">
|
||
<el-input v-model="basicInfo.ExchangeRate" readonly style="width:80px;" />
|
||
</el-form-item>
|
||
|
||
<el-button type="primary" size="small" @click="exportExcel">Export Excel</el-button>
|
||
<el-button
|
||
size="small"
|
||
type="primary"
|
||
:loading="loading"
|
||
@click="handleWindowPrint( '#payDetailPdf2', htmlTitle )"
|
||
>Export PDF</el-button>
|
||
</el-form>
|
||
</div>
|
||
<el-table
|
||
id="payDetailPdf2"
|
||
height="90%"
|
||
:data="list"
|
||
:span-method="objectSpanMethod"
|
||
border
|
||
show-summary
|
||
:summary-method="getSummaries"
|
||
align="center"
|
||
size="small"
|
||
>
|
||
<el-table-column prop="TrialCode" label="Project ID" show-overflow-tooltip min-width="100" />
|
||
<el-table-column
|
||
prop="PaymentType"
|
||
label="Read Type"
|
||
show-overflow-tooltip
|
||
min-width="100"
|
||
>
|
||
<template slot-scope="scope">
|
||
<div>{{ scope.row.TrialCode!='Adjustment'? scope.row.PaymentType :scope.row.AdjustmentView.AdjustType }}</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="Count" label="Volume" show-overflow-tooltip min-width="100">
|
||
<template slot-scope="scope">
|
||
<div>{{ scope.row.TrialCode!='Adjustment'? scope.row.Count : scope.row.AdjustmentView.Note }}</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="BasePrice"
|
||
label="Base Rate ($)"
|
||
show-overflow-tooltip
|
||
min-width="100"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span>{{ scope.row.BasePrice | rounding }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="PersonalAdditional"
|
||
label="Personal Adjustment ($)"
|
||
show-overflow-tooltip
|
||
min-width="160"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span>{{ scope.row.PersonalAdditional | rounding }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="TrialAdditional"
|
||
label="Project Adjustment ($)"
|
||
show-overflow-tooltip
|
||
min-width="150"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span>{{ scope.row.TrialAdditional | rounding }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="TotalUnitPrice"
|
||
label="Adjusted Rate ($)"
|
||
show-overflow-tooltip
|
||
min-width="130"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span>{{ scope.row.TotalUnitPrice | rounding }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="PaymentUSD"
|
||
label="Subtotal ($)"
|
||
show-overflow-tooltip
|
||
min-width="100"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span>{{ scope.row.PaymentUSD | rounding }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="PaymentCNY"
|
||
:label="rmbTitle"
|
||
show-overflow-tooltip
|
||
min-width="120"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span v-if="basicInfo.ExchangeRate==0" style="color:red">{{ 'Setting Needed' }}</span>
|
||
<span v-else>{{ scope.row.PaymentCNY }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import { getMonthlyPaymentDetailList } from '@/api/financials'
|
||
import Excel from 'exceljs'
|
||
import floatObj from '@/utils/float-operation'
|
||
export default {
|
||
name: 'PaymentDetail',
|
||
filters: {
|
||
rounding(value) {
|
||
return value ? Number(value).toFixed(2) : value
|
||
// return value
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
basicInfo: {},
|
||
list: [],
|
||
spanArr: [],
|
||
pos: 0,
|
||
htmlTitle: '',
|
||
rmbTitle: '',
|
||
loading: false
|
||
}
|
||
},
|
||
mounted() {
|
||
const info = this.$router.currentRoute.query
|
||
this.basicInfo = (({ Id, DoctorId, ChineseName, LastName, FirstName, Code, ExchangeRate, RankName, YearMonth }) => ({ Id, DoctorId, ChineseName, LastName, FirstName, Code, ExchangeRate, RankName, YearMonth }))(info)
|
||
this.basicInfo.Name = `${this.basicInfo.FirstName} ${this.basicInfo.LastName} ${this.basicInfo.ChineseName}`
|
||
this.htmlTitle = this.basicInfo.ChineseName + '_' + this.basicInfo.YearMonth
|
||
this.getList()
|
||
},
|
||
methods: {
|
||
getList() {
|
||
getMonthlyPaymentDetailList(this.basicInfo.Id, this.basicInfo.DoctorId, this.basicInfo.YearMonth).then(res => {
|
||
this.list = res.Result.DetailList
|
||
this.rmbTitle = 'Subtotal(¥)'
|
||
this.getSpanArr(res.Result.DetailList)
|
||
this.list.forEach((item, index, array) => {
|
||
if (item.AdjustmentView) {
|
||
item.AdjustmentView.Note = `Note: ${item.AdjustmentView.Note}`
|
||
}
|
||
})
|
||
})
|
||
},
|
||
getSummaries(param) {
|
||
var that = this
|
||
const { columns, data } = param
|
||
const sums = []
|
||
columns.forEach((column, index) => {
|
||
if (index === 0) {
|
||
sums[index] = 'Total'
|
||
return
|
||
}
|
||
if (column.property === 'PaymentUSD') {
|
||
const values = data.map(item => Number(item[column.property]))
|
||
if (!values.every(value => isNaN(value))) {
|
||
sums[index] = values
|
||
.reduce((prev, curr) => {
|
||
const value = Number(curr)
|
||
if (!isNaN(value)) {
|
||
return floatObj.add(prev, curr)
|
||
} else {
|
||
return prev
|
||
}
|
||
}, 0)
|
||
}
|
||
}
|
||
if (column.property === 'PaymentCNY') {
|
||
const values = data.map(item => Number(item['PaymentCNY']))
|
||
sums[index] = values.reduce((prev, curr) => {
|
||
const value = Number(curr)
|
||
if (!isNaN(value)) {
|
||
return floatObj.add(prev, curr)
|
||
} else {
|
||
return prev
|
||
}
|
||
}, 0)
|
||
if (sums[index] === 0.0 && that.basicInfo.ExchangeRate === 0) {
|
||
sums[index] = 'Setting Needed'
|
||
}
|
||
return
|
||
}
|
||
})
|
||
return sums
|
||
},
|
||
getSpanArr(data) {
|
||
for (var i = 0; i < data.length; i++) {
|
||
if (i === 0) {
|
||
this.spanArr.push(1)
|
||
this.pos = 0
|
||
} else {
|
||
// 判断当前元素与上一个元素是否相同
|
||
if (data[i].TrialCode === data[i - 1].TrialCode) {
|
||
this.spanArr[this.pos] += 1
|
||
this.spanArr.push(0)
|
||
} else {
|
||
this.spanArr.push(1)
|
||
this.pos = i
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
|
||
if (columnIndex === 0) {
|
||
const _row = this.spanArr[rowIndex]
|
||
const _col = _row > 0 ? 1 : 0
|
||
return {
|
||
rowspan: _row,
|
||
colspan: _col
|
||
}
|
||
}
|
||
|
||
if (row.TrialCode === 'Adjustment') {
|
||
if (columnIndex === 2) {
|
||
return [1, 5]
|
||
} else if (columnIndex === 3 || columnIndex === 4 || columnIndex === 5 || columnIndex === 6) {
|
||
return [0, 0]
|
||
}
|
||
}
|
||
},
|
||
exportExcel() {
|
||
var workbook = new Excel.Workbook()
|
||
var sheet = workbook.addWorksheet(this.basicInfo.ChineseName + ' ' + this.basicInfo.YearMonth)
|
||
sheet.properties.defaultRowHeight = 22
|
||
sheet.columns = [
|
||
{ header: 'Project ID', key: 'TrialCode', width: 15 },
|
||
{ header: 'Type', key: 'PaymentType', width: 30 },
|
||
{ header: 'Count', key: 'Count', width: 15 },
|
||
{ header: 'Base Price', key: 'BasePrice', width: 15 },
|
||
{ header: 'Personal Additional', key: 'PersonalAdditional', width: 22 },
|
||
{ header: 'Trial Additional', key: 'TrialAdditional', width: 22 },
|
||
{ header: 'Total Price', key: 'TotalUnitPrice', width: 22 },
|
||
{ header: 'Total Fee', key: 'PaymentUSD', width: 22 },
|
||
{ header: 'Subtotal(¥)', key: 'PaymentCNY', width: 22 }
|
||
]
|
||
|
||
var that = this
|
||
|
||
var tempTotalFee = 0
|
||
var tempTotalFeeInCN = 0
|
||
this.list.forEach(element => {
|
||
tempTotalFee += parseFloat(element.PaymentUSD)
|
||
tempTotalFeeInCN += parseFloat(element.PaymentCNY)
|
||
})
|
||
|
||
var rowsCount = Number(this.list.length + 1)
|
||
|
||
// 处理标题
|
||
var titleRows = 4
|
||
sheet.mergeCells('A1', 'I2')
|
||
sheet.getCell('A1').value = 'Monthly Payment' // that.basicInfo.DoctorChineseName + ' ' + that.date + ' 费用明细'
|
||
sheet.getCell('A1').alignment = { vertical: 'middle', horizontal: 'center' }
|
||
sheet.getCell('A1').font = { name: 'SimSun', family: 4, size: 13, bold: true }
|
||
|
||
sheet.mergeCells('A3', 'D3')
|
||
// that.basicInfo.FirstName + ' ' + that.basicInfo.LastName + ' Name CN:'+
|
||
sheet.getCell('A3').value = 'Name:' + this.basicInfo.ChineseName + ' ID:' + that.basicInfo.Code
|
||
sheet.mergeCells('E3', 'I3')
|
||
// sheet.getCell('E3').value =
|
||
// ' Rank:' +
|
||
// that.basicInfo.RankName +
|
||
// ' Month:' +
|
||
// that.basicInfo.YearMonth +
|
||
// ' Exchange Rate: ' +
|
||
// Number(that.basicInfo.ExchangeRate).toFixed(2)
|
||
sheet.getCell('E3').value =
|
||
' Rank:' +
|
||
that.basicInfo.RankName +
|
||
' Month:' +
|
||
that.basicInfo.YearMonth +
|
||
' Exchange Rate: ' +
|
||
Number(that.basicInfo.ExchangeRate)
|
||
sheet.getCell('A3').alignment = { vertical: 'middle', horizontal: 'left' }
|
||
sheet.getCell('E3').alignment = { vertical: 'middle', horizontal: 'right' }
|
||
// heet.mergeCells('A4', 'H4')
|
||
|
||
sheet.getCell('A4').value = 'Project ID'
|
||
sheet.getCell('B4').value = 'Read Type'
|
||
sheet.getCell('C4').value = 'Volume'
|
||
sheet.getCell('D4').value = 'Base Rate($)'
|
||
sheet.getCell('E4').value = 'Personal Adjustment($)'
|
||
sheet.getCell('F4').value = 'Project Adjustment($)'
|
||
sheet.getCell('G4').value = 'Adjusted Rate($)'
|
||
sheet.getCell('H4').value = 'Subtotal($)'
|
||
sheet.getCell('I4').value = 'Subtotal(¥)'
|
||
sheet.getRow(4).font = { name: 'SimSun', family: 4, size: 11, bold: true }
|
||
|
||
sheet.addRows(this.list)
|
||
// 合并项目编号单元格
|
||
var projectCount = Math.floor(Number(this.list.length / 9)) // 项目个数
|
||
|
||
for (let i = 0; i < projectCount; i++) {
|
||
var tempR1 = 'A' + (10 * i + titleRows + 1)
|
||
var tempR2 = 'A' + (10 * (i + 1) + titleRows)
|
||
if (10 * (i + 1) < rowsCount) {
|
||
sheet.mergeCells(tempR1, tempR2)
|
||
sheet.getCell(tempR1).alignment = { vertical: 'middle', horizontal: 'center' }
|
||
}
|
||
}
|
||
|
||
// 合并奖励单元格
|
||
|
||
var awardCount = this.list.filter(t => t.TrialCode === 'Volume Reward').length
|
||
|
||
var adjustMentCount = this.list.filter(t => t.TrialCode === 'Adjustment').length
|
||
|
||
if (awardCount > 0) {
|
||
var R1 = 'A' + (projectCount * 10 + titleRows + 1)
|
||
var R2 = 'A' + (projectCount * 10 + titleRows + awardCount)
|
||
sheet.mergeCells(R1, R2)
|
||
sheet.getCell(R1).alignment = { vertical: 'middle', horizontal: 'center' }
|
||
}
|
||
|
||
if (adjustMentCount > 0) {
|
||
// 处理调整行列合并
|
||
|
||
var R3 = 'A' + (projectCount * 10 + titleRows + awardCount + 1)
|
||
var R4 = 'A' + (rowsCount + titleRows - 1)
|
||
|
||
sheet.mergeCells(R3, R4)
|
||
sheet.getCell(R3).alignment = { vertical: 'middle', horizontal: 'center' }
|
||
|
||
// 行合并
|
||
var i = 0
|
||
for (i = 0; i < adjustMentCount; i++) {
|
||
var adjustMentCell1 = 'B' + (projectCount * 10 + titleRows + awardCount + 1 + i)
|
||
var adjustMentCell2 = 'C' + (projectCount * 10 + titleRows + awardCount + 1 + i)
|
||
var adjustMentCell3 = 'G' + (projectCount * 10 + titleRows + awardCount + 1 + i)
|
||
sheet.mergeCells(adjustMentCell2, adjustMentCell3)
|
||
var index = projectCount * 10 + awardCount + i
|
||
|
||
sheet.getCell(adjustMentCell1).value = this.list[index].AdjustmentView.AdjustType
|
||
sheet.getCell(adjustMentCell2).value = this.list[index].AdjustmentView.Note
|
||
}
|
||
}
|
||
|
||
var tempCell = 'A' + (rowsCount + 1 + titleRows - 1)
|
||
var tempCell1 = 'B' + (rowsCount + 1 + titleRows - 1)
|
||
var tempCell2 = 'G' + (rowsCount + 1 + titleRows - 1)
|
||
var tempCell3 = 'H' + (rowsCount + 1 + titleRows - 1)
|
||
var tempCell4 = 'I' + (rowsCount + 1 + titleRows - 1)
|
||
sheet.mergeCells(tempCell1, tempCell2)
|
||
sheet.getCell(tempCell).value = 'Total' // that.date + ' 费用总计: '
|
||
sheet.getCell(tempCell3).value = tempTotalFee
|
||
sheet.getCell(tempCell4).value = tempTotalFeeInCN
|
||
|
||
sheet.getCell(tempCell3).font = { name: 'SimSun', family: 4, size: 13, bold: true }
|
||
sheet.getRow(rowsCount + titleRows).font = { name: 'SimSun', family: 4, size: 13, bold: true }
|
||
sheet.getColumn(7).numFmt = '#,##0.00'
|
||
sheet.getColumn(8).numFmt = '#,##0.00'
|
||
sheet.getColumn(9).numFmt = '#,##0.00'
|
||
sheet.eachRow((row, number) => {
|
||
if (number > 3) {
|
||
row.eachCell((cell, rowNumber) => {
|
||
cell.border = {
|
||
top: { style: 'thin' },
|
||
left: { style: 'thin' },
|
||
bottom: { style: 'thin' },
|
||
right: { style: 'thin' }
|
||
}
|
||
})
|
||
}
|
||
})
|
||
workbook.xlsx
|
||
.writeBuffer({
|
||
base64: true
|
||
})
|
||
.then(function(xls64) {
|
||
var data = new Blob([xls64], {
|
||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||
})
|
||
|
||
if ('msSaveOrOpenBlob' in navigator) {
|
||
// ie使用的下载方式
|
||
window.navigator.msSaveOrOpenBlob(data, that.basicInfo.ChineseName + ' ' + that.basicInfo.YearMonth + '.xlsx')
|
||
} else {
|
||
var a = document.createElement('a')
|
||
|
||
var url = URL.createObjectURL(data)
|
||
a.href = url
|
||
a.download = that.basicInfo.ChineseName + ' ' + that.basicInfo.YearMonth + '.xlsx'
|
||
document.body.appendChild(a)
|
||
a.click()
|
||
setTimeout(function() {
|
||
document.body.removeChild(a)
|
||
window.URL.revokeObjectURL(url)
|
||
}, 0)
|
||
}
|
||
})
|
||
},
|
||
|
||
handleWindowPrint(ele, fileName, vm) {
|
||
var oIframe = document.createElement('iframe')
|
||
oIframe.style.display = 'none'
|
||
var oScript = document.createElement('script')
|
||
var oStyle = document.createElement('style')
|
||
oStyle.type = 'text/css'
|
||
document.body.appendChild(oIframe)
|
||
document.head.getElementsByTagName('title')[0].innerText = `${fileName}`
|
||
|
||
oIframe.contentDocument.head.innerHTML = `<meta charset="utf-8">
|
||
<title>${fileName}</title>
|
||
<meta name="format-detection" content="telephone=no">
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1.0">`
|
||
|
||
var divHeader = ' <div style="text-align:center; font-size:20px:"> Monthly Payment </div>'
|
||
var divElement = `<div style='display: flex;justify-content: space-between;margin:25px 0px 20px'>
|
||
<label>Name: ${this.basicInfo.ChineseName}</label>
|
||
<label>ID: ${this.basicInfo.Code}</label>
|
||
<label>Rank: ${this.basicInfo.RankName}</label>
|
||
<label>Month: ${this.basicInfo.YearMonth}</label>
|
||
<label>Exchange Rate: ${this.basicInfo.ExchangeRate}</label>
|
||
</div>`
|
||
|
||
oIframe.contentDocument.body.innerHTML = divHeader + divElement + document.querySelector(ele).outerHTML
|
||
// oIframe.contentDocument.getElementsByClassName('el-table__body-wrapper')[0].style.maxHeight = '100%'
|
||
|
||
// 页面打印缩放比例设置
|
||
oIframe.contentDocument.body.style.zoom = 0.75
|
||
// oIframe.contentDocument.getElementById('payDetailPdf2').removeAttribute('el-table--scrollable-y')
|
||
oIframe.contentDocument.getElementsByClassName('el-table--scrollable-y').style = ''
|
||
oIframe.contentDocument.getElementsByClassName('el-table__body-wrapper')[0].style = {
|
||
'max-height': '100%'
|
||
// ,'width':'100%'
|
||
}
|
||
|
||
oIframe.contentDocument.getElementsByClassName('el-table__header-wrapper')[0].remove()
|
||
|
||
var ostatFirstTr = document.createElement('tr')
|
||
ostatFirstTr.innerHTML = `
|
||
<td >
|
||
<div class="cell">Trial ID</div>
|
||
</td>
|
||
<td >
|
||
<div class="cell">Read Type</div>
|
||
</td>
|
||
<td >
|
||
<div class="cell">Volume</div>
|
||
</td>
|
||
<td >
|
||
<div class="cell">Base Rate ($)</div>
|
||
</td>
|
||
<td >
|
||
<div class="cell">Personal Adjustment ($)</div>
|
||
</td>
|
||
<td>
|
||
<div class="cell">Trial Adjustment ($)</div>
|
||
</td>
|
||
<td >
|
||
<div class="cell">Adjusted Rate ($)</div>
|
||
</td>
|
||
<td>
|
||
<div class="cell">Subtotal ($)</div>
|
||
</td>
|
||
<td >
|
||
<div class="cell">Subtotal(¥)</div>
|
||
</td>
|
||
<th></th>`
|
||
|
||
oIframe.contentDocument.getElementsByClassName('el-table__body')[0].children[1].appendChild(ostatFirstTr)
|
||
|
||
var oldEle = oIframe.contentDocument.getElementsByClassName('el-table__body')[0].children[1].firstChild // 现有的元素
|
||
oldEle.parentNode.insertBefore(ostatFirstTr, oldEle)
|
||
// 将newEle插入到oldEle之前
|
||
|
||
var tempTotalFee = 0
|
||
var tempTotalFeeInCN = 0
|
||
this.list.forEach(element => {
|
||
tempTotalFee += parseFloat(element.PaymentUSD)
|
||
tempTotalFeeInCN += parseFloat(element.PaymentCNY)
|
||
})
|
||
// tempTotalFee = tempTotalFee.toFixed(2)
|
||
// tempTotalFeeInCN = tempTotalFeeInCN.toFixed(2)
|
||
|
||
// 移除尾部统计行
|
||
oIframe.contentDocument.getElementsByClassName('el-table__footer-wrapper')[0].remove()
|
||
// 创建尾部统计行Last
|
||
var ostatLastTr = document.createElement('tr')
|
||
ostatLastTr.innerHTML = `
|
||
<td >
|
||
<div class="cell">Total</div>
|
||
</td>
|
||
<td >
|
||
<div class="cell"></div>
|
||
</td>
|
||
<td >
|
||
<div class="cell"></div>
|
||
</td>
|
||
<td >
|
||
<div class="cell"></div>
|
||
</td>
|
||
<td >
|
||
<div class="cell"></div>
|
||
</td>
|
||
<td>
|
||
<div class="cell"></div>
|
||
</td>
|
||
<td >
|
||
<div class="cell"></div>
|
||
</td>
|
||
<td>
|
||
<div class="cell">${tempTotalFee}</div>
|
||
</td>
|
||
<td >
|
||
<div class="cell">${tempTotalFeeInCN}</div>
|
||
</td>
|
||
<th></th>`
|
||
oIframe.contentDocument.getElementsByClassName('el-table__body')[0].lastChild.appendChild(ostatLastTr)
|
||
|
||
oStyle.innerHTML = `.el-table td{border:1px solid #ccc;}
|
||
th{text-align:center} td{text-align:right}
|
||
@page{size: landscape;}
|
||
`
|
||
|
||
oIframe.contentDocument.body.appendChild(oStyle)
|
||
oScript.innerText =
|
||
`if (window.navigator.userAgent.indexOf("Edge") >= 0)
|
||
{
|
||
window.print();
|
||
|
||
}
|
||
else{window.print();}`
|
||
|
||
oIframe.contentDocument.body.appendChild(oScript)
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.monthly-paymentDetail{
|
||
.el-table {
|
||
overflow: visible !important;
|
||
}
|
||
}
|
||
|
||
</style>
|