wallet.vue 9.0 KB

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