aircraft-admin/src/views/order/settlementOrder/orderDetail/index.vue

415 lines
11 KiB
Vue
Raw Normal View History

<template>
<div class="app-container">
<!-- 页面标题 -->
<h2 class="page-title">结算单详情</h2>
<!-- 查询区域 -->
<div class="head-container">
<div class="filter-container">
<div class="filter-item">
<span class="label">订单批次号</span>
<el-input
v-model="query.batchNo"
placeholder="请输入订单批次号"
style="width: 200px"
clearable
@input="handleSearch"
/>
</div>
<div class="filter-item">
<span class="label">景区</span>
<el-select
v-model="query.scenicArea"
placeholder="请选择景区"
clearable
style="width: 200px"
@change="handleSearch"
>
<el-option
v-for="item in scenicAreaOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="filter-item">
<span class="label">日期</span>
<el-date-picker
v-model="query.dateRange"
type="daterange"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']"
:default-value="defaultDateRange"
style="width: 350px"
@change="handleSearch"
/>
</div>
</div>
</div>
<!-- 订单列表区域 -->
<div class="order-list-container">
<div class="list-header">
<span class="list-title">订单列表</span>
</div>
<!-- 表格 -->
<el-table
ref="table"
v-loading="loading"
:data="paginatedData"
style="width: 100%"
>
<el-table-column prop="customerName" label="客户名称" align="center" />
<el-table-column prop="phone" label="手机号码" align="center" />
<el-table-column prop="createTime" label="下单时间" align="center" width="180" />
<el-table-column prop="totalAmount" label="下单费用" align="center">
<template slot-scope="scope">
<span>{{ scope.row.totalAmount.toLocaleString('zh', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}</span>
</template>
</el-table-column>
<el-table-column prop="scenicName" label="景区" align="center" />
<el-table-column prop="routeIds" label="路线" align="center" />
<el-table-column prop="createBy" label="订单发起人" align="center" />
<el-table-column
prop="orderType"
label="订单类型"
align="center"
>
<template slot-scope="scope">
<span>{{ scope.row.orderType === 1 ? '载物飞行' : '载人飞行' }}</span>
</template>
</el-table-column>
<el-table-column
prop="mainOrderStatus"
label="订单状态"
align="center"
>
<template slot-scope="scope">
<span :class="getSettlementStatusClass(scope.row.mainOrderStatus)">
{{ getOrderStatus(scope.row.mainOrderStatus) }}
</span>
</template>
</el-table-column>
<el-table-column
prop="settlementStatus"
label="结算状态"
align="center"
>
<template slot-scope="scope">
<span :class="getSettlementStatusClass(scope.row.settlementStatus)">
{{ getSettlementStatusText(scope.row.settlementStatus) }}
</span>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-container">
<el-pagination
:current-page.sync="page.current"
:page-sizes="[10, 20, 50, 100]"
:page-size="page.size"
:total="tableData.length"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
<!-- 操作按钮 -->
<div class="action-buttons">
<el-button
v-if="settlementStatus === 0"
type="primary"
@click="handleCancelSettlement"
>
取消结算
</el-button>
<el-button type="primary" @click="handlePrint">导出结算单</el-button>
<el-button
v-if="settlementStatus === 0"
type="success"
@click="handleStatusChange(1)"
>
确认结算
</el-button>
<el-button
v-if="settlementStatus === 1"
type="success"
@click="handleStatusChange(2)"
>
完成结算
</el-button>
</div>
<!-- PDF导出组件 -->
<settlement-pdf
ref="settlementPdf"
:order-data="currentOrder"
v-show="false"
/>
</div>
</template>
<script>
import { getSettleOrderDetail, updateSettleOrderStatus } from '@/api/order'
import { getDetail } from "@/api/system/pilot";
import { getCustomerId } from '@/api/system/customer'
import { getScenicValue } from '@/api/dropdown'
import SettlementPdf from './settlementPdf.vue'
export default {
name: "orderDetail",
components: {
SettlementPdf
},
data() {
const defaultStartDate = new Date();
const defaultEndDate = new Date();
return {
loading: false,
scenicAreaOptions: [],
settlementStatus: 0,
currentOrder: null,
query: {
batchNo: "",
scenicArea: "",
dateRange: [defaultStartDate, defaultEndDate],
},
defaultDateRange: [defaultStartDate, defaultEndDate],
page: {
current: 1,
size: 10
},
tableData: [],
selection: [],
};
},
computed: {
paginatedData() {
const start = (this.page.current - 1) * this.page.size
const end = start + this.page.size
return this.tableData.slice(start, end)
}
},
async created() {
// 获取景区下拉数据
const scenicResponse = await getScenicValue()
this.scenicAreaOptions = scenicResponse.map(item => ({
value: item.key,
label: item.value
}))
// 获取订单详情并处理数据
const orderId = this.$route.query.orderId
if (orderId) {
this.loading = true
try {
const settleOrderDetail = await getSettleOrderDetail(orderId)
await Promise.all(settleOrderDetail.map(async (item) => {
// 获取客户名称
const customerResponse = await getCustomerId(item.customerId)
item.customerName = customerResponse.name
// 获取飞行员信息
const pilotResponse = await getDetail(item.orderInitiatorId)
item.createBy = pilotResponse.name
// 获取景区名称
const scenic = scenicResponse.find(s => s.key === item.attractionId)
item.scenicName = scenic ? scenic.value : ''
}))
this.tableData = settleOrderDetail
if(settleOrderDetail.length > 0) {
this.currentOrder = settleOrderDetail[0]
this.settlementStatus = settleOrderDetail[0].settlementStatus
}
} catch (error) {
console.error('Error fetching order details:', error)
this.$message.error('获取订单详情失败')
} finally {
this.loading = false
}
}
},
methods: {
async 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 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
// 重置分页到第一页
this.page.current = 1
} catch (error) {
console.error('Error searching orders:', error)
this.$message.error('搜索订单失败')
} finally {
this.loading = false
}
},
getOrderStatus(status) {
const statusMap = {
0: "未进行",
1: "进行中",
2: "已完成",
3: "已取消"
};
return statusMap[status] || "未知状态";
},
getSettlementStatusText(status) {
const statusMap = {
0: '结算中',
1: '已确认',
2: '结算完成',
3: '已取消'
};
return statusMap[status] || '未知状态';
},
getSettlementStatusClass(status) {
return {
'status-red': [0, 3].includes(status),
'status-green': status === 2,
'status-orange': status === 1
};
},
async handleCancelSettlement() {
try {
await updateSettleOrderStatus(this.$route.query.orderId, 3)
this.settlementStatus = 3
this.$message.success('取消结算成功')
this.handleSearch() // 刷新数据
} catch (error) {
console.error('Error canceling settlement:', error)
this.$message.error('取消结算失败')
}
},
handleSizeChange(val) {
this.page.size = val;
this.page.current = 1; // 重置到第一页
},
handleCurrentChange(val) {
this.page.current = val;
},
async handlePrint() {
// 调用PDF组件的导出方法
if (this.currentOrder) {
try {
await this.$refs.settlementPdf.generatePDF()
} catch (error) {
console.error('Error generating PDF:', error)
this.$message.error('导出PDF失败')
}
} else {
this.$message.warning('没有可导出的订单数据')
}
},
async handleStatusChange(status) {
try {
await updateSettleOrderStatus(this.$route.query.orderId, status)
this.settlementStatus = status
const statusText = status === 1 ? '已确认' : '已完成'
this.$message.success(`结算单状态已更新为:${statusText}`)
this.handleSearch() // 刷新数据
} catch (error) {
console.error('Error updating settlement status:', error)
this.$message.error('更新结算状态失败')
}
}
}
};
</script>
<style lang="scss" scoped>
.app-container {
padding: 20px;
}
.page-title {
margin-bottom: 20px;
font-size: 22px;
font-weight: bold;
color: #303133;
}
.filter-container {
background-color: #fff;
margin-bottom: 20px;
.filter-item {
display: inline-flex;
align-items: center;
margin-right: 20px;
.label {
color: #606266;
margin-right: 8px;
}
}
}
.order-list-container {
background-color: #fff;
.list-header {
margin-bottom: 20px;
.list-title {
font-size: 16px;
font-weight: bold;
color: #303133;
}
}
}
.action-buttons {
text-align: center;
margin: 20px 0;
padding: 20px 0;
.el-button {
margin: 0 10px;
}
}
.status-red {
color: #f56c6c;
}
.status-green {
color: #67c23a;
}
.status-orange {
color: #e6a23c;
}
.el-table {
margin-bottom: 70px;
margin-top: 20px;
::v-deep .el-table__body-wrapper {
overflow-x: auto;
}
}
.el-button--text {
color: #409eff;
&:hover {
color: #66b1ff;
}
}
</style>