wallet.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. <template>
  2. <view class="page flex-column">
  3. <navigation-bar
  4. autoFixedStyle="background-color:#fff;"
  5. title="我的钱包"
  6. @ready="ready"
  7. ></navigation-bar>
  8. <view class="head flex-shrink">
  9. <view>
  10. <image class="bg" src="../static/wallet-banner.png"></image>
  11. <view class="fg pt-48 pl-48 pr-48">
  12. <view class="flex-align-center">
  13. <uni-icons
  14. type="wallet-filled"
  15. size="24"
  16. color="#ffffff"
  17. ></uni-icons>
  18. <view class="fs-36 color-fff fw-500 ml-16">我的钱包</view>
  19. <view
  20. class="btn flex-center fs-28 ml-auto"
  21. @click="to(`/pages-user/wallet-refund/wallet-refund`)"
  22. >退款
  23. </view
  24. >
  25. </view>
  26. <view class="price mt-50" v-if="user">
  27. <text class="color-fff fw-600 fs-48" style="vertical-align: top"
  28. >¥
  29. </text
  30. >
  31. <text
  32. class="color-fff fw-600 ml-12"
  33. style="font-size: 46px; line-height: 46px"
  34. >{{ user.balance }}
  35. </text
  36. >
  37. </view>
  38. </view>
  39. </view>
  40. </view>
  41. <view class="body flex-grow flex-column">
  42. <view class="tabs flex-shrink flex-align-center">
  43. <view
  44. v-for="(item, index) in tabs"
  45. :key="index"
  46. class="flex-align-center fs-30 mr-60"
  47. :style="{
  48. color:
  49. tab === item.value ? '#1c2b29;' : '#5c6b69;',
  50. fontWeight: tab === item.value ? '600' : '400',
  51. }"
  52. @click="changeTab(index)"
  53. >{{
  54. item.label
  55. }}
  56. <view
  57. :style="{ opacity: tab === item.value ? '1' : '0' }"
  58. class="active"
  59. ></view
  60. >
  61. </view>
  62. </view>
  63. <view class="list pl-30 pr-30">
  64. <view
  65. class="item flex-align-center pressable"
  66. hover-class="pressed"
  67. hover-stay-time="80"
  68. v-for="(item, index) in dataList"
  69. :key="index"
  70. @click="detail(index)"
  71. >
  72. <view>
  73. <view class="fs-30 fw-500" key="title" duration="300">{{
  74. typeMap[item.type - 1]
  75. }}
  76. </view>
  77. <view v-if="item.type!==2">
  78. <view class="fs-24" style="color: #8c9997">余额</view>
  79. </view>
  80. <view v-else>
  81. <text class="refund-status" :style="refundStyle(item.status)">{{ refundLabel(item.status) }}</text>
  82. </view>
  83. </view>
  84. <view class="ml-auto" style="text-align: right">
  85. <view class="fs-30 fw-500">
  86. <text>{{ item.type == 3 ? "- " : "" }}{{ item.amount }}</text>
  87. <text class="fs-24 ml-6">元</text>
  88. </view>
  89. <view class="fs-24" style="color: #8c9997">{{
  90. item.transactionTime
  91. }}
  92. </view>
  93. </view>
  94. <view class="ml-32" v-if="item.type === 3">
  95. <uni-icons
  96. type="right"
  97. size="12"
  98. color="rgba(28,43,41,0.4)"
  99. ></uni-icons>
  100. </view>
  101. <view class="ml-32" v-else>&nbsp;&nbsp;&nbsp;</view>
  102. </view>
  103. </view>
  104. <view style="height: 170rpx"></view>
  105. </view>
  106. <style-bottom-view background="#ffffff">
  107. <view class="pl-40 pr-40 pb-30 pt-30">
  108. <style-button
  109. type="primary"
  110. @click="to(`/pages-user/wallet-recharge/wallet-recharge`)"
  111. >充值
  112. </style-button
  113. >
  114. </view>
  115. </style-bottom-view>
  116. </view>
  117. </template>
  118. <script setup lang="ts">
  119. import {useInfiniteScroll} from "../../utils/infinite-scroll";
  120. import {onReachBottom, onPullDownRefresh, onShow} from "@dcloudio/uni-app";
  121. import {fetchWallet, listRefund} from "../../api/user";
  122. import {to} from "../../utils/navigate";
  123. import {ref} from "vue";
  124. import {rpxToPx} from "@/utils/device";
  125. import { requireAuth } from "@/utils/auth";
  126. const user = ref();
  127. const dataList = ref([])
  128. const tab = ref(0);
  129. const tabs = ref([
  130. {
  131. label: "全部",
  132. value: 0,
  133. },
  134. {
  135. label: "充值",
  136. value: 1,
  137. },
  138. {
  139. label: "消费",
  140. value: 3,
  141. },
  142. {
  143. label: "退款",
  144. value: 2,
  145. },
  146. ]);
  147. const refundStatusMap = ref([
  148. {label: '退款成功 ', value: 'SUCCESS', color: '#4cd964'},
  149. {label: '退款关闭 ', value: 'CLOSED', color: '#000000'},
  150. {label: '退款处理中 ', value: 'PROCESSING', color: '#007aff'},
  151. {label: '退款异常 ', value: 'ABNORMAL', color: '#dd524d'},
  152. {label: '退款已申请 ', value: 'NEW', color: '#f0ad4e'},
  153. ])
  154. const typeMap = ref(["充值", "退款", "消费"]);
  155. /*const infiniteScroller = useInfiniteScroll(10, (page) => {
  156. return fetchWallet(tab.value, page, 10).then((res: any) => {
  157. if (res && res.length) {
  158. res.forEach((item: any) => {
  159. item.amount = (Number(item.amount) / 100).toFixed(2);
  160. });
  161. }
  162. return res;
  163. });
  164. });*/
  165. const scrollViewHeight = ref(0);
  166. onShow(() => {
  167. if (!requireAuth()) {
  168. return;
  169. }
  170. loadData();
  171. if (getApp<any>().globalData.user) {
  172. user.value = getApp<any>().globalData.user;
  173. }
  174. })
  175. onReachBottom(() => {
  176. // if(tab.value!==2){
  177. // infiniteScroller.next();
  178. // }
  179. loadData();
  180. });
  181. onPullDownRefresh(() => {
  182. // if(tab.value!==2){
  183. // infiniteScroller.refresh();
  184. // }
  185. loadData();
  186. });
  187. const ready = (e: any) => {
  188. scrollViewHeight.value =
  189. getApp<any>().globalData.device.windowHeight -
  190. (e.detail.navigationBarHeight + rpxToPx(380));
  191. };
  192. const refundLabel = (value: string) => {
  193. return refundStatusMap.value.find((item: any) => item.value === value)?.label
  194. }
  195. const refundStyle = (value: string) => {
  196. let rf = refundStatusMap.value.find((item: any) => item.value === value);
  197. return setupLabelColorStyle(rf?.color)
  198. }
  199. const setupLabelColorStyle = (hex: string = "#000000", opacity = 0.2) => {
  200. if (!hex) {
  201. hex = "#000000"
  202. }
  203. hex = hex.replace("#", "");
  204. // Convert the hex value to RGB values
  205. const r = parseInt(hex.substring(0, 2), 16);
  206. const g = parseInt(hex.substring(2, 4), 16);
  207. const b = parseInt(hex.substring(4, 6), 16);
  208. return {
  209. /* 'text-shadow': `2px 2px 3px rgba(${r},${g},${b},${opacity})`,
  210. 'background-color': `rgba(${r},${g},${b},${opacity})`,*/
  211. 'color': `rgb(${r},${g},${b})`
  212. }
  213. }
  214. const changeTab = (index: number) => {
  215. tab.value = tabs.value[index].value;
  216. loadData();
  217. /* if (tab.value === 2) {
  218. let user = getApp<any>().globalData.user;
  219. if (user) {
  220. listRefund({userId: user.id,pageSize:1000}).then((res: any) => {
  221. console.log(res)
  222. let dataList = (res.list || []).map(item => {
  223. item.amount = (Number(item.refund) / 100).toFixed(2);
  224. item.type = 2;
  225. if (item.successTime) {
  226. item.transactionTime = item.successTime.slice(0, 3).join("-") + " " + item.successTime.slice(3, 6).join(":")
  227. }
  228. return item;
  229. })
  230. infiniteScroller.setList(dataList);
  231. })
  232. } else {
  233. infiniteScroller.refresh();
  234. }
  235. }*/
  236. }
  237. const loadData = () => {
  238. if (!user) return;
  239. if (tab.value !== 2) {
  240. fetchWallet(tab.value, 1, 1000).then((res: any) => {
  241. if (res && res.length) {
  242. res.forEach((item: any) => {
  243. item.amount = (Number(item.amount) / 100).toFixed(2);
  244. });
  245. }
  246. dataList.value = res;
  247. });
  248. } else {
  249. listRefund({userId: user.value.id, pageSize: 1000}).then((res: any) => {
  250. console.log(res)
  251. let list = (res.list || []).map(item => {
  252. item.amount = (Number(item.refund) / 100).toFixed(2);
  253. item.type = 2;
  254. if (item.successTime) {
  255. item.transactionTime = item.successTime.slice(0, 3).join("-") + " " + item.successTime.slice(3, 6).join(":")
  256. }
  257. return item;
  258. })
  259. dataList.value = list;
  260. })
  261. }
  262. }
  263. const detail = (index: number) => {
  264. if (!dataList.value) {
  265. return;
  266. }
  267. if (dataList.value[index].type === 3) {
  268. uni.navigateTo({
  269. url: `/pages-charge/order/order?id=${dataList.value[index]?.orderNo}`,
  270. });
  271. }
  272. };
  273. </script>
  274. <style lang="scss">
  275. .page {
  276. height: 100vh;
  277. width: 100vw;
  278. background: linear-gradient(
  279. 180deg,
  280. #d9efec 0%,
  281. rgba(255, 255, 255, 0) 60.13%
  282. );
  283. .head {
  284. padding: 30rpx 40rpx;
  285. & > view {
  286. position: relative;
  287. height: 320rpx;
  288. border-radius: 40rpx;
  289. overflow: hidden;
  290. .bg {
  291. height: 100%;
  292. width: 100%;
  293. }
  294. .fg {
  295. position: absolute;
  296. left: 0px;
  297. top: 0px;
  298. height: 100%;
  299. width: 100%;
  300. .btn {
  301. width: 120rpx;
  302. height: 64rpx;
  303. border-radius: 40rpx;
  304. background: rgba(255, 255, 255, 0.3);
  305. color: var(--color-primary-deep);
  306. }
  307. }
  308. }
  309. }
  310. .body {
  311. .tabs {
  312. padding: 0 40rpx;
  313. & > view {
  314. position: relative;
  315. height: 72rpx;
  316. transition: opacity 0.22s cubic-bezier(0.22, 1, 0.36, 1);
  317. .active {
  318. position: absolute;
  319. left: 50%;
  320. bottom: 0px;
  321. transform: translateX(-50%);
  322. width: 40rpx;
  323. height: 6rpx;
  324. border-radius: 6rpx;
  325. background-color: var(--color-primary);
  326. transition: opacity 0.22s cubic-bezier(0.22, 1, 0.36, 1);
  327. }
  328. }
  329. }
  330. .list {
  331. .item {
  332. height: 130rpx;
  333. border-bottom: 1rpx solid var(--divider);
  334. &:last-child {
  335. border-bottom: none;
  336. }
  337. }
  338. }
  339. }
  340. }
  341. .refund-status {
  342. display: inline-block;
  343. //padding: 8rpx;
  344. font-size: 22rpx;
  345. font-weight: 500;
  346. }
  347. </style>