openAccount.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. <template>
  2. <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
  3. <cwg-header :title="params.type === 1 ? t('Ib.NewAccount.TitleM') : t('Ib.NewAccount.TitleP')">
  4. <template #right>
  5. <view class="header-btn" @click="backIndex">
  6. <cwg-icon name="icon_back" :size="18" />
  7. <text>{{ t('Ib.Settings.Title') }}</text>
  8. </view>
  9. </template>
  10. </cwg-header>
  11. <view class="main-content account-content" v-if="showPage">
  12. <view class="box" v-if="isAllLoginTypesHidden">
  13. <view style="margin: 20px 0; font-size: 14px; line-height: 1.7;">
  14. <text>{{ t('news_add_field.OpenAccount.Des3') }}</text>
  15. </view>
  16. </view>
  17. <view class="box" v-else>
  18. <view class="tit">
  19. <cwg-icon name="icon_arrow_right" :size="16" />
  20. <text>{{ t('Ib.NewAccount.Title1') }}</text>
  21. </view>
  22. <view class="des">{{ t('Ib.NewAccount.Des1') }}</view>
  23. <view class="b-card">
  24. <uni-forms ref="formRef" :model="params" :rules="rules" label-position="top">
  25. <uni-row :gutter="20">
  26. <uni-col :xs="24" :sm="12" :md="8">
  27. <uni-forms-item :label="t('Ib.NewAccount.Platform')" name="platform" required>
  28. <cwg-combox v-model:value="params.platform" :options="[{ text: 'MT4', value: 'MT4' }]"
  29. :placeholder="t('placeholder.choose')" />
  30. </uni-forms-item>
  31. </uni-col>
  32. <uni-col :xs="24" :sm="12" :md="8">
  33. <uni-forms-item :label="t('Ib.NewAccount.LoginType')" name="accountType" required>
  34. <cwg-combox v-model:value="params.accountType" :options="accountTypeOptions"
  35. :placeholder="t('placeholder.choose')" @change="onAccountTypeChange" />
  36. </uni-forms-item>
  37. </uni-col>
  38. <uni-col :xs="24" :sm="12" :md="8">
  39. <uni-forms-item :label="t('Ib.NewAccount.Lever')" name="leverage" required>
  40. <cwg-combox v-model:value="params.leverage" :options="formatOptions(optionsLev)"
  41. :placeholder="t('placeholder.choose')" />
  42. </uni-forms-item>
  43. </uni-col>
  44. <uni-col :xs="24" :sm="12" :md="8">
  45. <uni-forms-item :label="t('Ib.NewAccount.Currency')" name="currency" required>
  46. <cwg-combox v-model:value="params.currency" :options="formatOptions(optionsCur)"
  47. :placeholder="t('placeholder.choose')" />
  48. </uni-forms-item>
  49. </uni-col>
  50. <uni-col :xs="24" :sm="12" :md="8">
  51. <uni-forms-item :label="t('Ib.NewAccount.Commission')" name="commission" required>
  52. <cwg-combox v-model:value="params.commission" :options="formatOptions(optionsCom)"
  53. :placeholder="t('placeholder.choose')" />
  54. </uni-forms-item>
  55. </uni-col>
  56. <uni-col :span="24">
  57. <button class="s-btn" type="primary" @click="newAccount">{{ t('Ib.NewAccount.Btn') }}</button>
  58. </uni-col>
  59. </uni-row>
  60. </uni-forms>
  61. </view>
  62. </view>
  63. <view class="box">
  64. <view style="margin: 20px 0; font-size: 14px; line-height: 1.7;">
  65. <template v-if="params.type === 1">
  66. <view style="font-weight: bold; margin-bottom: 5px;">{{ t('Ib.NewAccount.Dec1') }}</view>
  67. <view>{{ t('Ib.NewAccount.Dec2') }}</view>
  68. </template>
  69. <template v-if="params.type === 2">
  70. <view style="font-weight: bold; margin-bottom: 5px;">{{ t('Ib.NewAccount.Dec3') }}</view>
  71. <view>{{ t('Ib.NewAccount.Dec4') }}</view>
  72. </template>
  73. </view>
  74. </view>
  75. <view class="box" v-if="params.accountType === 6">
  76. <view style="margin: 20px 0; font-size: 14px; line-height: 1.7;">
  77. <view>
  78. <text>{{ t('Ib.NewAccount.Dec5') }}</text>
  79. <text class="crm-cursor" style="color: #368FEC;" @click="openLeverageMargin">{{ t('Ib.NewAccount.Dec6')
  80. }}</text>
  81. <text>{{ t('Ib.NewAccount.Dec7') }}</text>
  82. </view>
  83. </view>
  84. </view>
  85. </view>
  86. <!-- 提交结果弹窗 -->
  87. <cwg-popup :visible="dialogCheck" :showClose="false" :showFooters="true" :confirmText="t('Btn.Confirm')"
  88. :cancelText="t('Btn.Cancel')" @confirm="closeDia" @close="closeDia">
  89. <view class="result-dialog">
  90. <view v-if="dialogVisible" class="icon-wrap">
  91. <cwg-icon name="icon_success" :size="50" color="#67C23A" />
  92. <view class="result-text">{{ t('ApplicationDialog.Des1') }}</view>
  93. <view class="result-sub-text">{{ t('ApplicationDialog.Des12') }}</view>
  94. </view>
  95. <view v-else class="icon-wrap">
  96. <cwg-icon name="icon_warning" :size="50" color="#E6A23C" />
  97. <view class="result-text">{{ RES }}</view>
  98. </view>
  99. </view>
  100. </cwg-popup>
  101. </cwg-page-wrapper>
  102. </template>
  103. <script setup lang="ts">
  104. import { ref, reactive, computed, onMounted } from 'vue'
  105. import { onLoad } from '@dcloudio/uni-app'
  106. import { useI18n } from 'vue-i18n'
  107. import { ibApi } from '@/service/ib'
  108. import { isAfterJuly28 } from '@/utils/dateUtils'
  109. import Config from '@/config/index'
  110. const { t, locale } = useI18n()
  111. const { Code } = Config
  112. const pictLoading = ref(false)
  113. const showPage = ref(false)
  114. const showLogin = ref<string[]>([])
  115. const showData = ref<any[]>([])
  116. const flag = ref(false)
  117. const RES = ref('')
  118. const dialogCheck = ref(false)
  119. const dialogVisible = ref(false)
  120. const optionsLev = ref<string[]>([])
  121. const optionsCur = ref<string[]>([])
  122. const optionsCom = ref<string[]>([])
  123. const formRef = ref()
  124. const params = reactive({
  125. type: 1,
  126. currency: '',
  127. commission: '',
  128. leverage: '',
  129. accountType: '' as string | number,
  130. platform: '',
  131. })
  132. const rules = {
  133. currency: { rules: [{ required: true, errorMessage: t('vaildate.select.empty') }] },
  134. commission: { rules: [{ required: true, errorMessage: t('vaildate.select.empty') }] },
  135. leverage: { rules: [{ required: true, errorMessage: t('vaildate.select.empty') }] },
  136. accountType: { rules: [{ required: true, errorMessage: t('vaildate.select.empty') }] },
  137. platform: { rules: [{ required: true, errorMessage: t('vaildate.select.empty') }] },
  138. }
  139. // 是否全部类型被隐藏
  140. const isAllLoginTypesHidden = computed(() => {
  141. const hiddenStr = showLogin.value.join(',')
  142. return hiddenStr.includes('1') && hiddenStr.includes('2') && hiddenStr.includes('3') &&
  143. hiddenStr.includes('6') && hiddenStr.includes('7') && hiddenStr.includes('8')
  144. })
  145. // 动态计算下拉类型选项
  146. const accountTypeOptions = computed(() => {
  147. const list = []
  148. if (!showLogin.value.includes('1')) list.push({ value: 1, text: t('AccountType.ClassicAccount') })
  149. if (!showLogin.value.includes('2')) list.push({ value: 2, text: t('AccountType.SeniorAccount') })
  150. if (!showLogin.value.includes('3') && !isAfterJuly28()) list.push({ value: 3, text: t('AccountType.AgencyAccount') })
  151. if (!showLogin.value.includes('6')) list.push({ value: 6, text: t('AccountType.SpeedAccount') })
  152. if (!showLogin.value.includes('7')) list.push({ value: 7, text: t('AccountType.StandardAccount') })
  153. if (!showLogin.value.includes('8')) list.push({ value: 8, text: t('AccountType.CentAccount') })
  154. return list
  155. })
  156. // 格式化普通数组为 combox 所需的 [{text, value}] 格式
  157. const formatOptions = (arr: string[]) => {
  158. return (arr || []).map(item => ({ text: String(item), value: item }))
  159. }
  160. // 监听账户类型切换以回填下拉框
  161. const onAccountTypeChange = (type: number) => {
  162. params.leverage = ''
  163. params.currency = ''
  164. params.commission = ''
  165. const target = showData.value.find(item => item.type == type)
  166. if (target) {
  167. optionsLev.value = target.leverage || []
  168. optionsCur.value = target.currency || []
  169. optionsCom.value = target.commission || []
  170. }
  171. }
  172. // 获取必填配置项
  173. const getMustData = async () => {
  174. const res = await ibApi.MamApplyData({})
  175. if (res.code === Code.StatusOK) {
  176. showData.value = res.data || []
  177. } else {
  178. uni.showToast({ title: res.msg, icon: 'none' })
  179. }
  180. }
  181. // 获取排除类型
  182. const getExcludeShowLogin = async () => {
  183. pictLoading.value = true
  184. try {
  185. const res = await ibApi.excludeShowLogin({})
  186. if (res.code === Code.StatusOK) {
  187. showLogin.value = res.data?.excludeShowLoginTypes || []
  188. showPage.value = true
  189. } else {
  190. uni.showToast({ title: res.msg, icon: 'none' })
  191. }
  192. } finally {
  193. pictLoading.value = false
  194. }
  195. }
  196. // 提交申请
  197. const newAccount = async () => {
  198. try {
  199. await formRef.value?.validate()
  200. } catch (error) {
  201. return
  202. }
  203. if (flag.value) return
  204. flag.value = true
  205. try {
  206. const res = await ibApi.MamApplyAdd({ ...params })
  207. if (res.code === Code.StatusOK) {
  208. dialogCheck.value = true
  209. dialogVisible.value = true
  210. } else {
  211. RES.value = res.msg
  212. dialogCheck.value = true
  213. dialogVisible.value = false
  214. }
  215. } catch (err) {
  216. RES.value = t('Msg.Fail')
  217. dialogCheck.value = true
  218. dialogVisible.value = false
  219. } finally {
  220. flag.value = false
  221. }
  222. }
  223. // 关闭弹窗
  224. const closeDia = () => {
  225. formRef.value?.clearValidate()
  226. // 也可以选择重置表单:
  227. Object.assign(params, { currency: '', commission: '', leverage: '', accountType: '', platform: '' })
  228. dialogCheck.value = false
  229. dialogVisible.value = false
  230. }
  231. const backIndex = () => {
  232. uni.navigateBack({ delta: 1 })
  233. }
  234. const openLeverageMargin = () => {
  235. const url = ['cn', 'zhHant'].includes(locale.value)
  236. ? 'https://www.cwgvu.com/cn/leveragemargin'
  237. : 'https://www.cwgvu.com/en/leveragemargin'
  238. // #ifdef H5
  239. window.open(url, '_blank')
  240. // #endif
  241. // #ifndef H5
  242. uni.showToast({ title: t('Msg.NotSupportedInApp'), icon: 'none' })
  243. // #endif
  244. }
  245. onLoad((options: any) => {
  246. if (options && options.type) {
  247. params.type = Number(options.type)
  248. } else {
  249. params.type = 1
  250. }
  251. getExcludeShowLogin()
  252. getMustData()
  253. })
  254. </script>
  255. <style lang="scss" scoped>
  256. @import "@/uni.scss";
  257. .header-btn {
  258. display: flex;
  259. align-items: center;
  260. font-size: px2rpx(14);
  261. color: var(--bs-heading-color);
  262. cursor: pointer;
  263. text {
  264. margin-left: px2rpx(5);
  265. }
  266. }
  267. .main-content {
  268. padding: px2rpx(10);
  269. min-height: calc(100vh - 100px);
  270. }
  271. .box {
  272. padding: px2rpx(15) px2rpx(20);
  273. background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
  274. border-radius: px2rpx(4);
  275. margin-bottom: px2rpx(20);
  276. .tit {
  277. display: flex;
  278. align-items: center;
  279. font-size: px2rpx(16);
  280. font-weight: bold;
  281. margin-bottom: px2rpx(10);
  282. text {
  283. margin-left: px2rpx(5);
  284. }
  285. }
  286. .des {
  287. font-size: px2rpx(14);
  288. font-weight: bold;
  289. line-height: 1.5;
  290. margin-bottom: px2rpx(20);
  291. color: var(--bs-heading-color);
  292. }
  293. }
  294. .b-card {
  295. margin-top: px2rpx(15);
  296. }
  297. .s-btn {
  298. margin-top: px2rpx(10);
  299. min-width: px2rpx(120);
  300. }
  301. .crm-cursor {
  302. cursor: pointer;
  303. text-decoration: underline;
  304. }
  305. .result-dialog {
  306. text-align: center;
  307. padding: px2rpx(20);
  308. .icon-wrap {
  309. margin-bottom: px2rpx(20);
  310. }
  311. .result-text {
  312. font-size: px2rpx(16);
  313. font-weight: bold;
  314. margin-top: px2rpx(20);
  315. margin-bottom: px2rpx(10);
  316. }
  317. .result-sub-text {
  318. font-size: px2rpx(12);
  319. color: var(--bs-heading-color);
  320. margin-bottom: px2rpx(20);
  321. }
  322. .dialog-footer {
  323. display: flex;
  324. justify-content: center;
  325. gap: px2rpx(15);
  326. margin-top: px2rpx(30);
  327. button {
  328. min-width: px2rpx(100);
  329. margin: 0;
  330. }
  331. }
  332. }
  333. </style>