From 797fa07355a312a06541ca105a00928e95dbded6 Mon Sep 17 00:00:00 2001
From: zym2525 <540361168@qq.com>
Date: 星期日, 23 二月 2025 14:39:44 +0800
Subject: [PATCH] fix: some

---
 packages/components/src/components/NoData/NoData.vue                                       |   22 
 packages/components/src/components/InfiniteLoading/InfiniteLoading.vue                     |    2 
 packages/components/src/views/Order/components/PhoneOrder.vue                              |   34 
 apps/taro/src/stores/modules/user.ts                                                       |   22 
 apps/taro/src/app.config.ts                                                                |    1 
 packages/components/src/hooks/infiniteLoading.ts                                           |  294 +++++++++
 apps/taro/src/constants/router.ts                                                          |    1 
 packages/components/src/utils/types.ts                                                     |    6 
 apps/taro/src/components/Tabs/ProTabPane.vue                                               |   61 ++
 apps/taro/src/subpackages/recharge/phoneBillRecharge/InnerPage.vue                         |    4 
 apps/taro/src/components/Tabs/ProTabs.vue                                                  |  536 +++++++++++++++++
 packages/components/src/views/PhoneBillRecharge/PhoneBillRecharge.vue                      |    2 
 apps/taro/src/hooks/user.ts                                                                |    6 
 apps/taro/src/utils/storage/auth.ts                                                        |   11 
 packages/components/src/index.ts                                                           |    3 
 packages/components/src/styles/loading.scss                                                |   43 +
 packages/components/src/styles/index.scss                                                  |    1 
 packages/components/src/views/SelectPayTypeView/SelectPayTypeView.vue                      |   44 
 apps/taro/src/subpackages/recharge/selectPayType/InnerPage.vue                             |   14 
 packages/components/src/components/Layout/layout.ts                                        |   19 
 apps/taro/src/utils/blLifeRecharge.ts                                                      |    3 
 packages/components/src/styles/rechargeGrid.scss                                           |    2 
 packages/components/src/components/Layout/LoadingLayout.vue                                |   33 +
 packages/components/src/utils/lifeRechargeAccountModel.ts                                  |   20 
 apps/taro/src/components/Tabs/tabs.ts                                                      |  354 +++++++++++
 apps/taro/src/subpackages/order/order/InnerPage.vue                                        |   15 
 apps/taro/src/subpackages/recharge/rechargeElectricResult/rechargeElectricResult.vue       |   21 
 apps/taro/src/pages/mine/index.vue                                                         |    4 
 apps/taro/src/subpackages/recharge/rechargeElectricResult/rechargeElectricResult.config.ts |    3 
 apps/taro/src/subpackages/login/loginByForm/verificationCodeLoginForm.vue                  |    5 
 apps/taro/src/custom-tab-bar/index.tsx                                                     |    4 
 apps/taro/src/subpackages/recharge/rechargeResult/rechargeResult.config.ts                 |    3 
 packages/components/assets/icon-back-top.png                                               |    0 
 packages/components/src/constants/index.ts                                                 |   11 
 packages/components/src/utils/lifeRecharge.ts                                              |   16 
 packages/components/src/utils/lifeRechargeServices.ts                                      |   70 ++
 packages/components/src/views/RechargeResultView/RechargeResultView.vue                    |   17 
 packages/components/src/hooks/index.ts                                                     |   51 +
 38 files changed, 1,683 insertions(+), 75 deletions(-)

diff --git a/apps/taro/src/app.config.ts b/apps/taro/src/app.config.ts
index 1f44a78..b6e2fa8 100644
--- a/apps/taro/src/app.config.ts
+++ b/apps/taro/src/app.config.ts
@@ -58,6 +58,7 @@
         'electricBillRecharge/electricBillRecharge',
         'selectPayType/selectPayType',
         'rechargeResult/rechargeResult',
+        'rechargeElectricResult/rechargeElectricResult',
       ],
     },
     {
diff --git a/apps/taro/src/components/Tabs/ProTabPane.vue b/apps/taro/src/components/Tabs/ProTabPane.vue
new file mode 100644
index 0000000..345f7db
--- /dev/null
+++ b/apps/taro/src/components/Tabs/ProTabPane.vue
@@ -0,0 +1,61 @@
+<template>
+  <view class="nut-tab-pane" v-if="shouldBeRender" :style="paneStyle">
+    <slot></slot>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { CSSProperties, inject, ref, computed, watch } from 'vue';
+
+defineOptions({
+  name: 'ProTabPane',
+});
+
+const props = defineProps({
+  title: {
+    type: [String, Number],
+    default: '',
+  },
+  subTitle: {
+    type: [String, Number],
+    default: '',
+  },
+  paneKey: {
+    type: [String, Number],
+    default: '',
+  },
+  disabled: {
+    type: Boolean,
+    default: false,
+  },
+  lazy: {
+    type: Boolean,
+    default: true,
+  },
+  badgeValue: {
+    type: Number,
+    default: 0,
+  },
+});
+
+const parentOption = inject('tabsOpiton') as any;
+
+const paneStyle = computed(() => {
+  return {
+    display:
+      parentOption.animatedTime.value === 0 && props.paneKey !== parentOption.activeKey.value
+        ? 'none'
+        : undefined,
+  } as CSSProperties;
+});
+
+const active = computed(() => props.paneKey === parentOption.activeKey.value);
+
+const loaded = ref(active.value);
+
+const shouldBeRender = computed(() => !props.lazy || loaded.value || active.value);
+
+watch(active, (val) => {
+  if (val) loaded.value = true;
+});
+</script>
diff --git a/apps/taro/src/components/Tabs/ProTabs.vue b/apps/taro/src/components/Tabs/ProTabs.vue
new file mode 100644
index 0000000..b2c7c8c
--- /dev/null
+++ b/apps/taro/src/components/Tabs/ProTabs.vue
@@ -0,0 +1,536 @@
+<template>
+  <view
+    ref="container"
+    class="nut-tabs"
+    :class="[direction, { fullHeight, noContent: !showPaneContent, flexTitle }]"
+  >
+    <div :class="['pro-tabs__titles_wrapper', { isTransparent }]">
+      <scroll-view
+        :id="`nut-tabs__titles_${name}`"
+        :scroll-x="getScrollX"
+        :scroll-y="getScrollY"
+        :scroll-with-animation="true"
+        :scroll-left="scrollLeft"
+        :scroll-top="scrollTop"
+        :enable-flex="true"
+        class="nut-tabs__titles tabs-scrollview"
+        :class="{
+          [type]: type,
+          scrollable: titleScroll,
+          'scroll-vertical': getScrollY,
+          [size]: size,
+        }"
+        :style="tabsNavStyle"
+        enhanced
+        :show-scrollbar="false"
+        @scroll="onScroll"
+      >
+        <view class="nut-tabs__list">
+          <slot v-if="$slots.titles" name="titles"></slot>
+          <template v-else>
+            <view
+              v-for="(item, index) in titles"
+              :key="item.paneKey"
+              class="nut-tabs__titles-item taro"
+              :style="titleStyle"
+              :class="{ active: item.paneKey == modelValue, disabled: item.disabled }"
+              @click="tabMethods.tabChange(item, index)"
+            >
+              <view
+                v-if="type == 'line'"
+                class="nut-tabs__titles-item__line"
+                :style="tabsActiveStyle"
+              ></view>
+              <view
+                v-if="type == 'smile'"
+                class="nut-tabs__titles-item__smile"
+                :style="tabsActiveStyle"
+              >
+                <JoySmile :color="color" />
+              </view>
+              <nut-badge
+                right="-12"
+                top="4"
+                :value="item.badgeValue"
+                :max="99"
+                :hidden="!item.badgeValue"
+                color="#FC0B0B"
+              >
+                <view class="nut-tabs__titles-item__text" :class="{ ellipsis: ellipsis }"
+                  >{{ item.title }}
+                </view>
+              </nut-badge>
+              <view class="nut-tabs__sub-titles-item__text" :class="{ ellipsis: ellipsis }"
+                >{{ item.subTitle }}
+              </view>
+            </view>
+            <view
+              v-if="canShowLabel"
+              class="nut-tabs__titles-item nut-tabs__titles-placeholder"
+            ></view>
+          </template>
+        </view>
+      </scroll-view>
+      <slot name="right"></slot>
+    </div>
+
+    <view
+      :id="'tabsContentRef-' + refRandomId"
+      ref="tabsContentRef"
+      class="nut-tabs__content"
+      :style="contentStyle"
+      @touchstart="touchMethods.onTouchStart"
+      @touchmove="touchMethods.onTouchMove"
+      @touchend="touchMethods.onTouchEnd"
+      @touchcancel="touchMethods.onTouchEnd"
+      v-show="showPaneContent"
+    >
+      <slot name="default"></slot>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { JoySmile } from '@nutui/icons-vue-taro';
+import { tabsProps, Title, TypeOfFun, RectItem, raf, pxCheck, useTabContentTouch } from './tabs';
+import Taro from '@tarojs/taro';
+import {
+  CSSProperties,
+  useSlots,
+  computed,
+  ref,
+  onMounted,
+  provide,
+  VNode,
+  Ref,
+  nextTick,
+  watch,
+  onActivated,
+} from 'vue';
+import { useTaroRect, useScrollDistance } from 'senin-mini/hooks';
+
+defineOptions({
+  name: 'ProTabs',
+});
+
+const props = defineProps(tabsProps);
+
+const emit = defineEmits<{
+  (e: 'update:modelValue', value: string | number): void;
+  (e: 'click', item: Title): void;
+  (e: 'change', item: Title): void;
+}>();
+
+const slots = useSlots();
+
+const container = ref(null);
+provide('tabsOpiton', {
+  activeKey: computed(() => props.modelValue || '0'),
+  autoHeight: computed(() => props.autoHeight),
+  animatedTime: computed(() => props.animatedTime),
+});
+const titles: Ref<Title[]> = ref([]);
+const renderTitles = (vnodes: VNode[]) => {
+  vnodes.forEach((vnode: VNode, index: number) => {
+    let type = vnode.type;
+    type = (type as any).name || type;
+    if (type === 'nut-tab-pane' || type === 'ProTabPane') {
+      let title = new Title();
+      if (vnode.props?.title || vnode.props?.['pane-key'] || vnode.props?.['paneKey']) {
+        let paneKeyType = TypeOfFun(vnode.props?.['pane-key']);
+        let paneIndex =
+          paneKeyType === 'number' || paneKeyType === 'string'
+            ? String(vnode.props?.['pane-key'])
+            : null;
+        let camelPaneKeyType = TypeOfFun(vnode.props?.['paneKey']);
+        let camelPaneIndex =
+          camelPaneKeyType === 'number' || camelPaneKeyType === 'string'
+            ? String(vnode.props?.['paneKey'])
+            : null;
+        title.title = vnode.props?.title;
+        title.subTitle = vnode.props?.subTitle;
+        title.badgeValue = vnode.props?.badgeValue;
+        title.paneKey = paneIndex || camelPaneIndex || String(index);
+        title.disabled = vnode.props?.disabled;
+      } else {
+        // title.titleSlot = vnode.children?.title() as VNode[];
+      }
+      titles.value.push(title);
+    } else {
+      if (vnode.children === ' ') {
+        return;
+      }
+      renderTitles(vnode.children as VNode[]);
+    }
+  });
+};
+
+const currentIndex = ref((props.modelValue as number) || 0);
+const findTabsIndex = (value: string | number) => {
+  let index = titles.value.findIndex((item) => item.paneKey === value);
+  if (titles.value.length === 0) {
+    // console.warn('[NutUI] <Tabs> 褰撳墠鏈壘鍒� TabPane 缁勪欢鍏冪礌 , 璇锋鏌� .');
+  } else if (index === -1) {
+    // console.warn('[NutUI] <Tabs> 璇锋鏌� v-model 鍊兼槸鍚︿负 paneKey ,濡� paneKey 鏈缃紝璇烽噰鐢ㄤ笅鏍囨帶鍒� .');
+  } else {
+    currentIndex.value = index;
+  }
+};
+const getScrollX = computed(() => {
+  return props.titleScroll && props.direction === 'horizontal';
+});
+const getScrollY = computed(() => {
+  return props.titleScroll && props.direction === 'vertical';
+});
+const titleRef = ref([]) as Ref<HTMLElement[]>;
+// const scrollLeft = ref(0);
+const scrollTop = ref(0);
+const scrollWithAnimation = ref(false);
+const getRect = (selector: string) => {
+  return new Promise((resolve) => {
+    Taro.createSelectorQuery()
+      .select(selector)
+      .boundingClientRect()
+      .exec((rect = []) => {
+        resolve(rect[0]);
+      });
+  });
+};
+const getAllRect = (selector: string) => {
+  return new Promise((resolve) => {
+    Taro.createSelectorQuery()
+      .selectAll(selector)
+      .boundingClientRect()
+      .exec((rect = []) => resolve(rect[0]));
+  });
+};
+const navRectRef = ref();
+const titleRectRef = ref<RectItem[]>([]);
+const canShowLabel = ref(false);
+const scrollIntoView = () => {
+  if (!props.name) return;
+
+  raf(() => {
+    Promise.all([
+      getRect(`#nut-tabs__titles_${props.name}`),
+      getAllRect(`#nut-tabs__titles_${props.name} .nut-tabs__titles-item`),
+    ]).then(([navRect, titleRects]: any) => {
+      navRectRef.value = navRect;
+      titleRectRef.value = titleRects;
+
+      if (navRectRef.value) {
+        if (props.direction === 'vertical') {
+          const titlesTotalHeight = titleRects.reduce(
+            (prev: number, curr: RectItem) => prev + curr.height,
+            0
+          );
+          if (titlesTotalHeight > navRectRef.value.height) {
+            canShowLabel.value = true;
+          } else {
+            canShowLabel.value = false;
+          }
+        } else {
+          const titlesTotalWidth = titleRects.reduce(
+            (prev: number, curr: RectItem) => prev + curr.width,
+            0
+          );
+          if (titlesTotalWidth > navRectRef.value.width) {
+            canShowLabel.value = true;
+          } else {
+            canShowLabel.value = false;
+          }
+        }
+      }
+
+      const titleRect: RectItem = titleRectRef.value[currentIndex.value];
+
+      let to = 0;
+      if (props.direction === 'vertical') {
+        const DEFAULT_PADDING = 11;
+        const top = titleRects
+          .slice(0, currentIndex.value)
+          .reduce((prev: number, curr: RectItem) => prev + curr.height + 0, DEFAULT_PADDING);
+        to = top - (navRectRef.value.height - titleRect.height) / 2;
+      } else {
+        const DEFAULT_PADDING = 31;
+        const left = titleRects
+          .slice(0, currentIndex.value)
+          .reduce((prev: number, curr: RectItem) => prev + curr.width + 20, DEFAULT_PADDING);
+        to = left - (navRectRef.value?.width ?? 0 - titleRect?.width ?? 0) / 2;
+      }
+
+      nextTick(() => {
+        scrollWithAnimation.value = true;
+      });
+
+      scrollDirection(to, props.direction);
+    });
+  });
+};
+
+const {
+  onScroll,
+  scrollDistance: scrollLeft,
+  setScrollDistance: setScrollLeft,
+} = useScrollDistance({ direction: 'horizontal' });
+
+const scrollDirection = (to: number, direction: 'horizontal' | 'vertical') => {
+  let count = 0;
+  const from = direction === 'horizontal' ? scrollLeft.value : scrollTop.value;
+  const frames = 1;
+
+  function animate() {
+    if (direction === 'horizontal') {
+      scrollLeft.value = Math.max(0.1, to);
+    } else {
+      scrollTop.value += (to - from) / frames;
+    }
+
+    if (++count < frames) {
+      raf(animate);
+    }
+  }
+
+  if (direction === 'horizontal') {
+    setScrollLeft(Math.max(0.1, to));
+  } else {
+    animate();
+  }
+};
+const init = (vnodes: VNode[] = slots.default?.()) => {
+  titles.value = [];
+  vnodes = vnodes?.filter((item) => typeof item.children !== 'string');
+  if (vnodes && vnodes.length) {
+    renderTitles(vnodes);
+  }
+  findTabsIndex(props.modelValue);
+  setTimeout(() => {
+    scrollIntoView();
+  }, 500);
+};
+
+watch(
+  () => slots.default?.(),
+  (vnodes: VNode[]) => {
+    init(vnodes);
+  }
+);
+watch(
+  () => props.modelValue,
+  (value: string | number) => {
+    findTabsIndex(value);
+    setTimeout(() => {
+      scrollIntoView();
+    }, 500);
+  }
+);
+onMounted(init);
+onActivated(init);
+const tabMethods = {
+  isBegin: () => {
+    return currentIndex.value === 0;
+  },
+  isEnd: () => {
+    return currentIndex.value === titles.value.length - 1;
+  },
+  next: () => {
+    currentIndex.value += 1;
+    tabMethods.updateValue(titles.value[currentIndex.value]);
+  },
+  prev: () => {
+    currentIndex.value -= 1;
+    tabMethods.updateValue(titles.value[currentIndex.value]);
+  },
+  updateValue: (item: Title) => {
+    emit('update:modelValue', item.paneKey);
+    emit('change', item);
+  },
+  tabChange: (item: Title, index: number) => {
+    emit('click', item);
+    if (item.disabled || currentIndex.value === index) {
+      return;
+    }
+    currentIndex.value = index;
+    tabMethods.updateValue(item);
+  },
+  setTabItemRef: (el: HTMLElement, index: number) => {
+    titleRef.value[index] = el;
+  },
+};
+const { tabsContentRef, touchState, touchMethods } = useTabContentTouch(
+  props,
+  tabMethods,
+  Taro,
+  useTaroRect
+);
+const contentStyle = computed(() => {
+  let offsetPercent = currentIndex.value * 100;
+  if (touchState.moving) {
+    offsetPercent += touchState.offset;
+  }
+  let style: CSSProperties = {
+    transform:
+      props.direction === 'horizontal'
+        ? `translate3d(-${offsetPercent}%, 0, 0)`
+        : `translate3d( 0,-${offsetPercent}%, 0)`,
+    transitionDuration: touchState.moving ? undefined : `${props.animatedTime}ms`,
+  };
+  if (props.animatedTime === 0) {
+    style = {};
+  }
+  return style;
+});
+const tabsNavStyle = computed(() => {
+  return {
+    background: props.background,
+  };
+});
+const tabsActiveStyle = computed(() => {
+  return {
+    color: props.type === 'smile' ? props.color : '',
+    background: props.type === 'line' ? props.color : '',
+  };
+});
+const titleStyle = computed(() => {
+  if (!props.titleGutter) return {};
+  const px = pxCheck(props.titleGutter);
+  if (props.direction === 'vertical') {
+    return { marginTop: px, marginBottom: px };
+  }
+  return { marginLeft: px, marginRight: px };
+});
+const refRandomId = Math.random().toString(36).slice(-8);
+</script>
+
+<style lang="scss">
+@import '@/styles/common.scss';
+
+.pro-tabs__titles_wrapper {
+  display: flex;
+  align-items: center;
+  background-color: #fff;
+  position: relative;
+  z-index: 10;
+  box-shadow: none;
+  padding: 0 boleGetCssVar('size', 'body-padding-h');
+  margin-bottom: 8px;
+
+  &.isTransparent {
+    background-color: transparent;
+    margin-bottom: 0;
+  }
+}
+
+.nut-tabs.noContent {
+  box-shadow: none;
+  position: relative;
+  z-index: 9;
+}
+
+.flexTitle {
+  box-shadow: none;
+  position: relative;
+  z-index: 9;
+
+  .pro-tabs__titles_wrapper {
+    padding: 0;
+
+    .nut-tabs__titles.tabs-scrollview .nut-tabs__list .nut-tabs__titles-item {
+      flex: 1;
+      margin: 0;
+      min-width: 0;
+      flex-shrink: 0;
+    }
+  }
+}
+
+.nut-tabs__titles.tabs-scrollview {
+  background-color: transparent;
+  flex: 1;
+  min-width: 0;
+  box-sizing: border-box;
+  height: 104rpx;
+  @include hiddenScrollBar;
+
+  .nut-tabs__list {
+    height: 104rpx;
+    justify-content: flex-start;
+
+    .nut-tabs__titles-item {
+      flex: none;
+      width: auto;
+      margin-right: 78rpx;
+      flex-direction: column;
+      font-size: 26rpx;
+      color: boleGetCssVar('text-color', 'secondary');
+      align-items: center;
+      transition: all 0.3s ease;
+      min-width: 0;
+
+      .nut-tabs__sub-titles-item__text {
+        font-size: 20rpx;
+        color: boleGetCssVar('text-color', 'regular');
+      }
+
+      .nut-tabs__titles-item__text {
+        font-size: 28rpx;
+        color: boleGetCssVar('text-color', 'regular');
+        line-height: 40rpx;
+      }
+
+      &.active {
+        color: #222;
+        font-weight: 700;
+        font-size: 30rpx;
+
+        .nut-tabs__sub-titles-item__text {
+          color: boleGetCssVar('color', 'primary');
+        }
+
+        .nut-tabs__titles-item__line {
+          width: 100%;
+        }
+
+        .nut-tabs__titles-item__text {
+          color: boleGetCssVar('text-color', 'primary');
+        }
+      }
+
+      &:last-child {
+        margin-right: 0;
+      }
+
+      &:first-child {
+        margin-left: 0 !important;
+      }
+
+      .nut-tabs__titles-item__line {
+        //   width: 100%;
+        background: boleGetCssVar('color', 'primary');
+        bottom: 0;
+        height: 4rpx;
+        max-width: 40rpx;
+      }
+    }
+  }
+}
+
+.nut-tabs.fullHeight {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+
+  .nut-tabs__content {
+    flex: 1;
+    min-height: 0;
+
+    .nut-tab-pane {
+      padding: 0;
+      background-color: transparent;
+      overflow: hidden;
+      display: flex;
+      flex-direction: column;
+    }
+  }
+}
+</style>
diff --git a/apps/taro/src/components/Tabs/tabs.ts b/apps/taro/src/components/Tabs/tabs.ts
new file mode 100644
index 0000000..4647f84
--- /dev/null
+++ b/apps/taro/src/components/Tabs/tabs.ts
@@ -0,0 +1,354 @@
+import { ref, PropType, onMounted, reactive } from 'vue';
+
+export type TabsSize = 'large' | 'normal' | 'small';
+
+export class Title {
+  title = '';
+  subTitle = '';
+  //@ts-ignore
+  titleSlot?: VNode[];
+  paneKey = '';
+  disabled = false;
+  badgeValue = 0;
+  constructor() {}
+}
+
+export const tabsProps = {
+  modelValue: {
+    type: [String, Number],
+    default: 0,
+  },
+  color: {
+    type: String,
+    default: '',
+  },
+  direction: {
+    type: String as PropType<'horizontal' | 'vertical'>,
+    default: 'horizontal', //vertical
+  },
+  size: {
+    type: String as PropType<TabsSize>,
+    default: 'normal',
+  },
+  type: {
+    type: String,
+    default: 'smile', //card銆乴ine銆乻mile
+  },
+  titleScroll: {
+    type: Boolean,
+    default: false,
+  },
+  ellipsis: {
+    type: Boolean,
+    default: true,
+  },
+  swipeable: {
+    type: Boolean,
+    default: false,
+  },
+  autoHeight: {
+    type: Boolean,
+    default: false,
+  },
+  background: {
+    type: String,
+    default: '',
+  },
+  animatedTime: {
+    type: [Number, String],
+    default: 0,
+  },
+  titleGutter: {
+    type: [Number, String],
+    default: 0,
+  },
+  sticky: {
+    type: Boolean,
+    default: false,
+  },
+  top: {
+    type: Number,
+    default: 0,
+  },
+  name: {
+    type: String,
+    default: '',
+  },
+  fullHeight: {
+    type: Boolean,
+    default: false,
+  },
+  showPaneContent: {
+    type: Boolean,
+    default: true,
+  },
+  flexTitle: {
+    type: Boolean,
+    default: false,
+  },
+  isTransparent: {
+    type: Boolean,
+    default: false,
+  },
+};
+
+export const TypeOfFun = (value: any) => {
+  if (null === value) {
+    return 'null';
+  }
+
+  const type = typeof value;
+  if ('undefined' === type || 'string' === type) {
+    return type;
+  }
+
+  const typeString = toString.call(value);
+  switch (typeString) {
+    case '[object Array]':
+      return 'array';
+    case '[object Date]':
+      return 'date';
+    case '[object Boolean]':
+      return 'boolean';
+    case '[object Number]':
+      return 'number';
+    case '[object Function]':
+      return 'function';
+    case '[object RegExp]':
+      return 'regexp';
+    case '[object Object]':
+      if (undefined !== value.nodeType) {
+        if (3 === value.nodeType) {
+          return /\S/.test(value.nodeValue) ? 'textnode' : 'whitespace';
+        } else {
+          return 'element';
+        }
+      } else {
+        return 'object';
+      }
+    default:
+      return 'unknow';
+  }
+};
+
+export type RectItem = {
+  bottom: number;
+  dataset: { sid: string };
+  height: number;
+  id: string;
+  left: number;
+  right: number;
+  top: number;
+  width: number;
+};
+
+const _window = window as any;
+
+export function requestAniFrame() {
+  if (typeof _window !== 'undefined') {
+    return (
+      _window.requestAnimationFrame ||
+      _window.webkitRequestAnimationFrame ||
+      function (callback: Function) {
+        _window.setTimeout(callback, 1000 / 60);
+      }
+    );
+  } else {
+    return function (callback: Function) {
+      setTimeout(callback, 1000 / 60);
+    };
+  }
+}
+
+export const raf = requestAniFrame();
+
+export const pxCheck = (value: string | number): string => {
+  return isNaN(Number(value)) ? String(value) : `${value}px`;
+};
+
+const MIN_DISTANCE = 10;
+
+type Direction = '' | 'vertical' | 'horizontal';
+
+function getDirection(x: number, y: number) {
+  if (x > y && x > MIN_DISTANCE) {
+    return 'horizontal';
+  }
+  if (y > x && y > MIN_DISTANCE) {
+    return 'vertical';
+  }
+  return '';
+}
+
+type TouchPosition = 'left' | 'right' | 'top' | 'bottom' | '';
+
+export function useTouch() {
+  const startX = ref(0);
+  const startY = ref(0);
+  const moveX = ref(0);
+  const moveY = ref(0);
+  const deltaX = ref(0);
+  const deltaY = ref(0);
+  const offsetX = ref(0);
+  const offsetY = ref(0);
+  const direction = ref<Direction>('');
+
+  const isVertical = () => direction.value === 'vertical';
+  const isHorizontal = () => direction.value === 'horizontal';
+
+  const reset = () => {
+    deltaX.value = 0;
+    deltaY.value = 0;
+    offsetX.value = 0;
+    offsetY.value = 0;
+    direction.value = '';
+  };
+
+  const start = (event: TouchEvent) => {
+    reset();
+    startX.value = event.touches[0].clientX;
+    startY.value = event.touches[0].clientY;
+  };
+
+  const move = (event: TouchEvent) => {
+    const touch = event.touches[0];
+    deltaX.value = touch.clientX - startX.value;
+    deltaY.value = touch.clientY - startY.value;
+    moveX.value = touch.clientX;
+    moveY.value = touch.clientY;
+    offsetX.value = Math.abs(deltaX.value);
+    offsetY.value = Math.abs(deltaY.value);
+
+    if (!direction.value) {
+      direction.value = getDirection(offsetX.value, offsetY.value);
+    }
+  };
+
+  return {
+    move,
+    start,
+    reset,
+    startX,
+    startY,
+    moveX,
+    moveY,
+    deltaX,
+    deltaY,
+    offsetX,
+    offsetY,
+    direction,
+    isVertical,
+    isHorizontal,
+  };
+}
+
+export const useTabContentTouch = (props: any, tabMethods: any, taro?: any, useTaroRect?: any) => {
+  const tabsContentRef = ref<HTMLElement>();
+
+  const tabsContentRefRect = ref({ width: 0, height: 0 });
+  const initTaroWidth = () => {
+    if (taro && taro.getEnv() !== taro.ENV_TYPE.WEB) {
+      useTaroRect(tabsContentRef).then(
+        (rect: any) => {
+          tabsContentRefRect.value.width = rect?.width || 0;
+          tabsContentRefRect.value.height = rect?.height || 0;
+        },
+        () => {}
+      );
+    } else {
+      tabsContentRefRect.value.width = tabsContentRef.value?.clientWidth || 0;
+      tabsContentRefRect.value.height = tabsContentRef.value?.clientHeight || 0;
+    }
+  };
+
+  onMounted(() => {
+    setTimeout(() => {
+      initTaroWidth();
+    }, 100);
+  });
+  const touchState = reactive({
+    offset: 0,
+    moving: false,
+  });
+  const touch = useTouch();
+  let position: TouchPosition = '';
+  const setoffset = (deltaX: number, deltaY: number) => {
+    let offset = deltaX;
+    if (props.direction === 'horizontal') {
+      position = deltaX > 0 ? 'right' : 'left';
+      // 璁$畻鎷栨嫿 鐧惧垎姣�
+      offset = (Math.abs(offset) / tabsContentRefRect.value.width) * 100;
+    } else {
+      position = deltaY > 0 ? 'bottom' : 'top';
+      offset = deltaY;
+      // 璁$畻鎷栨嫿 鐧惧垎姣�
+      offset = (Math.abs(offset) / tabsContentRefRect.value?.height) * 100;
+    }
+    // 鎷栨嫿闃堝�� 85%
+    if (offset > 85) {
+      offset = 85;
+    }
+    switch (position) {
+      case 'left':
+      case 'top':
+        // 璧峰tab鎷栨嫿鎷︽埅
+        if (tabMethods.isEnd()) {
+          offset = 0;
+          touchState.moving = false;
+        }
+        break;
+      case 'right':
+      case 'bottom':
+        offset = -offset;
+        // 鏈綅tab鎷栨嫿鎷︽埅
+        if (tabMethods.isBegin()) {
+          offset = 0;
+          touchState.moving = false;
+        }
+        break;
+    }
+    touchState.offset = offset;
+  };
+  const touchMethods = {
+    onTouchStart(event: TouchEvent) {
+      if (!props.swipeable) return;
+      touch.start(event);
+    },
+    onTouchMove(event: TouchEvent) {
+      if (!props.swipeable) return;
+      touch.move(event);
+      touchState.moving = true;
+      setoffset(touch.deltaX.value, touch.deltaY.value);
+
+      if (props.direction === 'horizontal' && touch.isHorizontal()) {
+        event.preventDefault();
+        event.stopPropagation();
+      }
+      if (props.direction === 'vertical' && touch.isVertical()) {
+        event.preventDefault();
+        event.stopPropagation();
+      }
+    },
+    onTouchEnd() {
+      if (touchState.moving) {
+        touchState.moving = false;
+        switch (position) {
+          case 'left':
+          case 'top':
+            // 澶т簬 35%闃堝�� 鍒囨崲鑷充笅涓� Tab
+            if (touchState.offset > 35) {
+              tabMethods.next();
+            }
+            break;
+          case 'right':
+          case 'bottom':
+            if (touchState.offset < -35) {
+              tabMethods.prev();
+            }
+            break;
+        }
+      }
+    },
+  };
+  return { touchMethods, touchState, tabsContentRef };
+};
diff --git a/apps/taro/src/constants/router.ts b/apps/taro/src/constants/router.ts
index 35682a6..1445fda 100644
--- a/apps/taro/src/constants/router.ts
+++ b/apps/taro/src/constants/router.ts
@@ -13,4 +13,5 @@
   order = '/subpackages/order/order/order',
   selectPayType = '/subpackages/recharge/selectPayType/selectPayType',
   rechargeResult = '/subpackages/recharge/rechargeResult/rechargeResult',
+  rechargeElectricResult = '/subpackages/recharge/rechargeElectricResult/rechargeElectricResult',
 }
diff --git a/apps/taro/src/custom-tab-bar/index.tsx b/apps/taro/src/custom-tab-bar/index.tsx
index e2b4683..4c50faf 100644
--- a/apps/taro/src/custom-tab-bar/index.tsx
+++ b/apps/taro/src/custom-tab-bar/index.tsx
@@ -73,7 +73,7 @@
           Message.confirm({ message: '璇峰墠寰�鐧诲綍' })
             .then(() => {
               Taro.navigateTo({
-                url: `${RouterPath.authorization}?redirect=${url}`,
+                url: `${RouterPath.loginByForm}?redirect=${url}`,
               });
             })
             .finally(() => {
@@ -93,7 +93,7 @@
           Message.confirm({ message: '璇峰墠寰�鐧诲綍' })
             .then(() => {
               Taro.navigateTo({
-                url: `${RouterPath.authorization}?redirect=${RouterPath.home}`,
+                url: `${RouterPath.loginByForm}?redirect=${RouterPath.home}`,
               });
             })
             .finally(() => {
diff --git a/apps/taro/src/hooks/user.ts b/apps/taro/src/hooks/user.ts
index 29a6ef4..f1308ee 100644
--- a/apps/taro/src/hooks/user.ts
+++ b/apps/taro/src/hooks/user.ts
@@ -11,7 +11,8 @@
 export function useUser() {
   const userStore = useUserStore();
 
-  const { userDetail, userInfo, locationCity, virtualUserId } = storeToRefs(userStore);
+  const { userDetail, userInfo, locationCity, virtualUserId, virtualPhoneNumber } =
+    storeToRefs(userStore);
 
   function updateUserInfo() {
     return userStore.getCurrentUserInfo();
@@ -23,6 +24,7 @@
     updateUserInfo,
     locationCity,
     virtualUserId,
+    virtualPhoneNumber,
   };
 }
 
@@ -52,7 +54,7 @@
     }
     if (needAuth && !isLogin.value) {
       Taro.navigateTo({
-        url: `${RouterPath.authorization}?redirect=${router.path}&${object2query(router.params)}`,
+        url: `${RouterPath.loginByForm}?redirect=${router.path}&${object2query(router.params)}`,
       });
     }
   });
diff --git a/apps/taro/src/pages/mine/index.vue b/apps/taro/src/pages/mine/index.vue
index 2717095..d7d2380 100644
--- a/apps/taro/src/pages/mine/index.vue
+++ b/apps/taro/src/pages/mine/index.vue
@@ -13,7 +13,7 @@
     <div class="mine-page-top-view" @click="goLogin">
       <img class="mine-avatar" :src="DefaultAvatar" alt="" />
       <div class="user-info">
-        <div class="user-info-name" v-if="isLogin">{{ userDetail?.userName ?? '123' }}</div>
+        <div class="user-info-name" v-if="isLogin">{{ virtualPhoneNumber }}</div>
         <div class="mine-go-login" v-else>鐧诲綍</div>
       </div>
     </div>
@@ -37,7 +37,7 @@
 import { useUserStore } from '@/stores/modules/user';
 import { useUserStoreWithOut } from '@/stores/modules/user';
 
-const { userDetail } = useUser();
+const { userDetail, virtualPhoneNumber } = useUser();
 const isLogin = useIsLogin();
 const systemStore = useSystemStore();
 const userStore = useUserStore();
diff --git a/apps/taro/src/stores/modules/user.ts b/apps/taro/src/stores/modules/user.ts
index b101a3d..8525d95 100644
--- a/apps/taro/src/stores/modules/user.ts
+++ b/apps/taro/src/stores/modules/user.ts
@@ -11,6 +11,7 @@
   setStorageVirtualUserId,
   getStorageVirtualUserId,
   removeStorageVirtualUserId,
+  LoginVirtualRes,
 } from '@/utils/storage/auth';
 import * as accountServices from '@life-payment/services/api/Account';
 import * as userServices from '@life-payment/services/api/User';
@@ -34,6 +35,7 @@
   firstSetLocation?: boolean;
 
   virtualUserId?: string;
+  virtualPhoneNumber?: string;
 }
 
 const goAuthorization = debounce(
@@ -57,6 +59,7 @@
   state: (): UserState => {
     const userInfo = getCacheUserInfo();
     const userDetail = getUserDetail();
+    const storageVirtualUser = getStorageVirtualUserId();
 
     return {
       // user info
@@ -68,7 +71,8 @@
       userDetail: userDetail,
       firstGetUserDetail: true,
 
-      virtualUserId: getStorageVirtualUserId() ?? '',
+      virtualUserId: storageVirtualUser?.virtualUserId ?? '',
+      virtualPhoneNumber: storageVirtualUser?.virtualPhoneNumber ?? '',
     };
   },
   getters: {
@@ -129,7 +133,10 @@
       );
 
       if (res) {
-        this.loginVirtualSuccess(res);
+        this.loginVirtualSuccess({
+          virtualUserId: res,
+          virtualPhoneNumber: data.phoneNumber,
+        });
       }
       return res;
     },
@@ -158,15 +165,16 @@
       } catch (error) {}
     },
 
-    async loginVirtualSuccess(virtualUserId: string) {
+    async loginVirtualSuccess(virtualUserRes: LoginVirtualRes) {
       try {
-        this.setVirtualUserId(virtualUserId);
+        this.setVirtualUserId(virtualUserRes);
       } catch (error) {}
     },
 
-    setVirtualUserId(virtualUserId: string) {
-      this.virtualUserId = virtualUserId;
-      setStorageVirtualUserId(virtualUserId);
+    setVirtualUserId(virtualUserRes: LoginVirtualRes) {
+      this.virtualUserId = virtualUserRes.virtualUserId;
+      this.virtualPhoneNumber = virtualUserRes.virtualPhoneNumber;
+      setStorageVirtualUserId(virtualUserRes);
     },
 
     async wxMiniAppUserLoginFromScan(wxIndentityRes: API.WxMiniAppIndentityInfo, uuid: string) {
diff --git a/apps/taro/src/subpackages/login/loginByForm/verificationCodeLoginForm.vue b/apps/taro/src/subpackages/login/loginByForm/verificationCodeLoginForm.vue
index ea7179d..e95a502 100644
--- a/apps/taro/src/subpackages/login/loginByForm/verificationCodeLoginForm.vue
+++ b/apps/taro/src/subpackages/login/loginByForm/verificationCodeLoginForm.vue
@@ -102,7 +102,10 @@
             showLoading: false,
           }
         );
-        userStore.loginVirtualSuccess(res);
+        userStore.loginVirtualSuccess({
+          virtualPhoneNumber: form.phoneNumber,
+          virtualUserId: res,
+        });
         jump();
       }
     } else {
diff --git a/apps/taro/src/subpackages/order/order/InnerPage.vue b/apps/taro/src/subpackages/order/order/InnerPage.vue
index 0bdfd9d..eac44ba 100644
--- a/apps/taro/src/subpackages/order/order/InnerPage.vue
+++ b/apps/taro/src/subpackages/order/order/InnerPage.vue
@@ -1,17 +1,24 @@
 <template>
-  <ContentScrollView :paddingH="false">
-    <Order />
-  </ContentScrollView>
+  <ProTabs v-model="orderType" name="user-home-tabs" class="user-home-tabs" flexTitle fullHeight>
+    <ProTabPane title="璇濊垂璁㈠崟" pane-key="1">
+      <PhoneOrder />
+    </ProTabPane>
+    <ProTabPane title="鐢佃垂璁㈠崟" pane-key="2">
+      <ElectricOrder />
+    </ProTabPane>
+  </ProTabs>
 </template>
 
 <script setup lang="ts">
-import { Order } from '@life-payment/components';
+import { PhoneOrder, ElectricOrder } from '@life-payment/components';
 import Taro from '@tarojs/taro';
 
 defineOptions({
   name: 'InnerPage',
 });
 
+const orderType = ref('1');
+
 function goPay() {
   Taro.navigateTo({
     url: RouterPath.selectPayType,
diff --git a/apps/taro/src/subpackages/recharge/phoneBillRecharge/InnerPage.vue b/apps/taro/src/subpackages/recharge/phoneBillRecharge/InnerPage.vue
index f44d4e2..f6549ba 100644
--- a/apps/taro/src/subpackages/recharge/phoneBillRecharge/InnerPage.vue
+++ b/apps/taro/src/subpackages/recharge/phoneBillRecharge/InnerPage.vue
@@ -5,7 +5,7 @@
 </template>
 
 <script setup lang="ts">
-import { PhoneBillRecharge } from '@life-payment/components';
+import { PhoneBillRecharge, BlLifeRecharge } from '@life-payment/components';
 import Taro from '@tarojs/taro';
 
 defineOptions({
@@ -14,7 +14,7 @@
 
 function goPay(orderNo: string) {
   Taro.navigateTo({
-    url: `${RouterPath.selectPayType}?orderNo=${orderNo}`,
+    url: `${RouterPath.selectPayType}?orderNo=${orderNo}&lifePayOrderType=${BlLifeRecharge.constants.LifePayOrderTypeEnum.璇濊垂璁㈠崟}`,
   });
 }
 </script>
diff --git a/apps/taro/src/subpackages/recharge/rechargeElectricResult/rechargeElectricResult.config.ts b/apps/taro/src/subpackages/recharge/rechargeElectricResult/rechargeElectricResult.config.ts
new file mode 100644
index 0000000..305fdb1
--- /dev/null
+++ b/apps/taro/src/subpackages/recharge/rechargeElectricResult/rechargeElectricResult.config.ts
@@ -0,0 +1,3 @@
+export default definePageConfig({
+  disableScroll: true,
+});
diff --git a/apps/taro/src/subpackages/recharge/rechargeElectricResult/rechargeElectricResult.vue b/apps/taro/src/subpackages/recharge/rechargeElectricResult/rechargeElectricResult.vue
new file mode 100644
index 0000000..b073adc
--- /dev/null
+++ b/apps/taro/src/subpackages/recharge/rechargeElectricResult/rechargeElectricResult.vue
@@ -0,0 +1,21 @@
+<template>
+  <PageLayout title="鍏呭�兼垚鍔�" class="rechargeElectricResult-page-wrapper" hasBorder>
+    <ContentScrollView>
+      <RechargeResultView
+        style="margin-top: 40px"
+        @go-back-home="goHome()"
+        title="鏀粯鎴愬姛锛屽厖鍊兼灏嗗湪0-72灏忔椂鍐呭埌璐�"
+      />
+    </ContentScrollView>
+  </PageLayout>
+</template>
+
+<script setup lang="ts">
+import { PageLayout } from '@/components';
+import { goHome } from '@/utils';
+import { RechargeResultView } from '@life-payment/components';
+
+defineOptions({
+  name: 'rechargeElectricResult',
+});
+</script>
diff --git a/apps/taro/src/subpackages/recharge/rechargeResult/rechargeResult.config.ts b/apps/taro/src/subpackages/recharge/rechargeResult/rechargeResult.config.ts
index e69de29..305fdb1 100644
--- a/apps/taro/src/subpackages/recharge/rechargeResult/rechargeResult.config.ts
+++ b/apps/taro/src/subpackages/recharge/rechargeResult/rechargeResult.config.ts
@@ -0,0 +1,3 @@
+export default definePageConfig({
+  disableScroll: true,
+});
diff --git a/apps/taro/src/subpackages/recharge/selectPayType/InnerPage.vue b/apps/taro/src/subpackages/recharge/selectPayType/InnerPage.vue
index c5c7245..d1ea8c1 100644
--- a/apps/taro/src/subpackages/recharge/selectPayType/InnerPage.vue
+++ b/apps/taro/src/subpackages/recharge/selectPayType/InnerPage.vue
@@ -1,13 +1,23 @@
 <template>
   <ContentScrollView>
-    <SelectPayTypeView style="margin-top: 40px" />
+    <SelectPayTypeView style="margin-top: 40px" @paySuccess="handePaySuccess" />
   </ContentScrollView>
 </template>
 
 <script setup lang="ts">
-import { SelectPayTypeView } from '@life-payment/components';
+import { SelectPayTypeView, LifeRechargeConstants } from '@life-payment/components';
+import Taro from '@tarojs/taro';
 
 defineOptions({
   name: 'selectPayType',
 });
+
+function handePaySuccess(
+  orderNo: string,
+  lifePayOrderType: LifeRechargeConstants.LifePayOrderTypeEnum
+) {
+  Taro.navigateTo({
+    url: `${RouterPath.rechargeResult}?orderNo=${orderNo}&lifePayOrderType=${lifePayOrderType}`,
+  });
+}
 </script>
diff --git a/apps/taro/src/utils/blLifeRecharge.ts b/apps/taro/src/utils/blLifeRecharge.ts
index a030b56..c4441f3 100644
--- a/apps/taro/src/utils/blLifeRecharge.ts
+++ b/apps/taro/src/utils/blLifeRecharge.ts
@@ -4,5 +4,6 @@
 
 export const blLifeRecharge = new BlLifeRecharge({
   request,
-  userId: getStorageVirtualUserId() ?? '',
+  userId: getStorageVirtualUserId()?.virtualUserId ?? '',
+  phoneNumber: getStorageVirtualUserId()?.virtualPhoneNumber ?? '',
 });
diff --git a/apps/taro/src/utils/storage/auth.ts b/apps/taro/src/utils/storage/auth.ts
index 85c6baf..7533669 100644
--- a/apps/taro/src/utils/storage/auth.ts
+++ b/apps/taro/src/utils/storage/auth.ts
@@ -41,12 +41,17 @@
   return storageLocal.removeItem(StorageKey.USER_DETAIL_KEY);
 }
 
+export type LoginVirtualRes = {
+  virtualUserId: string;
+  virtualPhoneNumber: string;
+};
+
 export function getStorageVirtualUserId() {
-  return storageLocal.getItem<string>(StorageKey.VirtualUserId_KEY);
+  return storageLocal.getItem<LoginVirtualRes>(StorageKey.VirtualUserId_KEY);
 }
 
-export function setStorageVirtualUserId(virtualUserId: string) {
-  return storageLocal.setItem(StorageKey.VirtualUserId_KEY, virtualUserId);
+export function setStorageVirtualUserId(res: LoginVirtualRes) {
+  return storageLocal.setItem(StorageKey.VirtualUserId_KEY, res);
 }
 
 export function removeStorageVirtualUserId() {
diff --git a/packages/components/assets/icon-back-top.png b/packages/components/assets/icon-back-top.png
new file mode 100644
index 0000000..0b64e13
--- /dev/null
+++ b/packages/components/assets/icon-back-top.png
Binary files differ
diff --git a/packages/components/src/components/InfiniteLoading/InfiniteLoading.vue b/packages/components/src/components/InfiniteLoading/InfiniteLoading.vue
index 5a8aebe..bc55a9d 100644
--- a/packages/components/src/components/InfiniteLoading/InfiniteLoading.vue
+++ b/packages/components/src/components/InfiniteLoading/InfiniteLoading.vue
@@ -64,7 +64,7 @@
 import { FetchNextPageOptions } from '@tanstack/vue-query';
 import { Loading } from '@nutui/icons-vue-taro';
 import { useScrollDistance } from 'senin-mini/hooks';
-import IconBackTop from '@/assets/components/icon-back-top.png';
+import IconBackTop from '../../../assets/icon-back-top.png';
 
 defineOptions({
   name: 'InfiniteLoading',
diff --git a/packages/components/src/components/Layout/LoadingLayout.vue b/packages/components/src/components/Layout/LoadingLayout.vue
new file mode 100644
index 0000000..ff721f1
--- /dev/null
+++ b/packages/components/src/components/Layout/LoadingLayout.vue
@@ -0,0 +1,33 @@
+<template>
+  <div v-if="loading" class="loading-layout-loading-content-wrapper">
+    <IconFont name="loading" />
+    <div class="list-empty-hint-text">鏁版嵁鍔犺浇涓�......</div>
+  </div>
+  <Empty
+    v-else-if="error"
+    class="loading-layout-error-wrapper"
+    status="error"
+    description="鍔犺浇澶辫触"
+  >
+    <div :style="{ marginTop: '10px' }">
+      <nut-button type="primary" @click="loadError"> 閲嶈瘯 </nut-button>
+    </div>
+  </Empty>
+  <template v-else>
+    <NoData v-if="showNoData" />
+    <slot v-else></slot>
+  </template>
+</template>
+
+<script setup lang="ts">
+import { loadingLayoutProps } from './layout';
+import { IconFont } from '@nutui/icons-vue-taro';
+import NoData from '../NoData/NoData.vue';
+import { Button as NutButton, Empty } from '@nutui/nutui-taro';
+
+defineOptions({
+  name: 'LoadingLayout',
+});
+
+const props = defineProps(loadingLayoutProps);
+</script>
diff --git a/packages/components/src/components/Layout/layout.ts b/packages/components/src/components/Layout/layout.ts
new file mode 100644
index 0000000..a43fe7f
--- /dev/null
+++ b/packages/components/src/components/Layout/layout.ts
@@ -0,0 +1,19 @@
+import { PropType } from 'vue';
+
+export const loadingLayoutProps = {
+  loading: {
+    type: Boolean,
+  },
+  error: {
+    type: Boolean,
+  },
+  showNoData: {
+    type: Boolean,
+  },
+  loadError: {
+    type: Function as PropType<(...args: any[]) => any>,
+  },
+  id: {
+    type: String,
+  },
+};
diff --git a/packages/components/src/components/NoData/NoData.vue b/packages/components/src/components/NoData/NoData.vue
new file mode 100644
index 0000000..ce0511e
--- /dev/null
+++ b/packages/components/src/components/NoData/NoData.vue
@@ -0,0 +1,22 @@
+<template>
+  <div class="no-data-wrapper">
+    <img class="no-data-img" :src="NoDataImage" alt="" />
+    <span class="no-data-text">鏆傛棤鏁版嵁</span>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+
+const NoDataImage = `'https://parkmanagement.oss-cn-hangzhou.aliyuncs.com/mini/assets/no-data.png`;
+
+export default defineComponent({
+  name: 'NoData',
+
+  setup() {
+    return {
+      NoDataImage,
+    };
+  },
+});
+</script>
diff --git a/packages/components/src/constants/index.ts b/packages/components/src/constants/index.ts
index a3916b6..70fec56 100644
--- a/packages/components/src/constants/index.ts
+++ b/packages/components/src/constants/index.ts
@@ -12,3 +12,14 @@
   [IspCode.dianxin]: '涓浗鐢典俊',
   [IspCode.liantong]: '涓浗鑱旈��',
 };
+
+export enum OrderInputType {
+  /**
+   * 鍗囧簭
+   */
+  Asc,
+  /**
+   * 闄嶅簭
+   */
+  Desc,
+}
diff --git a/packages/components/src/hooks/index.ts b/packages/components/src/hooks/index.ts
index 8513ce7..687cb7c 100644
--- a/packages/components/src/hooks/index.ts
+++ b/packages/components/src/hooks/index.ts
@@ -3,9 +3,13 @@
   LifePayRateListOutput,
   PhoneParValueOutput,
   PhoneParValueResponse,
+  QueryLifePayOrderListInput,
+  LifeRechargeConstants,
 } from '../utils';
 import { useQuery } from '@tanstack/vue-query';
-import { computed } from 'vue';
+import { computed, MaybeRef, reactive, unref } from 'vue';
+import { useInfiniteLoading } from './infiniteLoading';
+import { OrderInputType } from '../constants';
 
 export function useGetRate() {
   const { blLifeRecharge } = useLifeRechargeContext();
@@ -57,3 +61,48 @@
     phoneParValueList,
   };
 }
+
+export type UseGetUserLifePayOrderPageOptions = {
+  lifePayOrderType?: MaybeRef<LifeRechargeConstants.LifePayOrderTypeEnum>;
+};
+
+export function useGetUserLifePayOrderPage(options: UseGetUserLifePayOrderPageOptions = {}) {
+  const { lifePayOrderType } = options;
+
+  const { blLifeRecharge } = useLifeRechargeContext();
+
+  // const queryState = reactive({
+  //   lifePayOrderType: LifeRechargeConstants.LifePayOrderTypeEnum,
+  // });
+
+  const { infiniteLoadingProps } = useInfiniteLoading(
+    ({ pageParam }) => {
+      let params: QueryLifePayOrderListInput = {
+        pageModel: {
+          rows: 20,
+          page: pageParam,
+          orderInput: [{ property: 'id', order: OrderInputType.Desc }],
+        },
+        lifePayOrderType: unref(lifePayOrderType),
+        userId: blLifeRecharge.accountModel.userId,
+      };
+
+      return blLifeRecharge.services.getUserLifePayOrderPage(params, {
+        showLoading: false,
+      });
+    },
+    {
+      queryKey: [
+        'blLifeRecharge/getUserLifePayOrderPage',
+        {
+          lifePayOrderType,
+          userId: blLifeRecharge.accountModel.userId,
+        },
+      ],
+    }
+  );
+
+  return {
+    infiniteLoadingProps,
+  };
+}
diff --git a/packages/components/src/hooks/infiniteLoading.ts b/packages/components/src/hooks/infiniteLoading.ts
new file mode 100644
index 0000000..d7b0fe1
--- /dev/null
+++ b/packages/components/src/hooks/infiniteLoading.ts
@@ -0,0 +1,294 @@
+import {
+  useInfiniteQuery,
+  QueryKey,
+  useMutation,
+  useQueryClient,
+  InfiniteData,
+  RefetchOptions,
+  RefetchQueryFilters,
+} from '@tanstack/vue-query';
+import { UnwrapNestedRefs, Ref, ref, reactive, computed } from 'vue';
+import Taro from '@tarojs/taro';
+
+export type BaseData<T = any> = {
+  data?: T[];
+  objectData?: any;
+  pageModel?: {
+    rows?: number;
+    page?: number;
+    totalCount?: number;
+    totalPage?: number;
+  };
+};
+
+export interface OrderInput {
+  property?: string;
+  order?: number;
+}
+
+export type ExtraParams = {
+  [key: string]: any;
+  orderByProperty?: string;
+};
+
+export type ServiceContext = {
+  pageParam?: any;
+  signal?: AbortSignal;
+};
+
+export type InfiniteGroupOptions = {
+  groupIndex?: number;
+  itemIndex?: number;
+};
+
+type Service<TData, TExtraParams extends ExtraParams> = (
+  context: ServiceContext,
+  extraParamsState: UnwrapNestedRefs<TExtraParams>
+) => Promise<TData>;
+
+type UseInfiniteLoadingOptions<T, TExtraParams extends ExtraParams> = {
+  /**
+   * @deprecated
+   */
+  defaultExtraParams?: TExtraParams;
+  enabled?: Ref<boolean> | boolean;
+  queryKey?: QueryKey;
+  onSuccess?: (data: InfiniteData<BaseData<T>>) => void;
+  onRefetch?: () => any;
+  useLocalData?: boolean;
+  refeshDidShow?: boolean;
+  select?: (data: InfiniteData<BaseData<T>>) => InfiniteData<BaseData<T>>;
+};
+// QueryFunction<BaseData<T>, (string | DeepUnwrapRef<UnwrapNestedRefs<TExtraParams>>)[], any>
+export function useInfiniteLoading<T, TExtraParams extends ExtraParams>(
+  service: Service<BaseData<T>, TExtraParams>,
+  options: UseInfiniteLoadingOptions<T, TExtraParams> = {}
+) {
+  const {
+    defaultExtraParams = {} as TExtraParams,
+    enabled = ref(true),
+    queryKey,
+    onSuccess,
+    onRefetch: _onRefetch,
+    useLocalData = false,
+    refeshDidShow = true,
+    select,
+  } = options;
+
+  const extraParamState = reactive({
+    ...defaultExtraParams,
+  });
+
+  const localData = ref({
+    pageParams: [],
+    pages: [],
+  });
+
+  const {
+    data,
+    error,
+    fetchNextPage,
+    hasNextPage,
+    isFetching,
+    isFetchingNextPage,
+    isLoading,
+    isError,
+    refetch,
+    isInitialLoading,
+    fetchPreviousPage,
+    hasPreviousPage,
+  } = useInfiniteQuery({
+    queryKey: queryKey,
+    queryFn: ({ pageParam = 1, signal }) => {
+      return service({ pageParam, signal }, extraParamState);
+    },
+    // initialPageParam: 1,
+    getNextPageParam: (lastPage, pages) => {
+      if (!lastPage) return 1;
+      if (
+        (lastPage.pageModel.page - 1) * lastPage.pageModel.rows + lastPage.data.length <
+          lastPage.pageModel.totalCount &&
+        lastPage.pageModel.totalCount > 0
+      ) {
+        return lastPage.pageModel.page + 1;
+      }
+    },
+    getPreviousPageParam: (firstPage, pages) => {
+      if (!firstPage) return 1;
+      if (
+        (firstPage.pageModel.page - 1) * firstPage.pageModel.rows + firstPage.data.length <
+          firstPage.pageModel.totalCount &&
+        firstPage.pageModel.totalCount > 0
+      ) {
+        return firstPage.pageModel.page + 1;
+      }
+    },
+    enabled: enabled,
+    onSuccess(data) {
+      // console.log('data2: ', data);
+      localData.value.pageParams = data.pageParams;
+      //@ts-ignore
+      localData.value.pages = data.pages;
+      onSuccess?.(data);
+    },
+    select(data) {
+      return select ? select(data) : data;
+    },
+  });
+
+  const _data = computed<InfiniteData<BaseData<T>>>(() =>
+    useLocalData ? (localData.value as any) : data.value
+  );
+
+  const queryClient = useQueryClient();
+
+  const { mutateAsync } = useMutation({
+    mutationFn: ({ pageParam }: ServiceContext) => fetchNextPage(pageParam),
+
+    // onSettled: async () => {
+    //   return await queryClient.invalidateQueries({ queryKey: queryKey });
+    // },
+  });
+
+  const { mutate: setListItem } = useMutation({
+    mutationFn: (data: { dataKey?: string; data: Partial<T> }) => {
+      return Promise.resolve(data);
+    },
+    onSuccess: ({ dataKey = 'id', data }) => {
+      console.log('dataKey: ', data);
+      const pagesArray: InfiniteData<BaseData<T>> = useLocalData
+        ? localData.value
+        : queryClient.getQueryData(queryKey);
+      console.log('pagesArray: ', pagesArray);
+      const newPagesArray =
+        pagesArray?.pages.map((page) => {
+          return {
+            ...page,
+            data: page.data.map((item) => {
+              if (item[dataKey] === data[dataKey]) {
+                return {
+                  ...item,
+                  ...data,
+                };
+              } else {
+                return item;
+              }
+            }),
+          };
+        }) ?? [];
+      if (useLocalData) {
+        console.log('newPagesArray: ', newPagesArray);
+        localData.value.pageParams = pagesArray.pageParams;
+        localData.value.pages = newPagesArray;
+      } else {
+        queryClient.setQueryData(queryKey, () => ({
+          pages: newPagesArray,
+          pageParams: pagesArray.pageParams,
+        }));
+      }
+    },
+  });
+
+  function onRefetch(options?: RefetchOptions & RefetchQueryFilters<unknown>) {
+    _onRefetch?.();
+    return refetch(options);
+  }
+
+  const infiniteLoadingProps = computed(() => ({
+    fetchNextPage,
+    listData: _data.value,
+    flattenListData: flattenListData.value,
+    // error: error.value,
+    hasMore: hasNextPage.value,
+    isFetching: isFetching.value,
+    isFetchingNextPage: isFetchingNextPage.value,
+    isLoading: isLoading.value,
+    isError: !!isError.value,
+    refetch: onRefetch,
+  }));
+
+  const flattenListData = computed(() => {
+    let list: BaseData<T>['data'] = [];
+    if (data && _data.value) {
+      _data.value?.pages.forEach((group) => {
+        group.data.forEach((item) => {
+          list.push(item);
+        });
+      });
+    }
+    return list;
+  });
+
+  if (refeshDidShow) {
+    useRefeshDidShow({ queryKey: queryKey });
+  }
+
+  const infiniteLoadingRef = ref<{ backToTop(): void; scrollToBottom(dis?: number): void }>();
+
+  function setByIndex(options: InfiniteGroupOptions = {}) {
+    refetch({ refetchPage: (page, index) => index === options.groupIndex, type: 'inactive' });
+  }
+
+  function updatePageByIndex(options: InfiniteGroupOptions = {}) {
+    refetch({ refetchPage: (page, index) => index === options.groupIndex, type: 'inactive' });
+  }
+
+  function remove() {
+    queryClient.invalidateQueries({ queryKey: queryKey });
+  }
+
+  function invalidateQueries() {
+    return queryClient.invalidateQueries({ queryKey: queryKey });
+  }
+
+  const listActions = {
+    setByIndex,
+    updatePageByIndex,
+    remove,
+  };
+
+  return {
+    infiniteLoadingProps,
+    flattenListData,
+    extraParamState,
+    mutateAsync,
+    setListItem,
+    cancel: () => queryClient.cancelQueries(queryKey),
+    infiniteLoadingRef,
+    listActions,
+    invalidateQueries,
+    fetchPreviousPage,
+    hasPreviousPage,
+  };
+}
+
+export type ListActionsType = {
+  setByIndex: (options?: InfiniteGroupOptions) => void;
+  updatePageByIndex: (options?: InfiniteGroupOptions) => void;
+  remove: () => void;
+};
+
+type UseRefeshDidShowOptions = {
+  queryKey: QueryKey;
+};
+
+export function useRefeshDidShow({ queryKey }: UseRefeshDidShowOptions) {
+  const queryClient = useQueryClient();
+  const showUpdate = ref(false);
+
+  Taro.useDidShow(() => {
+    if (showUpdate.value) {
+      queryClient.invalidateQueries({
+        queryKey: queryKey,
+      });
+    }
+  });
+
+  Taro.useDidHide(() => {
+    showUpdate.value = true;
+  });
+
+  Taro.useUnload(() => {
+    showUpdate.value = false;
+  });
+}
diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts
index 83f40ea..5806c92 100644
--- a/packages/components/src/index.ts
+++ b/packages/components/src/index.ts
@@ -1,7 +1,8 @@
 export { default as RechargeGrid } from './views/RechargeGrid/RechargeGrid.vue';
-export { default as Order } from './views/Order/Order.vue';
 export { default as PhoneBillRecharge } from './views/PhoneBillRecharge/PhoneBillRecharge.vue';
 export { default as electricBillRecharge } from './views/electricBillRecharge/electricBillRecharge.vue';
 export { default as SelectPayTypeView } from './views/SelectPayTypeView/SelectPayTypeView.vue';
 export { default as RechargeResultView } from './views/RechargeResultView/RechargeResultView.vue';
+export { default as PhoneOrder } from './views/Order/components/PhoneOrder.vue';
+export { default as ElectricOrder } from './views/Order/components/ElectricOrder.vue';
 export * from './utils';
diff --git a/packages/components/src/styles/index.scss b/packages/components/src/styles/index.scss
index e60a34e..37b4cc0 100644
--- a/packages/components/src/styles/index.scss
+++ b/packages/components/src/styles/index.scss
@@ -5,6 +5,7 @@
 @use './layout.scss' as *;
 @use './rechargeGrid.scss' as *;
 @use './components.scss' as *;
+@use './loading.scss' as *;
 
 :root,
 page {
diff --git a/packages/components/src/styles/loading.scss b/packages/components/src/styles/loading.scss
new file mode 100644
index 0000000..b5dacbe
--- /dev/null
+++ b/packages/components/src/styles/loading.scss
@@ -0,0 +1,43 @@
+@use './common.scss' as *;
+
+.no-data-wrapper {
+  display: flex;
+  width: 100%;
+  height: 100%;
+  justify-content: center;
+  align-items: center;
+  flex-direction: column;
+
+  .no-data-img {
+    width: 284px;
+    height: 202px;
+  }
+
+  .no-data-text {
+    font-size: 20px;
+    color: #333333;
+    line-height: 2.4;
+  }
+}
+
+.loading-layout-loading-content-wrapper {
+  padding: 40px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  .nut-icon {
+    color: boleGetCssVar('text-color', 'primary');
+    margin-right: 8px;
+  }
+
+  .list-empty-hint-text {
+    line-height: 1;
+    font-size: 30px;
+    color: boleGetCssVar('text-color', 'primary');
+  }
+}
+
+.loading-layout-error-wrapper {
+  height: 100%;
+}
diff --git a/packages/components/src/styles/rechargeGrid.scss b/packages/components/src/styles/rechargeGrid.scss
index a4a127f..6bff098 100644
--- a/packages/components/src/styles/rechargeGrid.scss
+++ b/packages/components/src/styles/rechargeGrid.scss
@@ -24,7 +24,7 @@
 
 .parValue-radio-group {
   width: 100%;
-  display: grid;
+  display: grid !important;
   grid-template-columns: repeat(3, 1fr);
   grid-gap: 10px;
 
diff --git a/packages/components/src/utils/lifeRecharge.ts b/packages/components/src/utils/lifeRecharge.ts
index 5afe980..1cdaf07 100644
--- a/packages/components/src/utils/lifeRecharge.ts
+++ b/packages/components/src/utils/lifeRecharge.ts
@@ -5,31 +5,37 @@
 } from './lifeRechargeServices';
 import { IRequest, BlLifeRechargeOptions } from './types';
 import { LifeRechargeConstants } from './lifeRechargeConstants';
+import { BlLifeRechargeAccountModel } from './lifeRechargeAccountModel';
 
 export class BlLifeRecharge<T extends IRequest = IRequest> {
   services: BlLifeRechargeServices<T>;
-  userId = '';
+  accountModel: BlLifeRechargeAccountModel;
 
   static constants = LifeRechargeConstants;
   constants = LifeRechargeConstants;
 
   constructor(options: BlLifeRechargeOptions<T>) {
     this.services = new BlLifeRechargeServices(options);
-    this.userId = options.userId || '';
+    this.accountModel = new BlLifeRechargeAccountModel({
+      userId: options.userId,
+      phoneNumber: options.phoneNumber,
+    });
   }
 
   async login(body: PhoneMesssageCodeLoginInput, options?: RequestConfig) {
     let res = await this.services.lifePayPhoneMesssageCodeLogin(body, options);
-    this.userId = res;
+    this.accountModel.setUserId(res);
+    this.accountModel.setPhoneNumber(body.phoneNumber);
     return res;
   }
 
   loginout() {
-    this.userId = '';
+    this.accountModel.setUserId('');
+    this.accountModel.setPhoneNumber('');
   }
 
   isLogin() {
-    return !!this.userId;
+    return !!this.accountModel.userId;
   }
 
   getRechargeParValue(amount: number, rate: number) {
diff --git a/packages/components/src/utils/lifeRechargeAccountModel.ts b/packages/components/src/utils/lifeRechargeAccountModel.ts
new file mode 100644
index 0000000..67f1d9a
--- /dev/null
+++ b/packages/components/src/utils/lifeRechargeAccountModel.ts
@@ -0,0 +1,20 @@
+import { BlLifeRechargeAccountModelOptions } from './types';
+
+export class BlLifeRechargeAccountModel {
+  userId = '';
+  phoneNumber = '';
+
+  constructor(options: BlLifeRechargeAccountModelOptions = {}) {
+    const { userId, phoneNumber } = options;
+    this.setUserId(userId);
+    this.setPhoneNumber(phoneNumber);
+  }
+
+  setUserId(userId: string) {
+    this.userId = userId;
+  }
+
+  setPhoneNumber(phoneNumber: string) {
+    this.phoneNumber = phoneNumber;
+  }
+}
diff --git a/packages/components/src/utils/lifeRechargeServices.ts b/packages/components/src/utils/lifeRechargeServices.ts
index d45d643..9b6957e 100644
--- a/packages/components/src/utils/lifeRechargeServices.ts
+++ b/packages/components/src/utils/lifeRechargeServices.ts
@@ -99,6 +99,18 @@
       ...(options || {}),
     });
   }
+
+  /** 鑾峰彇鎴戠殑璁㈠崟鍒嗛〉鏁版嵁 POST /api/LifePay/GetUserLifePayOrderPage */
+  async getUserLifePayOrderPage(body: QueryLifePayOrderListInput, options?: RequestConfig) {
+    return this.request<UserLifePayOrderOutputPageOutput>('/api/LifePay/GetUserLifePayOrderPage', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      data: body,
+      ...(options || {}),
+    });
+  }
 }
 
 export interface PhoneMesssageCodeLoginInput {
@@ -210,3 +222,61 @@
   orderNo: string;
   lifePayType?: LifeRechargeConstants.LifePayTypeEnum;
 }
+
+export interface QueryLifePayOrderListInput {
+  pageModel?: Pagination;
+  lifePayOrderType?: LifeRechargeConstants.LifePayOrderTypeEnum;
+  /** 寮�濮嬫敮浠樻椂闂� */
+  beginPayTime?: string;
+  /** 缁撴潫鏀粯鏃堕棿 */
+  endPayTime?: string;
+  payStatus?: LifeRechargeConstants.LifePayStatusEnum;
+  lifePayOrderStatus?: LifeRechargeConstants.LifePayOrderStatusEnum;
+  /** 寮�濮嬪畬鎴愭椂闂� */
+  beginFinishTime?: string;
+  /** 缁撴潫瀹屾垚鏃堕棿 */
+  endFinishTime?: string;
+  /** 鐢ㄦ埛Id */
+  userId?: string;
+}
+
+export interface Pagination {
+  rows?: number;
+  page?: number;
+  orderInput?: OrderInput[];
+  totalCount?: number;
+  totalPage?: number;
+}
+
+export interface OrderInput {
+  property?: string;
+  order?: any;
+}
+
+export interface UserLifePayOrderOutputPageOutput {
+  pageModel?: Pagination;
+  objectData?: any;
+  data?: UserLifePayOrderOutput[];
+}
+
+export interface UserLifePayOrderOutput {
+  id?: string;
+  lifePayType?: LifeRechargeConstants.LifePayTypeEnum;
+  lifePayOrderType?: LifeRechargeConstants.LifePayOrderTypeEnum;
+  /** 璁㈠崟鍙� */
+  orderNo?: string;
+  /** 鍏呭�奸噾棰� */
+  rechargeAmount?: number;
+  /** 浼樻儬閲戦 */
+  discountAmount?: number;
+  /** 瀹炰粯閲戦 */
+  payAmount?: number;
+  /** 鏀粯鏃堕棿 */
+  payTime?: string;
+  payStatus?: LifeRechargeConstants.LifePayStatusEnum;
+  lifePayOrderStatus?: LifeRechargeConstants.LifePayOrderStatusEnum;
+  /** 瀹屾垚鏃堕棿 */
+  finishTime?: string;
+  /** 璁㈠崟璇︾粏鏁版嵁 */
+  orderParamDetailJsonStr?: string;
+}
diff --git a/packages/components/src/utils/types.ts b/packages/components/src/utils/types.ts
index f28bcae..eec3753 100644
--- a/packages/components/src/utils/types.ts
+++ b/packages/components/src/utils/types.ts
@@ -10,6 +10,10 @@
   request: T;
 };
 
-export type BlLifeRechargeOptions<T extends IRequest> = BlLifeRechargeServicesOptions<T> & {
+export type BlLifeRechargeAccountModelOptions = {
   userId?: string;
+  phoneNumber?: string;
 };
+
+export type BlLifeRechargeOptions<T extends IRequest> = BlLifeRechargeServicesOptions<T> &
+  BlLifeRechargeAccountModelOptions & {};
diff --git a/packages/components/src/views/Order/components/PhoneOrder.vue b/packages/components/src/views/Order/components/PhoneOrder.vue
index 530a7cf..782d440 100644
--- a/packages/components/src/views/Order/components/PhoneOrder.vue
+++ b/packages/components/src/views/Order/components/PhoneOrder.vue
@@ -1,23 +1,25 @@
 <template>
-  <!-- <InfiniteLoading scrollViewClassName="common-infinite-scroll-list" v-bind="infiniteLoadingProps">
-    <template #renderItem="{ item }"> -->
-  <OrderCard title="璇濊垂鍏呭��" status="寰呮敮浠�">
-    <OrderCardItem label="鍏呭�艰处鍙�:" :value="'18888888888'" />
-    <OrderCardItem label="涓嬪崟鏃堕棿:" :value="'18888888888'" />
-    <OrderCardItem label="鍏呭�奸噾棰�:" :value="'18888888888'" />
-    <OrderCardItem label="浼樻儬閲戦:" :value="'18888888888'" />
-    <OrderCardItem label="瀹炰粯閲戦:" :value="'18888888888'" />
-    <OrderCardItem label="鏀粯鏃堕棿:" :value="'2025-02-19  17:15:54'" />
-    <OrderCardItem label="瀹屾垚鏃堕棿:" :value="'2025-02-19  17:15:54'" />
-  </OrderCard>
-  <!-- </template>
-  </InfiniteLoading> -->
+  <InfiniteLoading scrollViewClassName="common-infinite-scroll-list" v-bind="infiniteLoadingProps">
+    <template #renderItem="{ item }">
+      <OrderCard title="璇濊垂鍏呭��" status="寰呮敮浠�">
+        <OrderCardItem label="鍏呭�艰处鍙�:" :value="'18888888888'" />
+        <OrderCardItem label="涓嬪崟鏃堕棿:" :value="'18888888888'" />
+        <OrderCardItem label="鍏呭�奸噾棰�:" :value="'18888888888'" />
+        <OrderCardItem label="浼樻儬閲戦:" :value="'18888888888'" />
+        <OrderCardItem label="瀹炰粯閲戦:" :value="'18888888888'" />
+        <OrderCardItem label="鏀粯鏃堕棿:" :value="'2025-02-19  17:15:54'" />
+        <OrderCardItem label="瀹屾垚鏃堕棿:" :value="'2025-02-19  17:15:54'" />
+      </OrderCard>
+    </template>
+  </InfiniteLoading>
 </template>
 
 <script setup lang="ts">
 import InfiniteLoading from '../../../components/InfiniteLoading/InfiniteLoading.vue';
 import OrderCard from '../../../components/Card/OrderCard.vue';
 import OrderCardItem from '../../../components/Card/OrderCardItem.vue';
+import { useGetUserLifePayOrderPage } from '../../../hooks';
+import { BlLifeRecharge } from '../../../utils';
 
 defineOptions({
   name: 'PhoneOrder',
@@ -27,7 +29,7 @@
 
 // const props = withDefaults(defineProps<Props>(), {});
 
-const infiniteLoadingProps = {};
+const { infiniteLoadingProps } = useGetUserLifePayOrderPage({
+  lifePayOrderType: BlLifeRecharge.constants.LifePayOrderTypeEnum.璇濊垂璁㈠崟,
+});
 </script>
-
-<style lang="scss"></style>
diff --git a/packages/components/src/views/PhoneBillRecharge/PhoneBillRecharge.vue b/packages/components/src/views/PhoneBillRecharge/PhoneBillRecharge.vue
index 43fb296..191f9fc 100644
--- a/packages/components/src/views/PhoneBillRecharge/PhoneBillRecharge.vue
+++ b/packages/components/src/views/PhoneBillRecharge/PhoneBillRecharge.vue
@@ -176,7 +176,7 @@
 async function goPay() {
   try {
     let params: LifePhoneDataCreateLifePayOrderInput = {
-      userId: blLifeRecharge.userId,
+      userId: blLifeRecharge.accountModel.userId,
       productData: {
         ispCode: form.ispCode,
         parValue: 0.1,
diff --git a/packages/components/src/views/RechargeResultView/RechargeResultView.vue b/packages/components/src/views/RechargeResultView/RechargeResultView.vue
index d83124d..4d89ab3 100644
--- a/packages/components/src/views/RechargeResultView/RechargeResultView.vue
+++ b/packages/components/src/views/RechargeResultView/RechargeResultView.vue
@@ -1,6 +1,6 @@
 <template>
   <div class="recharge-result-view">
-    <div class="recharge-result-view-title">鏀粯鎴愬姛锛屽厖鍊兼灏嗗湪0-24灏忔椂鍐呭埌璐�</div>
+    <div class="recharge-result-view-title">{{ title }}</div>
     <div class="recharge-result-view-tips">
       鍚屼竴鍙风爜鍏呭�兼湡闂达紝鏈埌璐﹀墠鍒囧嬁鍦ㄥ叾浠栦换浣曞钩鍙板啀娆″厖鍊笺�傚洜姝ら�犳垚鐨勮祫閲戞崯澶遍』鐢ㄦ埛鑷鎵挎媴锛侊紒锛�
     </div>
@@ -14,13 +14,24 @@
 </template>
 
 <script setup lang="ts">
+import Taro from '@tarojs/taro';
+import { BlLifeRecharge } from '@life-payment/components';
+
 defineOptions({
   name: 'RechargeResultView',
 });
 
-// type Props = {};
+type Props = {
+  title?: string;
+};
 
-// const props = withDefaults(defineProps<Props>(), {});
+const props = withDefaults(defineProps<Props>(), {
+  title: '鏀粯鎴愬姛锛屽厖鍊兼灏嗗湪0-24灏忔椂鍐呭埌璐�',
+});
+
+const router = Taro.useRouter();
+const orderNo = router.params?.orderNo ?? '';
+const lifePayOrderType = Number(router.params?.lifePayOrderType ?? '');
 
 const emit = defineEmits<{
   (e: 'goBackHome'): void;
diff --git a/packages/components/src/views/SelectPayTypeView/SelectPayTypeView.vue b/packages/components/src/views/SelectPayTypeView/SelectPayTypeView.vue
index 6df3a0e..1511491 100644
--- a/packages/components/src/views/SelectPayTypeView/SelectPayTypeView.vue
+++ b/packages/components/src/views/SelectPayTypeView/SelectPayTypeView.vue
@@ -31,11 +31,16 @@
 // const props = withDefaults(defineProps<Props>(), {});
 
 const emit = defineEmits<{
-  (e: 'paySuccess', id: number): void;
+  (
+    e: 'paySuccess',
+    orderNo: string,
+    lifePayOrderType: LifeRechargeConstants.LifePayOrderTypeEnum
+  ): void;
 }>();
 
 const router = Taro.useRouter();
 const orderNo = router.params?.orderNo ?? '';
+const lifePayOrderType = Number(router.params?.lifePayOrderType ?? '');
 
 const { blLifeRecharge } = useLifeRechargeContext();
 
@@ -58,22 +63,23 @@
   } catch (error) {}
 }
 
-// useQuery({
-//   queryKey: ['platformServicePayServices/getPlaformServicePayQRCode', orderNo],
-//   queryFn: async () => {
-//     return await blLifeRecharge.services.getPayStatusByOrderNo(
-//       {
-//         orderNo,
-//       },
-//       {
-//         showLoading: false,
-//       }
-//     );
-//   },
-//   onSuccess(data) {
-//     if (data === blLifeRecharge.constants.LifePayStatusEnum.宸叉敮浠�) {
-//     }
-//   },
-//   refetchInterval: 1000 * 3,
-// });
+useQuery({
+  queryKey: ['platformServicePayServices/getPayStatusByOrderNo', orderNo],
+  queryFn: async () => {
+    return await blLifeRecharge.services.getPayStatusByOrderNo(
+      {
+        orderNo,
+      },
+      {
+        showLoading: false,
+      }
+    );
+  },
+  onSuccess(data) {
+    if (data === blLifeRecharge.constants.LifePayStatusEnum.宸叉敮浠�) {
+      emit('paySuccess', orderNo, lifePayOrderType);
+    }
+  },
+  refetchInterval: 1000 * 3,
+});
 </script>

--
Gitblit v1.9.1