|
|
@@ -0,0 +1,738 @@
|
|
|
+<!--
|
|
|
+ 商城订单申请售后页
|
|
|
+ 供订单详情「申请售后」进入;顾客勾选商品/金额后提交待审核申请,商家在 hdApp 审核
|
|
|
+-->
|
|
|
+<template>
|
|
|
+ <view class="refund-page">
|
|
|
+ <!-- 已有申请:展示进度 -->
|
|
|
+ <template v-if="apply && apply.id">
|
|
|
+ <view class="card-section">
|
|
|
+ <view class="section-title">
|
|
|
+ <text class="title-text">申请进度</text>
|
|
|
+ </view>
|
|
|
+ <view class="status-block">
|
|
|
+ <text class="status-tag" :class="'st-' + apply.status">{{ apply.statusText || statusText(apply.status) }}</text>
|
|
|
+ <view class="status-row">
|
|
|
+ <text class="label">退款金额</text>
|
|
|
+ <text class="price">¥{{ parseFloat(apply.refundPrice) || 0 }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="status-row" v-if="apply.remark">
|
|
|
+ <text class="label">备注</text>
|
|
|
+ <text class="value">{{ apply.remark }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="status-row" v-if="apply.status == 2 && apply.rejectReason">
|
|
|
+ <text class="label">驳回原因</text>
|
|
|
+ <text class="value reject">{{ apply.rejectReason }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="status-row">
|
|
|
+ <text class="label">申请时间</text>
|
|
|
+ <text class="value">{{ apply.addTime || '' }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="bottom-actions" v-if="apply.status == 0">
|
|
|
+ <button class="action-btn cancel-btn" @tap="doCancel">撤销申请</button>
|
|
|
+ </view>
|
|
|
+ <view class="bottom-actions" v-else>
|
|
|
+ <button class="action-btn cancel-btn" @tap="goBack">返回</button>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <!-- 无可申请金额 / 不可申请 -->
|
|
|
+ <template v-else-if="!canApply">
|
|
|
+ <view class="card-section empty-tip">
|
|
|
+ <text>当前订单暂不支持申请售后</text>
|
|
|
+ <text class="sub" v-if="refundDeadlineTip">{{ refundDeadlineTip }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="bottom-actions">
|
|
|
+ <button class="action-btn cancel-btn" @tap="goBack">返回</button>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <!-- 申请表单 -->
|
|
|
+ <template v-else>
|
|
|
+ <view class="tip-bar" v-if="refundDeadlineTip">
|
|
|
+ <text>{{ refundDeadlineTip }}</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 退款方式 -->
|
|
|
+ <view class="card-section">
|
|
|
+ <view class="section-title">
|
|
|
+ <text class="title-text">退款方式</text>
|
|
|
+ </view>
|
|
|
+ <view class="refund-type-buttons">
|
|
|
+ <button
|
|
|
+ class="type-btn"
|
|
|
+ :class="refundType == 1 ? 'active' : ''"
|
|
|
+ @tap="refundType = 1"
|
|
|
+ >退货并退款</button>
|
|
|
+ <button
|
|
|
+ class="type-btn"
|
|
|
+ :class="refundType == 2 ? 'active' : ''"
|
|
|
+ @tap="onOnlyRefund"
|
|
|
+ >只退款</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 商品选择(退货并退款) -->
|
|
|
+ <view class="card-section" v-if="refundType == 1">
|
|
|
+ <view class="section-title">
|
|
|
+ <text class="title-text">退货商品</text>
|
|
|
+ </view>
|
|
|
+ <view class="product-list-compact">
|
|
|
+ <template v-if="!$util.isEmpty(goodsInfoList)">
|
|
|
+ <!-- key 勿用 'g'+i 字符串拼接:会随 v-model 编进 data-event-opts 导致小程序编译失败 -->
|
|
|
+ <view class="product-row" v-for="(res, i) in goodsInfoList" :key="res.goodsId || i">
|
|
|
+ <view class="product-basic-info">
|
|
|
+ <text class="product-name-compact">{{ res.name }}</text>
|
|
|
+ <view class="product-meta">
|
|
|
+ <text class="stock-info">{{ parseFloat(res.num) }}份 × ¥{{ parseFloat(res.unitPrice) }}</text>
|
|
|
+ <text class="available-info">可退 {{ getRemainNum(res) }}份</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="refund-control">
|
|
|
+ <view class="input-item">
|
|
|
+ <text class="input-label">数量</text>
|
|
|
+ <input
|
|
|
+ class="refund-input-compact"
|
|
|
+ type="number"
|
|
|
+ placeholder="0"
|
|
|
+ :value="res.refundCount"
|
|
|
+ placeholder-style="color:#ccc"
|
|
|
+ @input="onGoodsCountInput(i, $event)"
|
|
|
+ />
|
|
|
+ <text class="unit-label">份</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ <template v-if="!$util.isEmpty(itemInfoList)">
|
|
|
+ <view class="product-row" v-for="(res, i) in itemInfoList" :key="res.itemId || i">
|
|
|
+ <view class="product-basic-info">
|
|
|
+ <text class="product-name-compact">{{ res.name }}</text>
|
|
|
+ <view class="product-meta">
|
|
|
+ <text class="stock-info">{{ parseFloat(res.num) }}{{ res.unitName || '份' }} × ¥{{ parseFloat(res.unitPrice) }}</text>
|
|
|
+ <text class="available-info">可退 {{ getRemainNum(res) }}{{ res.unitName || '份' }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="refund-control">
|
|
|
+ <view class="input-item">
|
|
|
+ <text class="input-label">数量</text>
|
|
|
+ <input
|
|
|
+ class="refund-input-compact"
|
|
|
+ type="number"
|
|
|
+ placeholder="0"
|
|
|
+ :value="res.refundCount"
|
|
|
+ placeholder-style="color:#ccc"
|
|
|
+ @input="onItemCountInput(i, $event)"
|
|
|
+ />
|
|
|
+ <text class="unit-label">{{ res.unitName || '份' }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ <view v-if="$util.isEmpty(goodsInfoList) && $util.isEmpty(itemInfoList)" class="empty-tip">
|
|
|
+ <text>暂无可退商品</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 金额信息 -->
|
|
|
+ <view class="card-section">
|
|
|
+ <view class="section-title">
|
|
|
+ <text class="title-text">金额信息</text>
|
|
|
+ </view>
|
|
|
+ <view class="amount-info">
|
|
|
+ <view class="amount-row">
|
|
|
+ <text class="amount-label">订单金额</text>
|
|
|
+ <text class="amount-value">¥{{ parseFloat(orderInfo.orderPrice) || 0 }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="amount-row" v-if="hasTkPrice">
|
|
|
+ <text class="amount-label">已退金额</text>
|
|
|
+ <text class="amount-value">¥{{ parseFloat(orderInfo.tkPrice) || 0 }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="amount-row">
|
|
|
+ <text class="amount-label">可退金额</text>
|
|
|
+ <text class="amount-value available">¥{{ couldRefundPrice }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="amount-row" v-if="hasHbAmount">
|
|
|
+ <text class="amount-label">红包减免</text>
|
|
|
+ <text class="amount-value">¥{{ parseFloat(orderInfo.hbAmount) || 0 }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="amount-row">
|
|
|
+ <text class="amount-label required">退款金额</text>
|
|
|
+ <text class="amount-value refund-money">¥{{ refundMoney }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="amount-hint" v-if="refundType == 1">按勾选数量自动计算,不可修改</view>
|
|
|
+ <view class="amount-hint" v-else>仅退款默认按可退金额申请,全额退清后未过期红包将自动退回</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 备注 -->
|
|
|
+ <view class="card-section">
|
|
|
+ <view class="section-title">
|
|
|
+ <text class="title-text">备注</text>
|
|
|
+ </view>
|
|
|
+ <view class="remark-container">
|
|
|
+ <textarea
|
|
|
+ class="remark-textarea"
|
|
|
+ v-model="remark"
|
|
|
+ placeholder="选填,说明售后原因"
|
|
|
+ placeholder-style="color:#999"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="bottom-actions">
|
|
|
+ <button class="action-btn cancel-btn" @tap="goBack">取消</button>
|
|
|
+ <button class="action-btn confirm-btn" @tap="askSubmit">提交申请</button>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getRefundData, createRefund, cancelRefund } from '@/api/refund'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'orderRefund',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ orderInfo: {},
|
|
|
+ goodsInfoList: [],
|
|
|
+ itemInfoList: [],
|
|
|
+ couldRefundPrice: 0,
|
|
|
+ refundType: 1,
|
|
|
+ remark: '',
|
|
|
+ apply: null,
|
|
|
+ canApply: 0,
|
|
|
+ refundDeadlineTip: '',
|
|
|
+ submitting: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ /** 是否展示已退金额行(避免模板里写 > 比较,兼容小程序 WXML) */
|
|
|
+ hasTkPrice() {
|
|
|
+ return Number(this.orderInfo.tkPrice) > 0
|
|
|
+ },
|
|
|
+ /** 是否展示红包减免行 */
|
|
|
+ hasHbAmount() {
|
|
|
+ return this.orderInfo.hbAmount && Number(this.orderInfo.hbAmount) > 0
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 退款金额:退货并退款按勾选数量×单价;仅退款用可退金额
|
|
|
+ */
|
|
|
+ refundMoney() {
|
|
|
+ if (this.refundType == 2) {
|
|
|
+ return this.couldRefundPrice
|
|
|
+ }
|
|
|
+ let price = 0
|
|
|
+ ;(this.goodsInfoList || []).forEach(item => {
|
|
|
+ const count = Number(item.refundCount) || 0
|
|
|
+ if (count > 0) {
|
|
|
+ price += count * Number(item.unitPrice || 0)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ ;(this.itemInfoList || []).forEach(item => {
|
|
|
+ const count = Number(item.refundCount) || 0
|
|
|
+ if (count > 0) {
|
|
|
+ price += count * Number(item.unitPrice || 0)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return parseFloat(price.toFixed(2))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ statusText(status) {
|
|
|
+ const map = { 0: '待审核', 1: '已通过', 2: '已驳回', 3: '已取消' }
|
|
|
+ return map[status] || ''
|
|
|
+ },
|
|
|
+ /** 可退剩余数量 */
|
|
|
+ getRemainNum(res) {
|
|
|
+ return Number(res.num) - Number(res.refundNum || 0)
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 成品退货数量输入
|
|
|
+ * 不用 v-model 绑 v-for 项,避免 key 表达式写入 data-event-opts
|
|
|
+ */
|
|
|
+ onGoodsCountInput(index, e) {
|
|
|
+ const val = e && e.detail ? e.detail.value : ''
|
|
|
+ this.$set(this.goodsInfoList[index], 'refundCount', val)
|
|
|
+ },
|
|
|
+ /** 单品退货数量输入 */
|
|
|
+ onItemCountInput(index, e) {
|
|
|
+ const val = e && e.detail ? e.detail.value : ''
|
|
|
+ this.$set(this.itemInfoList[index], 'refundCount', val)
|
|
|
+ },
|
|
|
+ goBack() {
|
|
|
+ uni.navigateBack({ delta: 1 })
|
|
|
+ },
|
|
|
+ /** 切换为只退款 */
|
|
|
+ onOnlyRefund() {
|
|
|
+ this.refundType = 2
|
|
|
+ },
|
|
|
+ init() {
|
|
|
+ const id = this.option.id
|
|
|
+ if (!id) {
|
|
|
+ this.$msg('缺少订单信息')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.showLoading({ mask: true })
|
|
|
+ getRefundData({ id }).then(res => {
|
|
|
+ uni.hideLoading()
|
|
|
+ if (res.code != 1) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const data = res.data || {}
|
|
|
+ this.orderInfo = data.orderInfo || {}
|
|
|
+ this.couldRefundPrice = Number(data.couldRefundPrice) || 0
|
|
|
+ this.apply = data.apply || null
|
|
|
+ this.canApply = data.canApply || 0
|
|
|
+ this.refundDeadlineTip = data.refundDeadlineTip || ''
|
|
|
+ this.goodsInfoList = (data.goodsInfoList || []).map(ele => ({
|
|
|
+ ...ele,
|
|
|
+ refundCount: '',
|
|
|
+ refundNum: ele.refundNum || 0
|
|
|
+ }))
|
|
|
+ this.itemInfoList = (data.itemInfoList || []).map(ele => ({
|
|
|
+ ...ele,
|
|
|
+ refundCount: '',
|
|
|
+ refundNum: ele.refundNum || 0
|
|
|
+ }))
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 组装勾选商品参数并校验数量
|
|
|
+ */
|
|
|
+ buildProduct() {
|
|
|
+ const selectProduct = []
|
|
|
+ let hasError = false
|
|
|
+ ;(this.goodsInfoList || []).forEach(ele => {
|
|
|
+ const count = Number(ele.refundCount) || 0
|
|
|
+ const remain = Number(ele.num) - Number(ele.refundNum || 0)
|
|
|
+ if (count > remain) {
|
|
|
+ this.$msg(ele.name + '超过可退数量')
|
|
|
+ hasError = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (count > 0) {
|
|
|
+ selectProduct.push({
|
|
|
+ productId: ele.goodsId,
|
|
|
+ name: ele.name || '',
|
|
|
+ num: count,
|
|
|
+ unitType: ele.unitType || 0,
|
|
|
+ unitName: ele.unitName || '份',
|
|
|
+ unitPrice: ele.unitPrice,
|
|
|
+ property: 0
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ ;(this.itemInfoList || []).forEach(ele => {
|
|
|
+ const count = Number(ele.refundCount) || 0
|
|
|
+ const remain = Number(ele.num) - Number(ele.refundNum || 0)
|
|
|
+ if (count > remain) {
|
|
|
+ this.$msg(ele.name + '超过可退数量')
|
|
|
+ hasError = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (count > 0) {
|
|
|
+ selectProduct.push({
|
|
|
+ productId: ele.itemId,
|
|
|
+ name: ele.name || '',
|
|
|
+ num: count,
|
|
|
+ unitType: ele.unitType || 0,
|
|
|
+ unitName: ele.unitName || '',
|
|
|
+ unitPrice: ele.unitPrice,
|
|
|
+ property: 1
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return { selectProduct, hasError }
|
|
|
+ },
|
|
|
+ askSubmit() {
|
|
|
+ if (this.submitting) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ let selectProduct = []
|
|
|
+ if (this.refundType == 1) {
|
|
|
+ const built = this.buildProduct()
|
|
|
+ if (built.hasError) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ selectProduct = built.selectProduct
|
|
|
+ if (this.$util.isEmpty(selectProduct)) {
|
|
|
+ this.$msg('请选择要退的商品')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (Number(this.refundMoney) <= 0) {
|
|
|
+ this.$msg('退款金额必须大于0')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (Number(this.refundMoney) > Number(this.couldRefundPrice)) {
|
|
|
+ this.$msg('退款金额超过可退金额')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.showModal({
|
|
|
+ title: '确认提交',
|
|
|
+ content: '申请退款 ¥' + this.refundMoney + ',提交后需商家审核',
|
|
|
+ success: res => {
|
|
|
+ if (res.confirm) {
|
|
|
+ this.doSubmit(selectProduct)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ doSubmit(selectProduct) {
|
|
|
+ this.submitting = true
|
|
|
+ uni.showLoading({ mask: true, title: '提交中' })
|
|
|
+ const params = {
|
|
|
+ id: this.option.id,
|
|
|
+ price: this.refundMoney,
|
|
|
+ remark: this.remark,
|
|
|
+ refundType: this.refundType,
|
|
|
+ product: JSON.stringify(selectProduct || [])
|
|
|
+ }
|
|
|
+ createRefund(params).then(res => {
|
|
|
+ uni.hideLoading()
|
|
|
+ this.submitting = false
|
|
|
+ if (res.code == 1) {
|
|
|
+ this.$msg(res.msg || '提交成功')
|
|
|
+ this.init()
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ this.submitting = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ doCancel() {
|
|
|
+ if (!this.apply || !this.apply.id) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.showModal({
|
|
|
+ title: '提示',
|
|
|
+ content: '确认撤销该售后申请?',
|
|
|
+ success: res => {
|
|
|
+ if (!res.confirm) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.showLoading({ mask: true })
|
|
|
+ cancelRefund({ id: this.apply.id }).then(r => {
|
|
|
+ uni.hideLoading()
|
|
|
+ if (r.code == 1) {
|
|
|
+ this.$msg('已撤销')
|
|
|
+ this.apply = null
|
|
|
+ this.init()
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.refund-page {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: #f5f6f8;
|
|
|
+ padding: 20upx 0 200upx;
|
|
|
+}
|
|
|
+
|
|
|
+.tip-bar {
|
|
|
+ margin: 0 20upx 20upx;
|
|
|
+ padding: 20upx;
|
|
|
+ background: #fff5f5;
|
|
|
+ border: 1upx solid #ffd6dc;
|
|
|
+ border-radius: 12upx;
|
|
|
+ color: $mainColor;
|
|
|
+ font-size: 24upx;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+
|
|
|
+.card-section {
|
|
|
+ background: #fff;
|
|
|
+ margin: 0 20upx 20upx;
|
|
|
+ border-radius: 16upx;
|
|
|
+ box-shadow: 0 2upx 12upx rgba(0, 0, 0, 0.06);
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.section-title {
|
|
|
+ padding: 30upx 30upx 20upx;
|
|
|
+ border-bottom: 1upx solid #f0f0f0;
|
|
|
+ .title-text {
|
|
|
+ font-size: 32upx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.refund-type-buttons {
|
|
|
+ padding: 30upx;
|
|
|
+ display: flex;
|
|
|
+ .type-btn {
|
|
|
+ flex: 1;
|
|
|
+ height: 80upx;
|
|
|
+ line-height: 80upx;
|
|
|
+ border-radius: 40upx;
|
|
|
+ font-size: 28upx;
|
|
|
+ background: #f8f9fa;
|
|
|
+ color: #666;
|
|
|
+ border: 1upx solid #ddd;
|
|
|
+ margin-right: 24upx;
|
|
|
+ &:last-child {
|
|
|
+ margin-right: 0;
|
|
|
+ }
|
|
|
+ &.active {
|
|
|
+ background: linear-gradient(135deg, #ff8fa3, #ff4d6d);
|
|
|
+ color: #fff;
|
|
|
+ border-color: transparent;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.product-list-compact {
|
|
|
+ padding: 0 20upx 20upx;
|
|
|
+ margin-top: 10upx;
|
|
|
+}
|
|
|
+
|
|
|
+.product-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 20upx;
|
|
|
+ margin-top: 12upx;
|
|
|
+ background: #fafbfc;
|
|
|
+ border-radius: 8upx;
|
|
|
+ border: 1upx solid #eef0f2;
|
|
|
+ &:first-child {
|
|
|
+ margin-top: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.product-basic-info {
|
|
|
+ flex: 1;
|
|
|
+ margin-right: 16upx;
|
|
|
+ .product-name-compact {
|
|
|
+ font-size: 30upx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 8upx;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ max-width: 380upx;
|
|
|
+ }
|
|
|
+ .product-meta {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ .stock-info {
|
|
|
+ font-size: 24upx;
|
|
|
+ color: #666;
|
|
|
+ background: #f5f5f5;
|
|
|
+ padding: 4upx 8upx;
|
|
|
+ border-radius: 4upx;
|
|
|
+ margin-right: 12upx;
|
|
|
+ }
|
|
|
+ .available-info {
|
|
|
+ font-size: 24upx;
|
|
|
+ color: $mainColor;
|
|
|
+ background: rgba(255, 40, 66, 0.08);
|
|
|
+ padding: 4upx 8upx;
|
|
|
+ border-radius: 4upx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.refund-control {
|
|
|
+ .input-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .input-label {
|
|
|
+ font-size: 24upx;
|
|
|
+ color: #666;
|
|
|
+ margin-right: 8upx;
|
|
|
+ }
|
|
|
+ .unit-label {
|
|
|
+ font-size: 24upx;
|
|
|
+ color: #666;
|
|
|
+ margin-left: 8upx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .refund-input-compact {
|
|
|
+ width: 100upx;
|
|
|
+ height: 60upx;
|
|
|
+ background: #fff;
|
|
|
+ border: 1upx solid #ddd;
|
|
|
+ border-radius: 6upx;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 26upx;
|
|
|
+ color: #333;
|
|
|
+ &:focus {
|
|
|
+ border-color: $mainColor;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.amount-info {
|
|
|
+ padding: 20upx 30upx 30upx;
|
|
|
+}
|
|
|
+.amount-row {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 18upx 0;
|
|
|
+ border-bottom: 1upx solid #f0f0f0;
|
|
|
+ &:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+ .amount-label {
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #666;
|
|
|
+ &.required::after {
|
|
|
+ content: '*';
|
|
|
+ color: $mainColor;
|
|
|
+ margin-left: 4upx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .amount-value {
|
|
|
+ font-size: 30upx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ &.available {
|
|
|
+ color: $mainColor;
|
|
|
+ }
|
|
|
+ &.refund-money {
|
|
|
+ color: $mainColor;
|
|
|
+ font-size: 36upx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.amount-hint {
|
|
|
+ font-size: 22upx;
|
|
|
+ color: #999;
|
|
|
+ margin-top: 8upx;
|
|
|
+ line-height: 1.4;
|
|
|
+}
|
|
|
+
|
|
|
+.remark-container {
|
|
|
+ padding: 20upx 30upx 30upx;
|
|
|
+}
|
|
|
+.remark-textarea {
|
|
|
+ width: 100%;
|
|
|
+ height: 140upx;
|
|
|
+ background: #fafbfc;
|
|
|
+ border: 1upx solid #ddd;
|
|
|
+ border-radius: 8upx;
|
|
|
+ padding: 16upx;
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #333;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.status-block {
|
|
|
+ padding: 30upx;
|
|
|
+ .status-tag {
|
|
|
+ display: inline-block;
|
|
|
+ padding: 8upx 20upx;
|
|
|
+ border-radius: 8upx;
|
|
|
+ font-size: 26upx;
|
|
|
+ margin-bottom: 24upx;
|
|
|
+ &.st-0 {
|
|
|
+ background: #fff7e6;
|
|
|
+ color: #fa8c16;
|
|
|
+ }
|
|
|
+ &.st-1 {
|
|
|
+ background: rgba(255, 40, 66, 0.1);
|
|
|
+ color: $mainColor;
|
|
|
+ }
|
|
|
+ &.st-2 {
|
|
|
+ background: #fff1f0;
|
|
|
+ color: #ff4757;
|
|
|
+ }
|
|
|
+ &.st-3 {
|
|
|
+ background: #f5f5f5;
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .status-row {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 14upx 0;
|
|
|
+ font-size: 28upx;
|
|
|
+ .label {
|
|
|
+ color: #666;
|
|
|
+ }
|
|
|
+ .price {
|
|
|
+ color: $mainColor;
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 32upx;
|
|
|
+ }
|
|
|
+ .value {
|
|
|
+ color: #333;
|
|
|
+ max-width: 70%;
|
|
|
+ text-align: right;
|
|
|
+ &.reject {
|
|
|
+ color: #ff4757;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.empty-tip {
|
|
|
+ padding: 60upx 30upx;
|
|
|
+ text-align: center;
|
|
|
+ color: #999;
|
|
|
+ font-size: 28upx;
|
|
|
+ .sub {
|
|
|
+ display: block;
|
|
|
+ margin-top: 16upx;
|
|
|
+ font-size: 24upx;
|
|
|
+ color: $mainColor;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.bottom-actions {
|
|
|
+ z-index: 39;
|
|
|
+ position: fixed;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ background: #fff;
|
|
|
+ padding: 24upx 30upx;
|
|
|
+ padding-bottom: calc(24upx + env(safe-area-inset-bottom));
|
|
|
+ border-top: 1upx solid #eee;
|
|
|
+ display: flex;
|
|
|
+ box-shadow: 0 -4upx 12upx rgba(0, 0, 0, 0.06);
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn {
|
|
|
+ flex: 1;
|
|
|
+ height: 88upx;
|
|
|
+ line-height: 88upx;
|
|
|
+ border-radius: 44upx;
|
|
|
+ font-size: 32upx;
|
|
|
+ font-weight: 600;
|
|
|
+ border: none;
|
|
|
+ margin-right: 24upx;
|
|
|
+ &:last-child {
|
|
|
+ margin-right: 0;
|
|
|
+ }
|
|
|
+ &.cancel-btn {
|
|
|
+ background: #f8f9fa;
|
|
|
+ color: #666;
|
|
|
+ border: 1upx solid #ddd;
|
|
|
+ }
|
|
|
+ &.confirm-btn {
|
|
|
+ background: linear-gradient(135deg, #ff8fa3, #ff4d6d);
|
|
|
+ color: #fff;
|
|
|
+ box-shadow: 0 4upx 12upx rgba(255, 77, 109, 0.3);
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|