wallet.vue 10 KB

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