index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <template>
  2. <div class="page-view" ref="scrollContainerRef" @scroll="handleScroll">
  3. <div class="page-content">
  4. <div class="nav-bar">
  5. <div class="title-section" @click="onGoBack">
  6. <button class="back-btn">
  7. <img src="@/assets/images/common/back.svg" alt="back" class="w-full h-full" />
  8. </button>
  9. <span class="page-title">{{ $t("转账记录") }}</span>
  10. </div>
  11. </div>
  12. <div class="records-container">
  13. <page-loading v-if="isLoading" />
  14. <template v-else>
  15. <div v-for="(record, index) in list" :key="index" class="transfer-item">
  16. <div class="item-content">
  17. <div class="item-left">
  18. <img :src="record.icon" class="coin-icon" />
  19. <div class="transfer-info">
  20. <div class="transfer-type">{{ record.symbol }} {{ record.directionName }}</div>
  21. <div class="transfer-time">{{ formateTimestamp(record.createdAt) }}</div>
  22. </div>
  23. </div>
  24. <div class="item-right">
  25. <div class="amount-info">
  26. <div class="amount" :class="record.direction">
  27. {{ record.direction === 2 ? "-" : "+" }}{{ record.amount }} {{ record.symbol }}
  28. </div>
  29. <div class="status-badge" :class="getStatusText(record.status)">
  30. {{ record.stateName }}
  31. </div>
  32. </div>
  33. </div>
  34. </div>
  35. </div>
  36. <no-data v-if="list.length === 0" />
  37. </template>
  38. <loading-more :show="isLoadingMore" />
  39. </div>
  40. </div>
  41. </div>
  42. </template>
  43. <script setup lang="ts">
  44. import { ref, onMounted } from "vue";
  45. import NoData from "@/components/NoData/index.vue";
  46. import { useRouter } from "vue-router";
  47. import { requestGetAssetBill } from "@/api";
  48. import PageLoading from "@/components/PageLoading/index.vue";
  49. import LoadingMore from "@/components/LoadingMore/index.vue";
  50. import { formateTimestamp } from "@/utils/utils";
  51. import useLoadPageList from "@/hooks/useLoadPageList";
  52. const router = useRouter();
  53. const scrollContainerRef = ref<HTMLDivElement>(null);
  54. const { list, isLoading, isLoadingMore, handleScroll, getList } = useLoadPageList<AssetBill>(
  55. requestGetAssetBill,
  56. scrollContainerRef,
  57. {},
  58. 15
  59. );
  60. const getStatusText = (status: number) => {
  61. const statusMap = {
  62. 0: "pending",
  63. 1: "pending",
  64. 2: "success",
  65. 3: "failed",
  66. 4: "failed",
  67. 5: "failed"
  68. };
  69. return statusMap[status as keyof typeof statusMap] || status;
  70. };
  71. const onGoBack = () => {
  72. router.replace({ name: "finance" });
  73. };
  74. onMounted(() => {
  75. getList();
  76. });
  77. </script>
  78. <style lang="scss" scoped>
  79. .page-view {
  80. height: 100%;
  81. overflow: auto;
  82. .page-content {
  83. position: relative;
  84. padding: 8px 16px;
  85. min-height: 200px;
  86. padding-bottom: 50px;
  87. }
  88. }
  89. .nav-bar {
  90. position: relative;
  91. width: 100%;
  92. margin-bottom: 16px;
  93. .title-section {
  94. display: flex;
  95. align-items: center;
  96. gap: 5px;
  97. .back-btn {
  98. display: flex;
  99. align-items: center;
  100. justify-content: center;
  101. width: 20px;
  102. height: 20px;
  103. background: none;
  104. border: none;
  105. color: #ffffff;
  106. cursor: pointer;
  107. .back-icon {
  108. width: 16px;
  109. height: 16px;
  110. }
  111. }
  112. .page-title {
  113. font-size: 14px;
  114. font-weight: 500;
  115. color: #929296;
  116. }
  117. }
  118. }
  119. .records-container {
  120. width: 100%;
  121. .transfer-item {
  122. width: 100%;
  123. .item-content {
  124. display: flex;
  125. justify-content: space-between;
  126. align-items: center;
  127. padding: 16px 0;
  128. height: 74px;
  129. .item-left {
  130. display: flex;
  131. align-items: center;
  132. flex: 1;
  133. .coin-icon {
  134. width: 36px;
  135. height: 36px;
  136. margin-right: 12px;
  137. display: flex;
  138. align-items: center;
  139. justify-content: center;
  140. .icon {
  141. font-size: 36px;
  142. }
  143. }
  144. .transfer-info {
  145. display: flex;
  146. flex-direction: column;
  147. gap: 2px;
  148. .transfer-type {
  149. font-size: 16px;
  150. line-height: 24px;
  151. color: #ffffff;
  152. }
  153. .transfer-time {
  154. font-size: 12px;
  155. line-height: 16px;
  156. color: #929296;
  157. }
  158. }
  159. }
  160. .item-right {
  161. display: flex;
  162. align-items: center;
  163. gap: 12px;
  164. .amount-info {
  165. display: flex;
  166. flex-direction: column;
  167. align-items: flex-end;
  168. gap: 6px;
  169. .amount {
  170. font-size: 16px;
  171. line-height: 24px;
  172. text-align: right;
  173. color: #fff;
  174. }
  175. .status-badge {
  176. padding: 3px 5px;
  177. border-radius: 2px;
  178. font-size: 12px;
  179. line-height: 14px;
  180. text-align: center;
  181. &.pending {
  182. background: rgba(255, 110, 0, 0.12);
  183. color: #ff6e00;
  184. }
  185. &.success {
  186. background: rgba(74, 230, 153, 0.12);
  187. color: #14ae69;
  188. }
  189. &.failed {
  190. background: rgba(233, 39, 0, 0.12);
  191. color: #e92700;
  192. }
  193. }
  194. }
  195. .more-icon {
  196. width: 24px;
  197. height: 24px;
  198. color: rgba(255, 255, 255, 0.6);
  199. cursor: pointer;
  200. svg {
  201. width: 100%;
  202. height: 100%;
  203. }
  204. }
  205. }
  206. }
  207. }
  208. }
  209. </style>