| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243 |
- <template>
- <view class="page-three-container">
- <!-- 支付信息卡片 -->
- <view class="info-card">
- <view class="info-card-title">支付信息</view>
- <up-row class="info-row" justify="space-between">
- <up-col span="5.8">
- <view class="info-label">开户人</view>
- <up-input v-model="paymentInfo.customName" placeholder="请输入开户人姓名" class="info-input"
- @blur="handleCustomNameInput" />
- </up-col>
- <up-col span="5.8">
- <view class="info-label">银行名称</view>
- <up-input v-model="paymentInfo.bankName" placeholder="请输入银行名称" class="info-input" :disabled="isAlipayPayment"
- @blur="handleBankNameInput" />
- </up-col>
- </up-row>
- <up-row class="info-row">
- <up-col span="12">
- <view class="info-label">{{ bankAccountLabel }}</view>
- <up-input v-model="paymentInfo.bankAccount" :placeholder="bankAccountPlaceholder" class="info-input"
- :type="isAlipayPayment ? 'text' : 'number'" @input="handleBankAccountInput" @blur="handleBankAccountBlur" />
- </up-col>
- </up-row>
- <up-row class="info-row">
- <up-col span="12">
- <view class="info-label">身份证号</view>
- <up-input v-model="paymentInfo.idNumber" placeholder="请输入身份证号" class="info-input"
- @blur="handleIdNumberInput" />
- </up-col>
- </up-row>
- <up-row class="info-row">
- <up-col span="12">
- <view class="info-label">支付方式选择</view>
- <up-radio-group iconPlacement="left" v-model="paymentMethodRadio" placement="column"
- @change="handlePaymentMethodRadioChange">
- <up-radio shape="circle" label="小葫芦线上支付" name="online" :customStyle="{ marginBottom: '16rpx' }" />
- <up-radio shape="circle" label="小葫芦线上支付宝" name="online_alipay" :customStyle="{ marginBottom: '16rpx' }" />
- <up-radio shape="circle" label="线下支付" name="offline" :customStyle="{ marginBottom: '16rpx' }" />
- </up-radio-group>
- </up-col>
- </up-row>
- <up-row class="info-row">
- <up-col span="12">
- <view class="info-label">支付方式</view>
- <up-input :disabled="paymentMethodRadio === 'online' || paymentMethodRadio === 'online_alipay'"
- v-model="paymentMethod" placeholder="请输入支付方式" class="info-input" />
- </up-col>
- </up-row>
- </view>
- <!-- 核价信息卡片 -->
- <view v-if="hasInquiryInfo" class="info-card">
- <view class="info-card-title">核价信息</view>
- <up-row class="info-row">
- <up-col span="6">
- <view class="info-label">核价人数</view>
- <view class="info-value">{{ currentReceipt.inquiryCount || 0 }}</view>
- </up-col>
- <up-col span="6">
- <view class="info-label">核价价格</view>
- <view class="info-value">
- ¥{{ currentReceipt.inquiryPrice || 0 }}
- <text v-if="hasMorePricingPrice" class="pricing-more" @click.stop="handlePricing">更多</text>
- </view>
- </up-col>
- </up-row>
- </view>
- <!-- 高清实物图卡片 -->
- <view class="card-wrap">
- <view class="detail-image-section">
- <view class="detail-image-header">
- <text class="detail-image-title">高清实物图(拖拽排序)</text>
- <up-button type="primary" shape="circle" plain text="核价" size="small" class="pricing-btn"
- @click="handlePricing"></up-button>
- </view>
- <view class="detail-image-content">
- <view class="detail-image-list">
- <view v-for="(item, index) in displayImages" :key="item.id || `detail-${index}`" class="detail-image-item"
- :class="{
- 'dragging': draggingIndex === index,
- 'can-drop': canDropIndex === index && draggingIndex !== index
- }" :style="draggingIndex === index ? draggingStyle : ''" @touchstart.stop="onTouchStart($event, index)"
- @touchmove.stop="onTouchMove($event, index)" @touchend.stop="onTouchEnd">
- <PicComp :src="item.fileUrl" @needPreviewPic="previewImageDetail" />
- <view class="image-type-tag">{{ getImageType(index) }}</view>
- <view class="detail-delete-btn" @click.stop="handleHideImage(item, index)">
- ×
- </view>
- </view>
- <view class="detail-upload-btn" @click="handleUploadImage">
- <up-icon name="plus" size="40rpx" color="#999" />
- </view>
- </view>
- </view>
- </view>
- </view>
- <!-- 支付总额卡片 -->
- <view class="card-wrap payment-card">
- <view class="payment-section">
- <view class="payment-total-container">
- <text class="payment-label">支付总额</text>
- <view class="payment-amount-wrap">
- <up-input v-model="paymentAmount" class="payment-amount" type="number" decimal="2" prefix="¥"
- @blur="handlePaymentAmountBlur" />
- </view>
- <view class="pay-now-btn-wrap">
- <up-button type="primary" shape="circle" plain text="立即支付" size="small"
- @click="handlePayNowClick"></up-button>
- </view>
- </view>
- <view class="payment-buttons-row">
- <view class="payment-button" @click="handleUnpaidClick">
- <up-icon name="star" size="40rpx" color="#ff9500" />
- <text class="button-text">未收</text>
- </view>
- <view class="payment-button" @click="handleFollowUpClick">
- <up-icon name="chat" size="40rpx" color="#108cff" />
- <text class="button-text">待跟进</text>
- </view>
- </view>
- </view>
- </view>
- <!-- 下一步按钮 -->
- <!-- <up-button class="next-btn" @click="handleNext" type="primary" size="middle">
- 下一步
- </up-button> -->
- <!-- 未收评级模态窗 -->
- <up-modal showCancelButton showConfirmButton @confirm="confirmUnpaid" @cancel="onUnpaidModalCancel"
- :show="unpaidModalVisible" title="未收评级">
- <view class="modal-content">
- <up-rate v-model="unpaidRating" :count="5" :size="50" active-color="#ff9500" />
- <view class="unpaid-benefit-fee-wrap">
- <view class="unpaid-benefit-fee-label">好处费</view>
- <up-input v-model="unpaidBenefitFee" class="unpaid-benefit-fee-input" type="number" :decimal="2"
- placeholder="请输入好处费(金额)" @input="handleUnpaidBenefitFeeInput" />
- </view>
- </view>
- </up-modal>
- <!-- 待跟进模态窗 -->
- <up-modal showCancelButton showConfirmButton @confirm="confirmFollowUp" @cancel="followUpModalVisible = false"
- :show="followUpModalVisible" title="填写跟进细节">
- <view class="modal-content">
- <up-textarea v-model="followUpNotes" placeholder="请输入情况" confirm-type="done"
- style="width: 100%; margin-bottom: 30rpx;" />
- </view>
- </up-modal>
- <!-- 确认支付模态窗 -->
- <up-modal showCancelButton showConfirmButton @confirm="confirmRiskWarning" @cancel="riskWarningModalVisible = false"
- confirmText="确认并继续付款" :show="riskWarningModalVisible" title="付款警示" :content="'湖南耒阳地区身份证号请确认!'">
- </up-modal>
- <!-- 核价对话框:与公海询价一致,不传 isShowHistory(不显示核价历史),编辑用 editForm(不显示价格/备注输入栏) -->
- <add-inquiry-dialog ref="pricingDialog" :clueId="pricingClueId" :editOrAdd="pricingEditOrAdd"
- :editInfo="pricingEditInfo" :type="2" title="核价" :isShowChart="pricingIsShowChart"
- @submitSuccess="onPricingSuccess" />
- <up-modal :show="payNowModalVisible" title="确认支付信息" :showConfirmButton="false">
- <view class="modal-content">
- <view class="payment-amount-display">¥{{ paymentAmount }}</view>
- <view class="payment-info-section">
- <view class="info-item">
- <text class="info-label">收款姓名:</text>
- <text class="info-value">{{ paymentInfo.customName || '未填写' }}</text>
- </view>
- <view class="info-item">
- <text class="info-label">开户银行:</text>
- <text class="info-value">{{ paymentInfo.bankName || '未填写' }}</text>
- </view>
- <view class="info-item">
- <text class="info-label">银行卡号:</text>
- <text class="info-value">{{ paymentInfo.bankAccount || '未填写' }}</text>
- </view>
- <view class="info-item">
- <text class="info-label">支付方式:</text>
- <text class="info-value">{{ paymentMethod || '未填写' }}</text>
- </view>
- </view>
- <up-button type="primary" size="large" @click="confirmTransfer" style="margin-top: 40rpx;">
- 确认转账
- </up-button>
- <up-button type="primary" :plain="true" @click="payNowModalVisible = false" size="large"
- style="margin-top: 20rpx;">
- 取消
- </up-button>
- </view>
- </up-modal>
- </view>
- </template>
- <script>
- import PicComp from './PicComp.vue'
- import imageUpload from '../utils/imageUpload.js'
- import addInquiryDialog from '@/components/add-inquiry-dialog/index.vue'
- export default {
- name: 'PageThree',
- components: {
- PicComp,
- addInquiryDialog
- },
- props: {
- orderDetail: {
- type: Object,
- default: () => ({})
- },
- orderId: {
- type: String,
- default: ''
- },
- currentReceipt: {
- type: Object,
- default: () => ({})
- }
- },
- data() {
- return {
- paymentInfo: {
- customName: '',
- bankName: '',
- bankAccount: '',
- idNumber: ''
- },
- paymentMethodRadio: 'offline',
- paymentMethod: '',
- paymentAmount: '0.00',
- detailImages: [],
- // 拖拽相关
- draggingIndex: -1,
- canDropIndex: -1,
- startX: 0,
- startY: 0,
- currentX: 0,
- currentY: 0,
- // 模态窗
- unpaidModalVisible: false,
- followUpModalVisible: false,
- payNowModalVisible: false,
- riskWarningModalVisible: false,
- unpaidRating: 0,
- unpaidBenefitFee: '',
- followUpNotes: '',
- // 核价相关
- pricingClueId: '',
- pricingEditOrAdd: 'receptFormAdd',
- pricingEditInfo: {},
- pricingIsShowChart: false
- }
- },
- computed: {
- // 显示前6个图片用于拖拽
- displayImages() {
- return this.detailImages.slice(0, 6)
- },
- // 拖拽时的样式
- draggingStyle() {
- if (this.draggingIndex === -1) return ''
- return {
- transform: `translate(${this.currentX - this.startX}px, ${this.currentY - this.startY}px)`,
- zIndex: 1000
- }
- },
- // 是否为支付宝支付
- isAlipayPayment() {
- return this.paymentMethodRadio === 'online_alipay'
- },
- // 银行账号标签
- bankAccountLabel() {
- return this.isAlipayPayment ? '支付宝账号' : '银行账号'
- },
- // 银行账号占位符
- bankAccountPlaceholder() {
- return this.isAlipayPayment ? '请输入支付宝账号' : '请输入银行账号'
- },
- // 是否有核价信息(至少一人出价时才展示卡片)
- hasInquiryInfo() {
- const n = this.currentReceipt && this.currentReceipt.inquiryCount
- return n != null && Number(n) > 0
- },
- // 是否有多人核价出价(显示「更多」)
- hasMorePricingPrice() {
- const n = this.currentReceipt && this.currentReceipt.inquiryCount
- return (n != null && Number(n) > 1)
- }
- },
- watch: {
- // 支付信息已保存到 receiptForm,不再从 orderDetail(sendForm) 读取
- currentReceipt: {
- handler(newVal, oldVal) {
- if (newVal) {
- //是为了修复一个问题,当上传高清图片时,支付方式会被重置,这里是为了避免这个问题
- // 仅当回单 id 变化时(切换了回单)才从 receipt 回填表单,避免上传图片等只更新 fileIds 时触发 watch 导致支付方式被重置
- const receiptIdChanged = !oldVal || oldVal.id !== newVal.id
- if (receiptIdChanged) {
- this.paymentAmount = newVal.tableFee || '0.00'
- // 从回单表 receiptForm 回填支付信息(与 PC 端一致)
- this.paymentInfo.customName = newVal.customName || ''
- this.paymentInfo.bankName = newVal.bankName || ''
- this.paymentInfo.bankAccount = newVal.bankCardNumber || ''
- this.paymentInfo.idNumber = newVal.idCard || ''
- this.initPaymentMethod(newVal.paymentMethod)
- }
- // 只有当 receipt id 变化时才重新加载图片,避免 fileIds 更新时重新加载
- if (receiptIdChanged) {
- this.loadDetailImages()
- }
- }
- },
- deep: true,
- immediate: true
- }
- },
- methods: {
- /**
- * 刷新图片列表(供父组件调用)
- */
- async refreshImageList() {
- await this.loadDetailImages()
- },
- /**
- * 加载细节图
- */
- async loadDetailImages() {
- if (!this.currentReceipt.id || !this.orderDetail.itemBrand) return
- try {
- const list = await imageUpload.getFileList(
- '2',
- '3',
- this.currentReceipt.id,
- this.orderDetail.itemBrand,
- this.currentReceipt.clueId
- )
- // 按照 fileIds 排序
- if (this.currentReceipt.fileIds && list && list.length > 0) {
- const sortedIds = this.currentReceipt.fileIds.split(',')
- list.sort((a, b) => {
- const indexA = sortedIds.indexOf(a.id)
- const indexB = sortedIds.indexOf(b.id)
- // 如果都不在列表中,保持原顺序
- if (indexA === -1 && indexB === -1) return 0
- // 如果 a 不在列表中,放到后面
- if (indexA === -1) return 1
- // 如果 b 不在列表中,放到后面
- if (indexB === -1) return -1
- // 都在列表中,按 index 排序
- return indexA - indexB
- })
- }
- this.detailImages = list || []
- } catch (error) {
- console.error('加载细节图失败:', error)
- }
- },
- /**
- * 初始化支付方式
- */
- initPaymentMethod(value) {
- if (value === '小葫芦线上支付') {
- this.paymentMethod = '小葫芦线上支付'
- this.paymentMethodRadio = 'online'
- } else if (value === '小葫芦线上支付宝') {
- this.paymentMethod = '小葫芦线上支付宝'
- this.paymentMethodRadio = 'online_alipay'
- this.paymentInfo.bankName = '支付宝'
- } else {
- this.paymentMethod = value || ''
- this.paymentMethodRadio = 'offline'
- }
- },
- /**
- * 支付方式选择改变
- */
- handlePaymentMethodRadioChange(value) {
- if (value === 'online') {
- this.paymentMethod = '小葫芦线上支付'
- // 恢复银行名称输入框
- if (this.paymentInfo.bankName === '支付宝') {
- this.paymentInfo.bankName = ''
- }
- } else if (value === 'online_alipay') {
- this.paymentMethod = '小葫芦线上支付宝'
- // 自动设置银行名称为支付宝
- this.paymentInfo.bankName = '支付宝'
- } else {
- this.paymentMethod = ''
- // 恢复银行名称输入框
- if (this.paymentInfo.bankName === '支付宝') {
- this.paymentInfo.bankName = ''
- }
- }
- },
- /**
- * 失焦后保存支付信息(开户人/银行名称/账号/身份证/支付总额)
- */
- async savePaymentInfoOnBlur() {
- if (!this.currentReceipt || !this.currentReceipt.id) return
- try {
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- sendFormId: this.currentReceipt.sendFormId || this.orderDetail.id,
- customName: this.paymentInfo.customName || '',
- bankName: this.paymentInfo.bankName || '',
- bankCardNumber: this.paymentInfo.bankAccount || '',
- idCard: this.paymentInfo.idNumber || '',
- tableFee: this.paymentAmount || '0.00'
- })
- } catch (e) {
- console.error('保存支付信息失败:', e)
- }
- },
- /**
- * 开户人输入处理 - 只允许中文,失焦保存
- */
- handleCustomNameInput(value) {
- const chineseReg = /[^\u4e00-\u9fa5]/g
- this.paymentInfo.customName = String(value ?? this.paymentInfo.customName ?? '').replace(chineseReg, '')
- this.savePaymentInfoOnBlur()
- },
- /**
- * 银行名称输入处理 - 只允许中文,失焦保存
- */
- handleBankNameInput(value) {
- const chineseReg = /[^\u4e00-\u9fa5]/g
- this.paymentInfo.bankName = String(value ?? this.paymentInfo.bankName ?? '').replace(chineseReg, '')
- this.savePaymentInfoOnBlur()
- },
- /**
- * 银行账号输入处理 - 只允许数字
- */
- handleBankAccountInput(value) {
- const numberReg = /[^\d]/g
- this.paymentInfo.bankAccount = String(value || '').replace(numberReg, '')
- },
- /**
- * 银行账号失焦保存
- */
- handleBankAccountBlur() {
- this.savePaymentInfoOnBlur()
- },
- /**
- * 身份证号输入处理 - 允许数字和X,失焦保存
- */
- handleIdNumberInput(value) {
- const reg = /[^\dxX]/g
- this.paymentInfo.idNumber = String(value ?? this.paymentInfo.idNumber ?? '').replace(reg, '')
- this.savePaymentInfoOnBlur()
- },
- /**
- * 支付总额失焦保存
- */
- async handlePaymentAmountBlur() {
- this.savePaymentInfoOnBlur()
- },
- /**
- * 获取图片类型
- */
- getImageType(index) {
- const types = ['正面', '反面', '侧面', '扣子', '编号']
- return types[index] || `细节${index - 4}`
- },
- /**
- * 触摸开始
- */
- onTouchStart(event, index) {
- if (this.draggingIndex !== -1) return
- this.draggingIndex = index
- const touch = event.touches[0]
- this.startX = touch.clientX
- this.startY = touch.clientY
- this.currentX = touch.clientX
- this.currentY = touch.clientY
- },
- /**
- * 触摸移动
- */
- onTouchMove(event, index) {
- if (this.draggingIndex === -1 || this.draggingIndex !== index) return
- const touch = event.touches[0]
- this.currentX = touch.clientX
- this.currentY = touch.clientY
- this.findTargetIndex(touch.clientX, touch.clientY)
- },
- /**
- * 触摸结束
- */
- async onTouchEnd() {
- if (this.draggingIndex === -1) return
- if (this.canDropIndex !== -1 && this.canDropIndex !== this.draggingIndex) {
- // 交换位置
- const images = [...this.detailImages]
- const temp = images[this.draggingIndex]
- images[this.draggingIndex] = images[this.canDropIndex]
- images[this.canDropIndex] = temp
- this.detailImages = images
- }
- this.resetDragState()
- //每次拖拽结束后把新的顺序传送给接口
- const fileIds = this.detailImages.map(item => item.id).join(',')
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- fileIds: fileIds
- })
- this.$emit('update-file-ids', fileIds)
- },
- /**
- * 查找目标索引
- */
- findTargetIndex(x, y) {
- const query = uni.createSelectorQuery().in(this)
- query.selectAll('.detail-image-item').boundingClientRect((rects) => {
- if (!rects || rects.length === 0) return
- let targetIndex = -1
- for (let i = 0; i < rects.length; i++) {
- if (i === this.draggingIndex) continue
- const rect = rects[i]
- if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
- targetIndex = i
- break
- }
- }
- this.canDropIndex = targetIndex
- }).exec()
- },
- /**
- * 重置拖拽状态
- */
- resetDragState() {
- this.draggingIndex = -1
- this.canDropIndex = -1
- this.startX = 0
- this.startY = 0
- this.currentX = 0
- this.currentY = 0
- },
- /**
- * 上传图片
- */
- async handleUploadImage() {
- try {
- const filePaths = await imageUpload.chooseImage(9)
- const uploadResults = await imageUpload.uploadFiles(filePaths)
- await imageUpload.bindOrderFile(
- this.currentReceipt.clueId,
- this.currentReceipt.id,
- '3',
- uploadResults
- )
- await this.loadDetailImages()
- //上传新图片完成之后也要把新数据给接口
- const fileIds = this.detailImages.map(item => item.id).join(',')
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- fileIds: fileIds
- })
- this.$emit('update-file-ids', fileIds)
- } catch (error) {
- console.error('上传失败:', error)
- }
- },
- /**
- * 隐藏图片
- */
- async handleHideImage(item, index) {
- const itemIndex = this.detailImages.findIndex(img => img.id === item.id || img.fileUrl === item.fileUrl)
- if (itemIndex !== -1) {
- this.detailImages.splice(itemIndex, 1)
- // 更新 fileIds
- const fileIds = this.detailImages.map(item => item.id).join(',')
- try {
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- fileIds: fileIds
- })
- this.$emit('update-file-ids', fileIds)
- uni.$u.toast('图片已隐藏')
- } catch (error) {
- console.error('更新失败:', error)
- }
- }
- },
- /**
- * 预览图片
- */
- previewImageDetail(src) {
- const urlList = this.detailImages.map(item => item.fileUrl)
- uni.previewImage({
- urls: urlList,
- current: src
- })
- },
- /**
- * 未收点击
- */
- handleUnpaidClick() {
- this.unpaidBenefitFee = ''
- this.unpaidModalVisible = true
- },
- /**
- * 未收弹窗取消 - 重置好处费
- */
- onUnpaidModalCancel() {
- this.unpaidModalVisible = false
- this.unpaidBenefitFee = ''
- },
- /**
- * 好处费输入 - 限制仅可输入金额(数字、最多两位小数)
- */
- handleUnpaidBenefitFeeInput(e) {
- const value = (e && e.detail && e.detail.value !== undefined) ? e.detail.value : e
- let val = String(value ?? '').trim()
- if (!val) {
- this.unpaidBenefitFee = ''
- return
- }
- // 只保留数字和第一个小数点,且小数点后最多两位
- const parts = val.replace(/[^\d.]/g, '').split('.')
- if (parts.length > 2) {
- val = parts[0] + '.' + parts.slice(1).join('')
- }
- if (parts.length === 2 && parts[1].length > 2) {
- val = parts[0] + '.' + parts[1].slice(0, 2)
- }
- this.unpaidBenefitFee = val
- },
- /**
- * 待跟进点击
- */
- handleFollowUpClick() {
- this.followUpModalVisible = true
- },
- /**
- * 立即支付点击
- */
- async handlePayNowClick() {
- // 与 PC 端一致:先做必填校验
- if (this.paymentAmount <= 0) {
- uni.$u.toast('请填写正确的支付总额')
- return
- }
- // 支付方式必填(与 PC 一致)
- if (!this.paymentMethod) {
- uni.$u.toast('请填写支付方式')
- return
- }
- // 仅线上支付时校验开户人/银行/身份证;线下支付不校验(与 PC 一致)
- if (this.paymentMethodRadio === 'online' || this.paymentMethodRadio === 'online_alipay') {
- if (!this.paymentInfo.customName || !this.paymentInfo.bankName ||
- !this.paymentInfo.bankAccount || !this.paymentInfo.idNumber) {
- uni.$u.toast('请填写完整的开户人信息、身份证号、银行名称、银行卡号')
- return
- }
- }
- // 保存支付信息到回单表(后端需 sendFormId 才能更新发单表的开户人/银行/身份证等)
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- sendFormId: this.currentReceipt.sendFormId || this.orderDetail.id,
- tableFee: this.paymentAmount,
- fileIds: this.detailImages.map(item => item.id).join(','),
- customName: this.paymentInfo.customName || '',
- bankName: this.paymentInfo.bankName || '',
- bankCardNumber: this.paymentInfo.bankAccount || '',
- idCard: this.paymentInfo.idNumber || ''
- })
- // 湖南耒阳身份证号确认(仅当已填写身份证时校验,与 PC 一致)
- if (this.paymentInfo.idNumber && String(this.paymentInfo.idNumber).startsWith('430481')) {
- this.riskWarningModalVisible = true
- return
- }
- // 线下支付:不弹确认框,直接更新支付方式并进入下一步(后端需 sendFormId 更新发单表支付方式)
- if (this.paymentMethodRadio === 'offline') {
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- sendFormId: this.currentReceipt.sendFormId || this.orderDetail.id,
- paymentMethod: this.paymentMethod || ''
- })
- this.handleNext()
- return
- }
- this.payNowModalVisible = true
- },
- /**
- * 确认风险警示
- */
- async confirmRiskWarning() {
- this.riskWarningModalVisible = false
- // 线下支付:不弹确认框,直接更新支付方式并进入下一步(后端需 sendFormId 更新发单表支付方式)
- if (this.paymentMethodRadio === 'offline') {
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- sendFormId: this.currentReceipt.sendFormId || this.orderDetail.id,
- paymentMethod: this.paymentMethod || ''
- })
- this.handleNext()
- return
- }
- this.payNowModalVisible = true
- },
- /**
- * 确认转账
- */
- async confirmTransfer() {
- this.payNowModalVisible = false
- // 支付方式保存(后端需 sendFormId 更新发单表)
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- sendFormId: this.currentReceipt.sendFormId || this.orderDetail.id,
- paymentMethod: this.paymentMethod || ''
- })
- // 根据 radio 选择判断:线上支付(online / online_alipay)需调用支付接口,线下则直接下一步
- if (this.paymentMethodRadio === 'online' || this.paymentMethodRadio === 'online_alipay') {
- this.$emit('confirm-pay')
- } else {
- this.handleNext()
- }
- },
- /**
- * 确认未收
- */
- async confirmUnpaid() {
- try {
- // 若填写了好处费,先更新回单表
- if (this.currentReceipt?.id && (this.unpaidBenefitFee !== '' && this.unpaidBenefitFee != null)) {
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- benefitFee: this.unpaidBenefitFee
- })
- }
- await uni.$u.api.addOrderFollow({
- orderId: this.orderId,
- content: `未收评分_${this.unpaidRating}`
- })
- await uni.$u.api.oderForm({
- status: '4',
- id: this.orderId
- })
- uni.$u.toast('提交未收评级成功')
- this.unpaidModalVisible = false
- this.unpaidBenefitFee = ''
- // 刷新当前收单数据,以便第四页好处费等字段同步
- this.$emit('price-updated')
- } catch (error) {
- console.error('提交失败:', error)
- uni.$u.toast('提交失败')
- }
- },
- /**
- * 确认跟进
- */
- async confirmFollowUp() {
- try {
- await uni.$u.api.addOrderFollow({
- orderId: this.orderId,
- content: `待跟进_${this.followUpNotes}`
- })
- uni.$u.toast('提交待跟进记录成功')
- this.followUpModalVisible = false
- this.followUpNotes = ''
- } catch (error) {
- console.error('提交失败:', error)
- uni.$u.toast('提交失败')
- }
- },
- /**
- * 下一步
- */
- async handleNext() {
- // 与 PC 端一致:支付信息通过 updateReceiptForm 保存;后端需 sendFormId 才能更新发单表的开户人/银行/身份证等
- await uni.$u.api.updateReceiptForm({
- id: this.currentReceipt.id,
- sendFormId: this.currentReceipt.sendFormId || this.orderDetail.id,
- tableFee: this.paymentAmount,
- fileIds: this.detailImages.map(item => item.id).join(','),
- customName: this.paymentInfo.customName || '',
- bankName: this.paymentInfo.bankName || '',
- bankCardNumber: this.paymentInfo.bankAccount || '',
- idCard: this.paymentInfo.idNumber || '',
- // paymentMethod: this.paymentMethod || ''
- })
- this.$emit('save', {
- nowPage: 'formThree',
- form: {
- ...this.paymentInfo
- },
- fileIds: this.detailImages.map(item => item.id).join(',')
- })
- this.$emit('next', {
- nowPage: 'formThree',
- form: {
- ...this.paymentInfo
- }
- })
- },
- /**
- * 核价:与公海询价一致逻辑。count 为 null → 未提出,新增;count 为 0 → 已提出无人出价,回显不显示柱状图;count > 0 → 显示柱状图。多人出价时核价信息区显示「更多」点击也走此处并带柱状图。
- */
- async handlePricing() {
- const brandList = await this.$getDicts('crm_form_brand')
- if (!this.currentReceipt || !this.currentReceipt.clueId) {
- uni.$u.toast('缺少线索ID')
- return
- }
- if (!this.currentReceipt.brand) {
- uni.$u.toast('缺少品牌信息')
- return
- }
- if (!this.displayImages || this.displayImages.length === 0) {
- uni.$u.toast('请先上传图片')
- return
- }
- this.pricingClueId = this.currentReceipt.id
- const brandDictLabel = this.currentReceipt.brand
- const brandDictValue = brandList.find(item => item.dictLabel === this.currentReceipt.brand)?.dictValue
- const imgsUrl = this.displayImages.map(item => item.fileUrl).filter(url => url)
- const count = this.currentReceipt.inquiryCount != null ? Number(this.currentReceipt.inquiryCount) : null
- if (count === null) {
- // 未提出核价:新增
- this.pricingIsShowChart = false
- this.pricingEditOrAdd = 'receptFormAdd'
- this.pricingEditInfo = {
- dictLabel: brandDictLabel,
- dictValue: brandDictValue,
- imgsUrl,
- model: this.currentReceipt.model,
- code: this.currentReceipt.code || '',
- price: ''
- }
- this.$nextTick(() => this.$refs.pricingDialog.showDialog())
- return
- }
- // 已提出核价(count 为 0 或 >0):拉详情回显
- try {
- const data = { clueId: this.pricingClueId, type: 2 }
- const res = await uni.$u.api.inquiryDetail(data)
- if (res.code === 200 && res.data) {
- this.pricingEditOrAdd = 'editForm'
- this.pricingIsShowChart = (res.data.count != null && Number(res.data.count) > 0)
- this.pricingEditInfo = {
- ...res.data,
- // dictLabel: brandDictLabel || res.data.dictLabel,
- // dictValue: brandDictValue || res.data.dictValue,
- // imgsUrl: imgsUrl.length > 0 ? imgsUrl : (res.data.imgsUrl || [])
- }
- this.$nextTick(() => this.$refs.pricingDialog.showDialog())
- } else {
- this.pricingIsShowChart = false
- this.pricingEditOrAdd = 'receptFormAdd'
- this.pricingEditInfo = {
- dictLabel: brandDictLabel,
- dictValue: brandDictValue,
- imgsUrl,
- model: this.currentReceipt.model,
- code: this.currentReceipt.code || '',
- price: ''
- }
- this.$nextTick(() => this.$refs.pricingDialog.showDialog())
- }
- } catch (e) {
- this.pricingIsShowChart = false
- this.pricingEditOrAdd = 'receptFormAdd'
- this.pricingEditInfo = {
- dictLabel: brandDictLabel,
- dictValue: brandDictValue,
- imgsUrl,
- model: this.currentReceipt.model,
- code: this.currentReceipt.code || '',
- price: ''
- }
- this.$nextTick(() => this.$refs.pricingDialog.showDialog())
- }
- },
- /** 核价提交成功后刷新当前回单,以便核价人数/价格更新 */
- onPricingSuccess() {
- this.$refs.pricingDialog.closeDialog()
- this.$emit('price-updated')
- },
- }
- }
- </script>
- <style scoped lang="scss">
- @import '../styles/common.scss';
- .page-three-container {
- @extend .page-container;
- padding-bottom: 100rpx;
- }
- .info-card {
- @extend .card-wrap;
- padding: 20rpx;
- margin-top: 20rpx;
- box-sizing: border-box;
- width: 100%;
- max-width: 100%;
- }
- .info-card-title {
- @include font-styles($size: title, $weight: bold, $color: primary);
- margin-bottom: 25rpx;
- padding-bottom: 15rpx;
- border-bottom: 1rpx solid map-get($colors, border);
- }
- .info-row {
- margin-bottom: 20rpx;
- }
- .info-label {
- @include font-styles($size: tiny, $weight: regular, $color: tertiary);
- margin-bottom: 8rpx;
- display: block;
- }
- .pricing-more {
- margin-left: 12rpx;
- font-size: 24rpx;
- color: #3c9cff;
- border: 1rpx solid #3c9cff;
- border-radius: 10rpx;
- padding: 4rpx 12rpx;
- }
- .info-input {
- border-radius: 8rpx;
- border: 1rpx solid #e5e7eb;
- padding: 12rpx 16rpx;
- width: 100%;
- box-sizing: border-box;
- }
- .detail-image-section {
- padding: 20rpx;
- }
- .detail-image-header {
- display: grid;
- grid-template-columns: 1fr auto;
- margin-bottom: 20rpx;
- padding-bottom: 20rpx;
- padding-right: 100rpx;
- /* 右侧留空,避免被固定页面导航遮挡,使整行(含核价按钮)左移 */
- border-bottom: 1rpx solid map-get($colors, border);
- }
- .detail-image-title {
- @include font-styles($size: content, $weight: bold, $color: primary);
- }
- .detail-image-list {
- display: flex;
- flex-wrap: wrap;
- gap: 20rpx;
- position: relative;
- }
- .detail-image-item {
- position: relative;
- width: 200rpx;
- height: 200rpx;
- touch-action: none;
- transition: transform 0.2s ease, opacity 0.2s ease;
- z-index: 1;
- box-sizing: border-box;
- &.dragging {
- opacity: 0.6;
- transform: scale(1.05);
- z-index: 999;
- box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.2);
- }
- &.can-drop {
- outline: 2rpx dashed #108cff;
- outline-offset: -2rpx;
- background-color: rgba(16, 140, 255, 0.1);
- border-radius: 8rpx;
- }
- }
- .image-type-tag {
- position: absolute;
- top: 10rpx;
- left: 10rpx;
- background-color: rgba(0, 0, 0, 0.6);
- color: white;
- padding: 5rpx 10rpx;
- border-radius: 12rpx;
- font-size: 22rpx;
- z-index: 1;
- }
- .detail-delete-btn {
- position: absolute;
- top: -10rpx;
- right: -10rpx;
- width: 40rpx;
- height: 40rpx;
- background-color: #ff4d4f;
- color: #fff;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- font-weight: bold;
- z-index: 10;
- cursor: pointer;
- }
- .detail-upload-btn {
- width: 200rpx;
- height: 200rpx;
- border: 8rpx dashed #ddd;
- border-radius: 30rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: #f9f9f9;
- cursor: pointer;
- }
- .pricing-button {
- margin-top: 0;
- }
- .payment-card {
- margin-top: 20rpx;
- }
- .payment-section {
- padding: 20rpx;
- }
- .payment-total-container {
- background-color: #f5f7fa;
- border: 2rpx solid #e5e7eb;
- border-radius: 12rpx;
- padding: 0rpx 30rpx;
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 24rpx;
- }
- .payment-label {
- font-size: 36rpx;
- font-weight: 700;
- min-width: 140rpx;
- flex-shrink: 0;
- }
- .payment-amount-wrap {
- flex: 1;
- display: flex;
- justify-content: center;
- align-items: center;
- min-width: 0;
- }
- .payment-amount-wrap .payment-amount {
- font-size: 48rpx;
- font-weight: 600;
- color: #f53f3f;
- width: 100%;
- max-width: 240rpx;
- border: none;
- text-align: center;
- }
- /* 让 up-input 内部输入框文字居中 */
- .payment-amount-wrap :deep(.up-input__content__field-wrapper__field),
- .payment-amount-wrap :deep(input) {
- text-align: center !important;
- }
- .pay-now-btn-wrap {
- flex-shrink: 0;
- display: inline-flex;
- }
- .payment-total-container .pay-now-btn-wrap .up-button,
- .payment-total-container .pay-now-btn-wrap .u-btn {
- width: auto !important;
- min-width: 0 !important;
- flex: none !important;
- }
- .payment-buttons-row {
- display: flex;
- gap: 20rpx;
- margin-bottom: 24rpx;
- }
- .payment-button {
- flex: 1;
- border-radius: 12rpx;
- padding: 5rpx 0;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- background-color: #f5f7fa;
- border: 2rpx solid #e5e7eb;
- cursor: pointer;
- gap: 12rpx;
- }
- .button-text {
- font-size: 28rpx;
- font-weight: 500;
- color: inherit;
- }
- .modal-content {
- width: 100%;
- padding: 40rpx 20rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- }
- .unpaid-benefit-fee-wrap {
- width: 100%;
- margin-top: 32rpx;
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- }
- .unpaid-benefit-fee-label {
- font-size: 28rpx;
- color: #333;
- margin-bottom: 16rpx;
- }
- .unpaid-benefit-fee-input {
- width: 100%;
- border: 2rpx solid #e5e7eb;
- border-radius: 12rpx;
- padding: 20rpx 24rpx;
- box-sizing: border-box;
- }
- .payment-amount-display {
- font-size: 64rpx;
- font-weight: bold;
- color: #108cff;
- text-align: center;
- margin-bottom: 40rpx;
- width: 100%;
- }
- .payment-info-section {
- width: 100%;
- background-color: #f5f7fa;
- border: 2rpx solid #e5e7eb;
- border-radius: 12rpx;
- padding: 30rpx 20rpx;
- margin-bottom: 40rpx;
- }
- .info-item {
- display: flex;
- margin-bottom: 20rpx;
- align-items: center;
- justify-content: space-between;
- &:last-child {
- margin-bottom: 0;
- }
- }
- .next-btn {
- position: fixed;
- bottom: 10rpx;
- left: 2.5%;
- width: 95%;
- height: 80rpx;
- line-height: 80rpx;
- text-align: center;
- border-radius: 20rpx;
- z-index: 1000;
- }
- </style>
|