添加了html2pdf库,以及结算单管理接入接口
This commit is contained in:
parent
a69c3d1908
commit
79bd6b57dd
@ -44,6 +44,7 @@
|
|||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
"file-saver": "1.3.8",
|
"file-saver": "1.3.8",
|
||||||
"fuse.js": "3.4.4",
|
"fuse.js": "3.4.4",
|
||||||
|
"html2pdf.js": "^0.10.3",
|
||||||
"js-beautify": "^1.10.2",
|
"js-beautify": "^1.10.2",
|
||||||
"js-cookie": "2.2.0",
|
"js-cookie": "2.2.0",
|
||||||
"jsencrypt": "^3.0.0-rc.1",
|
"jsencrypt": "^3.0.0-rc.1",
|
||||||
|
@ -9,4 +9,11 @@ export function getScenicValue (data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { getScenicValue }
|
// 获取用户名称下拉
|
||||||
|
export function getUserNameValue (userType) {
|
||||||
|
return request({
|
||||||
|
url: `api/dataDropdown/obtainUserListByType/${userType}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export default { getScenicValue, getUserNameValue }
|
||||||
|
@ -44,7 +44,13 @@ export function generateSettlementOrder(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取生成结算单确认列表
|
// 获取生成结算单确认列表
|
||||||
// export function get
|
export function getGenerateSettleOrderConfirmList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/api/settlementOrder/generateSettlementOrderConfirmList',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 更新结算单状态
|
// 更新结算单状态
|
||||||
export function updateSettleOrderStatus(settlementOrderId, settlementOrderStatus) {
|
export function updateSettleOrderStatus(settlementOrderId, settlementOrderStatus) {
|
||||||
@ -53,3 +59,11 @@ export function updateSettleOrderStatus(settlementOrderId, settlementOrderStatus
|
|||||||
method: 'put',
|
method: 'put',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打印结算单数据
|
||||||
|
export function printSettleOrderData(settlementOrderId) {
|
||||||
|
return request({
|
||||||
|
url: `api/settlementOrder/printSettlementOrder/${settlementOrderId}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -39,4 +39,12 @@ export function allCustomer() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { add, enable, del, edit, allCustomer }
|
// 查询单个客户信息
|
||||||
|
export function getCustomerId(id) {
|
||||||
|
return request({
|
||||||
|
url: `aerocraftAdminApi/cnCustomer/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { add, enable, del, edit, allCustomer, getCustomerId }
|
||||||
|
@ -517,7 +517,7 @@ export default {
|
|||||||
if (response) {
|
if (response) {
|
||||||
// 确保有total字段
|
// 确保有total字段
|
||||||
if (response.total !== undefined) {
|
if (response.total !== undefined) {
|
||||||
this.page.total = response.total;
|
this.page.total = Number(response.total);
|
||||||
}
|
}
|
||||||
// 确保records数组存在且是数组类型
|
// 确保records数组存在且是数组类型
|
||||||
if (response && Array.isArray(response)) {
|
if (response && Array.isArray(response)) {
|
||||||
|
@ -144,7 +144,7 @@ export default {
|
|||||||
this.getScenics();
|
this.getScenics();
|
||||||
this.getPilots();
|
this.getPilots();
|
||||||
this.getCustomers();
|
this.getCustomers();
|
||||||
this.getList();
|
// this.getList();
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -207,7 +207,7 @@ export default {
|
|||||||
id: record.id,
|
id: record.id,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
this.page.total = response.total || 0;
|
this.page.total = Number(response.total) || 0;
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
<div class="filter-container">
|
<div class="filter-container">
|
||||||
<div class="filter-item">
|
<div class="filter-item">
|
||||||
<span class="label">景区:</span>
|
<span class="label">景区:</span>
|
||||||
<el-select v-model="query.scenicArea" placeholder="请选择景区" clearable style="width: 200px;">
|
<el-select v-model="query.attractionId" placeholder="请选择景区" clearable style="width: 200px;">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in scenicAreaOptions"
|
v-for="item in scenicAreaOptions"
|
||||||
:key="item.value"
|
:key="item.id"
|
||||||
:label="item.label"
|
:label="item.name"
|
||||||
:value="item.value"
|
:value="item.id"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
@ -56,19 +56,29 @@
|
|||||||
<el-table-column prop="customerName" label="客户名称" align="center" />
|
<el-table-column prop="customerName" label="客户名称" align="center" />
|
||||||
<el-table-column prop="phoneNumber" label="手机号码" align="center" />
|
<el-table-column prop="phoneNumber" label="手机号码" align="center" />
|
||||||
<el-table-column prop="orderTime" label="下单时间" align="center" width="180" />
|
<el-table-column prop="orderTime" label="下单时间" align="center" width="180" />
|
||||||
<el-table-column prop="orderAmount" label="下单费用" align="center" />
|
<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>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="scenicArea" label="景区" align="center" />
|
<el-table-column prop="scenicArea" label="景区" align="center" />
|
||||||
<el-table-column prop="route" label="路线" align="center" />
|
<el-table-column prop="route" label="路线" align="center" />
|
||||||
<el-table-column prop="initiator" label="订单发起人" align="center" />
|
<el-table-column prop="initiator" label="订单发起人" align="center" />
|
||||||
<el-table-column prop="orderType" label="订单类型" align="center" />
|
<el-table-column prop="orderType" label="订单类型" align="center" />
|
||||||
<el-table-column prop="orderStatus" label="订单状态" align="center">
|
<el-table-column prop="orderStatus" label="订单状态" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.orderStatus }}</span>
|
<span :class="['status-text', scope.row.orderStatus === '已完成' ? 'success' : '']">
|
||||||
|
{{ scope.row.orderStatus }}
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="settlementStatus" label="结算状态" align="center">
|
<el-table-column prop="settlementStatus" label="结算状态" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.settlementStatus }}</span>
|
<span :class="['status-text', scope.row.settlementStatus === '已结算' ? 'success' : '']">
|
||||||
|
{{ scope.row.settlementStatus }}
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -123,9 +133,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
先调用获取生成结算单确认列表接口,当点击确认生成时调用生成结算单接口
|
||||||
|
-->
|
||||||
<script>
|
<script>
|
||||||
|
import { getOrderList, getGenerateSettleOrderConfirmList, generateSettlementOrder } from "@/api/order";
|
||||||
|
import { allAreas } from "@/api/system/area";
|
||||||
|
import { allScenic } from "@/api/system/scenic";
|
||||||
|
import { allCustomer } from "@/api/system/customer";
|
||||||
|
import { getList } from "@/api/system/pilot";
|
||||||
|
import { getUser } from "@/api/system/user";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'generateOrder',
|
name: 'generateOrder',
|
||||||
|
created() {
|
||||||
|
this.getScenics();
|
||||||
|
this.getCustomers();
|
||||||
|
this.getPilots();
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
const defaultStartDate = new Date('2015-10-02')
|
const defaultStartDate = new Date('2015-10-02')
|
||||||
const defaultEndDate = new Date('2015-10-10')
|
const defaultEndDate = new Date('2015-10-10')
|
||||||
@ -134,7 +161,8 @@ export default {
|
|||||||
settlementList: [],
|
settlementList: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
query: {
|
query: {
|
||||||
scenicArea: '',
|
attractionId: undefined,
|
||||||
|
customerId: undefined,
|
||||||
dateRange: [defaultStartDate, defaultEndDate]
|
dateRange: [defaultStartDate, defaultEndDate]
|
||||||
},
|
},
|
||||||
defaultDateRange: [defaultStartDate, defaultEndDate],
|
defaultDateRange: [defaultStartDate, defaultEndDate],
|
||||||
@ -143,36 +171,134 @@ export default {
|
|||||||
size: 10,
|
size: 10,
|
||||||
total: 0
|
total: 0
|
||||||
},
|
},
|
||||||
scenicAreaOptions: [
|
scenicAreaOptions: [],
|
||||||
{ value: 'baiYunShan', label: '白云山' },
|
customerOptions: [],
|
||||||
{ value: 'huangShan', label: '黄山' },
|
pilotOptions: [],
|
||||||
{ value: 'taiShan', label: '泰山' }
|
tableData: [],
|
||||||
],
|
|
||||||
tableData: [
|
|
||||||
{
|
|
||||||
customerName: '小明',
|
|
||||||
phoneNumber: '12345678',
|
|
||||||
orderTime: '2024-01-01 00:00:00',
|
|
||||||
orderAmount: '100.00',
|
|
||||||
scenicArea: '白云山',
|
|
||||||
route: 'a-b',
|
|
||||||
initiator: '小红',
|
|
||||||
orderType: '载物飞行',
|
|
||||||
orderStatus: '已完成',
|
|
||||||
settlementStatus: '未结算'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
selection: []
|
selection: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
const params = {
|
||||||
|
attractionId: this.query.attractionId,
|
||||||
|
customerId: this.query.customerId,
|
||||||
|
startTime: this.query.dateRange ? this.query.dateRange[0] : null,
|
||||||
|
endTime: this.query.dateRange ? this.query.dateRange[1] : null,
|
||||||
|
current: this.page.current,
|
||||||
|
size: this.page.size,
|
||||||
|
mainOrderStatus: 2, // 只查询已完成的订单
|
||||||
|
settlementStatus: 0 // 只查询未结算的订单
|
||||||
|
};
|
||||||
|
getOrderList(params)
|
||||||
|
.then((response) => {
|
||||||
|
this.tableData = response.records.map((record) => {
|
||||||
|
const customer = this.customerOptions.find(
|
||||||
|
(c) => c.id === record.customerId
|
||||||
|
);
|
||||||
|
const scenic = this.scenicAreaOptions.find(s => s.id === record.attractionId);
|
||||||
|
const initiator = this.pilotOptions.find(p => p.id === record.orderInitiatorId);
|
||||||
|
return {
|
||||||
|
id: record.id,
|
||||||
|
customerName: customer ? customer.name : "未知客户",
|
||||||
|
phoneNumber: record.customerPhone,
|
||||||
|
orderTime: record.orderCreateTime,
|
||||||
|
orderAmount: record.amount,
|
||||||
|
totalAmount: record.totalAmount,
|
||||||
|
surchargeAmount: record.surchargeAmount,
|
||||||
|
scenicArea: scenic ? scenic.name : "未知景区",
|
||||||
|
route: record.routeName,
|
||||||
|
initiator: initiator ? initiator.name : "未知发起人",
|
||||||
|
orderType: record.orderType === 1 ? "载物飞行" : "载人飞行",
|
||||||
|
orderStatus: this.getOrderStatus(record.mainOrderStatus),
|
||||||
|
settlementStatus: this.getSettlementStatus(record.settlementStatus),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
this.page.total = Number(response.total) || 0;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async getScenics() {
|
||||||
|
try {
|
||||||
|
let res = [];
|
||||||
|
const userRes = await getUser({ id: store.getters.user.id });
|
||||||
|
if (userRes && userRes.content && userRes.content.length > 0) {
|
||||||
|
const userInfo = userRes.content[0];
|
||||||
|
if (userInfo.roles && userInfo.roles.length > 0) {
|
||||||
|
this.userRole = userInfo.roles[0].name;
|
||||||
|
if (this.userRole === "区域负责人") {
|
||||||
|
res = await allScenic({areaId: userInfo.areaId});
|
||||||
|
} else if (this.userRole === "管理员" || this.userRole === "财务") {
|
||||||
|
res = await allScenic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res && Array.isArray(res)) {
|
||||||
|
this.scenicAreaOptions = res.map((scenic) => ({
|
||||||
|
id: scenic.id,
|
||||||
|
name: scenic.name
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
this.getList();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取景区列表失败:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async getPilots() {
|
||||||
|
try {
|
||||||
|
const res = await getList();
|
||||||
|
if (res) {
|
||||||
|
this.pilotOptions = res.content.map((pilot) => ({
|
||||||
|
id: pilot.id,
|
||||||
|
name: pilot.name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取飞行员列表失败:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async getCustomers() {
|
||||||
|
try {
|
||||||
|
const res = await allCustomer();
|
||||||
|
if (res) {
|
||||||
|
this.customerOptions = res.map((customer) => ({
|
||||||
|
id: customer.id,
|
||||||
|
name: customer.name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取客户列表失败:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getOrderStatus(status) {
|
||||||
|
const statusMap = {
|
||||||
|
0: "未进行",
|
||||||
|
1: "进行中",
|
||||||
|
2: "已完成",
|
||||||
|
3: "已取消"
|
||||||
|
};
|
||||||
|
return statusMap[status] || "未知状态";
|
||||||
|
},
|
||||||
|
|
||||||
|
getSettlementStatus(status) {
|
||||||
|
const statusMap = {
|
||||||
|
0: "未结算",
|
||||||
|
1: "结算中",
|
||||||
|
2: "结算完成"
|
||||||
|
};
|
||||||
|
return statusMap[status] || "未知状态";
|
||||||
|
},
|
||||||
|
|
||||||
handleSearch() {
|
handleSearch() {
|
||||||
// 仅显示已完成且未结算的订单
|
this.page.current = 1;
|
||||||
this.loading = true
|
this.getList();
|
||||||
// 实际环境中应该调用API
|
|
||||||
setTimeout(() => {
|
|
||||||
this.loading = false
|
|
||||||
}, 500)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSelectAll() {
|
handleSelectAll() {
|
||||||
@ -182,14 +308,12 @@ export default {
|
|||||||
this.selection = val
|
this.selection = val
|
||||||
},
|
},
|
||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
this.page.size = val
|
this.page.size = val;
|
||||||
this.page.total = this.tableData.length // 更新总数
|
this.getList();
|
||||||
// 重新加载数据
|
|
||||||
},
|
},
|
||||||
handleCurrentChange(val) {
|
handleCurrentChange(val) {
|
||||||
this.page.current = val
|
this.page.current = val;
|
||||||
this.page.total = this.tableData.length // 更新总数
|
this.getList();
|
||||||
// 重新加载数据
|
|
||||||
},
|
},
|
||||||
handleDetail(row) {
|
handleDetail(row) {
|
||||||
// 查看详情
|
// 查看详情
|
||||||
@ -221,14 +345,46 @@ export default {
|
|||||||
amount: '100元' // 示例数据,实际应根据订单计算
|
amount: '100元' // 示例数据,实际应根据订单计算
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// 调用接口获取结算确认列表
|
||||||
|
getGenerateSettleOrderConfirmList({
|
||||||
|
orders: this.selection.map(order => order.id)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.success) {
|
||||||
|
// 成功获取结算确认列表
|
||||||
|
this.settlementList = response.data || []
|
||||||
|
} else {
|
||||||
|
this.$message.error('获取结算确认列表失败: ' + response.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('获取结算确认列表失败:', error)
|
||||||
|
this.$message.error('获取结算确认列表失败,请稍后再试')
|
||||||
|
})
|
||||||
|
|
||||||
// 显示确认弹窗
|
// 显示确认弹窗
|
||||||
this.dialogVisible = true
|
this.dialogVisible = true
|
||||||
},
|
},
|
||||||
|
|
||||||
handleConfirm() {
|
handleConfirm() {
|
||||||
|
// 调用生成结算单接口
|
||||||
|
generateSettlementOrder({
|
||||||
|
orders: this.selection.map(order => order.id)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.success) {
|
||||||
|
this.$message.success('结算单生成成功')
|
||||||
this.dialogVisible = false
|
this.dialogVisible = false
|
||||||
// 跳转到订单详情页
|
|
||||||
this.$router.push('/order/orderDetail')
|
this.$router.push('/order/orderDetail')
|
||||||
|
} else {
|
||||||
|
this.$message.error('结算单生成失败: ' + response.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('生成结算单失败:', error)
|
||||||
|
this.$message.error('生成结算单失败,请稍后再试')
|
||||||
|
})
|
||||||
|
this.dialogVisible = false
|
||||||
},
|
},
|
||||||
|
|
||||||
handleCancel() {
|
handleCancel() {
|
||||||
@ -239,6 +395,13 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.status-text {
|
||||||
|
color: #f56c6c;
|
||||||
|
&.success {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.app-container {
|
.app-container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
@ -28,16 +28,11 @@
|
|||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
>
|
>
|
||||||
<el-table-column prop="batchNo" label="订单批次号" align="left" />
|
<el-table-column prop="batchNo" label="订单批次号" align="center" />
|
||||||
<el-table-column prop="status" label="结算状态" align="left">
|
<el-table-column prop="settlementTimeScope" label="结算时间" width="180" align="center" />
|
||||||
<template slot-scope="scope">
|
<el-table-column prop="operator" label="制单人" align="center" />
|
||||||
<span>{{ scope.row.status }}</span>
|
<el-table-column prop="updateTime" label="导出时间" width="180" align="center" />
|
||||||
</template>
|
<el-table-column prop="settlementStatus" label="结算状态" align="center">
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="settlementTime" label="结算时间" width="180" align="left" />
|
|
||||||
<el-table-column prop="operator" label="制单人" align="left" />
|
|
||||||
<el-table-column prop="exportTime" label="导出时间" width="180" align="left" />
|
|
||||||
<el-table-column prop="settlementStatus" label="结算状态" align="left">
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.settlementStatus }}</span>
|
<span>{{ scope.row.settlementStatus }}</span>
|
||||||
</template>
|
</template>
|
||||||
@ -78,6 +73,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getSettleOrderList } from '@/api/order'
|
||||||
|
import { getUserNameValue } from '@/api/dropdown'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'settlementOrder',
|
name: 'settlementOrder',
|
||||||
data() {
|
data() {
|
||||||
@ -93,26 +91,65 @@ export default {
|
|||||||
},
|
},
|
||||||
tableData: [
|
tableData: [
|
||||||
{
|
{
|
||||||
batchNo: 'JS123456789',
|
attractionId: 2,
|
||||||
status: '结算中',
|
batchNo: "JS_2025072600008",
|
||||||
settlementTime: '2025-01-01 00:00:00',
|
createBy: "admin",
|
||||||
operator: '小明',
|
createTime: "2025-07-26 14:42:38",
|
||||||
exportTime: '2025-01-01 00:00:00',
|
operatorId: 1,
|
||||||
settlementStatus: '结算中'
|
settlementStatus: 2,
|
||||||
|
settlementTimeScope: "2025-07-19 17:00:00~2025-07-19 17:00:00",
|
||||||
|
updateBy: "admin",
|
||||||
|
updateTime: "2025-07-26 14:42:38"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
batchNo: 'JS123456789',
|
|
||||||
status: '待付款',
|
|
||||||
settlementTime: '2025-01-01 00:00:00',
|
|
||||||
operator: '小明',
|
|
||||||
exportTime: '2025-01-01 00:00:00',
|
|
||||||
settlementStatus: '已确认'
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
selection: []
|
selection: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async fetchData() {
|
||||||
|
this.loading = true
|
||||||
|
try {
|
||||||
|
const response = await getSettleOrderList(this.query)
|
||||||
|
const operatorList = await getUserNameValue(0); // 只请求一次,避免每条都请求
|
||||||
|
|
||||||
|
const operatorMap = new Map();
|
||||||
|
operatorList.forEach(item => {
|
||||||
|
operatorMap.set(item.key, item.value);
|
||||||
|
});
|
||||||
|
response.records = response.records.map(record => ({
|
||||||
|
...record,
|
||||||
|
settlementStatus: this.getSettlementStatus(record.settlementStatus),
|
||||||
|
operator: record.operatorId ? (operatorMap.get(record.operatorId) || '未知') : '未知',
|
||||||
|
}))
|
||||||
|
console.log('获取结算单列表:', response)
|
||||||
|
this.tableData = response.records || []
|
||||||
|
this.page.total = Number(response.total) || 0
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取结算单列表失败:', error)
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getSettlementStatus(status) {
|
||||||
|
const statusMap = {
|
||||||
|
0: "结算中",
|
||||||
|
1: "已确认",
|
||||||
|
2: "结算完成",
|
||||||
|
3: "已取消",
|
||||||
|
};
|
||||||
|
return statusMap[status] || "未知状态";
|
||||||
|
},
|
||||||
|
async getOperatorName(operatorId) {
|
||||||
|
const response = await getUserNameValue(0);
|
||||||
|
if (!response || response.length === 0) {
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
const operatorName = response.find(item => item.key === operatorId);
|
||||||
|
return operatorName.value || '未知';
|
||||||
|
},
|
||||||
handleSearch() {
|
handleSearch() {
|
||||||
// 实现搜索逻辑
|
// 实现搜索逻辑
|
||||||
console.log('搜索条件:', this.query)
|
console.log('搜索条件:', this.query)
|
||||||
@ -131,6 +168,11 @@ export default {
|
|||||||
handleDetail(row) {
|
handleDetail(row) {
|
||||||
// 查看详情
|
// 查看详情
|
||||||
console.log('查看详情:', row)
|
console.log('查看详情:', row)
|
||||||
|
// 跳转到订单详情页
|
||||||
|
this.$router.push({
|
||||||
|
path: '/order/orderDetail',
|
||||||
|
query: { orderId: row.id.toString() }
|
||||||
|
})
|
||||||
},
|
},
|
||||||
handlePrint(row) {
|
handlePrint(row) {
|
||||||
// 打印结算单
|
// 打印结算单
|
||||||
@ -151,7 +193,6 @@ export default {
|
|||||||
.filter-container {
|
.filter-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px;
|
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
|
||||||
.filter-item {
|
.filter-item {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
placeholder="请输入订单批次号"
|
placeholder="请输入订单批次号"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
clearable
|
clearable
|
||||||
|
@input="handleSearch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="filter-item">
|
<div class="filter-item">
|
||||||
@ -22,6 +23,7 @@
|
|||||||
placeholder="请选择景区"
|
placeholder="请选择景区"
|
||||||
clearable
|
clearable
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
|
@change="handleSearch"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in scenicAreaOptions"
|
v-for="item in scenicAreaOptions"
|
||||||
@ -42,6 +44,7 @@
|
|||||||
:default-time="['00:00:00', '23:59:59']"
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
:default-value="defaultDateRange"
|
:default-value="defaultDateRange"
|
||||||
style="width: 350px"
|
style="width: 350px"
|
||||||
|
@change="handleSearch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -57,25 +60,38 @@
|
|||||||
<el-table
|
<el-table
|
||||||
ref="table"
|
ref="table"
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:data="tableData"
|
:data="paginatedData"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
<el-table-column prop="customerName" label="客户名称" align="center" />
|
<el-table-column prop="customerName" label="客户名称" align="center" />
|
||||||
<el-table-column prop="phoneNumber" label="手机号码" align="center" />
|
<el-table-column prop="phone" label="手机号码" align="center" />
|
||||||
<el-table-column
|
<el-table-column prop="createTime" label="下单时间" align="center" width="180" />
|
||||||
prop="orderTime"
|
<el-table-column prop="totalAmount" label="下单费用" align="center">
|
||||||
label="下单时间"
|
|
||||||
align="center"
|
|
||||||
width="180"
|
|
||||||
/>
|
|
||||||
<el-table-column prop="orderAmount" label="下单费用" align="center" />
|
|
||||||
<el-table-column prop="scenicArea" label="景区" align="center" />
|
|
||||||
<el-table-column prop="route" label="路线" align="center" />
|
|
||||||
<el-table-column prop="initiator" label="订单发起人" align="center" />
|
|
||||||
<el-table-column prop="orderType" label="订单类型" align="center" />
|
|
||||||
<el-table-column prop="orderStatus" label="订单状态" align="center">
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.orderStatus }}</span>
|
<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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
@ -85,7 +101,7 @@
|
|||||||
>
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span :class="getSettlementStatusClass(scope.row.settlementStatus)">
|
<span :class="getSettlementStatusClass(scope.row.settlementStatus)">
|
||||||
{{ scope.row.settlementStatus }}
|
{{ getSettlementStatusText(scope.row.settlementStatus) }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -96,7 +112,7 @@
|
|||||||
:current-page.sync="page.current"
|
:current-page.sync="page.current"
|
||||||
:page-sizes="[10, 20, 50, 100]"
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
:page-size="page.size"
|
:page-size="page.size"
|
||||||
:total="page.total"
|
:total="tableData.length"
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
@size-change="handleSizeChange"
|
@size-change="handleSizeChange"
|
||||||
@current-change="handleCurrentChange"
|
@current-change="handleCurrentChange"
|
||||||
@ -107,31 +123,58 @@
|
|||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
<el-button
|
<el-button
|
||||||
|
v-if="settlementStatus === 0"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleCancelSettlement"
|
@click="handleCancelSettlement"
|
||||||
:disabled="settlementStatus !== '结算中'"
|
|
||||||
>
|
>
|
||||||
取消结算
|
取消结算
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" @click="handlePrint"> 打印结算单 </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>
|
</div>
|
||||||
|
|
||||||
|
<!-- PDF导出组件 -->
|
||||||
|
<settlement-pdf
|
||||||
|
ref="settlementPdf"
|
||||||
|
:order-data="currentOrder"
|
||||||
|
v-show="false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<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 {
|
export default {
|
||||||
name: "orderDetail",
|
name: "orderDetail",
|
||||||
|
components: {
|
||||||
|
SettlementPdf
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
const defaultStartDate = new Date("2015-10-02");
|
const defaultStartDate = new Date();
|
||||||
const defaultEndDate = new Date("2015-10-10");
|
const defaultEndDate = new Date();
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
settlementStatus: "结算中", // 当前结算单状态
|
scenicAreaOptions: [],
|
||||||
scenicAreaOptions: [
|
settlementStatus: 0,
|
||||||
{ value: "baiYunShan", label: "白云山" },
|
currentOrder: null,
|
||||||
{ value: "huangShan", label: "黄山" },
|
|
||||||
{ value: "taiShan", label: "泰山" },
|
|
||||||
],
|
|
||||||
query: {
|
query: {
|
||||||
batchNo: "",
|
batchNo: "",
|
||||||
scenicArea: "",
|
scenicArea: "",
|
||||||
@ -140,98 +183,152 @@ export default {
|
|||||||
defaultDateRange: [defaultStartDate, defaultEndDate],
|
defaultDateRange: [defaultStartDate, defaultEndDate],
|
||||||
page: {
|
page: {
|
||||||
current: 1,
|
current: 1,
|
||||||
size: 10,
|
size: 10
|
||||||
total: 3,
|
|
||||||
},
|
},
|
||||||
tableData: [
|
tableData: [],
|
||||||
{
|
|
||||||
customerName: "小明",
|
|
||||||
phoneNumber: "12345678",
|
|
||||||
orderTime: "2024-01-01 00:00:00",
|
|
||||||
orderAmount: "100.00",
|
|
||||||
scenicArea: "白云山",
|
|
||||||
route: "a-b",
|
|
||||||
initiator: "小红",
|
|
||||||
orderType: "载物飞行",
|
|
||||||
orderStatus: "已完成",
|
|
||||||
settlementStatus: "未结算",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
customerName: "小明",
|
|
||||||
phoneNumber: "12345678",
|
|
||||||
orderTime: "2024-01-01 00:00:00",
|
|
||||||
orderAmount: "100.00",
|
|
||||||
scenicArea: "白云山",
|
|
||||||
route: "a-b",
|
|
||||||
initiator: "小红",
|
|
||||||
orderType: "载物飞行",
|
|
||||||
orderStatus: "进行中",
|
|
||||||
settlementStatus: "结算中",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
customerName: "小明",
|
|
||||||
phoneNumber: "12345678",
|
|
||||||
orderTime: "2024-01-01 00:00:00",
|
|
||||||
orderAmount: "100.00",
|
|
||||||
scenicArea: "白云山",
|
|
||||||
route: "a-b",
|
|
||||||
initiator: "小红",
|
|
||||||
orderType: "载物飞行",
|
|
||||||
orderStatus: "已完成",
|
|
||||||
settlementStatus: "结算完成",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
selection: [],
|
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: {
|
methods: {
|
||||||
handleSearch() {
|
async handleSearch() {
|
||||||
// 实现搜索逻辑
|
this.loading = true
|
||||||
console.log("搜索条件:", this.query);
|
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) {
|
getSettlementStatusClass(status) {
|
||||||
return {
|
return {
|
||||||
"status-red": ["未结算", "结算中"].includes(status),
|
'status-red': [0, 3].includes(status),
|
||||||
|
'status-green': status === 2,
|
||||||
|
'status-orange': status === 1
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
async handleCancelSettlement() {
|
||||||
handleCancelSettlement() {
|
try {
|
||||||
if (this.settlementStatus === "结算中") {
|
await updateSettleOrderStatus(this.$route.query.orderId, 3)
|
||||||
// 更新所有订单的结算状态为未结算
|
this.settlementStatus = 3
|
||||||
this.tableData.forEach((order) => {
|
this.$message.success('取消结算成功')
|
||||||
order.settlementStatus = "未结算";
|
this.handleSearch() // 刷新数据
|
||||||
});
|
} catch (error) {
|
||||||
this.settlementStatus = "未结算";
|
console.error('Error canceling settlement:', error)
|
||||||
this.$message.success("已取消结算");
|
this.$message.error('取消结算失败')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
this.page.size = val;
|
this.page.size = val;
|
||||||
// 重新加载数据
|
this.page.current = 1; // 重置到第一页
|
||||||
},
|
},
|
||||||
handleCurrentChange(val) {
|
handleCurrentChange(val) {
|
||||||
this.page.current = val;
|
this.page.current = val;
|
||||||
// 重新加载数据
|
|
||||||
},
|
},
|
||||||
handleDetail(row) {
|
async handlePrint() {
|
||||||
// 查看详情
|
// 调用PDF组件的导出方法
|
||||||
console.log("查看详情:", row);
|
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('没有可导出的订单数据')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handlePrint() {
|
async handleStatusChange(status) {
|
||||||
// 根据当前状态流转到下一个状态
|
try {
|
||||||
switch (this.settlementStatus) {
|
await updateSettleOrderStatus(this.$route.query.orderId, status)
|
||||||
case "结算中":
|
this.settlementStatus = status
|
||||||
this.settlementStatus = "已确认";
|
const statusText = status === 1 ? '已确认' : '已完成'
|
||||||
this.$message.success("结算单状态已更新为:已确认");
|
this.$message.success(`结算单状态已更新为:${statusText}`)
|
||||||
break;
|
this.handleSearch() // 刷新数据
|
||||||
case "已确认":
|
} catch (error) {
|
||||||
this.settlementStatus = "已完成";
|
console.error('Error updating settlement status:', error)
|
||||||
this.$message.success("结算单状态已更新为:已完成");
|
this.$message.error('更新结算状态失败')
|
||||||
break;
|
|
||||||
case "已完成":
|
|
||||||
// 执行打印逻辑
|
|
||||||
console.log("打印结算单");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,26 +390,19 @@ export default {
|
|||||||
.status-red {
|
.status-red {
|
||||||
color: #f56c6c;
|
color: #f56c6c;
|
||||||
}
|
}
|
||||||
|
.status-green {
|
||||||
// .pagination-container {
|
color: #67c23a;
|
||||||
// position: fixed;
|
}
|
||||||
// bottom: 0;
|
.status-orange {
|
||||||
// left: 200px;
|
color: #e6a23c;
|
||||||
// right: 0;
|
}
|
||||||
// height: 60px;
|
|
||||||
// background: white;
|
|
||||||
// padding: 10px;
|
|
||||||
// text-align: left;
|
|
||||||
// box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.08);
|
|
||||||
// z-index: 1000;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .el-pagination {
|
|
||||||
// padding: 10px 20px;
|
|
||||||
// }
|
|
||||||
|
|
||||||
.el-table {
|
.el-table {
|
||||||
margin-bottom: 70px;
|
margin-bottom: 70px;
|
||||||
|
margin-top: 20px;
|
||||||
|
::v-deep .el-table__body-wrapper {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-button--text {
|
.el-button--text {
|
||||||
@ -321,11 +411,4 @@ export default {
|
|||||||
color: #66b1ff;
|
color: #66b1ff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table {
|
|
||||||
margin-top: 20px;
|
|
||||||
::v-deep .el-table__body-wrapper {
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
233
src/views/order/settlementOrder/orderDetail/settlementPdf.vue
Normal file
233
src/views/order/settlementOrder/orderDetail/settlementPdf.vue
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- PDF 可见区域 -->
|
||||||
|
<div id="pdf-content" ref="pdfContent" style="width: 100%; margin: 0 auto; padding: 20px;">
|
||||||
|
<h2 class="pdf-title">爱尚云收款结算单</h2>
|
||||||
|
|
||||||
|
<div class="info-row">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">结算单号:</span>
|
||||||
|
<span class="value">{{ data.statementId }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">结算时间:</span>
|
||||||
|
<span class="value">{{ data.date }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-row">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">委托方:</span>
|
||||||
|
<span class="value">{{ data.customer }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">数量:</span>
|
||||||
|
<span class="value">{{ data.quantity }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-row">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">金额(RMB):</span>
|
||||||
|
<span class="value">{{ data.amount }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">大写:</span>
|
||||||
|
<span class="value">{{ data.amountCN }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table border="1" cellspacing="0" cellpadding="5" width="100%">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 20%;">订单号</th>
|
||||||
|
<th style="width: 25%;">执行时间</th>
|
||||||
|
<th style="width: 15%;">重量</th>
|
||||||
|
<th style="width: 20%;">金额</th>
|
||||||
|
<th style="width: 20%;">确认人</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(item, index) in data.items" :key="index">
|
||||||
|
<td>{{ item.orderNo }}</td>
|
||||||
|
<td>{{ item.execTime }}</td>
|
||||||
|
<td>{{ item.weight }}</td>
|
||||||
|
<td>{{ item.amount }}</td>
|
||||||
|
<td>{{ item.confirmer }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import html2pdf from 'html2pdf.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SettlementPdf',
|
||||||
|
props: {
|
||||||
|
orderData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
statementId: '',
|
||||||
|
date: '',
|
||||||
|
customer: '',
|
||||||
|
quantity: '',
|
||||||
|
amount: '',
|
||||||
|
amountCN: '',
|
||||||
|
items: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
orderData: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.formatData(newVal)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatData(orderData) {
|
||||||
|
if (!orderData) {
|
||||||
|
console.warn('No order 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 || ''
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
generatePDF() {
|
||||||
|
const element = this.$refs.pdfContent
|
||||||
|
const opt = {
|
||||||
|
margin: 0.5,
|
||||||
|
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()
|
||||||
|
},
|
||||||
|
convertToChinese(num) {
|
||||||
|
const digitCN = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
|
||||||
|
const unitCN = ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿']
|
||||||
|
let str = ''
|
||||||
|
|
||||||
|
// 处理整数部分
|
||||||
|
const intNum = Math.floor(num)
|
||||||
|
const intStr = intNum.toString()
|
||||||
|
for (let i = 0; i < intStr.length; i++) {
|
||||||
|
const digit = parseInt(intStr[i])
|
||||||
|
str += digitCN[digit] + unitCN[intStr.length - 1 - i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理小数部分
|
||||||
|
const decimalNum = Math.round((num - intNum) * 100)
|
||||||
|
if (decimalNum > 0) {
|
||||||
|
str += '元'
|
||||||
|
const decStr = decimalNum.toString().padStart(2, '0')
|
||||||
|
if (decStr[0] !== '0') {
|
||||||
|
str += digitCN[parseInt(decStr[0])] + '角'
|
||||||
|
}
|
||||||
|
if (decStr[1] !== '0') {
|
||||||
|
str += digitCN[parseInt(decStr[1])] + '分'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str += '元整'
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.pdf-title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-family: SimSun, "宋体", serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
line-height: 1.8;
|
||||||
|
font-size: 20px;
|
||||||
|
font-family: SimSun, "宋体", serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
flex: 0 0 45%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
/* display: flex;
|
||||||
|
flex-wrap: wrap; */
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item .label {
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item .value {
|
||||||
|
box-sizing: border-box;
|
||||||
|
/* 增加下划线与字体距离 */
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 16px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 30px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
text-align: center;
|
||||||
|
padding: 12px 8px;
|
||||||
|
word-break: break-word;
|
||||||
|
white-space: normal;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 执行时间列的样式 */
|
||||||
|
th:nth-child(2),
|
||||||
|
td:nth-child(2) {
|
||||||
|
font-family: Calibri, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 重量列的样式 */
|
||||||
|
td:nth-child(3) {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pdf-content {
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user