global-list.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <template>
  2. <cwg-page-wrapper>
  3. <view class="bank-transaction-page">
  4. <view class="filters-container" :style="{ top: statusBarHeight + 53 + 'px' }">
  5. <view class="filter-item">
  6. <text class="filter-label">{{ t('global.p25') }}</text>
  7. <cwg-picker v-model="payoutCurrency" :options="currencyList" />
  8. </view>
  9. <view class="filter-item">
  10. <text class="filter-label">{{ t('card.Form.f45') }}</text>
  11. <cwg-picker v-model="statusFilterIndex" :options="statusOptions" />
  12. </view>
  13. <view class="filter-item">
  14. <text class="filter-label">{{ t('card.Form.f43') }}</text>
  15. <view class="filter-picker" @click="open">
  16. <view class="picker-value">
  17. <text class="picker-text">{{ dateFilter || t('card.Form.f57') }}</text>
  18. <uni-icons type="calendar" size="14" color="#6b7280" class="picker-icon" />
  19. </view>
  20. </view>
  21. <cwg-date-picker v-model:show="show" v-model="dateFilter" mode="date" @confirm="onDateConfirm"
  22. :minDate="minDate" :maxDate="maxDate" />
  23. </view>
  24. <view class="reset-btn" @click="resetFilters">
  25. <uni-icons type="loop" size="16" color="#2563eb" />
  26. </view>
  27. </view>
  28. <view class="content">
  29. <GlobalList ref="globalListRef" :cardNo="cardNo" :payoutCurrency="payoutCurrency"
  30. :statusIndex="statusFilterIndex" :dateFilter="dateFilter" />
  31. </view>
  32. </view>
  33. </cwg-page-wrapper>
  34. </template>
  35. <script setup lang="ts">
  36. import { ref, computed, watch } from 'vue';
  37. import { onLoad } from '@dcloudio/uni-app';
  38. import { useI18n } from 'vue-i18n';
  39. import useGlobalStore from '@/stores/use-global-store';
  40. import GlobalList from './components/GlobalList.vue';
  41. import { globalStatusText1 } from '@/utils/dataMap';
  42. import useCardStore from "@/stores/use-card-store";
  43. const cardStore = useCardStore();
  44. const globalStore = useGlobalStore()
  45. const statusBarHeight = computed(() => globalStore.statusBarHeight);
  46. const { t } = useI18n();
  47. const minDate = ref(new Date(2000, 0, 1).getTime());
  48. const maxDate = ref(new Date().getTime());
  49. const cardNo = ref('');
  50. onLoad((options) => {
  51. cardNo.value = options.cardNo || '';
  52. });
  53. const statusOptions = computed(() => {
  54. return globalStatusText1
  55. });
  56. const currencyList = computed(() => {
  57. const res = cardStore.currencyList.map(item => { return { label: item.payoutCurrency, value: item.payoutCurrency } });
  58. return res;
  59. });
  60. const payoutCurrency = ref();
  61. const statusFilterIndex = ref(0);
  62. const dateFilter = ref('');
  63. const show = ref(false)
  64. const onDateConfirm = (e: any) => {
  65. dateFilter.value = e.formatted;
  66. };
  67. function open() {
  68. show.value = true
  69. }
  70. const resetFilters = () => {
  71. payoutCurrency.value = '';
  72. statusFilterIndex.value = 0;
  73. dateFilter.value = '';
  74. };
  75. </script>
  76. <style scoped lang="scss">
  77. @import "@/uni.scss";
  78. .page-wrapper {
  79. padding: 0;
  80. border: 0;
  81. }
  82. .bank-transaction-page {
  83. // background-color: #f9fafb;
  84. }
  85. .wallet-header {
  86. background: linear-gradient(135deg, #2563eb 0%, #60a5fa 100%);
  87. }
  88. /* Header */
  89. .header {
  90. background: linear-gradient(135deg, #2563eb 0%, #60a5fa 100%);
  91. padding: px2rpx(16);
  92. padding-bottom: px2rpx(20);
  93. }
  94. .header-content {
  95. display: flex;
  96. flex-direction: column;
  97. gap: px2rpx(16);
  98. }
  99. .header-title {
  100. display: flex;
  101. align-items: center;
  102. gap: px2rpx(8);
  103. }
  104. .title-text {
  105. color: #ffffff;
  106. font-size: px2rpx(20);
  107. }
  108. .stats-container {
  109. display: flex;
  110. gap: px2rpx(12);
  111. }
  112. .stat-card {
  113. flex: 1;
  114. background-color: rgba(255, 255, 255, 0.15);
  115. backdrop-filter: blur(px2rpx(10));
  116. border-radius: px2rpx(12);
  117. padding: px2rpx(12);
  118. }
  119. .stat-header {
  120. display: flex;
  121. align-items: center;
  122. gap: px2rpx(6);
  123. margin-bottom: px2rpx(8);
  124. }
  125. .icons {
  126. width: px2rpx(20);
  127. height: px2rpx(20);
  128. }
  129. .stat-label {
  130. font-size: px2rpx(12);
  131. color: rgba(255, 255, 255, 0.9);
  132. }
  133. .stat-value {
  134. font-size: px2rpx(20);
  135. color: #ffffff;
  136. display: block;
  137. margin-bottom: px2rpx(4);
  138. }
  139. .stat-count {
  140. font-size: px2rpx(11);
  141. color: rgba(255, 255, 255, 0.8);
  142. }
  143. /* Tabs */
  144. .tabs-container {
  145. background-color: #ffffff;
  146. display: flex;
  147. border-bottom: 1px solid #e5e7eb;
  148. position: sticky;
  149. top: 0;
  150. z-index: 10;
  151. }
  152. .tab-item {
  153. flex: 1;
  154. display: flex;
  155. align-items: center;
  156. justify-content: center;
  157. gap: px2rpx(6);
  158. padding: px2rpx(16);
  159. position: relative;
  160. transition: all 0.3s;
  161. }
  162. .tab-text {
  163. font-size: px2rpx(15);
  164. color: #9ca3af;
  165. transition: color 0.3s;
  166. }
  167. .tab-text-active {
  168. color: #2563eb;
  169. }
  170. .tab-indicator {
  171. position: absolute;
  172. bottom: 0;
  173. left: 0;
  174. right: 0;
  175. height: px2rpx(3);
  176. background-color: #2563eb;
  177. border-radius: px2rpx(3) px2rpx(3) 0 0;
  178. }
  179. /* Content */
  180. .content {
  181. padding: 0;
  182. }
  183. .filters-container {
  184. display: flex;
  185. align-items: center;
  186. gap: px2rpx(8);
  187. padding: px2rpx(12) px2rpx(16);
  188. background-color: #ffffff;
  189. position: sticky;
  190. top: 0;
  191. z-index: 10;
  192. overflow-x: auto;
  193. -webkit-overflow-scrolling: touch;
  194. }
  195. .filter-item {
  196. display: flex;
  197. align-items: center;
  198. gap: px2rpx(4);
  199. flex-shrink: 0;
  200. min-width: 0;
  201. }
  202. .filter-label {
  203. font-size: px2rpx(12);
  204. color: #6b7280;
  205. white-space: nowrap;
  206. flex-shrink: 0;
  207. }
  208. .filter-picker {
  209. background-color: #ffffff;
  210. border: 1px solid #e5e7eb;
  211. border-radius: px2rpx(8);
  212. padding: px2rpx(6) px2rpx(8);
  213. display: flex;
  214. align-items: center;
  215. min-width: px2rpx(60);
  216. max-width: px2rpx(120);
  217. flex-shrink: 1;
  218. }
  219. .picker-value {
  220. display: flex;
  221. align-items: center;
  222. gap: px2rpx(4);
  223. width: 100%;
  224. min-width: 0;
  225. }
  226. .picker-text {
  227. flex: 1;
  228. min-width: 0;
  229. font-size: px2rpx(12);
  230. color: #111827;
  231. overflow: hidden;
  232. text-overflow: ellipsis;
  233. white-space: nowrap;
  234. }
  235. .picker-icon {
  236. flex-shrink: 0;
  237. width: px2rpx(14);
  238. height: px2rpx(14);
  239. }
  240. .reset-btn {
  241. background-color: #ffffff;
  242. border: 1px solid #e5e7eb;
  243. border-radius: px2rpx(8);
  244. padding: px2rpx(6) px2rpx(10);
  245. display: flex;
  246. align-items: center;
  247. justify-content: center;
  248. flex-shrink: 0;
  249. min-width: px2rpx(36);
  250. }
  251. </style>