openAccount.vue 12 KB

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