cwg-sidebar.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. <template>
  2. <view class="cwg-sidebar">
  3. <view class="wallet-widget">
  4. <view class="wallet-header" :class="{'header-bottom':isWalletOpen}" @click="isWalletOpen = !isWalletOpen">
  5. <view class="wallet-header-left">
  6. <cwg-icon name="crm-payment" :size="16" color="#141d22" />
  7. <text class="wallet-header-text">{{ mode === 'customer' ? formattedBalance : ibBalance }} USD</text>
  8. </view>
  9. <view class="wallet-header-right" :class="{ 'expanded': isWalletOpen }">
  10. <cwg-icon name="crm-chevron-down" :size="16" color="#6c8595" />
  11. </view>
  12. </view>
  13. <view class="wallet-body" v-if="isWalletOpen">
  14. <view class="wallet-body-header">
  15. <text class="drawer-title">隐藏余额</text>
  16. <switch :checked="!isShow" @change="toggleShow" color="#6c8595" style="transform:scale(0.7); margin-right: -10px;" />
  17. </view>
  18. <view class="wallet-body-content">
  19. <view class="balance-amount">{{ mode === 'customer' ? formattedBalance : ibBalance }} USD</view>
  20. <view class="wallet-type">{{ mode === 'customer' ? t('wallet.pendingWithdraw') : t('Ib.Index.TotalRevenue') }}</view>
  21. <view class="wallet-id-box">
  22. {{ mode === 'customer' ? formattedPendingWithdrawAmount : ibTotalBalance }}
  23. </view>
  24. </view>
  25. <view class="wallet-actions" v-if="mode === 'customer'">
  26. <button class="action-btn" @click.stop="goPages(1)" v-t="'wallet.item6'"></button>
  27. <button class="action-btn" @click.stop="goPages(2)" v-t="'wallet.item7'"></button>
  28. </view>
  29. <view class="wallet-actions" v-if="mode === 'ib'">
  30. <button class="action-btn" @click.stop="goIbPages(1)" v-t="'Custom.Index.Withdrawals'"></button>
  31. <button class="action-btn" @click.stop="goIbPages(2)" v-t="'Home.page_ib.item4'"></button>
  32. <!-- <button class="action-btn" @click.stop="goIbPages(3)" v-t="'Ib.Transfer.CommissionIssue'"></button>-->
  33. </view>
  34. </view>
  35. </view>
  36. <view class="menu-list">
  37. <view class="menu" v-for="(item, index) in menus" :key="item.path">
  38. <view class="menu-item" @click="handleClick(index)">
  39. <cwg-icon :name="item.icon" :size="20" color="#6c8595" />
  40. <view class="menu-label" v-t="item.label" />
  41. <view class="chevron-icon" :class="{ 'expanded': item.isOpenMenu }">
  42. <cwg-icon v-if="item.children && item.children.length" name="crm-chevron-down" :size="20"
  43. color="#6c8595" />
  44. </view>
  45. </view>
  46. <view :ref="(el) => setSubmenuRef(index, el)" class="submenu-box" :a="index" :key1="item.path + index"
  47. :b="item" :style="{
  48. height: !(item.children && item.children.length) ? '0px' : item.isOpenMenu ? item.submenuHeight + 'px' : '0px',
  49. transition: 'height 281ms cubic-bezier(0.4, 0, 0.2, 1)'
  50. }" :class="{ 'active': item.isOpenMenu }">
  51. <cwg-submenu v-if="item.children && item.children.length" :submenu-items="item.children"
  52. @submenu-click="handleSubmenuClick" />
  53. </view>
  54. </view>
  55. </view>
  56. <view class="menu fixed">
  57. <view class="menu-item ib-box" @click="setMode('ib')" v-if="mode !== 'ib' && ibStatus">
  58. <cwg-icon name="crm-ib" :size="20" color="#6c8595" />
  59. <view class="menu-label" v-t="'Home.msg.Ib'" />
  60. </view>
  61. <view class="menu-item ib-box" @click="setMode('customer')" v-if="mode !== 'customer'">
  62. <cwg-icon name="crm-trade" :size="20" color="#6c8595" />
  63. <view class="menu-label" v-t="'Home.msg.Custom'" />
  64. </view>
  65. </view>
  66. </view>
  67. </template>
  68. <script lang="ts" setup>
  69. import { ref, computed, watch, onMounted } from 'vue'
  70. import useUserStore from '@/stores/use-user-store'
  71. import { useMenuSplit } from '@/composables/useMenuSplit'
  72. import { storeToRefs } from 'pinia'
  73. import { drawApi } from '@/service/draw'
  74. import { ibApi } from '@/service/ib'
  75. import { userToken } from '@/composables/config'
  76. import useRouter from '@/hooks/useRouter'
  77. import { useI18n } from 'vue-i18n'
  78. const { t } = useI18n()
  79. const router = useRouter()
  80. const handleClick1 = (item: MenuItem) => {
  81. console.log(item)
  82. emit('handle-click', item)
  83. }
  84. const { menus, setSubmenuRef, setMode, handleClick, handleSubmenuClick, mode } = useMenuSplit(handleClick1)
  85. const userStore = useUserStore()
  86. const { userInfo } = storeToRefs(userStore)
  87. const emit = defineEmits(['handle-click'])
  88. // ib按钮展示
  89. const ibStatus = computed(() => {
  90. const info: any = userInfo.value
  91. return !!info && !!info.customInfo && info.customInfo.ibInvalid == 0 && !!info.ibInfo
  92. })
  93. const isWalletOpen = ref(true)
  94. const isShow = ref(true)
  95. const walletbalance = ref(0)
  96. const pendingWithdrawAmount = ref(0)
  97. const ibData = ref({} as any)
  98. const NumberDecimal = (value: any) => {
  99. let realVal = ''
  100. if (!isNaN(value) && value !== '') {
  101. realVal = parseFloat(value).toFixed(2)
  102. } else {
  103. realVal = '0.00'
  104. }
  105. return realVal
  106. }
  107. const NumberDesensitization = (value: any) => {
  108. let realVal = ''
  109. if (!isNaN(value) && value !== '') {
  110. value = value.toString()
  111. realVal = value.substr(0, 2) + '****' + value.substr(-2)
  112. } else {
  113. realVal = '--'
  114. }
  115. return realVal
  116. }
  117. const formattedBalance = computed(() => {
  118. const value = walletbalance.value || '0'
  119. const decimalValue = NumberDecimal(value)
  120. return isShow.value ? decimalValue : NumberDesensitization(decimalValue)
  121. })
  122. const ibBalance = computed(() => {
  123. const value = NumberDecimal(ibData.value?.balance || 0)
  124. return isShow.value ? value : NumberDesensitization(value)
  125. })
  126. const formattedPendingWithdrawAmount = computed(() => {
  127. const value = pendingWithdrawAmount.value || '0'
  128. const decimalValue = NumberDecimal(value)
  129. return isShow.value ? decimalValue : NumberDesensitization(decimalValue)
  130. })
  131. const ibTotalBalance = computed(() => {
  132. const value = NumberDecimal(ibData.value?.all || 0)
  133. return isShow.value ? value : NumberDesensitization(value)
  134. })
  135. const getWalletList = async () => {
  136. let res = await drawApi.walletbalance({})
  137. if (res.code == 200) {
  138. if (res.data != null) {
  139. walletbalance.value = res.data
  140. }
  141. } else {
  142. uni.showToast({ title: res.msg, icon: 'none' })
  143. }
  144. }
  145. //获取处理中出金金额
  146. const getPendingWithdrawAmount = async () => {
  147. let res = await drawApi.pendingWithdrawAmount({})
  148. if (res.code == 200) {
  149. if (res.data != null) {
  150. pendingWithdrawAmount.value = res.data
  151. }
  152. } else {
  153. uni.showToast({
  154. title: res.msg,
  155. icon: 'none',
  156. })
  157. }
  158. }
  159. const getIbData = async () => {
  160. const res = await ibApi.IbData()
  161. if (res.code === 200) {
  162. if (res.data != null) ibData.value = res.data
  163. } else {
  164. uni.showToast({ title: res.msg, icon: 'none' })
  165. }
  166. }
  167. watch(() => mode.value, (newMode) => {
  168. if (!userToken.value) return
  169. if (newMode == 'customer') {
  170. getWalletList()
  171. getPendingWithdrawAmount()
  172. } else if (newMode == 'ib') {
  173. getIbData()
  174. }
  175. }, { immediate: true })
  176. const toggleShow = (e: any) => {
  177. isShow.value = !e.detail.value
  178. }
  179. const goPages = (type: number) => {
  180. let path = ''
  181. if (type == 1) {
  182. path = '/pages/customer/wallet-transfer'
  183. } else if (type == 2) {
  184. path = '/pages/customer/wallet-history'
  185. }
  186. if (path) router.push(path)
  187. }
  188. const goIbPages = (type: number) => {
  189. let path = ''
  190. let query = {}
  191. if (type == 1) {
  192. path = '/pages/ib/withdraw-select'
  193. } else if (type == 2) {
  194. path = '/pages/ib/transfer'
  195. } else if (type == 3) {
  196. path = '/pages/ib/transfer'
  197. query = { tab: 2 }
  198. }
  199. if (path) router.push({ path, query })
  200. }
  201. </script>
  202. <style scoped lang="scss">
  203. @import "@/uni.scss";
  204. .cwg-sidebar {
  205. width: px2rpx(280);
  206. color: #6c8595;
  207. height: calc(100vh - 56px);
  208. overflow: auto;
  209. display: flex;
  210. flex-direction: column;
  211. align-items: center;
  212. padding: px2rpx(8);
  213. padding-top: px2rpx(20);
  214. box-sizing: border-box;
  215. gap: px2rpx(8);
  216. border-right: 1px solid rgba(108, 133, 149, 0.12);
  217. .wallet-widget {
  218. width: 100%;
  219. //border-radius: px2rpx(4);
  220. border-top: 1px solid rgba(108, 133, 149, 0.12);
  221. border-bottom: 1px solid rgba(108, 133, 149, 0.12);
  222. overflow: hidden;
  223. margin-bottom: px2rpx(4);
  224. .header-bottom{
  225. border-bottom: 1px solid rgba(108, 133, 149, 0.12);
  226. }
  227. .wallet-header {
  228. display: flex;
  229. align-items: center;
  230. justify-content: space-between;
  231. padding: px2rpx(10) px2rpx(12);
  232. //background: #f4f6f8;
  233. cursor: pointer;
  234. .wallet-header-left {
  235. display: flex;
  236. align-items: center;
  237. gap: px2rpx(8);
  238. }
  239. .wallet-header-text {
  240. font-size: 14px;
  241. color: #141d22;
  242. font-weight: 500;
  243. }
  244. .wallet-header-right {
  245. transition: transform 0.3s;
  246. &.expanded {
  247. transform: rotate(180deg);
  248. }
  249. }
  250. }
  251. .wallet-body {
  252. padding: px2rpx(12);
  253. background: #ffffff;
  254. .wallet-body-header {
  255. display: flex;
  256. align-items: center;
  257. justify-content: space-between;
  258. margin-bottom: px2rpx(12);
  259. .drawer-title {
  260. font-size: 13px;
  261. color: #6c8595;
  262. }
  263. }
  264. .wallet-body-content {
  265. margin-bottom: px2rpx(16);
  266. .balance-amount {
  267. font-size: 16px;
  268. font-weight: 600;
  269. color: #141d22;
  270. margin-bottom: px2rpx(4);
  271. }
  272. .wallet-type {
  273. font-size: 12px;
  274. color: #999;
  275. margin-bottom: px2rpx(4);
  276. }
  277. .wallet-id-box {
  278. display: flex;
  279. align-items: center;
  280. gap: px2rpx(4);
  281. .wallet-id {
  282. font-size: 12px;
  283. color: #999;
  284. }
  285. }
  286. }
  287. .wallet-actions {
  288. display: flex;
  289. gap: px2rpx(8);
  290. .action-btn {
  291. flex: 1;
  292. height: px2rpx(32);
  293. line-height: px2rpx(32);
  294. background-color: #f5f7fa;
  295. color: #141d22;
  296. font-size: 13px;
  297. border-radius: px2rpx(4);
  298. margin: 0;
  299. &::after {
  300. border: none;
  301. }
  302. &:active {
  303. background-color: #e4e7ed;
  304. }
  305. }
  306. }
  307. }
  308. }
  309. .logo {
  310. width: px2rpx(54);
  311. }
  312. .menu-list {
  313. flex: 1;
  314. width: 100%;
  315. overflow-y: auto;
  316. display: flex;
  317. flex-direction: column;
  318. gap: px2rpx(8);
  319. }
  320. .submenu-box {
  321. width: 100%;
  322. height: 0;
  323. overflow: hidden;
  324. }
  325. .menu {
  326. width: 100%;
  327. position: relative;
  328. display: flex;
  329. flex-direction: column;
  330. align-items: center;
  331. box-sizing: border-box;
  332. }
  333. .menu-item {
  334. width: 100%;
  335. height: px2rpx(40);
  336. cursor: pointer;
  337. display: flex;
  338. align-items: center;
  339. justify-content: space-between;
  340. gap: px2rpx(8);
  341. padding: px2rpx(10);
  342. box-sizing: border-box;
  343. font-size: 14px;
  344. .menu-label {
  345. flex: 1;
  346. }
  347. &:hover {
  348. background: rgba(108, 133, 149, 0.12) !important;
  349. border: 1px solid rgb(145, 163, 176) !important;
  350. border-radius: px2rpx(4);
  351. }
  352. .expanded .icon {
  353. transform: rotate(180deg);
  354. }
  355. }
  356. .ib-box {
  357. background: rgba(140, 69, 246, 0.08) !important;
  358. border: 1px solid rgba(140, 69, 246, 0.2) !important;
  359. font-size: px2rpx(18);
  360. font-weight: 600;
  361. color: #141d22;
  362. &:hover {
  363. background: rgba(140, 69, 246, 0.08) !important;
  364. border: 1px solid rgba(140, 69, 246, 0.2) !important;
  365. }
  366. }
  367. .zy-box {
  368. display: flex;
  369. align-items: center;
  370. justify-content: center;
  371. }
  372. .fixed {
  373. position: relative;
  374. width: 100%;
  375. display: flex;
  376. align-items: center;
  377. justify-content: center;
  378. gap: px2rpx(8);
  379. }
  380. }
  381. </style>