liushengqiang il y a 1 an
Parent
commit
bd4a646c07

+ 16 - 0
src/router/routes-common.ts

@@ -83,6 +83,22 @@ export default [
           title: '教材列表'
         }
       },
+      {
+        path: '/collection-record',
+        name: 'collection-record',
+        component: () => import('@/views/collection-record/index'),
+        meta: {
+          title: '领取记录'
+        }
+      },
+      {
+        path: '/collection-record-detail',
+        name: 'collection-record-detail',
+        component: () => import('@/views/collection-record-detail/index'),
+        meta: {
+          title: '领取详情'
+        }
+      },
     ]
   },
   ...rootRouter

+ 28 - 0
src/styles/index.less

@@ -235,3 +235,31 @@ body {
     margin-left: 15px;
   }
 }
+
+
+.van-overlay {
+  transition: all 0.25s;
+}
+
+.popup-custom {
+  transition: all 0.25s;
+  background: transparent;
+  overflow: initial;
+  max-width: 100%;
+}
+
+.popup-custom.van-scale {
+  transform-origin: center -25%;
+}
+
+/* 缩放动画 */
+.van-scale-enter-from,
+.van-scale-leave-to {
+  opacity: 0;
+  transform: scale(0.3);
+}
+
+.van-scale-enter-active,
+.van-scale-leave-active {
+  transition: all 0.25s;
+}

+ 18 - 0
src/views/collection-record-detail/images/icon_close.svg

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="52px" height="52px" viewBox="0 0 52 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>交易关闭</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFBFE" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="报名缴费" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="画板备份-2" transform="translate(-93.000000, -98.000000)">
+            <g id="交易关闭" transform="translate(93.000000, 98.000000)">
+                <rect id="矩形" x="0" y="0" width="52" height="52"></rect>
+                <path d="M26,52 C40.3594035,52 52,40.3594035 52,26 C52,11.6405965 40.3594035,0 26,0 C11.6405965,0 0,11.6405965 0,26 C0,40.3594035 11.6405965,52 26,52 Z M28.9839727,26.0090953 L36.9549872,33.9801098 L33.9710145,36.9640825 L26,28.993068 L18.0289855,36.9640825 L15.044075,33.9801098 L23.0150895,26.0090953 L14.955925,17.948993 L17.9398977,14.9640825 L26,23.0241848 L34.0601023,14.9640825 L37.044075,17.9480553 L28.9839727,26.0081576 L28.9839727,26.0090953 Z" id="形状结合" fill="url(#linearGradient-1)"></path>
+            </g>
+        </g>
+    </g>
+</svg>

Fichier diff supprimé car celui-ci est trop grand
+ 13 - 0
src/views/collection-record-detail/images/icon_refunding.svg


+ 18 - 0
src/views/collection-record-detail/images/icon_success.svg

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="52px" height="52px" viewBox="0 0 52 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>交易成功</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFBFE" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="报名缴费" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="画板备份-2" transform="translate(-494.000000, -206.000000)">
+            <g id="交易成功" transform="translate(494.000000, 206.000000)">
+                <rect id="矩形" x="0" y="0" width="52" height="52"></rect>
+                <path d="M26,0 C40.3594035,0 52,11.6405965 52,26 C52,40.3594035 40.3594035,52 26,52 C11.6405965,52 0,40.3594035 0,26 C0,11.6405965 11.6405965,0 26,0 Z M35.4700867,17 L24.0422711,28.3030329 L19.0107622,21.6516598 L15,24.768585 L23.4969475,36 L39,20.6660483 L35.4700867,17 Z" id="形状结合" fill="url(#linearGradient-1)"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 18 - 0
src/views/collection-record-detail/images/icon_tradeing.svg

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="52px" height="52px" viewBox="0 0 52 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>交易成功</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFBFE" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="报名缴费" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="画板备份-2" transform="translate(-499.000000, -98.000000)">
+            <g id="交易成功" transform="translate(499.000000, 98.000000)">
+                <rect id="矩形" x="0" y="0" width="52" height="52"></rect>
+                <path d="M26,52 C40.3594035,52 52,40.3594035 52,26 C52,11.6405965 40.3594035,0 26,0 C11.6405965,0 0,11.6405965 0,26 C0,40.3594035 11.6405965,52 26,52 Z M14,29 C15.6568542,29 17,27.6568542 17,26 C17,24.3431458 15.6568542,23 14,23 C12.3431458,23 11,24.3431458 11,26 C11,27.6568542 12.3431458,29 14,29 Z M26,29 C27.6568542,29 29,27.6568542 29,26 C29,24.3431458 27.6568542,23 26,23 C24.3431458,23 23,24.3431458 23,26 C23,27.6568542 24.3431458,29 26,29 Z M38,29 C39.6568542,29 41,27.6568542 41,26 C41,24.3431458 39.6568542,23 38,23 C36.3431458,23 35,24.3431458 35,26 C35,27.6568542 36.3431458,29 38,29 Z" id="形状结合" fill="url(#linearGradient-1)"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 272 - 0
src/views/collection-record-detail/index.module.less

@@ -0,0 +1,272 @@
+.paymentTitle {
+    min-height: 177px;
+    background: linear-gradient(180deg, rgba(91, 236, 255, 1) 0%, rgba(37, 156, 254, 1) 100%);
+    border-radius: 0px 0px 8px 8px;
+
+    :global {
+
+        .van-nav-bar .van-icon,
+        .van-nav-bar__title {
+            color: #fff;
+        }
+    }
+
+    .orderType {
+        padding-top: 35px;
+        padding-bottom: 90px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        color: #fff;
+
+        .img {
+            width: 52px;
+            height: 52px;
+            margin-right: 14px;
+        }
+
+        span {
+            font-size: 22px;
+            font-weight: 500;
+            line-height: 30px;
+        }
+    }
+
+    .orderPrice {
+        padding-top: 2px;
+        font-size: 22px;
+        text-align: center;
+        font-size: 14px;
+    }
+}
+
+.mTop {
+    margin-top: -52px !important;
+}
+
+.cellGroup {
+    margin: 10px 13px;
+
+    .brandName {
+        line-height: 18px;
+        font-size: 12px;
+        padding: 0 6px;
+        border-radius: 4px;
+        background: linear-gradient(180deg, #FFF5E6 0%, #FFF6E7 100%);
+        border-radius: 4px;
+        border: 1px solid #FFE9D9;
+        color: #BE7332;
+    }
+
+    :global {
+        .van-cell {
+            padding: 16px 17px;
+            font-size: 16px;
+            color: #333333;
+        }
+
+        .van-cell__value {
+            flex: 0 auto;
+        }
+    }
+
+    .buyDetail {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 18px 18px 0;
+
+        i {
+            display: inline-block;
+            margin-right: 6px;
+            width: 4px;
+            height: 14px;
+            background: linear-gradient(180deg, #FFB790 0%, #FF8057 100%);
+            border-radius: 2px;
+        }
+
+        font-size: 16px;
+        font-weight: 500;
+        color: #333333;
+        line-height: 22px;
+
+        .buyDetailTitle {
+            display: flex;
+            align-items: center;
+        }
+
+        .refundBtn {
+            font-size: 16px;
+            color: #777777;
+            line-height: 22px;
+        }
+    }
+
+    .buyImg {
+        width: 58px;
+        height: 58px;
+        overflow: hidden;
+        border-radius: 5px;
+        margin-right: 9px;
+    }
+}
+
+.container {
+    :global {
+        .van-button {
+            font-size: 18px;
+            font-weight: 500;
+        }
+    }
+}
+
+.dialogTitle {
+    i {
+        display: inline-block;
+        width: 4px;
+        height: 14px;
+        background: #ff8057;
+        border-radius: 2px;
+        margin-right: 6px;
+    }
+
+    text-align: left;
+    font-size: 18px;
+    font-weight: 500;
+    color: #333333;
+    line-height: 25px;
+    padding: 20px 0 15px 25px;
+}
+
+.refundContent {
+    padding: 0 20px 25px;
+
+    .tips {
+        font-size: 15px;
+        color: #333333;
+        line-height: 21px;
+    }
+}
+
+.refundTitle {
+    padding-top: 25px;
+    font-size: 16px;
+    font-weight: 600;
+    color: #333333;
+    line-height: 22px;
+
+    span {
+        color: #f44541;
+    }
+}
+
+.phoneName {
+    background: #f2f2f2;
+    border-radius: 6px;
+}
+
+.cancelBtn {
+    height: 44px;
+    border: none;
+    background: linear-gradient(73deg, #5BECFF 0%, #259CFE 100%);
+    font-size: 16px;
+    font-weight: 500;
+    margin: 20px auto;
+    width: 88%;
+    &.orderNo{
+        background: #fff;
+        color: #777;
+        border: 1Px solid #777;
+    }
+}
+
+.cancelBox {
+    margin: 0 25px;
+    background: #FFFFFF;
+    border-radius: 10px;
+    overflow: hidden;
+
+    .boxContent {
+        padding: 20px;
+    }
+
+    .titleTag {
+        width: 4px;
+        height: 13px;
+        background: #FF8057 linear-gradient(73deg, #5BECFF 0%, #259CFE 100%);
+        border-radius: 2px;
+        margin-right: 6px;
+    }
+
+    .title {
+        display: flex;
+        align-items: center;
+        height: 25px;
+        font-size: 18px;
+        font-weight: 500;
+        color: #333333;
+        line-height: 25px;
+    }
+
+    .des {
+        padding: 15px 0;
+        font-size: 15px;
+        font-weight: 400;
+        color: #333333;
+        line-height: 21px;
+    }
+
+    .radioTitle {
+        font-size: 16px;
+        font-weight: 600;
+        color: rgba(51, 51, 51, 1);
+        line-height: 22px;
+    }
+
+    .radioDes {
+        padding: 10px;
+        background: #F2F2F2;
+        border-radius: 6px;
+        font-size: 15px;
+        font-weight: 400;
+        color: #333333;
+        line-height: 21px;
+
+        :global {
+            .van-field {
+                padding: 0;
+                background: transparent;
+            }
+        }
+    }
+
+    :global {
+        .van-cell {
+            padding: 18px 0;
+
+            &::after {
+                left: 0;
+                right: 0;
+            }
+        }
+    }
+
+    .radioBtns {
+        display: flex;
+        border-top: 1Px solid #F2F2F2;
+
+        :global {
+            .van-button {
+                border: none;
+                border-radius: 0;
+                font-size: 18px;
+                font-weight: 500;
+            }
+
+            .van-button:first-child {
+                border-right: 1Px solid #F2F2F2;
+                color: #777;
+            }
+        }
+    }
+}

+ 359 - 0
src/views/collection-record-detail/index.tsx

@@ -0,0 +1,359 @@
+import MHeader from '@/components/m-header';
+import { defineComponent, onMounted, reactive } from 'vue';
+import {
+  Button,
+  Cell,
+  CellGroup,
+  Field,
+  Image,
+  Popup,
+  Radio,
+  RadioGroup,
+  Tag,
+  showToast
+} from 'vant';
+import styles from './index.module.less';
+import iconRefunding from './images/icon_refunding.svg';
+import icon_success from './images/icon_success.svg';
+import iconClose from './images/icon_close.svg';
+import iconTradeing from './images/icon_tradeing.svg';
+import { useRoute, useRouter } from 'vue-router';
+import { browser, moneyFormat } from '@/helpers/utils';
+import { useEventListener, useWindowScroll } from '@vueuse/core';
+import {
+    api_userPaymentOrderCancelRefund,
+  api_userPaymentOrderDetail,
+  api_userPaymentOrderRefundPayment
+} from '../collection-record/api';
+import * as detailState from '@/state';
+
+export default defineComponent({
+  name: 'collection-record-detail',
+  setup() {
+    const route = useRoute();
+    const router = useRouter();
+    const state = reactive({
+      refund: route.query.refund,
+      orders: {} as any,
+      goodsInfos: [] as any,
+      background: 'transparent',
+      color: '#fff',
+      backIconColor: 'white' as any,
+      timer: null as any,
+      timerCount: 0 // 执行次数
+    });
+    const getDetails = async () => {
+      try {
+        if (!route.query.orderNo) return;
+        const { data } = await api_userPaymentOrderDetail(route.query.orderNo);
+
+        state.orders = data || {};
+        // state.orders.status = 'REFUNDED'
+        const tempGoods = data.goodsInfos || [];
+        tempGoods.forEach((item: any) => {
+          const img = item.goodsUrl ? item.goodsUrl.split(',')[0] : '';
+          item.goodsUrl = img;
+        });
+        state.goodsInfos = tempGoods;
+      } catch {
+        //
+      }
+    };
+
+    // 定时任务
+    const onTimeout = async () => {
+      // 判断订单状态,如果未支付则刷新
+      if (
+        ['WAIT_PAY', 'PAYING'].includes(state.orders.status) &&
+        state.timerCount <= 10
+      ) {
+        state.timer = setTimeout(async () => {
+          state.timerCount += 1;
+          await getDetails();
+          onTimeout();
+        }, 3000);
+      } else {
+        clearTimeout(state.timer);
+      }
+    };
+
+    const formatImg = (type: any) => {
+      const template: any = {
+        WAIT_PAY: iconTradeing,
+        PAYING: iconTradeing,
+        PAID: icon_success,
+        TIMEOUT: iconClose,
+        FAIL: iconClose,
+        CLOSED: iconClose,
+        REFUNDING: iconRefunding,
+        REFUNDED: icon_success
+      };
+      return template[type] || icon_success;
+    };
+
+    const formatOrderStatus = (status: string) => {
+      const temp: any = {
+        WAIT_PAY: '支付中',
+        PAYING: '支付中',
+        PAID: '支付成功',
+        TIMEOUT: '订单超时',
+        FAIL: '支付失败',
+        CLOSED: '订单关闭',
+        REFUNDING: '退款中',
+        REFUNDED: '已退款'
+      };
+      return temp[status];
+    };
+
+    onMounted(async () => {
+      await getDetails();
+      await onTimeout();
+      useEventListener(document, 'scroll', () => {
+        const { y } = useWindowScroll();
+        if (y.value > 52) {
+          state.background = '#fff';
+          state.color = '#323333';
+          state.backIconColor = 'black';
+        } else {
+          state.background = 'transparent';
+          state.color = '#fff';
+          state.backIconColor = 'white';
+        }
+      });
+    });
+
+    const data = reactive({
+      open: false
+    });
+    const forms = reactive({
+      refundReason: '',
+      refundReasonDes: ''
+    });
+
+    /** 取消订单 */
+    const handleCancel = async () => {
+      await api_userPaymentOrderRefundPayment({
+        merOrderNo: state.orders.orderNo,
+        serviceCharge: true,
+        paymentClient: 'STUDENT',
+        userId: detailState.state?.user?.data?.id,
+        refundReason:
+          forms.refundReason === '其他原因'
+            ? forms.refundReasonDes
+            : forms.refundReason,
+        userRefundOrderDetails: state.goodsInfos.map((goods: any) => ({
+          userPaymentOrderDetailId: goods.userPaymentOrderId,
+          num: goods.goodsNum
+        }))
+      });
+      showToast('申请退回成功');
+      getDetails();
+    };
+
+    /** 取消退款申请 */
+    const handleBack = async () => {
+        await api_userPaymentOrderCancelRefund(state.orders.orderNo)
+        showToast('撤销退回成功');
+    }
+    return () => (
+      <div class={styles.paymentResult}>
+        <div class={[styles.paymentTitle]}>
+          <MHeader background="transparent" />
+
+          {state.orders.id && (
+            <>
+              <div class={styles.orderType}>
+                <Image
+                  class={styles.img}
+                  src={formatImg(state.orders.status)}
+                />
+                <div class={styles.orderInfo}>
+                  <span>{formatOrderStatus(state.orders.status)}</span>
+                  {state.orders.status === 'PAID' ||
+                  state.orders.status === 'REFUNDING' ? (
+                    <div class={styles.orderPrice}>
+                      实付金额:¥ {moneyFormat(state.orders.paymentCashAmount)}
+                    </div>
+                  ) : (
+                    ''
+                  )}
+
+                  {state.orders.status === 'REFUNDED' && (
+                    <div class={styles.orderPrice}>
+                      退款金额:¥ {moneyFormat(state.orders.paymentCashAmount)}
+                    </div>
+                  )}
+                </div>
+              </div>
+            </>
+          )}
+        </div>
+
+        <CellGroup inset class={[styles.cellGroup, styles.mTop]}>
+          <Cell>
+            {{
+              title: () => '付款时间',
+              value: () => <span>{state.orders.payTime || '--'}</span>
+            }}
+          </Cell>
+          <Cell>
+            {{
+              title: () => '订单编号',
+              value: () => <span>{state.orders.orderNo}</span>
+            }}
+          </Cell>
+        </CellGroup>
+
+        <CellGroup inset class={styles.cellGroup}>
+          <div class={styles.buyDetail}>
+            <div class={styles.buyDetailTitle}>
+              <i></i> 购买详情
+            </div>
+          </div>
+          {state.goodsInfos.map((goods: any) => (
+            <Cell>
+              {{
+                icon: () => (
+                  <Image class={styles.buyImg} src={goods.goodsUrl} />
+                ),
+                title: () => (
+                  <div class={styles.buyContent}>
+                    <p class={styles.goodsTitle}>{goods.goodsName}</p>
+                    <Tag class={styles.brandName}>
+                      {state.orders.orderType === 'VIP'
+                        ? '12个月'
+                        : goods.brandName}
+                    </Tag>
+                  </div>
+                ),
+                value: () => <span>x {goods.goodsNum}</span>
+              }}
+            </Cell>
+          ))}
+        </CellGroup>
+
+        {state.orders.refundAudit === 'ING' && (
+          <Button
+            class={styles.cancelBtn}
+            block
+            round
+            type="primary"
+            onClick={() => handleBack()}>
+            撤销退回
+          </Button>
+        )}
+        {state.orders.refundable && (
+          <Button
+            class={[styles.cancelBtn, styles.orderNo]}
+            block
+            round
+            type="primary"
+            onClick={() => (data.open = true)}>
+            申请退回
+          </Button>
+        )}
+
+        <Popup
+          teleport="body"
+          v-model:show={data.open}
+          class={['popup-custom', 'van-scale']}
+          transition="van-scale">
+          <div class={styles.cancelBox}>
+            <div class={styles.boxContent}>
+              <div class={styles.title}>
+                <div class={styles.titleTag}></div> 申请退回
+              </div>
+              <div class={styles.des}>
+                您将要发起退回,退回需承担千分之六的手续费,确认退回后款项将原路返还到您的付款账户中。
+              </div>
+              <div class={styles.radioTitle}>
+                <span style={{ color: 'rgba(244, 69, 65, 1)' }}>*</span>
+                请选择您的退回原因
+              </div>
+              <RadioGroup v-model={forms.refundReason}>
+                <Cell>
+                  {{
+                    title: () => (
+                      <div>
+                        <Radio name="价格太贵了">价格太贵了</Radio>
+                      </div>
+                    )
+                  }}
+                </Cell>
+                <Cell>
+                  {{
+                    title: () => (
+                      <div>
+                        <Radio name="不喜欢/不想要">不喜欢/不想要</Radio>
+                      </div>
+                    )
+                  }}
+                </Cell>
+                <Cell>
+                  {{
+                    title: () => (
+                      <div>
+                        <Radio name="七天无理由退货">七天无理由退货</Radio>
+                      </div>
+                    )
+                  }}
+                </Cell>
+                <Cell>
+                  {{
+                    title: () => (
+                      <div>
+                        <Radio name="其他原因">其他原因</Radio>
+                      </div>
+                    )
+                  }}
+                </Cell>
+              </RadioGroup>
+              <div
+                class={styles.radioDes}
+                style={{
+                  display: forms.refundReason === '其他原因' ? '' : 'none'
+                }}>
+                <Field
+                  v-model={forms.refundReasonDes}
+                  rows="2"
+                  autosize
+                  label=""
+                  type="textarea"
+                  maxlength="50"
+                  placeholder="在这里填写退回原因"
+                />
+              </div>
+            </div>
+            <div class={styles.radioBtns}>
+              <Button
+                block
+                onClick={() => {
+                  if (!forms.refundReason) {
+                    showToast('请选择退回原因');
+                    return;
+                  }
+                  if (
+                    forms.refundReason === '其他原因' &&
+                    !forms.refundReasonDes
+                  ) {
+                    showToast('请输入退回原因');
+                    return;
+                  }
+                  handleCancel();
+                }}>
+                确认退回
+              </Button>
+              <Button
+                block
+                type="primary"
+                plain
+                onClick={() => (data.open = false)}>
+                取消
+              </Button>
+            </div>
+          </div>
+        </Popup>
+      </div>
+    );
+  }
+});

+ 52 - 0
src/views/collection-record/api.ts

@@ -0,0 +1,52 @@
+import request from '@/helpers/request';
+
+export const type_OrderStatus: { [_: string]: string } = {
+  WAIT_PAY: '待支付',
+  PAYING: '支付中',
+  PAID: '已付款',
+  TIMEOUT: '订单超时',
+  FAIL: '支付失败',
+  CLOSED: '已关闭',
+  REFUNDED: '已退款'
+};
+export interface IApiUserPaymentOrderPage {
+  /** 订单状态,可用值:WAIT_PAY,PAYING,PAID,TIMEOUT,FAIL,CLOSED,REFUNDED */
+  orderStatus:
+    | 'WAIT_PAY'
+    | 'PAYING'
+    | 'PAID'
+    | 'TIMEOUT'
+    | 'FAIL'
+    | 'CLOSED'
+    | 'REFUNDED';
+  /** 分页行数 */
+  rows: number;
+  /** 当前页 */
+  page: number;
+  /** 订单年份, 类似: 2023-06 */
+  paymentYear: string;
+}
+/** 获取领取列表 */
+export const api_userPaymentOrderPage = (
+  params: IApiUserPaymentOrderPage
+): Promise<any> => {
+  return request.post('/edu-app/userPaymentOrder/page', {
+    data: params
+  });
+};
+/** 申请退款 */
+export const api_userPaymentOrderRefundPayment = (
+  params: any
+): Promise<any> => {
+  return request.post('/edu-app/userPaymentOrder/refundPayment', {
+    data: params
+  });
+};
+/** 获取订单详情 */
+export const api_userPaymentOrderDetail = (params: any): Promise<any> => {
+  return request.get(`/edu-app/userPaymentOrder/detail/${params}`);
+};
+/** 取消订单退款 */
+export const api_userPaymentOrderCancelRefund = (params: any): Promise<any> => {
+  return request.post(`/edu-app/userPaymentOrder/cancelRefund/${params}`);
+};

+ 42 - 0
src/views/collection-record/component/item-skelete.tsx

@@ -0,0 +1,42 @@
+import {
+  Cell,
+  CellGroup,
+  SkeletonAvatar,
+  SkeletonParagraph,
+  SkeletonTitle
+} from 'vant';
+import { defineComponent } from 'vue';
+import styles from './item.module.less';
+
+export default defineComponent({
+  name: 'collection-record-item-skelete',
+  setup(props) {
+    return () => (
+      <div class={styles.item}>
+        <CellGroup inset>
+          <Cell center>
+            {{
+              title: () => <SkeletonParagraph rowWidth="52%" />,
+              value: () => <SkeletonParagraph />
+            }}
+          </Cell>
+          <Cell center>
+            {{
+              icon: () => <SkeletonAvatar />,
+              title: () => (
+                <div class={styles.name}>
+                  <SkeletonTitle />
+                </div>
+              ),
+              value: () => (
+                <div class={styles.price}>
+                  <SkeletonParagraph />
+                </div>
+              )
+            }}
+          </Cell>
+        </CellGroup>
+      </div>
+    );
+  }
+});

+ 86 - 0
src/views/collection-record/component/item.module.less

@@ -0,0 +1,86 @@
+.item {
+    margin-bottom: 12px;
+
+    :global {
+        .van-cell__title {
+            flex: 1;
+        }
+
+        .van-cell__value {
+            flex-shrink: 0;
+            flex: inherit;
+            min-width: 20%;
+        }
+
+        .van-cell__right-icon {
+            color: rgba(170, 170, 170, 1);
+        }
+    }
+
+    .time {
+        color: #777;
+        font-size: 16px;
+    }
+
+    .state {
+        font-size: 14px;
+
+        &.WAIT_PAY {
+            color: rgba(64, 196, 203, 1);
+        }
+
+        &.PAID {
+            color: rgba(28, 172, 241, 1);
+        }
+
+        &.REFUNDED {
+            color: rgba(255, 162, 68, 1);
+        }
+
+        &.CLOSED {
+            color: rgba(153, 153, 153, 1);
+        }
+    }
+
+    .icon {
+        width: 36px;
+        height: 36px;
+        margin-right: 10px;
+    }
+
+    .name {
+        color: #333;
+        font-size: 16px;
+    }
+
+    .price {
+        font-size: 12px;
+        color: rgba(255, 90, 86, 1);
+    }
+}
+
+.btns {
+    display: flex;
+    align-items: center;
+    padding: 10px 15px;
+
+    :global {
+        .van-button {
+            width: 80px;
+            height: 28px;
+            border-radius: 15px;
+            border: 1px solid #777;
+            padding: 0;
+            font-size: 14px;
+            font-weight: 400;
+            color: #777
+        }
+    }
+}
+
+.cancelBtn {
+    justify-content: center;
+    font-size: 16px;
+    color: #777;
+    line-height: 22px;
+}

+ 89 - 0
src/views/collection-record/component/item.tsx

@@ -0,0 +1,89 @@
+import {
+  Button,
+  Cell,
+  CellGroup,
+} from 'vant';
+import { defineComponent, reactive } from 'vue';
+import styles from './item.module.less';
+import icon_order from '../image/icon_order.svg';
+import { type_OrderStatus } from '../api';
+import { postMessage } from '@/helpers/native-message';
+
+export default defineComponent({
+  name: 'collection-record-item',
+  props: {
+    item: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  emits: ['cancel'],
+  setup(props, { emit }) {
+    
+
+    const handleOpenDetail = () => {
+      if (props.item?.id) {
+        postMessage({
+          api: 'openWebView',
+          content: {
+            url:
+              location.origin +
+              location.pathname +
+              '#/collection-record-detail?orderNo=' +
+              props.item?.orderNo,
+            orientation: 1,
+            isHideTitle: false
+          }
+        });
+      }
+    };
+    return () => (
+      <div class={styles.item} onClick={() => handleOpenDetail()}>
+        <CellGroup inset>
+          <Cell center>
+            {{
+              title: () => (
+                <div class={styles.time}>{props.item.createTime}</div>
+              ),
+              value: () => (
+                <div class={[styles.state, styles[props.item.status]]}>
+                  {type_OrderStatus[props.item.status]}
+                </div>
+              )
+            }}
+          </Cell>
+          <Cell center isLink>
+            {{
+              icon: () => <img class={styles.icon} src={icon_order} />,
+              title: () => (
+                <div class={styles.name}>{props.item.orderName}</div>
+              ),
+              value: () => (
+                <div class={styles.price}>
+                  ¥
+                  <span style={{ fontSize: '0.42667rem' }}>
+                    {props.item.originalPrice}
+                  </span>
+                </div>
+              )
+            }}
+          </Cell>
+          {props.item.status === 'WAIT_PAY' && (
+            <div class={styles.btns}>
+              <Button style={{ margin: '0 11px 0 auto' }} round size="small">
+                取消领取
+              </Button>
+              <Button round size="small">
+                继续领取
+              </Button>
+            </div>
+          )}
+          {props.item.refundable && (
+            <div class={[styles.btns, styles.cancelBtn]}>申请退回</div>
+          )}
+        </CellGroup>
+
+      </div>
+    );
+  }
+});

+ 78 - 0
src/views/collection-record/component/list.tsx

@@ -0,0 +1,78 @@
+import { PropType, defineComponent, onMounted, reactive } from 'vue';
+import {
+  IApiUserPaymentOrderPage,
+  api_userPaymentOrderPage,
+} from '../api';
+import Item from './item';
+import MFullRefresh from '@/components/m-full-refresh';
+import { List, showToast } from 'vant';
+import MEmpty from '@/components/m-empty';
+import ItemSkelete from './item-skelete';
+
+export default defineComponent({
+  name: 'collection-record-list',
+  props: {
+    orderStatus: {
+      type: String as PropType<IApiUserPaymentOrderPage['orderStatus']>,
+      default: ''
+    }
+  },
+  setup(props) {
+    const data = reactive({
+      page: 1,
+      list: [],
+      skelete: true,
+      refreshing: false,
+      finished: false,
+      loading: false
+    });
+    const getList = async () => {
+      data.loading = true;
+      const res = await api_userPaymentOrderPage({
+        page: data.page,
+        rows: 10,
+        orderStatus: props.orderStatus,
+        paymentYear: ''
+      });
+      if (res?.code === 200 && Array.isArray(res?.data?.rows)) {
+        data.list = res.data.rows;
+        data.finished = !res.data.next;
+      }
+      setTimeout(() => {
+        data.refreshing = false;
+      }, 500);
+      data.loading = false;
+      data.skelete = false;
+    };
+    onMounted(() => {
+      getList();
+    });
+    return () => (
+      <MFullRefresh
+        modelValue={data.refreshing}
+        onRefresh={() => {
+          data.refreshing = true;
+          data.finished = false;
+          console.log('下拉');
+          getList();
+        }}>
+        {data.skelete && new Array(5).fill(1).map(i => <ItemSkelete />)}
+
+        {data.list.length !== 0 && (
+          <List
+            loading={data.loading}
+            finished={data.finished}
+            finishedText=" ">
+            {data.list.map(item => {
+              return <Item item={item} />;
+            })}
+          </List>
+        )}
+
+        {!data.skelete && data.list.length === 0 && (
+          <MEmpty description="暂无记录" />
+        )}
+      </MFullRefresh>
+    );
+  }
+});

Fichier diff supprimé car celui-ci est trop grand
+ 14 - 0
src/views/collection-record/image/icon_order.svg


+ 56 - 0
src/views/collection-record/index.module.less

@@ -0,0 +1,56 @@
+.container {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    display: flex;
+    flex-direction: column;
+    height: 100vh;
+}
+
+.content {
+    flex: 1;
+    overflow: hidden;
+
+    :global {
+        .van-tabs {
+            height: 100%;
+        }
+
+        .van-tabs__wrap {
+            height: 44px;
+            --van-tab-text-color: #777;
+            .van-tab {
+                z-index: 2;
+            }
+
+            .van-tabs__line {
+                height: 6px;
+                background: linear-gradient(270deg, rgba(119, 255, 239, 0.59) 0%, #42CDFF 100%);
+                bottom: 0.73rem;
+                z-index: 1;
+            }
+        }
+
+        .van-tabs__content {
+            height: calc(100% - 44px);
+            overflow: hidden;
+        }
+        .van-tab__panel{
+            height: 100%;
+            overflow-x: hidden;
+            overflow-y: auto;
+        }
+    }
+}
+.wrap{
+    padding: 12px 0;
+    :global{
+        .van-list{
+            min-height: 82vh;
+        }
+        .van-empty{
+            height: 70vh;
+        }
+    }
+}

+ 43 - 0
src/views/collection-record/index.tsx

@@ -0,0 +1,43 @@
+import MHeader from '@/components/m-header';
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+import { Tab, Tabs } from 'vant';
+import List from './component/list';
+
+export default defineComponent({
+  name: 'collection-record',
+  setup() {
+    const data = reactive({
+      tab: '1'
+    });
+    return () => (
+      <div class={styles.container}>
+        <MHeader />
+        <div class={styles.content}>
+          <Tabs v-model:active={data.tab} animated swipeable>
+            <Tab name="1" title="待领取">
+              <div class={styles.wrap}>
+                <List orderStatus="WAIT_PAY" />
+              </div>
+            </Tab>
+            <Tab name="2" title="已领取">
+              <div class={styles.wrap}>
+                <List orderStatus="PAID" />
+              </div>
+            </Tab>
+            <Tab name="3" title="已关闭">
+              <div class={styles.wrap}>
+                <List orderStatus="CLOSED" />
+              </div>
+            </Tab>
+            <Tab name="4" title="已退回">
+              <div class={styles.wrap}>
+                <List orderStatus="REFUNDED" />
+              </div>
+            </Tab>
+          </Tabs>
+        </div>
+      </div>
+    );
+  }
+});

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff