From 668e570bd1db6bd00e4293b6977e6d3d051053ce Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期四, 27 十一月 2025 00:07:46 +0800
Subject: [PATCH] feat: 修改app录入界面及车辆用户同步

---
 app/pages/task/settlement.vue |  832 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 703 insertions(+), 129 deletions(-)

diff --git a/app/pages/task/settlement.vue b/app/pages/task/settlement.vue
index 865269b..920ef2f 100644
--- a/app/pages/task/settlement.vue
+++ b/app/pages/task/settlement.vue
@@ -13,7 +13,7 @@
         
         <view class="info-item">
           <view class="label">浠诲姟绫诲瀷:</view>
-          <view class="value">{{ getTaskTypeText(task.type) }}</view>
+          <view class="value">{{ taskTypeText }}</view>
         </view>
         
         <view class="info-item">
@@ -51,6 +51,40 @@
           <view class="label">鎬昏垂鐢�:</view>
           <view class="value total">楼{{ totalAmount }}</view>
         </view>
+        
+        <view class="amount-item paid-amount" v-if="paidAmount > 0">
+          <view class="label">宸叉敮浠�:</view>
+          <view class="value" style="color: #34C759;">楼{{ paidAmount }}</view>
+        </view>
+        
+        <view class="amount-item remaining-amount" v-if="paidAmount > 0">
+          <view class="label">鍓╀綑鏈粯:</view>
+          <view class="value" style="color: #ff9900; font-weight: bold;">楼{{ remainingAmount }}</view>
+        </view>
+      </view>
+      
+      <!-- 宸叉敮浠樿褰曞垪琛� -->
+      <view class="payment-history-section" v-if="paidPaymentList.length > 0">
+        <view class="section-title">鏀粯璁板綍</view>
+        <view 
+          class="payment-item" 
+          v-for="payment in paidPaymentList" 
+          :key="payment.id"
+        >
+          <view class="payment-info">
+            <view class="payment-method">
+              <text class="method-tag" :class="['method-' + payment.paymentMethod.toLowerCase()]">
+                {{ getPaymentMethodText(payment.paymentMethod) }}
+              </text>
+            </view>
+            <view class="payment-time">
+              {{ formatPaymentTime(payment.payTime) }}
+            </view>
+          </view>
+          <view class="payment-amount">
+            楼{{ payment.settlementAmount }}
+          </view>
+        </view>
       </view>
       
       <view class="settlement-form">
@@ -80,25 +114,11 @@
             class="form-textarea" 
             placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" 
             v-model="remark"
-          />
+          ></textarea>
         </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">
@@ -111,6 +131,57 @@
         淇濆瓨缁撶畻
       </button>
     </view>
+    
+    <!-- 鏀粯浜岀淮鐮佸脊绐� -->
+    <uni-popup ref="qrCodePopup" type="center" :mask-click="false">
+      <view class="qr-popup-content">
+        <view class="qr-popup-header">
+          <text class="qr-popup-title">{{ selectedPaymentMethod }}鏀粯</text>
+        </view>
+        
+        <view class="qr-popup-body">
+          <view class="qr-code-box" v-if="qrCodeImage">
+            <image class="qr-image" :src="qrCodeImage" mode="widthFix"></image>
+          </view>
+          
+          <view class="qr-loading" v-else>
+            <uni-icons type="spinner-cycle" size="40" color="#007AFF"></uni-icons>
+            <text class="loading-text">姝e湪鐢熸垚浜岀淮鐮�...</text>
+          </view>
+          
+          <view class="qr-tip-text">璇蜂娇鐢▄{ selectedPaymentMethod }}鎵爜鏀粯</view>
+          <view class="qr-amount">楼{{ settlementAmount }}</view>
+          
+          <view class="payment-status-box">
+            <view v-if="paymentStatus === 'pending'" class="status-waiting">
+              <uni-icons type="spinner-cycle" size="20" color="#ff9900"></uni-icons>
+              <text>绛夊緟鏀粯涓�...</text>
+            </view>
+            <view v-if="paymentStatus === 'success'" class="status-paid">
+              <uni-icons type="checkmarkempty" size="24" color="#4cd964"></uni-icons>
+              <text>鏀粯鎴愬姛</text>
+            </view>
+          </view>
+        </view>
+        
+        <view class="qr-popup-footer">
+          <button 
+            class="cancel-pay-btn" 
+            @click="cancelPayment"
+            v-if="paymentStatus !== 'success'"
+          >
+            鍙栨秷鏀粯
+          </button>
+          <button 
+            class="confirm-pay-btn" 
+            @click="confirmPaymentSuccess"
+            v-if="paymentStatus === 'success'"
+          >
+            纭畾
+          </button>
+        </view>
+      </view>
+    </uni-popup>
     
     <!-- 闄勫姞璐圭敤寮圭獥 -->
     <uni-popup ref="additionalFeesPopup" type="bottom">
@@ -150,18 +221,23 @@
         </view>
         
         <!-- 宸叉坊鍔犵殑璐圭敤鍒楄〃 -->
-        <view class="added-fees-list" v-if="selectedAdditionalFees.length > 0">
+        <view class="added-fees-list" v-if="additionalFeeList.length > 0">
           <view class="section-title">宸叉坊鍔犺垂鐢�</view>
           <view 
             class="fee-item" 
-            v-for="(fee, index) in selectedAdditionalFees" 
-            :key="index"
+            v-for="fee in additionalFeeList" 
+            :key="fee.id"
           >
             <view class="fee-info">
-              <view class="fee-name">{{ fee.name }}</view>
-              <view class="fee-price">楼{{ fee.price }} 脳 {{ fee.quantity }}</view>
+              <view class="fee-name">{{ fee.feeName }}</view>
+              <view class="fee-price">楼{{ fee.unitAmount }} 脳 {{ fee.quantity }}</view>
             </view>
-            <view class="fee-total">楼{{ (fee.price * fee.quantity).toFixed(2) }}</view>
+            <view class="fee-actions">
+              <view class="fee-total">楼{{ fee.totalAmount }}</view>
+              <view class="delete-btn" @click="removeFee(fee.id)" v-if="!paySuccess">
+                <uni-icons type="trash" size="20" color="#e54d42"></uni-icons>
+              </view>
+            </view>
           </view>
         </view>
         
@@ -174,103 +250,321 @@
 </template>
 
 <script>
+import { getPaymentInfo, addAdditionalFee, removeAdditionalFee, createPayment, getPaymentStatus } from '@/api/payment'
+import { getTask } from '@/api/task'
+
   export default {
     data() {
       return {
-        task: {
-          id: 1,
-          taskNo: 'RW20230515001',
-          type: 'emergency',
-          vehicle: '绮12345',
-          startLocation: '骞垮窞甯傚ぉ娌冲尯XX璺�123鍙�',
-          endLocation: '骞垮窞甯傜櫧浜戝尯YY璺�456鍙�'
-        },
-        baseAmount: 1000, // 鍩虹璐圭敤
-        additionalAmount: 0, // 闄勫姞璐圭敤
+        taskId: null,
+        task: {},
+        baseAmount: 0, // 鍩虹璐圭敤(鎴愪氦浠�)
+        additionalAmount: 0, // 闄勫姞璐圭敤姹囨��
         settlementAmount: '', // 缁撶畻閲戦
         remark: '', // 澶囨敞
-        paymentMethods: ['鐜伴噾', '鏀粯瀹�', '寰俊', '鎸傚笎'],
+        paymentMethods: [], // 浠庡瓧鍏稿姞杞芥敮浠樻柟寮�
+        paymentMethodDict: [], // 瀛楀吀鍘熷鏁版嵁
         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: [], // 宸查�夋嫨鐨勯檮鍔犺垂鐢�
+        qrCodeImage: '', // 浜岀淮鐮佸浘鐗囪矾寰�
+        paymentId: null,
+        pollTimer: null, // 杞瀹氭椂鍣�
+        additionalFeeTypes: [], // 浠庡瓧鍏稿姞杞�
+        additionalFeeList: [], // 宸叉坊鍔犵殑闄勫姞璐圭敤鍒楄〃
         selectedFeeTypeName: '', // 閫変腑鐨勮垂鐢ㄧ被鍨嬪悕绉�
-        newFeePrice: '' // 鏂板璐圭敤浠锋牸
+        selectedFeeTypeValue: '', // 閫変腑鐨勮垂鐢ㄧ被鍨嬪��
+        newFeePrice: '', // 鏂板璐圭敤浠锋牸
+        loading: false,
+        paySuccess: false, // 鏀粯鎴愬姛鏍囪
+        paidAmount: 0, // 宸叉敮浠橀噾棰�
+        paidPaymentList: [] // 宸叉敮浠樿褰曞垪琛�
       }
     },
     computed: {
       totalAmount() {
         return this.baseAmount + this.additionalAmount;
       },
+      // 鍓╀綑鏈敮浠橀噾棰�
+      remainingAmount() {
+        return this.totalAmount - this.paidAmount;
+      },
+      // 浠诲姟绫诲瀷鏄剧ず
+      taskTypeText() {
+        const typeMap = {
+          'EMERGENCY_TRANSFER': '鎬ユ晳杞繍',
+          'SCHEDULED_TRANSFER': '璁″垝杞繍',
+          'EMERGENCY_RESCUE': '鎬ユ晳鎶㈡晳',
+          'ORDINARY_TASK': '鏅�氫换鍔�'
+        }
+        return typeMap[this.task.type] || this.task.type
+      },
       canSave() {
-        // 鐜伴噾鍜屾寕甯愬彲浠ョ洿鎺ヤ繚瀛橈紝鍏朵粬鏀粯鏂瑰紡闇�瑕佹敮浠樻垚鍔熷悗鎵嶈兘淇濆瓨
+        // 宸插叏棰濇敮浠樺悗涓嶈兘鍐嶆淇濆瓨
+        if (this.remainingAmount <= 0) {
+          return false
+        }
+        
         if (!this.settlementAmount || !this.selectedPaymentMethod) {
-          return false;
+          return false
         }
         
-        if (this.selectedPaymentMethod === '鐜伴噾' || this.selectedPaymentMethod === '鎸傚笎') {
-          return true;
+        const amount = parseFloat(this.settlementAmount)
+        
+        // 鏍¢獙缁撶畻閲戦蹇呴』澶т簬0涓斾笉瓒呰繃鍓╀綑閲戦
+        if (amount <= 0 || amount > this.remainingAmount) {
+          return false
         }
         
-        // 鏀粯瀹濄�佸井淇$瓑闇�瑕佹敮浠樻垚鍔�
-        return this.paymentStatus === 'success';
+        const dictValue = this.getPaymentMethodValue(this.selectedPaymentMethod)
+        
+        // 1-鐜伴噾, 6-鎸傝处, 7-鏄撳尰閫氭寕璐� 鍙互鐩存帴淇濆瓨
+        if (dictValue === '1' || dictValue === '6' || dictValue === '7') {
+          return true
+        }
+        
+        // 3-寰俊鏀粯, 4-鏀粯瀹� 闇�瑕佹敮浠樻垚鍔熷悗鎵嶈兘淇濆瓨
+        if (dictValue === '3' || dictValue === '4') {
+          return this.paymentStatus === 'success'
+        }
+        
+        // 2-閾惰杞处, 5-POS鏀舵 鐩存帴淇濆瓨
+        return true
       },
       // 鑾峰彇璐圭敤绫诲瀷鍚嶇О鏁扮粍
       additionalFeeTypeNames() {
-        return this.additionalFeeTypes.map(fee => fee.name);
+        return this.additionalFeeTypes.map(fee => fee.dictLabel);
       }
     },
     onLoad(options) {
-      // 瀹為檯椤圭洰涓繖閲屼細閫氳繃API鑾峰彇浠诲姟璇︽儏
-      // const taskId = options.id;
-      // this.getTaskDetail(taskId);
+      if (options.taskId) {
+        this.taskId = options.taskId
+        this.loadPaymentMethods() // 鍔犺浇鏀粯鏂瑰紡瀛楀吀
+        this.loadPaymentInfo()
+        this.loadFeeTypes()
+      } else {
+        this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
+        setTimeout(() => {
+          uni.navigateBack()
+        }, 1500)
+      }
+    },
+    onUnload() {
+      // 娓呴櫎杞瀹氭椂鍣�
+      if (this.pollTimer) {
+        clearInterval(this.pollTimer)
+      }
     },
     methods: {
-      getTaskTypeText(type) {
-        const typeMap = {
-          'maintenance': '缁翠慨淇濆吇',
-          'refuel': '鍔犳补',
-          'inspection': '宸℃',
-          'emergency': '鎬ユ晳杞繍',
-          'welfare': '绂忕杞�'
-        }
-        return typeMap[type] || '鏈煡绫诲瀷'
+      // 鍔犺浇鏀粯鏂瑰紡瀛楀吀
+      loadPaymentMethods() {
+        this.$dict.getDicts('task_payment_method').then(res => {
+          // 杩囨护鎺夐��娆�(8)鍜岀Н鍒�(9)锛屽彧鏄剧ず1-7
+          this.paymentMethodDict = (res.data || []).filter(item => {
+            const value = parseInt(item.dictValue)
+            return value >= 1 && value <= 7
+          })
+          // 鎻愬彇鏄剧ず鍚嶇О鏁扮粍鐢ㄤ簬picker
+          this.paymentMethods = this.paymentMethodDict.map(item => item.dictLabel)
+        }).catch(err => {
+          console.error('鍔犺浇鏀粯鏂瑰紡瀛楀吀澶辫触', err)
+          this.$modal.showToast('鍔犺浇鏀粯鏂瑰紡澶辫触')
+        })
+      },
+      
+      // 鏍规嵁閫変腑鐨勫悕绉拌幏鍙栧瓧鍏稿��
+      getPaymentMethodValue(label) {
+        const method = this.paymentMethodDict.find(item => item.dictLabel === label)
+        return method ? method.dictValue : ''
+      },
+      
+      // 鍔犺浇鏀粯淇℃伅
+      loadPaymentInfo() {
+        this.loading = true
+        getPaymentInfo(this.taskId).then(res => {
+          const data = res.data
+          
+          // 浠诲姟鍩烘湰淇℃伅
+          this.task = {
+            taskNo: data.taskCode || '',
+            type: data.taskType || '',
+            vehicle: data.vehicleInfo || '鏈垎閰�',
+            startLocation: data.departureAddress || '鏈缃�',
+            endLocation: data.destinationAddress || '鏈缃�'
+          }
+          
+          // 璐圭敤淇℃伅
+          this.baseAmount = data.transferPrice || 0
+          this.additionalAmount = data.additionalAmount || 0
+          this.additionalFeeList = data.additionalFees || []
+          this.paidAmount = data.paidAmount || 0
+          this.paidPaymentList = data.paidPayments || [] // 鍔犺浇宸叉敮浠樿褰曞垪琛�
+          
+          // 榛樿缁撶畻閲戦涓哄墿浣欐湭鏀粯閲戦
+          const remaining = (data.totalAmount || 0) - this.paidAmount
+          this.settlementAmount = remaining > 0 ? remaining.toString() : ''
+          
+          // 濡傛灉宸插叏棰濇敮浠橈紝鎻愮ず宸茬粨绠�
+          if (remaining <= 0) {
+            this.paySuccess = true
+            this.$modal.showToast('璇ヤ换鍔″凡缁撶畻')
+          }
+          
+          this.loading = false
+        }).catch(err => {
+          console.error('鍔犺浇鏀粯淇℃伅澶辫触', err)
+          this.loading = false
+          this.$modal.showToast('鍔犺浇鏀粯淇℃伅澶辫触')
+        })
+      },
+      
+      // 鍔犺浇璐圭敤绫诲瀷瀛楀吀
+      loadFeeTypes() {
+        this.$dict.getDicts('task_additional_fee_type').then(res => {
+          this.additionalFeeTypes = res.data || []
+        })
       },
       
       onPaymentMethodChange(e) {
-        this.selectedPaymentMethod = this.paymentMethods[e.detail.value];
+        this.selectedPaymentMethod = this.paymentMethods[e.detail.value]
+        const dictValue = this.getPaymentMethodValue(this.selectedPaymentMethod)
         
-        // 濡傛灉閫夋嫨鏀粯瀹濇垨寰俊锛屾樉绀轰簩缁寸爜
-        if (this.selectedPaymentMethod === '鏀粯瀹�' || this.selectedPaymentMethod === '寰俊') {
-          this.showQRCode = true;
-          this.paymentStatus = 'pending';
-          // 妯℃嫙鏀粯鐘舵�佹鏌�
-          this.checkPaymentStatus();
+        // 3-寰俊鏀粯, 4-鏀粯瀹�
+        if (dictValue === '3' || dictValue === '4') {
+          this.openQRCodePopup(dictValue)
         } else {
-          this.showQRCode = false;
-          this.paymentStatus = 'pending';
+          // 鍏朵粬鏀粯鏂瑰紡涓嶆樉绀轰簩缁寸爜
+          this.showQRCode = false
+          this.paymentStatus = 'pending'
         }
+      },
+      
+      // 鎵撳紑鏀粯浜岀淮鐮佸脊绐�
+      openQRCodePopup(dictValue) {
+        // 閲嶇疆鐘舵��
+        this.qrCodeImage = ''
+        this.paymentStatus = 'pending'
+        this.showQRCode = true
+        
+        // 鎵撳紑寮圭獥
+        this.$refs.qrCodePopup.open()
+        
+        // 鐢熸垚浜岀淮鐮�
+        this.generateQRCode(dictValue)
+      },
+      
+      // 鍙栨秷鏀粯
+      cancelPayment() {
+        // 娓呴櫎杞
+        if (this.pollTimer) {
+          clearInterval(this.pollTimer);
+          this.pollTimer = null;
+        }
+        
+        // 鍏抽棴寮圭獥
+        this.$refs.qrCodePopup.close();
+        
+        // 閲嶇疆鐘舵��
+        this.selectedPaymentMethod = '';
+        this.showQRCode = false;
+        this.qrCodeImage = '';
+        this.paymentStatus = 'pending';
+      },
+      
+      // 纭鏀粯鎴愬姛
+      confirmPaymentSuccess() {
+        // 鍏抽棴寮圭獥
+        this.$refs.qrCodePopup.close();
+        
+        // 閲嶆柊鍔犺浇鏀粯淇℃伅锛屽埛鏂版樉绀�
+        this.loadPaymentInfo();
+        
+        // 閲嶇疆鐘舵�侊紝鍑嗗涓嬩竴绗旀敮浠�
+        this.selectedPaymentMethod = '';
+        this.showQRCode = false;
+        this.qrCodeImage = '';
+        this.paymentStatus = 'pending';
+        this.remark = '';
+        // settlementAmount 浼氬湪 loadPaymentInfo 涓嚜鍔ㄨ缃负鍓╀綑閲戦
+      },
+      
+      // 鐢熸垚鏀粯浜岀淮鐮�
+      generateQRCode(paymentMethod) {
+        // 鏍¢獙缁撶畻閲戦
+        if (!this.settlementAmount) {
+          this.$modal.showToast('璇峰厛杈撳叆缁撶畻閲戦');
+          this.$refs.qrCodePopup.close();
+          this.selectedPaymentMethod = '';
+          return;
+        }
+        
+        const amount = parseFloat(this.settlementAmount);
+        if (amount <= 0) {
+          this.$modal.showToast('缁撶畻閲戦蹇呴』澶т簬0');
+          this.$refs.qrCodePopup.close();
+          this.selectedPaymentMethod = '';
+          return;
+        }
+        
+        if (amount > this.remainingAmount) {
+          this.$modal.showToast(`缁撶畻閲戦涓嶈兘瓒呰繃鍓╀綑閲戦楼${this.remainingAmount}`);
+          this.$refs.qrCodePopup.close();
+          this.selectedPaymentMethod = '';
+          return;
+        }
+        
+        const data = {
+          taskId: this.taskId,
+          paymentMethod: paymentMethod,
+          settlementAmount: amount,
+          remark: this.remark
+        };
+        
+        createPayment(data).then(res => {
+          const result = res.data;
+          this.paymentId = result.paymentId;
+          this.qrCodeImage = result.codeUrl;
+          this.paymentStatus = 'pending';
+          
+          // 寮�濮嬭疆璇㈡敮浠樼姸鎬�
+          this.checkPaymentStatus();
+        }).catch(err => {
+          console.error('鐢熸垚鏀粯浜岀淮鐮佸け璐�', err);
+          this.$modal.showToast('鐢熸垚鏀粯浜岀淮鐮佸け璐�');
+          this.$refs.qrCodePopup.close();
+          this.selectedPaymentMethod = '';
+        });
       },
       
       // 璐圭敤绫诲瀷閫夋嫨
       onFeeTypeChange(e) {
-        this.selectedFeeTypeName = this.additionalFeeTypeNames[e.detail.value];
+        const index = e.detail.value
+        this.selectedFeeTypeName = this.additionalFeeTypes[index].dictLabel
+        this.selectedFeeTypeValue = this.additionalFeeTypes[index].dictValue
       },
       
+      // 杞妫�鏌ユ敮浠樼姸鎬�
       checkPaymentStatus() {
-        // 妯℃嫙鏀粯鐘舵�佹鏌ワ紝瀹為檯椤圭洰涓簲璇ラ�氳繃API杞妫�鏌ユ敮浠樼姸鎬�
-        setTimeout(() => {
-          // 妯℃嫙鏀粯鎴愬姛
-          this.paymentStatus = 'success';
-        }, 5000);
+        if (this.pollTimer) {
+          clearInterval(this.pollTimer);
+        }
+        
+        this.pollTimer = setInterval(() => {
+          getPaymentStatus(this.taskId, this.paymentId).then(res => {
+            const data = res.data;
+            if (data.payStatus === 'PAID') {
+              // 鏀粯鎴愬姛
+              this.paymentStatus = 'success';
+              clearInterval(this.pollTimer);
+              this.pollTimer = null;
+              
+              // 鍦ㄥ脊绐椾腑鏄剧ず鏀粯鎴愬姛鐘舵��
+              // 鐢ㄦ埛闇�瑕佺偣鍑�"纭畾"鎸夐挳鏉ュ叧闂脊绐楀苟鍒锋柊椤甸潰
+            }
+          }).catch(err => {
+            console.error('鏌ヨ鏀粯鐘舵�佸け璐�', err);
+          });
+        }, 2000); // 姣�2绉掕疆璇竴娆�
       },
       
       showAdditionalFees() {
@@ -293,76 +587,151 @@
           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
-          });
+        // 璋冪敤鎺ュ彛娣诲姞闄勫姞璐圭敤
+        const data = {
+          taskId: this.taskId,
+          feeType: this.selectedFeeTypeValue,
+          feeName: this.selectedFeeTypeName,
+          unitAmount: parseFloat(this.newFeePrice),
+          quantity: 1,
+          remark: ''
         }
         
-        // 娓呯┖杈撳叆妗�
-        this.selectedFeeTypeName = '';
-        this.newFeePrice = '';
-        
-        this.calculateAdditionalAmount();
-        this.$modal.showToast('璐圭敤娣诲姞鎴愬姛');
+        addAdditionalFee(data).then(res => {
+          this.$modal.showToast('璐圭敤娣诲姞鎴愬姛')
+          
+          // 娓呯┖杈撳叆妗�
+          this.selectedFeeTypeName = ''
+          this.selectedFeeTypeValue = ''
+          this.newFeePrice = ''
+          
+          // 閲嶆柊鍔犺浇鏀粯淇℃伅
+          this.loadPaymentInfo()
+        }).catch(err => {
+          console.error('娣诲姞璐圭敤澶辫触', err)
+          this.$modal.showToast('娣诲姞璐圭敤澶辫触')
+        })
       },
       
-      calculateAdditionalAmount() {
-        this.additionalAmount = this.selectedAdditionalFees.reduce((total, fee) => {
-          return total + (fee.price * fee.quantity);
-        }, 0);
+      // 鍒犻櫎闄勫姞璐圭敤
+      removeFee(feeId) {
+        this.$modal.confirm('纭畾瑕佸垹闄よ璐圭敤鍚楋紵').then(() => {
+          removeAdditionalFee({ taskId: this.taskId, feeId }).then(res => {
+            this.$modal.showToast('鍒犻櫎鎴愬姛')
+            // 閲嶆柊鍔犺浇鏀粯淇℃伅
+            this.loadPaymentInfo()
+          }).catch(err => {
+            console.error('鍒犻櫎璐圭敤澶辫触', err)
+            this.$modal.showToast('鍒犻櫎璐圭敤澶辫触')
+          })
+        }).catch(() => {})
       },
       
       confirmAdditionalFees() {
-        this.calculateAdditionalAmount();
         this.closeAdditionalFeesPopup();
+      },
+      
+      // 鑾峰彇鏀粯鏂瑰紡鏂囨湰
+      getPaymentMethodText(dictValue) {
+        const method = this.paymentMethodDict.find(item => item.dictValue === dictValue)
+        return method ? method.dictLabel : dictValue
+      },
+      
+      // 鏍煎紡鍖栨敮浠樻椂闂�
+      formatPaymentTime(time) {
+        if (!time) return '鏈煡'
+        const date = new Date(time)
+        const year = date.getFullYear()
+        const month = String(date.getMonth() + 1).padStart(2, '0')
+        const day = String(date.getDate()).padStart(2, '0')
+        const hour = String(date.getHours()).padStart(2, '0')
+        const minute = String(date.getMinutes()).padStart(2, '0')
+        return `${year}-${month}-${day} ${hour}:${minute}`
       },
       
       saveSettlement() {
         if (!this.settlementAmount) {
-          this.$modal.showToast('璇疯緭鍏ョ粨绠楅噾棰�');
-          return;
+          this.$modal.showToast('璇疯緭鍏ョ粨绠楅噾棰�')
+          return
         }
         
         if (!this.selectedPaymentMethod) {
-          this.$modal.showToast('璇烽�夋嫨鏀粯鏂瑰紡');
-          return;
+          this.$modal.showToast('璇烽�夋嫨鏀粯鏂瑰紡')
+          return
         }
         
-        // 妫�鏌ョ粨绠楅噾棰濇槸鍚﹀悎鐞�
-        if (parseFloat(this.settlementAmount) > this.totalAmount) {
-          this.$modal.showToast('缁撶畻閲戦涓嶈兘澶т簬鎬昏垂鐢�');
-          return;
+        const amount = parseFloat(this.settlementAmount)
+        
+        // 鏍¢獙缁撶畻閲戦蹇呴』澶т簬0
+        if (amount <= 0) {
+          this.$modal.showToast('缁撶畻閲戦蹇呴』澶т簬0')
+          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(() => {
-          // 鍙栨秷鎿嶄綔
-        });
+        // 鏍¢獙缁撶畻閲戦涓嶈兘瓒呰繃鍓╀綑閲戦
+        if (amount > this.remainingAmount) {
+          this.$modal.showToast(`缁撶畻閲戦涓嶈兘瓒呰繃鍓╀綑閲戦楼${this.remainingAmount}`)
+          return
+        }
+        
+        const dictValue = this.getPaymentMethodValue(this.selectedPaymentMethod)
+        
+        // 3-寰俊鏀粯, 4-鏀粯瀹� 宸茬粡鍦ㄩ�夋嫨鏃剁敓鎴愪簡浜岀淮鐮侊紝绛夊緟鏀粯瀹屾垚
+        if (dictValue === '3' || dictValue === '4') {
+          if (this.paymentStatus !== 'success') {
+            this.$modal.showToast('璇峰厛瀹屾垚鎵爜鏀粯')
+            return
+          }
+        }
+        
+        // 1-鐜伴噾, 2-閾惰杞处, 5-POS鏀舵, 6-鎸傝处, 7-鏄撳尰閫氭寕璐� 闇�瑕佸垱寤烘敮浠樿褰�
+        if (dictValue === '1' || dictValue === '2' || dictValue === '5' || dictValue === '6' || dictValue === '7') {
+          this.$modal.confirm('纭畾瑕佷繚瀛樼粨绠椾俊鎭悧锛�').then(() => {
+            const data = {
+              taskId: this.taskId,
+              paymentMethod: dictValue,
+              settlementAmount: amount,
+              remark: this.remark
+            }
+            
+            this.loading = true
+            createPayment(data).then(res => {
+              this.loading = false
+              const result = res.data
+              this.paymentId = result.paymentId
+              this.paymentStatus = 'success'
+              
+              // 閲嶆柊鍔犺浇鏀粯淇℃伅浠ヨ幏鍙栨渶鏂扮殑宸叉敮浠橀噾棰�
+              this.loadPaymentInfo()
+              
+              // 妫�鏌ユ槸鍚﹀叏棰濇敮浠橈紙浣跨敤鏈�鏂版暟鎹垽鏂級
+              setTimeout(() => {
+                if (this.remainingAmount <= 0) {
+                  this.paySuccess = true
+                  this.$modal.showToast('鏀粯鎴愬姛锛屽凡鍏ㄩ缁撶畻')
+                  setTimeout(() => {
+                    uni.navigateBack()
+                  }, 1500)
+                } else {
+                  this.$modal.showToast(`鏀粯鎴愬姛锛屽墿浣櫬�${this.remainingAmount.toFixed(2)}`)
+                  // 閲嶇疆琛ㄥ崟锛屽噯澶囦笅涓�绗旀敮浠�
+                  this.selectedPaymentMethod = ''
+                  this.remark = ''
+                }
+              }, 300) // 绛夊緟鏁版嵁鍔犺浇瀹屾垚
+            }).catch(err => {
+              this.loading = false
+              console.error('鍒涘缓鏀粯澶辫触', err)
+              this.$modal.showToast('鍒涘缓鏀粯澶辫触')
+            })
+          }).catch(() => {
+            // 鍙栨秷鎿嶄綔
+          })
+        } else {
+          // 鎵爜鏀粯锛堝井淇�/鏀粯瀹濓級鐨勬儏鍐典笉搴旇璧板埌杩欓噷
+          // 鍥犱负鎵爜鏀粯鍦� confirmPaymentSuccess 涓鐞�
+          this.$modal.showToast('璇峰厛瀹屾垚鎵爜鏀粯')
+        }
       }
     }
   }
@@ -505,6 +874,76 @@
       }
     }
     
+    .payment-history-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: 20rpx;
+        color: #333;
+      }
+      
+      .payment-item {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 20rpx 0;
+        border-bottom: 1rpx solid #f0f0f0;
+        
+        &:last-child {
+          border-bottom: none;
+        }
+        
+        .payment-info {
+          flex: 1;
+          
+          .payment-method {
+            margin-bottom: 10rpx;
+            
+            .method-tag {
+              display: inline-block;
+              padding: 4rpx 12rpx;
+              border-radius: 6rpx;
+              font-size: 24rpx;
+              color: white;
+              
+              &.method-cash {
+                background-color: #34C759;
+              }
+              
+              &.method-on_account {
+                background-color: #ff9500;
+              }
+              
+              &.method-wechat {
+                background-color: #09BB07;
+              }
+              
+              &.method-alipay {
+                background-color: #1677FF;
+              }
+            }
+          }
+          
+          .payment-time {
+            font-size: 24rpx;
+            color: #999;
+          }
+        }
+        
+        .payment-amount {
+          font-size: 32rpx;
+          font-weight: bold;
+          color: #34C759;
+        }
+      }
+    }
+    
     .settlement-form {
       background-color: white;
       border-radius: 15rpx;
@@ -618,6 +1057,130 @@
     }
   }
   
+  // 鏀粯浜岀淮鐮佸脊绐楁牱寮�
+  .qr-popup-content {
+    width: 600rpx;
+    background-color: white;
+    border-radius: 20rpx;
+    overflow: hidden;
+    
+    .qr-popup-header {
+      padding: 40rpx 30rpx 30rpx;
+      text-align: center;
+      border-bottom: 1rpx solid #f0f0f0;
+      
+      .qr-popup-title {
+        font-size: 36rpx;
+        font-weight: bold;
+        color: #333;
+      }
+    }
+    
+    .qr-popup-body {
+      padding: 40rpx 30rpx;
+      text-align: center;
+      
+      .qr-code-box {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-bottom: 30rpx;
+        
+        .qr-image {
+          width: 400rpx;
+          height: 400rpx;
+          border: 2rpx solid #f0f0f0;
+          border-radius: 10rpx;
+          padding: 20rpx;
+          box-sizing: border-box;
+        }
+      }
+      
+      .qr-loading {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        height: 400rpx;
+        margin-bottom: 30rpx;
+        
+        .loading-text {
+          margin-top: 20rpx;
+          font-size: 28rpx;
+          color: #999;
+        }
+      }
+      
+      .qr-tip-text {
+        font-size: 28rpx;
+        color: #666;
+        margin-bottom: 20rpx;
+      }
+      
+      .qr-amount {
+        font-size: 48rpx;
+        font-weight: bold;
+        color: #e54d42;
+        margin-bottom: 30rpx;
+      }
+      
+      .payment-status-box {
+        padding: 20rpx;
+        border-radius: 10rpx;
+        
+        .status-waiting {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          gap: 10rpx;
+          font-size: 28rpx;
+          color: #ff9900;
+          
+          text {
+            margin-left: 10rpx;
+          }
+        }
+        
+        .status-paid {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          gap: 10rpx;
+          font-size: 32rpx;
+          color: #4cd964;
+          font-weight: bold;
+          
+          text {
+            margin-left: 10rpx;
+          }
+        }
+      }
+    }
+    
+    .qr-popup-footer {
+      padding: 20rpx 30rpx 30rpx;
+      
+      .cancel-pay-btn,
+      .confirm-pay-btn {
+        width: 100%;
+        height: 80rpx;
+        border-radius: 10rpx;
+        font-size: 32rpx;
+        border: none;
+      }
+      
+      .cancel-pay-btn {
+        background-color: #f5f5f5;
+        color: #666;
+      }
+      
+      .confirm-pay-btn {
+        background-color: #4cd964;
+        color: white;
+      }
+    }
+  }
+  
   .popup-content {
     background-color: white;
     border-top-left-radius: 20rpx;
@@ -713,6 +1276,7 @@
         }
         
         .fee-info {
+          flex: 1;
           .fee-name {
             font-size: 28rpx;
             color: #333;
@@ -725,11 +1289,21 @@
           }
         }
         
+        .fee-actions {
+          display: flex;
+          align-items: center;
+          gap: 20rpx;
+        }
+        
         .fee-total {
           font-size: 28rpx;
           font-weight: bold;
           color: #e54d42;
         }
+        
+        .delete-btn {
+          padding: 10rpx;
+        }
       }
     }
     

--
Gitblit v1.9.1