修复结算单管理问题

This commit is contained in:
hr121 2025-08-02 11:56:29 +08:00
parent 20d0d35146
commit 6a09cbeb70
5 changed files with 173 additions and 105 deletions

View File

@ -63,9 +63,9 @@
align="center"
>
<template slot-scope="scope">
<div>基础费用{{ scope.row.amount.toFixed(2) }}</div>
<div>附加费用{{ scope.row.surchargeAmount.toFixed(4) }}</div>
<div>总费用{{ scope.row.totalAmount.toFixed(4) }}</div>
<!-- <div>基础费用{{ scope.row.amount.toFixed(2) }}</div>
<div>附加费用{{ scope.row.surchargeAmount.toFixed(4) }}</div> -->
<div>{{ scope.row.totalAmount.toFixed(4) }}</div>
</template>
</el-table-column>
<el-table-column prop="areaName" label="区域" align="center" />

View File

@ -58,9 +58,9 @@
<el-table-column prop="orderTime" label="下单时间" align="center" width="180" />
<el-table-column label="下单费用" width="180" align="center">
<template slot-scope="scope">
<div>基础费用{{ scope.row.orderAmount.toFixed(2) }}</div>
<div>附加费用{{ scope.row.surchargeAmount.toFixed(4) }}</div>
<div>总费用{{ scope.row.totalAmount.toFixed(4) }}</div>
<!-- <div>基础费用{{ scope.row.orderAmount.toFixed(2) }}</div>
<div>附加费用{{ scope.row.surchargeAmount.toFixed(4) }}</div> -->
<div>{{ scope.row.totalAmount.toFixed(4) }}</div>
</template>
</el-table-column>
<el-table-column prop="scenicArea" label="景区" align="center" />
@ -108,23 +108,17 @@
:visible.sync="dialogVisible"
width="50%"
>
<el-table :data="settlementList">
<el-table-column prop="scenicArea" label="委托方">
<template slot-scope="scope">
委托方{{ scope.row.scenicArea }}
</template>
</el-table-column>
<el-table-column prop="weight" label="重量">
<template slot-scope="scope">
重量{{ scope.row.weight }}
</template>
</el-table-column>
<el-table-column prop="amount" label="金额">
<template slot-scope="scope">
金额{{ scope.row.amount }}
</template>
</el-table-column>
</el-table>
<div class="settlement-list">
<el-card v-for="item in settlementList" :key="item.attractionId" class="settlement-card">
<div class="settlement-item">
<h3>委托方{{ getScenicName(item.attractionId) }}</h3>
<div class="settlement-info">
<p>重量{{ item.cargoWeight }} kg</p>
<p>金额{{ item.totalAmount }} </p>
</div>
</div>
</el-card>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认生成</el-button>
@ -329,38 +323,13 @@ export default {
return
}
//
const ordersByScenic = {}
this.selection.forEach(order => {
if (!ordersByScenic[order.scenicArea]) {
ordersByScenic[order.scenicArea] = []
}
ordersByScenic[order.scenicArea].push(order)
})
//
this.settlementList = Object.keys(ordersByScenic).map(scenicArea => ({
scenicArea: scenicArea,
weight: '100kg', //
amount: '100元' //
}))
//
getGenerateSettleOrderConfirmList(this.selection.map(order => order.id))
.then(response => {
if (response.success) {
//
this.settlementList = response.data || []
// attractionId,cargoWeight,totalAmount,
// attractionId
this.settlementList = this.settlementList.map(item => {
const scenic = this.scenicAreaOptions.find(s => s.id === item.attractionId)
return {
scenicArea: scenic ? scenic.name : '未知景区',
weight: item.cargoWeight,
amount: item.totalAmount
}
})
if (response) {
// 使API
this.settlementList = response || []
//
if (this.settlementList.length === 0) {
this.$message.warning('没有可生成结算单的订单')
@ -387,7 +356,7 @@ export default {
this.selection.map(order => order.id)
)
.then(response => {
if (response.success) {
if (response) {
this.$message.success('结算单生成成功')
this.dialogVisible = false
this.$router.push('/order/orderDetail')
@ -404,6 +373,11 @@ export default {
handleCancel() {
this.dialogVisible = false
},
getScenicName(attractionId) {
const scenic = this.scenicAreaOptions.find(s => s.id === attractionId)
return scenic ? scenic.name : '未知景区'
}
}
}
@ -486,4 +460,36 @@ export default {
margin: 20px 0;
padding: 20px 0;
}
.settlement-list {
padding: 10px;
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.settlement-card {
flex: 0 0 auto;
width: calc(33.33% - 7px);
min-width: 200px;
margin: 0;
.settlement-item {
text-align: center;
h3 {
margin: 0 0 8px 0;
color: #303133;
font-size: 14px;
}
.settlement-info {
p {
margin: 4px 0;
color: #606266;
font-size: 14px;
}
}
}
}
</style>

View File

@ -1,5 +1,12 @@
<template>
<div class="app-container">
<!-- PDF导出组件 -->
<settlement-pdf
v-if="currentSettlementId"
ref="settlementPdf"
:settlement-order-id="currentSettlementId"
v-show="false"
/>
<!-- 查询及操作区域 -->
<div class="head-container">
<div class="filter-container">
@ -75,8 +82,12 @@
<script>
import { getSettleOrderList } from '@/api/order'
import { getUserNameValue } from '@/api/dropdown'
import SettlementPdf from './orderDetail/settlementPdf.vue'
export default {
components: {
SettlementPdf
},
name: 'settlementOrder',
data() {
return {
@ -89,6 +100,7 @@ export default {
size: 10,
total: 2
},
currentSettlementId: null,
tableData: [
{
attractionId: 2,
@ -174,9 +186,20 @@ export default {
query: { orderId: row.id.toString() }
})
},
handlePrint(row) {
//
console.log('打印结算单:', row)
async handlePrint(row) {
if (row.id) {
this.currentSettlementId = row.id.toString()
try {
// vue
await this.$nextTick()
await this.$refs.settlementPdf.generatePDF()
} catch (error) {
console.error('Error generating PDF:', error)
this.$message.error('导出PDF失败')
}
} else {
this.$message.warning('没有结算单ID')
}
},
handleGenerate() {
this.$router.push('/order/generateOrder')

View File

@ -123,15 +123,15 @@
<!-- 操作按钮 -->
<div class="action-buttons">
<el-button
v-if="settlementStatus === 0"
:disabled="!(settlementStatus === 0)"
type="primary"
@click="handleCancelSettlement"
>
取消结算
</el-button>
<el-button type="primary" @click="handlePrint">导出结算单</el-button>
<el-button type="primary" @click="handlePrint">打印结算单</el-button>
<el-button
v-if="settlementStatus === 0"
v-if="settlementStatus === 2"
type="success"
@click="handleStatusChange(1)"
>
@ -148,15 +148,17 @@
<!-- PDF导出组件 -->
<settlement-pdf
v-if="$route.query.orderId"
ref="settlementPdf"
:order-data="currentOrder"
:settlement-order-id="$route.query.orderId"
v-show="false"
/>
</div>
</template>
<script>
import { getSettleOrderDetail, updateSettleOrderStatus } from '@/api/order'
import { getSettleOrderDetail, updateSettleOrderStatus, printSettleOrderData } from '@/api/order'
import { getDetail } from "@/api/system/pilot";
import { getCustomerId } from '@/api/system/customer'
import { getScenicValue } from '@/api/dropdown'
@ -175,6 +177,7 @@ export default {
scenicAreaOptions: [],
settlementStatus: 0,
currentOrder: null,
originalData: [], //
query: {
batchNo: "",
scenicArea: "",
@ -223,6 +226,7 @@ export default {
const scenic = scenicResponse.find(s => s.key === item.attractionId)
item.scenicName = scenic ? scenic.value : ''
}))
this.originalData = settleOrderDetail //
this.tableData = settleOrderDetail
if(settleOrderDetail.length > 0) {
this.currentOrder = settleOrderDetail[0]
@ -237,23 +241,39 @@ export default {
}
},
methods: {
async handleSearch() {
handleSearch() {
this.loading = true
try {
const params = {
batchNo: this.query.batchNo,
attractionId: this.query.scenicArea,
startTime: this.query.dateRange ? this.query.dateRange[0] : null,
endTime: this.query.dateRange ? this.query.dateRange[1] : null
//
const filteredData = this.originalData.filter(item => {
let matchesBatchNo = true
let matchesScenicArea = true
let matchesDateRange = true
//
if (this.query.batchNo) {
matchesBatchNo = item.batchNo.toLowerCase().includes(this.query.batchNo.toLowerCase())
}
const settleOrderDetail = await getSettleOrderDetail(params)
await Promise.all(settleOrderDetail.map(async (item) => {
const customerResponse = await getCustomerId(item.customerId)
item.customerName = customerResponse.name
const scenic = this.scenicAreaOptions.find(s => s.value === item.attractionId)
item.scenicName = scenic ? scenic.label : ''
}))
this.tableData = settleOrderDetail
//
if (this.query.scenicArea) {
matchesScenicArea = item.attractionId === this.query.scenicArea
}
//
if (this.query.dateRange && this.query.dateRange.length === 2) {
const orderDate = new Date(item.createTime)
const startDate = new Date(this.query.dateRange[0])
const endDate = new Date(this.query.dateRange[1])
startDate.setHours(0, 0, 0, 0)
endDate.setHours(23, 59, 59, 999)
matchesDateRange = orderDate >= startDate && orderDate <= endDate
}
return matchesBatchNo && matchesScenicArea && matchesDateRange
})
this.tableData = filteredData
//
this.page.current = 1
} catch (error) {
@ -307,16 +327,17 @@ export default {
this.page.current = val;
},
async handlePrint() {
// PDF
if (this.currentOrder) {
if (this.$route.query.orderId) {
try {
// Wait for Vue to render the component
await this.$nextTick()
await this.$refs.settlementPdf.generatePDF()
} catch (error) {
console.error('Error generating PDF:', error)
this.$message.error('导出PDF失败')
}
} else {
this.$message.warning('没有可导出的订单数据')
this.$message.warning('没有结算单ID')
}
},
async handleStatusChange(status) {

View File

@ -61,6 +61,7 @@
<script>
import html2pdf from 'html2pdf.js'
import { printSettleOrderData } from '@/api/order'
export default {
name: 'SettlementPdf',
@ -68,6 +69,10 @@ export default {
orderData: {
type: Object,
default: () => ({})
},
settlementOrderId: {
type: [String, Number],
required: true
}
},
data() {
@ -80,7 +85,8 @@ export default {
amount: '',
amountCN: '',
items: []
}
},
pdfData: null
}
},
watch: {
@ -94,39 +100,51 @@ export default {
}
},
methods: {
formatData(orderData) {
if (!orderData) {
console.warn('No order data provided')
async formatData(data) {
if (!data) {
console.warn('No data provided')
return
}
console.log('Formatting order data:', orderData)
// PDF
this.data = {
statementId: orderData.orderNo || '',
date: orderData.createTime || '',
customer: orderData.customerName || '',
quantity: orderData.cargoWeight ? `${orderData.cargoWeight}KG` : '0KG',
amount: orderData.totalAmount ? `${orderData.totalAmount}` : '0元',
amountCN: this.convertToChinese(orderData.totalAmount || 0),
items: [{
orderNo: orderData.orderType === 1?'载物飞行':'载人飞行' || orderData.orderNo || '',
execTime: orderData.orderFinishTime || '',
weight: orderData.cargoWeight ? `${orderData.cargoWeight}KG` : '0KG',
amount: orderData.totalAmount ? `${orderData.totalAmount}` : '0元',
confirmer: orderData.createBy || ''
}]
statementId: this.settlementOrderId || '',
date: data.settlementTimeScope || '',
customer: data.clientName || '',
quantity: data.cargoWeight ? `${data.cargoWeight}KG` : '0KG',
amount: data.totalAmount ? `${data.totalAmount}` : '0元',
amountCN: data.totalAmountUpper || '',
items: data.settlementDetailList ? data.settlementDetailList.map(item => ({
orderNo: item.orderNo || '',
execTime: item.orderCreateTime || '',
weight: item.cargoWeight ? `${item.cargoWeight}KG` : '0KG',
amount: item.totalAmount ? `${item.totalAmount}` : '0元',
confirmer: item.confirmPerson || ''
})) : []
}
},
generatePDF() {
async generatePDF() {
try {
//
const response = await printSettleOrderData(this.settlementOrderId)
this.pdfData = response
//
await this.formatData(response)
// PDF
const element = this.$refs.pdfContent
const opt = {
margin: 0.5,
filename: `${this.data.statementId}.pdf`,
filename: `结算单_${this.data.statementId}.pdf`,
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2 },
jsPDF: { unit: 'in', format: 'a4', orientation: 'portrait' }
}
return html2pdf().set(opt).from(element).save()
} catch (error) {
console.error('Error generating PDF:', error)
throw error
}
},
convertToChinese(num) {
const digitCN = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']