<template>
|
<view class="settlement-container">
|
<view class="settlement-header">
|
<text class="header-title">任务结算</text>
|
</view>
|
|
<scroll-view class="settlement-content" scroll-y="true">
|
<view class="task-info-section">
|
<view class="info-item">
|
<view class="label">任务编号:</view>
|
<view class="value">{{ task.taskNo }}</view>
|
</view>
|
|
<view class="info-item">
|
<view class="label">任务类型:</view>
|
<view class="value">{{ getTaskTypeText(task.type) }}</view>
|
</view>
|
|
<view class="info-item">
|
<view class="label">车辆信息:</view>
|
<view class="value">{{ task.vehicle }}</view>
|
</view>
|
|
<view class="info-item">
|
<view class="label">出发地:</view>
|
<view class="value">{{ task.startLocation }}</view>
|
</view>
|
|
<view class="info-item">
|
<view class="label">目的地:</view>
|
<view class="value">{{ task.endLocation }}</view>
|
</view>
|
</view>
|
|
<view class="amount-section">
|
<view class="section-title">费用信息</view>
|
|
<view class="amount-item">
|
<view class="label">基础费用:</view>
|
<view class="value">¥{{ baseAmount }}</view>
|
</view>
|
|
<view class="amount-item additional-fees" @click="showAdditionalFees">
|
<view class="label">附加费用:</view>
|
<view class="value">¥{{ additionalAmount }}
|
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
|
</view>
|
</view>
|
|
<view class="amount-item total-amount">
|
<view class="label">总费用:</view>
|
<view class="value total">¥{{ totalAmount }}</view>
|
</view>
|
</view>
|
|
<view class="settlement-form">
|
<view class="form-item">
|
<view class="form-label">结算金额</view>
|
<input
|
class="form-input"
|
type="digit"
|
placeholder="请输入结算金额"
|
v-model="settlementAmount"
|
/>
|
</view>
|
|
<view class="form-item">
|
<view class="form-label">支付方式</view>
|
<picker mode="selector" :range="paymentMethods" @change="onPaymentMethodChange">
|
<view class="form-input picker-input">
|
{{ selectedPaymentMethod || '请选择支付方式' }}
|
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
|
</view>
|
</picker>
|
</view>
|
|
<view class="form-item">
|
<view class="form-label">备注</view>
|
<textarea
|
class="form-textarea"
|
placeholder="请输入备注信息"
|
v-model="remark"
|
/>
|
</view>
|
</view>
|
|
<!-- 支付二维码区域 -->
|
<view v-if="showQRCode" class="qr-code-section">
|
<view class="section-title">请扫码支付</view>
|
<view class="qr-code-container">
|
<image class="qr-code" :src="qrCodeImage" mode="widthFix"></image>
|
<view class="qr-tip">请使用{{ selectedPaymentMethod }}扫码支付</view>
|
</view>
|
<view class="payment-status">
|
<view v-if="paymentStatus === 'pending'" class="status-pending">等待支付...</view>
|
<view v-if="paymentStatus === 'success'" class="status-success">
|
<uni-icons type="checkmarkempty" size="24" color="#4cd964"></uni-icons>
|
支付成功
|
</view>
|
</view>
|
</view>
|
</scroll-view>
|
|
<view class="action-section">
|
<button
|
v-if="!showQRCode || paymentStatus === 'success'"
|
class="submit-btn"
|
@click="saveSettlement"
|
:disabled="!canSave"
|
>
|
保存结算
|
</button>
|
</view>
|
|
<!-- 附加费用弹窗 -->
|
<uni-popup ref="additionalFeesPopup" type="bottom">
|
<view class="popup-content">
|
<view class="popup-header">
|
<text class="header-title">附加费用</text>
|
<view class="close-btn" @click="closeAdditionalFeesPopup">
|
<uni-icons type="close" size="20" color="#999"></uni-icons>
|
</view>
|
</view>
|
|
<!-- 简化版费用添加 -->
|
<view class="simple-fee-section">
|
<view class="form-item">
|
<view class="form-label">费用类型</view>
|
<picker mode="selector" :range="additionalFeeTypeNames" @change="onFeeTypeChange">
|
<view class="form-input picker-input">
|
{{ selectedFeeTypeName || '请选择费用类型' }}
|
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
|
</view>
|
</picker>
|
</view>
|
|
<view class="form-item">
|
<view class="form-label">费用金额</view>
|
<input
|
class="form-input"
|
type="digit"
|
placeholder="请输入费用金额"
|
v-model="newFeePrice"
|
/>
|
</view>
|
|
<view class="add-fee-btn">
|
<button class="confirm-btn" @click="addCustomFee">添加费用</button>
|
</view>
|
</view>
|
|
<!-- 已添加的费用列表 -->
|
<view class="added-fees-list" v-if="selectedAdditionalFees.length > 0">
|
<view class="section-title">已添加费用</view>
|
<view
|
class="fee-item"
|
v-for="(fee, index) in selectedAdditionalFees"
|
:key="index"
|
>
|
<view class="fee-info">
|
<view class="fee-name">{{ fee.name }}</view>
|
<view class="fee-price">¥{{ fee.price }} × {{ fee.quantity }}</view>
|
</view>
|
<view class="fee-total">¥{{ (fee.price * fee.quantity).toFixed(2) }}</view>
|
</view>
|
</view>
|
|
<view class="popup-footer">
|
<button class="confirm-btn" @click="confirmAdditionalFees">确定</button>
|
</view>
|
</view>
|
</uni-popup>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
data() {
|
return {
|
task: {
|
id: 1,
|
taskNo: 'RW20230515001',
|
type: 'emergency',
|
vehicle: '粤A12345',
|
startLocation: '广州市天河区XX路123号',
|
endLocation: '广州市白云区YY路456号'
|
},
|
baseAmount: 1000, // 基础费用
|
additionalAmount: 0, // 附加费用
|
settlementAmount: '', // 结算金额
|
remark: '', // 备注
|
paymentMethods: ['现金', '支付宝', '微信', '挂帐'],
|
selectedPaymentMethod: '',
|
showQRCode: false,
|
paymentStatus: 'pending', // pending, success
|
qrCodeImage: '/static/images/qrcode.png', // 二维码图片路径
|
additionalFeeTypes: [
|
{ name: '担架费', price: 200 },
|
{ name: '等待费', price: 100 },
|
{ name: '善后费', price: 150 },
|
{ name: '夜间服务费', price: 300 },
|
{ name: '长途费', price: 500 }
|
],
|
selectedAdditionalFees: [], // 已选择的附加费用
|
selectedFeeTypeName: '', // 选中的费用类型名称
|
newFeePrice: '' // 新增费用价格
|
}
|
},
|
computed: {
|
totalAmount() {
|
return this.baseAmount + this.additionalAmount;
|
},
|
canSave() {
|
// 现金和挂帐可以直接保存,其他支付方式需要支付成功后才能保存
|
if (!this.settlementAmount || !this.selectedPaymentMethod) {
|
return false;
|
}
|
|
if (this.selectedPaymentMethod === '现金' || this.selectedPaymentMethod === '挂帐') {
|
return true;
|
}
|
|
// 支付宝、微信等需要支付成功
|
return this.paymentStatus === 'success';
|
},
|
// 获取费用类型名称数组
|
additionalFeeTypeNames() {
|
return this.additionalFeeTypes.map(fee => fee.name);
|
}
|
},
|
onLoad(options) {
|
// 实际项目中这里会通过API获取任务详情
|
// const taskId = options.id;
|
// this.getTaskDetail(taskId);
|
},
|
methods: {
|
getTaskTypeText(type) {
|
const typeMap = {
|
'maintenance': '维修保养',
|
'refuel': '加油',
|
'inspection': '巡检',
|
'emergency': '急救转运',
|
'welfare': '福祉车'
|
}
|
return typeMap[type] || '未知类型'
|
},
|
|
onPaymentMethodChange(e) {
|
this.selectedPaymentMethod = this.paymentMethods[e.detail.value];
|
|
// 如果选择支付宝或微信,显示二维码
|
if (this.selectedPaymentMethod === '支付宝' || this.selectedPaymentMethod === '微信') {
|
this.showQRCode = true;
|
this.paymentStatus = 'pending';
|
// 模拟支付状态检查
|
this.checkPaymentStatus();
|
} else {
|
this.showQRCode = false;
|
this.paymentStatus = 'pending';
|
}
|
},
|
|
// 费用类型选择
|
onFeeTypeChange(e) {
|
this.selectedFeeTypeName = this.additionalFeeTypeNames[e.detail.value];
|
},
|
|
checkPaymentStatus() {
|
// 模拟支付状态检查,实际项目中应该通过API轮询检查支付状态
|
setTimeout(() => {
|
// 模拟支付成功
|
this.paymentStatus = 'success';
|
}, 5000);
|
},
|
|
showAdditionalFees() {
|
this.$refs.additionalFeesPopup.open();
|
},
|
|
closeAdditionalFeesPopup() {
|
this.$refs.additionalFeesPopup.close();
|
},
|
|
// 添加自定义费用
|
addCustomFee() {
|
if (!this.selectedFeeTypeName) {
|
this.$modal.showToast('请选择费用类型');
|
return;
|
}
|
|
if (!this.newFeePrice || isNaN(this.newFeePrice) || parseFloat(this.newFeePrice) <= 0) {
|
this.$modal.showToast('请输入有效的费用金额');
|
return;
|
}
|
|
// 查找选中的费用类型信息
|
const selectedFeeType = this.additionalFeeTypes.find(fee => fee.name === this.selectedFeeTypeName);
|
|
// 检查是否已存在同名费用
|
const existingFee = this.selectedAdditionalFees.find(fee => fee.name === this.selectedFeeTypeName);
|
if (existingFee) {
|
existingFee.quantity += 1;
|
} else {
|
this.selectedAdditionalFees.push({
|
name: this.selectedFeeTypeName,
|
price: parseFloat(this.newFeePrice),
|
quantity: 1
|
});
|
}
|
|
// 清空输入框
|
this.selectedFeeTypeName = '';
|
this.newFeePrice = '';
|
|
this.calculateAdditionalAmount();
|
this.$modal.showToast('费用添加成功');
|
},
|
|
calculateAdditionalAmount() {
|
this.additionalAmount = this.selectedAdditionalFees.reduce((total, fee) => {
|
return total + (fee.price * fee.quantity);
|
}, 0);
|
},
|
|
confirmAdditionalFees() {
|
this.calculateAdditionalAmount();
|
this.closeAdditionalFeesPopup();
|
},
|
|
saveSettlement() {
|
if (!this.settlementAmount) {
|
this.$modal.showToast('请输入结算金额');
|
return;
|
}
|
|
if (!this.selectedPaymentMethod) {
|
this.$modal.showToast('请选择支付方式');
|
return;
|
}
|
|
// 检查结算金额是否合理
|
if (parseFloat(this.settlementAmount) > this.totalAmount) {
|
this.$modal.showToast('结算金额不能大于总费用');
|
return;
|
}
|
|
this.$modal.confirm('确定要保存结算信息吗?').then(() => {
|
// 这里应该调用API保存结算信息
|
console.log('结算信息:', {
|
taskId: this.task.id,
|
baseAmount: this.baseAmount,
|
additionalAmount: this.additionalAmount,
|
totalAmount: this.totalAmount,
|
settlementAmount: this.settlementAmount,
|
paymentMethod: this.selectedPaymentMethod,
|
remark: this.remark,
|
additionalFees: this.selectedAdditionalFees
|
});
|
|
this.$modal.showToast('结算信息保存成功');
|
// 返回任务列表
|
this.$tab.navigateBack();
|
}).catch(() => {
|
// 取消操作
|
});
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss">
|
.settlement-container {
|
padding: 20rpx;
|
background-color: #f5f5f5;
|
height: 100vh;
|
display: flex;
|
flex-direction: column;
|
// 隐藏滚动条但保持滚动功能
|
::-webkit-scrollbar {
|
display: none;
|
width: 0 !important;
|
height: 0 !important;
|
background: transparent;
|
}
|
|
// Firefox滚动条隐藏
|
* {
|
scrollbar-width: none; /* Firefox */
|
}
|
|
// IE/Edge滚动条隐藏
|
* {
|
-ms-overflow-style: none; /* IE 10+ */
|
}
|
}
|
|
.settlement-header {
|
background-color: white;
|
border-radius: 15rpx;
|
padding: 30rpx;
|
margin-bottom: 20rpx;
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
flex-shrink: 0;
|
|
.header-title {
|
font-size: 36rpx;
|
font-weight: bold;
|
color: #333;
|
text-align: center;
|
}
|
}
|
|
.settlement-content {
|
flex: 1;
|
|
.task-info-section {
|
background-color: white;
|
border-radius: 15rpx;
|
padding: 30rpx;
|
margin-bottom: 20rpx;
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
.info-item {
|
display: flex;
|
margin-bottom: 20rpx;
|
padding-bottom: 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
&:last-child {
|
margin-bottom: 0;
|
padding-bottom: 0;
|
border-bottom: none;
|
}
|
|
.label {
|
font-size: 28rpx;
|
color: #666;
|
margin-right: 20rpx;
|
white-space: nowrap;
|
width: 150rpx;
|
}
|
|
.value {
|
font-size: 28rpx;
|
flex: 1;
|
word-break: break-all;
|
}
|
}
|
}
|
|
.amount-section {
|
background-color: white;
|
border-radius: 15rpx;
|
padding: 30rpx;
|
margin-bottom: 20rpx;
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
.section-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
margin-bottom: 30rpx;
|
color: #333;
|
}
|
|
.amount-item {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 20rpx;
|
padding-bottom: 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
&:last-child {
|
margin-bottom: 0;
|
padding-bottom: 0;
|
border-bottom: none;
|
}
|
|
&.additional-fees {
|
.value {
|
color: #007AFF;
|
}
|
}
|
|
&.total-amount {
|
.label {
|
font-weight: bold;
|
}
|
|
.value.total {
|
font-weight: bold;
|
font-size: 32rpx;
|
color: #e54d42;
|
}
|
}
|
|
.label {
|
font-size: 28rpx;
|
color: #333;
|
}
|
|
.value {
|
font-size: 28rpx;
|
color: #333;
|
}
|
}
|
}
|
|
.settlement-form {
|
background-color: white;
|
border-radius: 15rpx;
|
padding: 30rpx;
|
margin-bottom: 20rpx;
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
.form-item {
|
margin-bottom: 40rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
|
.form-label {
|
font-size: 28rpx;
|
margin-bottom: 15rpx;
|
color: #333;
|
}
|
|
.form-input {
|
height: 70rpx;
|
padding: 0 20rpx;
|
border: 1rpx solid #eee;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
|
&.picker-input {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
}
|
}
|
|
.form-textarea {
|
width: 100%;
|
min-height: 150rpx;
|
padding: 20rpx;
|
border: 1rpx solid #eee;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
resize: none;
|
}
|
}
|
}
|
|
.qr-code-section {
|
background-color: white;
|
border-radius: 15rpx;
|
padding: 30rpx;
|
margin-bottom: 20rpx;
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
text-align: center;
|
|
.section-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
margin-bottom: 30rpx;
|
color: #333;
|
}
|
|
.qr-code-container {
|
margin-bottom: 30rpx;
|
|
.qr-code {
|
width: 300rpx;
|
height: 300rpx;
|
margin: 0 auto 20rpx;
|
}
|
|
.qr-tip {
|
font-size: 26rpx;
|
color: #666;
|
}
|
}
|
|
.payment-status {
|
.status-pending {
|
font-size: 28rpx;
|
color: #ff9900;
|
}
|
|
.status-success {
|
font-size: 28rpx;
|
color: #4cd964;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
}
|
}
|
}
|
|
.action-section {
|
padding: 20rpx 0;
|
flex-shrink: 0;
|
|
.submit-btn {
|
width: 80%;
|
height: 80rpx;
|
background-color: #007AFF;
|
color: white;
|
border-radius: 10rpx;
|
font-size: 32rpx;
|
margin: 0 auto;
|
display: block;
|
|
&[disabled] {
|
background-color: #ccc;
|
}
|
}
|
}
|
|
.popup-content {
|
background-color: white;
|
border-top-left-radius: 20rpx;
|
border-top-right-radius: 20rpx;
|
padding: 30rpx;
|
max-height: 80vh;
|
|
.popup-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 30rpx;
|
padding-bottom: 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
.header-title {
|
font-size: 36rpx;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.close-btn {
|
padding: 10rpx;
|
}
|
}
|
|
.simple-fee-section {
|
padding: 20rpx 0;
|
border-bottom: 1rpx solid #f0f0f0;
|
margin-bottom: 20rpx;
|
|
.form-item {
|
margin-bottom: 30rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
|
.form-label {
|
font-size: 28rpx;
|
margin-bottom: 15rpx;
|
color: #333;
|
}
|
|
.form-input {
|
height: 70rpx;
|
padding: 0 20rpx;
|
border: 1rpx solid #eee;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
|
&.picker-input {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
}
|
}
|
}
|
|
.add-fee-btn {
|
margin-top: 20rpx;
|
|
.confirm-btn {
|
width: 100%;
|
height: 70rpx;
|
background-color: #007AFF;
|
color: white;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
}
|
}
|
}
|
|
.added-fees-list {
|
margin-bottom: 30rpx;
|
|
.section-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
margin-bottom: 20rpx;
|
color: #333;
|
}
|
|
.fee-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 20rpx 0;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
&:last-child {
|
border-bottom: none;
|
}
|
|
.fee-info {
|
.fee-name {
|
font-size: 28rpx;
|
color: #333;
|
margin-bottom: 10rpx;
|
}
|
|
.fee-price {
|
font-size: 26rpx;
|
color: #666;
|
}
|
}
|
|
.fee-total {
|
font-size: 28rpx;
|
font-weight: bold;
|
color: #e54d42;
|
}
|
}
|
}
|
|
.popup-footer {
|
.confirm-btn {
|
width: 100%;
|
height: 80rpx;
|
background-color: #007AFF;
|
color: white;
|
border-radius: 10rpx;
|
font-size: 32rpx;
|
}
|
}
|
}
|
</style>
|