diff --git a/page_shanghu/guanli/admin_worke.vue b/page_shanghu/guanli/admin_worke.vue index 9023531..3972bb5 100644 --- a/page_shanghu/guanli/admin_worke.vue +++ b/page_shanghu/guanli/admin_worke.vue @@ -182,6 +182,20 @@ + + + + + 用户投诉提醒 + + 您有 {{ complaintBadge }} 笔投诉订单待处理,请尽快处理 + + + 稍后处理 + 立即处理 + + + @@ -246,6 +260,8 @@ export default { userId:'', fuwuewm:false, weinum:0, + complaintModalVisible: false, + complaintEntryFrom: '', areaname:'', dateStat: {}, pendingStat: {}, @@ -265,6 +281,7 @@ export default { }, onLoad(option) { this.yyqid = option.id + this.complaintEntryFrom = option.entryFrom || '' wx.openBluetoothAdapter({ success: function (res) { console.log('蓝牙适配器初始化成功') @@ -375,7 +392,7 @@ export default { if (uni.getStorageSync('adminname')) this.areaname = uni.getStorageSync('adminname') tasks.push( this.getinfo({ silent: true }), - this.fetchComplaintBadge(), + this.fetchComplaintBadge({ showModal: false }), this.fetchAreaAbilityList() ) } @@ -394,17 +411,28 @@ export default { }) .catch(() => {}) }, - fetchComplaintBadge() { + fetchComplaintBadge(options = {}) { + const showModal = options.showModal !== false if (!this.areaId) return Promise.resolve() return this.$u.get(`/dashboard/complaint/statusMap?areaId=${this.areaId}`).then((res) => { if (res.code == 200){ let min = res.data['1'] || 0 let max = res.data['3'] || 0 this.weinum = Number(min) + Number(max) + if (showModal && this.weinum > 0) { + this.complaintModalVisible = true + } } }) .catch(() => {}) }, + btnComplaintLater() { + this.complaintModalVisible = false + }, + btnComplaintNow() { + this.complaintModalVisible = false + this.btnts() + }, // 点击配置语音 btnyy(){ uni.navigateTo({ @@ -536,7 +564,12 @@ export default { // 查询商户未处理投诉 getweicl() { if (!this.areaId) return - this.fetchComplaintBadge() + this.fetchComplaintBadge({ showModal: this.consumeComplaintEntryFlag() }) + }, + consumeComplaintEntryFlag() { + const from = this.complaintEntryFrom + this.complaintEntryFrom = '' + return from === 'nearbystores' || from === 'my' }, // 点击绑定服务号 btnfuwuewm(){ @@ -1345,6 +1378,74 @@ export default { transform: translateX(-100%); } } + .complaint-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 100; + display: flex; + align-items: center; + justify-content: center; + &__mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + } + &__content { + position: relative; + width: 620rpx; + background-color: #fff; + border-radius: 24rpx; + padding: 48rpx 40rpx 40rpx; + box-sizing: border-box; + z-index: 1; + } + &__title { + text-align: center; + font-size: 36rpx; + font-weight: 600; + color: #333; + } + &__desc { + margin-top: 32rpx; + text-align: center; + font-size: 30rpx; + color: #666; + line-height: 1.6; + } + &__num { + color: #FF473E; + font-weight: 600; + font-size: 36rpx; + } + &__actions { + display: flex; + margin-top: 48rpx; + gap: 24rpx; + } + &__btn { + flex: 1; + height: 88rpx; + line-height: 88rpx; + text-align: center; + border-radius: 44rpx; + font-size: 30rpx; + font-weight: 600; + &--later { + background-color: #F5F6F8; + color: #666; + } + &--now { + background-color: #4297F3; + color: #fff; + } + } + } .noticetc{ width: 680rpx; height: 80vh; diff --git a/page_shanghu/guanli/order_detail.vue b/page_shanghu/guanli/order_detail.vue index 23e861f..352e276 100644 --- a/page_shanghu/guanli/order_detail.vue +++ b/page_shanghu/guanli/order_detail.vue @@ -432,61 +432,113 @@ - - - 退款 - - - - 骑行费 + + + + 订单退款 + 在右侧填写退款金额,不得超过左侧实收金额 - > - - - - 调度费 - - > - + + 费用项目 + 退款(元) - - - 管理费 - - > - + + 骑行费 + ¥{{ formatRefundMoney(getRefundOriginal('riding')) }} + + - - - 车损费 - - > - + + 调度费 + ¥{{ formatRefundMoney(getRefundOriginal('dispatch')) }} + + - - - 退款原因 - - + + 管理费 + ¥{{ formatRefundMoney(getRefundOriginal('manage')) }} + + - - 当前操作总退款为¥{{ totalRefund }} + + 车损费 + ¥{{ formatRefundMoney(getRefundOriginal('deduction')) }} + + + + + 退款原因 + + + + 本次退款合计 + ¥{{ totalRefund }} - - 取消 - - - 确定 - + 取消 + 确认退款 + + + + + 确认退款 + + + 本次将退款 + ¥{{ totalRefund }} + + 确定要执行退款吗? + + + 取消 + 确定 + + @@ -762,6 +814,7 @@ import ZhimaNoDepositBadge from '@/components/zhima-no-deposit-badge/zhima-no-de distance: 0 }, tkflag: false, + refundConfirmFlag: false, amount: '', orderDeviceList: [], suitSeconds: '', @@ -837,12 +890,12 @@ import ZhimaNoDepositBadge from '@/components/zhima-no-deposit-badge/zhima-no-de }, computed: { totalRefund() { - return ( - Number(this.qxfei) + - Number(this.ddfei) + - Number(this.glfei) + - Number(this.csfei) - ).toFixed(2); // 保留两位小数 + return ( + Number(this.qxfei || 0) + + Number(this.ddfei || 0) + + Number(this.glfei || 0) + + Number(this.csfei || 0) + ).toFixed(2) }, formattedDuration() { // 获取开始时间(必须存在) @@ -1198,6 +1251,7 @@ import ZhimaNoDepositBadge from '@/components/zhima-no-deposit-badge/zhima-no-de qxqx() { this.zengsongflag = false this.tkflag = false + this.refundConfirmFlag = false this.orderActionBusy = false this.priceSubmitting = false this.qxfei = '' @@ -1366,21 +1420,86 @@ import ZhimaNoDepositBadge from '@/components/zhima-no-deposit-badge/zhima-no-de }) }, - // 点击退款 + getRefundOriginal(type) { + const keyMap = { + riding: 'actualReceivedRidingFee', + dispatch: 'actualReceivedDispatchFee', + manage: 'actualReceivedManageFee', + deduction: 'actualReceivedDeductionFee' + } + const v = Number(this.orderxqobj[keyMap[type]]) + return isNaN(v) ? 0 : v + }, + isRefundRowDisabled(type) { + return this.getRefundOriginal(type) <= 0 + }, + formatRefundMoney(val) { + const n = Number(val) + return (isNaN(n) ? 0 : n).toFixed(2) + }, + resetRefundForm() { + this.qxfei = '' + this.ddfei = '' + this.glfei = '' + this.csfei = '' + this.yuanyin = '' + }, + validateRefundForm() { + const rows = [ + { type: 'riding', val: this.qxfei, label: '骑行费' }, + { type: 'dispatch', val: this.ddfei, label: '调度费' }, + { type: 'manage', val: this.glfei, label: '管理费' }, + { type: 'deduction', val: this.csfei, label: '车损费' } + ] + let hasRefund = false + for (let i = 0; i < rows.length; i++) { + const row = rows[i] + const original = this.getRefundOriginal(row.type) + if (original <= 0) continue + const amount = Number(row.val || 0) + if (isNaN(amount) || amount < 0) { + uni.showToast({ title: row.label + '退款金额不正确', icon: 'none' }) + return false + } + if (amount > original) { + uni.showToast({ title: row.label + '退款不能超过实收', icon: 'none' }) + return false + } + if (amount > 0) hasRefund = true + } + if (!hasRefund) { + uni.showToast({ title: '请至少填写一项退款金额', icon: 'none' }) + return false + } + return true + }, + // 点击退款:先校验,再打开自定义确认弹窗 btntuikuan() { + if (!this.tkje) return + if (!this.validateRefundForm()) return + this.refundConfirmFlag = true + }, + closeRefundConfirm() { + this.refundConfirmFlag = false + }, + confirmRefundSubmit() { + this.refundConfirmFlag = false + this.submitRefundOrder() + }, + submitRefundOrder() { if (!this.tkje) return this.tkje = false uni.showLoading({ - title: '加载中...', + title: '退款中...', mask: true }) - let data = { + const data = { orderId: this.orid, - ridingRefund:this.qxfei == '' ? 0 : this.qxfei, - dispatchRefund:this.ddfei == '' ? 0 : this.ddfei, - manageRefund:this.glfei == '' ? 0 : this.glfei, - deductionRefund:this.csfei == '' ? 0 : this.csfei, - reason:this.yuanyin + ridingRefund: this.isRefundRowDisabled('riding') ? 0 : (this.qxfei === '' ? 0 : this.qxfei), + dispatchRefund: this.isRefundRowDisabled('dispatch') ? 0 : (this.ddfei === '' ? 0 : this.ddfei), + manageRefund: this.isRefundRowDisabled('manage') ? 0 : (this.glfei === '' ? 0 : this.glfei), + deductionRefund: this.isRefundRowDisabled('deduction') ? 0 : (this.csfei === '' ? 0 : this.csfei), + reason: this.yuanyin } this.$u.put(`/bst/order/refund`, data).then(res => { if (res.code == 200) { @@ -1389,11 +1508,8 @@ import ZhimaNoDepositBadge from '@/components/zhima-no-deposit-badge/zhima-no-de icon: 'success', duration: 2000 }) - this.qxfei = '' - this.ddfei = '' - this.glfei = '' - this.csfei = '' - this.yuanyin = '' + this.resetRefundForm() + this.refundConfirmFlag = false this.tkflag = false this.deviceInfo() this.getorderxq() @@ -1851,6 +1967,7 @@ import ZhimaNoDepositBadge from '@/components/zhima-no-deposit-badge/zhima-no-de } else { //否则为退款 if (this.toastIfOrderBusy()) return this.orderActionBusy = true + this.resetRefundForm() this.tkflag = true } }, @@ -3836,6 +3953,262 @@ import ZhimaNoDepositBadge from '@/components/zhima-no-deposit-badge/zhima-no-de .qd { background: #4C97E7; color: #fff; } } } + + .refund-modal { + width: 680rpx; + padding: 36rpx 32rpx 32rpx; + .tops { display: none; } + input { + width: auto; + height: auto; + background: transparent; + border-radius: 0; + padding: 0; + margin-bottom: 0; + } + .refund-modal__header { + display: flex; + align-items: flex-start; + margin-bottom: 28rpx; + } + .refund-modal__badge { + width: 72rpx; + height: 72rpx; + line-height: 72rpx; + text-align: center; + border-radius: 16rpx; + background: linear-gradient(135deg, #ff6b6b, #ff4444); + color: #fff; + font-size: 36rpx; + font-weight: 700; + flex-shrink: 0; + margin-right: 20rpx; + } + .refund-modal__head-text { + flex: 1; + min-width: 0; + } + .refund-modal__title { + display: block; + font-size: 36rpx; + font-weight: 700; + color: #1a1a1a; + line-height: 1.3; + } + .refund-modal__desc { + display: block; + margin-top: 8rpx; + font-size: 24rpx; + color: #888; + line-height: 1.5; + } + .refund-table__head, + .refund-table__row { + display: flex; + align-items: center; + padding: 0 16rpx; + box-sizing: border-box; + } + .refund-table__head { + height: 56rpx; + background: #f0f4f8; + border-radius: 10rpx; + margin-bottom: 12rpx; + font-size: 22rpx; + color: #666; + font-weight: 600; + } + .refund-table__row { + min-height: 88rpx; + margin-bottom: 12rpx; + border-radius: 12rpx; + background: #f8fafc; + border: 1rpx solid #e8edf2; + } + .refund-table__row--disabled { + background: #ececec; + border-color: #e0e0e0; + .col-name, + .col-original, + .col-refund-placeholder { + color: #aaa; + } + .col-original { + // background: #e4e4e4; + } + } + .col-name { + width: 120rpx; + flex-shrink: 0; + font-size: 28rpx; + color: #333; + font-weight: 500; + } + .col-original { + width: 140rpx; + flex-shrink: 0; + height: 64rpx; + line-height: 64rpx; + text-align: center; + font-size: 28rpx; + color: #666; + // background: #eef1f5; + border-radius: 8rpx; + margin-right: 100rpx; + } + .col-refund { + flex: 1; + text-align: right; + } + .col-refund-input { + flex: 1; + min-width: 0; + height: 64rpx; + line-height: 64rpx; + padding: 0 16rpx; + font-size: 30rpx; + font-weight: 600; + color: #ff4444; + background: #fff; + border: 2rpx solid #ffb4b4; + border-radius: 8rpx; + box-sizing: border-box; + } + .col-refund-placeholder { + flex: 1; + text-align: center; + font-size: 32rpx; + color: #bbb; + } + .refund-reason { + margin-top: 20rpx; + padding: 20rpx 16rpx; + background: #f8fafc; + border-radius: 12rpx; + border: 1rpx solid #e8edf2; + } + .refund-reason__label { + display: block; + font-size: 26rpx; + color: #666; + margin-bottom: 12rpx; + } + .refund-reason__input { + width: 100%; + height: 72rpx; + padding: 0 20rpx; + font-size: 28rpx; + background: #fff; + border: 1rpx solid #dde3ea; + border-radius: 8rpx; + box-sizing: border-box; + } + .refund-total { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 24rpx; + padding: 20rpx 24rpx; + background: #fff5f5; + border-radius: 12rpx; + border: 1rpx solid #ffd4d4; + } + .refund-total__label { + font-size: 28rpx; + color: #666; + } + .refund-total__amount { + font-size: 40rpx; + font-weight: 700; + color: #ff4444; + } + .refund-modal__confirm { + background: #ff4444 !important; + } + .anniu { + margin-top: 32rpx; + } + } + + .refund-confirm-mask { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background: rgba(0, 0, 0, 0.55); + z-index: 1100; + } + .refund-confirm-dialog { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 580rpx; + background: #fff; + border-radius: 24rpx; + z-index: 1101; + padding: 48rpx 40rpx 36rpx; + box-sizing: border-box; + box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.12); + } + .refund-confirm-dialog__title { + font-size: 36rpx; + font-weight: 700; + color: #1a1a1a; + text-align: center; + margin-bottom: 36rpx; + } + .refund-confirm-dialog__content { + text-align: center; + margin-bottom: 48rpx; + } + .refund-confirm-dialog__line1 { + display: flex; + align-items: baseline; + justify-content: center; + flex-wrap: wrap; + line-height: 1.5; + } + .refund-confirm-dialog__text { + font-size: 30rpx; + color: #333; + } + .refund-confirm-dialog__amount { + font-size: 44rpx; + font-weight: 700; + color: #ff4444; + margin-left: 8rpx; + } + .refund-confirm-dialog__line2 { + display: block; + margin-top: 20rpx; + font-size: 28rpx; + color: #666; + line-height: 1.5; + } + .refund-confirm-dialog__actions { + display: flex; + justify-content: space-between; + gap: 24rpx; + } + .refund-confirm-dialog__btn { + flex: 1; + height: 84rpx; + line-height: 84rpx; + text-align: center; + border-radius: 42rpx; + font-size: 32rpx; + } + .refund-confirm-dialog__btn--cancel { + background: #f5f7fa; + color: #666; + } + .refund-confirm-dialog__btn--ok { + background: #ff4444; + color: #fff; + font-weight: 600; + } .zengsongone.huanche-verify-modal { max-height: 85vh; diff --git a/pages.json b/pages.json index bdf5a00..db6f9f4 100644 --- a/pages.json +++ b/pages.json @@ -14,7 +14,7 @@ "path": "pages/index/index", "style": { "navigationBarTitleText": "首页", - "enablePullDownRefresh": false, + "enablePullDownRefresh": true, "navigationBarBackgroundColor": "#3996FD", "navigationBarTextStyle": "#FFFFFF", "navigationStyle": "custom" diff --git a/pages/index/index.vue b/pages/index/index.vue index 2466ccb..d2e2aa2 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -27,6 +27,8 @@ + @@ -330,6 +332,12 @@