give-dialog.vue 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677
  1. <template>
  2. <div class="overlay" v-if="visible">
  3. <div class="content"
  4. :style="{
  5. height: dialogHeight + 'px',
  6. width: showComType != 'preview' ? '600px' : 'auto'}">
  7. <div class="pop-mask"
  8. v-show="showCurrencyPop"
  9. @click.stop="showCurrencyPop = false"></div>
  10. <!-- 头部 -->
  11. <div class="head">
  12. <div class="left">
  13. <!-- 关闭按钮 -->
  14. <div class="close-btn" @click="close">
  15. <img class="icon-close"
  16. :src="require('@/assets/svg/icon-close.svg')"
  17. v-if="showComType == 'default'"/>
  18. <img class="icon-close"
  19. :src="require('@/assets/svg/icon-back.svg')"
  20. v-else/>
  21. </div>
  22. <!-- 标题 -->
  23. <div class="title">
  24. {{ currentComData[showComType]["title"] }}
  25. </div>
  26. </div>
  27. <div class="right">
  28. <!-- 更多按钮 -->
  29. <img :src="require('@/assets/svg/icon-more-l.svg')"
  30. class="more"
  31. @click="showMoreOption = true">
  32. <div class="area-option"
  33. v-if="showMoreOption"
  34. @click="showMoreOption = false">
  35. <div class="option">
  36. <div class="item" @click="goTransactionsList()">
  37. <img :src="require('@/assets/svg/icon-menu.svg')">
  38. <span>Transaction History</span>
  39. </div>
  40. </div>
  41. </div>
  42. </div>
  43. </div>
  44. <!-- 内容 -->
  45. <div class="body">
  46. <img src="@/assets/gif/icon-guide-select.gif"
  47. class="icon-guide-select"
  48. v-if="!currentCurrencyInfo.currencyCode && showComType == 'default'">
  49. <!-- 充值组件 -->
  50. <top-up v-if="showComType == 'topUp'"
  51. :asyncIng="asyncIng"
  52. :currentCurrencyInfo="tempCurrentCurrencyInfo"
  53. @topUpDone="topUpDone"></top-up>
  54. <!-- 表单填写容器 -->
  55. <div class="body-content" v-if="showComType != 'topUp'">
  56. <!-- 货币列表 -->
  57. <div class="currency-pop" v-show="showCurrencyPop">
  58. <currency-list
  59. ref="currencyListDom"
  60. @selectCurrency="selectCurrency"
  61. @setCurrencyList="setCurrentCurrencyInfo"></currency-list>
  62. </div>
  63. <div class="left" v-if="showComType != 'preview'">
  64. <div class="gift-pack-wrapper">
  65. <img class="icon"
  66. :src="require('@/assets/svg/icon-gift-pack.svg')"/>
  67. </div>
  68. <div class="bottom">
  69. </div>
  70. </div>
  71. <div class="right"
  72. :class="{'fill-right': showComType == 'preview'}">
  73. <div class="form-wrapper" v-if="showComType == 'default'">
  74. <img
  75. class="img-mode"
  76. :src="require('@/assets/svg/img-mode.svg')"
  77. />
  78. <!-- 金额、数量 -->
  79. <div class="form-base">
  80. <div class="item currency-select-wrapper">
  81. <div
  82. class="label currency-select"
  83. :class="{'selected': currentCurrencyInfo.currencyCode}"
  84. @click="selectCurrencyPopHandle"
  85. >
  86. <img v-if="currentCurrencyInfo.iconPath"
  87. class="icon"
  88. :src="currentCurrencyInfo.iconPath"
  89. />
  90. <div class="text">
  91. {{currentCurrencyInfo.currencyCode == 'USD' ? 'USD' : currentCurrencyInfo.tokenSymbol || 'Select a reward'}}
  92. </div>
  93. <img
  94. class="arrow"
  95. :src="currentCurrencyInfo.currencyCode ?
  96. require('@/assets/svg/icon-form-arrow-down.svg') : require('@/assets/svg/icon-form-white-arrow-down.svg')
  97. "
  98. />
  99. </div>
  100. <input
  101. v-model="baseFormData.amountValue"
  102. placeholder="0"
  103. autofocus
  104. @input="onAmountInput"
  105. @blur="onAmountBlur"
  106. />
  107. </div>
  108. <div class="item">
  109. <div class="label">
  110. <img
  111. class="icon"
  112. :src="
  113. require('@/assets/svg/icon-winners.svg')
  114. "
  115. />
  116. Winners
  117. </div>
  118. <input
  119. v-model="baseFormData.totalCount"
  120. placeholder="0"
  121. @input="onCountInput"
  122. @blur="onCountBlur"
  123. />
  124. </div>
  125. </div>
  126. <!-- 刷新按钮、充值 -->
  127. <div class="form-base-help" v-show="currentCurrencyInfo.currencyCode">
  128. <div class="currency-operation">
  129. <div class="balance">
  130. <img
  131. :src="
  132. require('@/assets/svg/icon-balance.svg')
  133. "
  134. />
  135. Balance
  136. </div>
  137. <div class="amount">
  138. {{currentCurrencyInfo.balance}}
  139. <img
  140. :class="{ 'icon-refresh-rotate': refreshRotate }"
  141. @click="updateCurrencyBanlce"
  142. :src="
  143. require('@/assets/svg/icon-form-refresh.svg')
  144. "
  145. />
  146. </div>
  147. <div v-if="currentCurrencyInfo.currencyCode != 'USD'" class="top-up" @click="goTopUp">Deposit</div>
  148. </div>
  149. <div class="msg">
  150. Recommend winners 100~10000
  151. </div>
  152. </div>
  153. <div class="form-label">Tasks</div>
  154. <!-- 转推、like、关注 -->
  155. <div class="form-require">
  156. <div
  157. class="form-item"
  158. v-for="(item, index) in formList"
  159. :key="index"
  160. >
  161. <div class="item-left">
  162. <div class="label">
  163. <img
  164. class="icon"
  165. :src="item.icon"
  166. />
  167. {{ item.label }}
  168. </div>
  169. <div
  170. class="control"
  171. v-if="item.nodeType == 'textarea'"
  172. >
  173. <follow-input
  174. :isAddSelf="!isBack"
  175. :atUserList="atUserList"
  176. @addUser="addFollowUser"
  177. @setUser="setFollowUser"
  178. @delUser="delFollowUser"
  179. ></follow-input>
  180. </div>
  181. <div
  182. class="control"
  183. v-if="item.nodeType == 'input'"
  184. >
  185. <!-- <div class="">
  186. <img :src="discordInviteInfo.icon" />
  187. <span>{{discordInviteInfo.name}}</span>
  188. </div> -->
  189. <input v-model="item.text"
  190. placeholder="Enter link address"
  191. class="discord-address"
  192. @input="onIptDiscordAddress($event, index)"
  193. @blur="onBlurDiscordAddress($event, index)" />
  194. </div>
  195. </div>
  196. <el-switch
  197. v-if="item.type == 2 || item.type == 7"
  198. v-model="item.checked"
  199. @change="formSwitchChange($event, item)"
  200. />
  201. <img
  202. v-if="item.type == 3"
  203. :src="
  204. require('@/assets/svg/icon-option-checked.svg')
  205. "
  206. />
  207. </div>
  208. </div>
  209. <!-- 机器人 -->
  210. <!-- <div class="anti-bot-wrapper">
  211. <div class="label">
  212. <img
  213. :src="
  214. require('@/assets/svg/icon-anti-bot.svg')
  215. "
  216. class="icon-bot"
  217. />
  218. Anti Bot
  219. <img
  220. :src="
  221. require('@/assets/svg/icon-beta.svg')
  222. "
  223. class="icon-beta"
  224. />
  225. <img
  226. :src="
  227. require('@/assets/svg/icon-question.svg')
  228. "
  229. class="icon-question"
  230. />
  231. </div>
  232. <el-switch v-model="openAntiBot" />
  233. </div> -->
  234. <!-- 提示 -->
  235. <ul class="tips-wrapper">
  236. <li class="row">
  237. Rewards can only be claimed after the target user completes all tasks you set.
  238. </li>
  239. <li class="row">
  240. Each user can only receive a reward once per task.
  241. </li>
  242. <li class="row">
  243. The reward will expire in 7 days once issued. Please promote it as much as possible within this period. After the experiment, the remaining rewards will be returned to your DeNet Wallet.
  244. </li>
  245. </ul>
  246. <div class="submit-btn-wrapper">
  247. <div class="submit-btn"
  248. :class="{ 'disabled-submit': iptErrMsgTxt != '' && !depositGuide }"
  249. @click="confirm">
  250. <img
  251. class="icon-loading"
  252. v-if="submitIng"
  253. :src="
  254. require('@/assets/svg/icon-btn-loading.svg')
  255. "
  256. />
  257. {{iptErrMsgTxt ? iptErrMsgTxt : 'NEXT'}}
  258. </div>
  259. </div>
  260. </div>
  261. <!-- 预览 -->
  262. <template v-else-if="showComType == 'preview'">
  263. <preview-card
  264. :currentCurrencyInfo="currentCurrencyInfo"
  265. :postData="publishRes"
  266. :baseFormData="baseFormData"
  267. :amountFontSize="previewFontSize"
  268. ></preview-card>
  269. </template>
  270. <!-- paypal支付按钮 -->
  271. <div v-show="showComType == 'preview'">
  272. <paypal-button
  273. :finalAmountData="finalAmountData"
  274. :payConfig="{
  275. paypalClientId,
  276. feeDesc: payConfig.feeDesc,
  277. paypalHtml,
  278. amount: baseFormData.amountValue,
  279. postId
  280. }"
  281. :currentCurrencyInfo="currentCurrencyInfo"
  282. @payPalFinsh="payPalFinsh"
  283. ></paypal-button>
  284. </div>
  285. </div>
  286. </div>
  287. </div>
  288. </div>
  289. <!-- 提示 -->
  290. <message-box
  291. :dialogVisible="showMessageBox"
  292. :title="messageBoxData.title"
  293. :content="messageBoxData.content"
  294. @cancel="messageBoxCancel"
  295. @confirm="messageBoxConfirm"
  296. ></message-box>
  297. </div>
  298. </template>
  299. <script setup>
  300. import { ref, watch, reactive, defineProps, defineEmits, onMounted, nextTick } from "vue";
  301. import { postPublish, verifyPaypalResult, syncChainTokenRechargeRecord, getCurrencyInfoByCode } from "@/http/publishApi";
  302. import { getInviteGuildInfo } from "@/http/discordApi";
  303. import { payCalcFee, getPayConfig } from "@/http/pay";
  304. import { getFrontConfig } from "@/http/account";
  305. import {setChromeStorage, getChromeStorage} from "@/uilts/chromeExtension"
  306. import { debounce } from "@/uilts/help"
  307. import Report from "@/log-center/log"
  308. import { ElMessage, ElLoading } from "element-plus";
  309. import "element-plus/es/components/message/style/css";
  310. import {create, all} from "mathjs";
  311. import messageBox from "@/view/components/message-box.vue";
  312. import currencyList from "@/view/components/currency-list.vue";
  313. import previewCard from "@/view/iframe/publish/components/preview-card";
  314. import followInput from "@/view/iframe/publish/components/follow-input";
  315. import paypalButton from "@/view/iframe/publish/components/paypal-button";
  316. import topUp from "@/view/iframe/publish/components/top-up.vue";
  317. const config = {
  318. number: 'BigNumber',
  319. }
  320. const math = create(all, config);
  321. //临时货币信息
  322. let tempCurrentCurrencyInfo = ref({});
  323. let paypalClientId = ref("");
  324. let payConfig = ref({});
  325. let paypalHtml = ref("");
  326. // 发布后返回的结果
  327. let publishRes = reactive({});
  328. //弹窗是否展示
  329. let visible = ref(true);
  330. //弹窗高度
  331. let dialogHeight = ref(680);
  332. // 当前展示组件内容 default(表单) preview(预览) topUp(充值)
  333. let showComType = ref("default");
  334. let currentComData = {
  335. default: {
  336. title: "Giveaway",
  337. },
  338. preview: {
  339. title: "Preview",
  340. },
  341. topUp: {
  342. title: "Deposit",
  343. },
  344. };
  345. // 机器人开关
  346. let openAntiBot = ref(false);
  347. // 是否正在提交
  348. let submitIng = ref(false);
  349. // 艾特关注人列表
  350. let atUserList = ref([]);
  351. // 表单错误提示
  352. let iptErrMsgTxt = ref("Select a reward");
  353. // 是否返回
  354. let isBack = ref(false);
  355. // 展示消息提示
  356. let showMessageBox = ref(false);
  357. // 展示货币列表pop
  358. let showCurrencyPop = ref(false);
  359. // 展示更多按钮下的选项
  360. let showMoreOption = ref(false);
  361. // 货币列表的dom
  362. let currencyListDom = ref('');
  363. // 刷新按钮旋转
  364. let refreshRotate = ref(false);
  365. // 预览字体大小
  366. let previewFontSize = ref(56);
  367. let postId = ref('');
  368. // 余额是否同步中
  369. let asyncIng = ref(false);
  370. // 提交按钮-充值引导提示
  371. let depositGuide = ref(false);
  372. let messageBoxData = ref({
  373. title: "",
  374. content: "",
  375. });
  376. // 真实支付金额数据
  377. let finalAmountData = ref({
  378. currencyCode: '',
  379. feeAmountValue: 0,
  380. finalAmountValue: 0,
  381. requestAmountValue: 0,
  382. });
  383. // 表单数据
  384. let baseFormData = reactive({
  385. amountCurrencyCode: '',
  386. amountValue: "",
  387. totalCount: "",
  388. });
  389. // 当前选择的货币信息
  390. let currentCurrencyInfo = ref({
  391. currencyCode: "",
  392. currencyName: "",
  393. balance: "",
  394. currencyType: "",
  395. iconPath: "",
  396. minAmount: "",
  397. tokenChain: "",
  398. tokenSymbol: "",
  399. usdEstimateBalance: ""
  400. });
  401. let formList = reactive([
  402. {
  403. label: "Follow",
  404. icon: require("@/assets/svg/icon-follow.svg"),
  405. nodeType: "textarea",
  406. type: 1,
  407. text: [],
  408. checked: true,
  409. },
  410. {
  411. label: "Retweet",
  412. icon: require("@/assets/svg/icon-retweet.svg"),
  413. nodeType: "div",
  414. type: 3,
  415. checked: true,
  416. },
  417. {
  418. label: "Like Tweet",
  419. icon: require("@/assets/svg/icon-like.svg"),
  420. nodeType: "div",
  421. type: 2,
  422. checked: true,
  423. },
  424. {
  425. label: "Join Discord",
  426. icon: require("@/assets/svg/icon-discord-mini.svg"),
  427. nodeType: "input",
  428. text: '',
  429. type: 7,
  430. checked: true,
  431. },
  432. ]);
  433. const discordInviteInfo = ref({});
  434. const props = defineProps({
  435. dialogVisible: {
  436. type: Boolean,
  437. default: false,
  438. },
  439. });
  440. watch(
  441. () => props.dialogVisible,
  442. (newVal) => {
  443. console.log("watch", newVal);
  444. visible.value = newVal;
  445. if (newVal) {
  446. Report.reportLog({
  447. pageSource: Report.pageSource.publisherDialog,
  448. businessType: Report.businessType.pageView,
  449. });
  450. getLocalCurrencyInfoByCode();
  451. setTimeout(() => {
  452. setDialogHeight();
  453. }, 300);
  454. }
  455. }
  456. );
  457. const emits = defineEmits(["close", "confirm", "payPalFinsh"]);
  458. const close = () => {
  459. if (showComType.value != "default") {
  460. showComType.value = "default";
  461. calcDomZoom();
  462. isBack.value = true;
  463. } else {
  464. initParams();
  465. emits("close", false);
  466. }
  467. };
  468. /**
  469. * 设置弹窗高度
  470. */
  471. const setDialogHeight = (resize = false) => {
  472. nextTick(() => {
  473. let clientHeight = window.innerHeight;
  474. let gapSafe = 40;
  475. console.log('resize',resize)
  476. if (dialogHeight.value > clientHeight - gapSafe) {
  477. dialogHeight.value = clientHeight - gapSafe;
  478. } else {
  479. if(resize) {
  480. dialogHeight.value = 680;
  481. }
  482. }
  483. })
  484. };
  485. const selectCurrencyPopHandle = () => {
  486. Report.reportLog({
  487. pageSource: Report.pageSource.currencySelectorPage,
  488. businessType: Report.businessType.pageView,
  489. });
  490. showCurrencyPop.value = true;
  491. nextTick(() => {
  492. if(currencyListDom.value) {
  493. currencyListDom.value.getCurrencyInfoList && currencyListDom.value.getCurrencyInfoList();
  494. }
  495. })
  496. }
  497. /**
  498. * 获取实际支付金额
  499. */
  500. const getPayAmount = async (amountValue) => {
  501. let res = await payCalcFee({
  502. params: {
  503. amountValue,
  504. currencyCode: currentCurrencyInfo.value.currencyCode,
  505. payChannel: 'paypal',
  506. },
  507. });
  508. if (res.code == 0) {
  509. let { finalAmountValue, feeDesc } = res.data;
  510. payConfig.value.feeDesc = feeDesc;
  511. if (finalAmountValue > 0) {
  512. finalAmountData.value = res.data;
  513. }
  514. }
  515. return res.data;
  516. };
  517. const confirm = () => {
  518. if(depositGuide.value) { //余额不够去充值
  519. goTopUp();
  520. return;
  521. }
  522. if (submitIng.value || iptErrMsgTxt.value) {
  523. return;
  524. }
  525. let { totalCount = 0 } = baseFormData;
  526. if (!totalCount) {
  527. return;
  528. }
  529. submitRequest();
  530. };
  531. /**
  532. * 货币列表-选中货币
  533. */
  534. const selectCurrency = (params) => {
  535. tempCurrentCurrencyInfo.value = params;
  536. depositGuide.value = false;
  537. if(params.currencyCode != "USD" && params.balance < params.minAmount) {
  538. let tokenSymbol = params.currencyCode == 'USD' ? 'USD' : params.tokenSymbol;
  539. messageBoxBlock({
  540. title: `Whether to deposit ${tokenSymbol}`,
  541. content: `Insufficient ${tokenSymbol} balance`,
  542. });
  543. } else {
  544. currentCurrencyInfo.value = params;
  545. setLocalSelectCurrencyInfo(currentCurrencyInfo.value);
  546. showCurrencyPop.value = false;
  547. finalAmountData.value.currencyCode = currentCurrencyInfo.value.currencyCode;
  548. calcDomZoom();
  549. resetFormIpt();
  550. onIptSetErrorTxt();
  551. }
  552. };
  553. const calcDomZoom = () => {
  554. nextTick(() => {
  555. let maxWidth = 68;
  556. var textWidth = document.querySelector('.text').offsetWidth;
  557. if(textWidth > 68) {
  558. var scale = maxWidth / textWidth;
  559. document.querySelector('.text').style.zoom = scale;
  560. }
  561. })
  562. }
  563. const resetFormIpt = () => {
  564. baseFormData.amountValue = "";
  565. baseFormData.totalCount = "";
  566. }
  567. const setLocalSelectCurrencyInfo = (params = {}) => {
  568. setChromeStorage({ selectCurrencyInfo : JSON.stringify(params)})
  569. }
  570. /**
  571. * 获取完货币列表
  572. */
  573. const setCurrentCurrencyInfo = (params) => {
  574. }
  575. const messageBoxBlock = ({ title = "", content = "" }) => {
  576. showMessageBox.value = true;
  577. messageBoxData.value.title = title;
  578. messageBoxData.value.content = content;
  579. };
  580. /**
  581. * 确定
  582. */
  583. const messageBoxConfirm = () => {
  584. showMessageBox.value = false;
  585. goTopUp();
  586. };
  587. /**
  588. * 取消
  589. */
  590. const messageBoxCancel = () => {
  591. currentCurrencyInfo.value = tempCurrentCurrencyInfo.value;
  592. setLocalSelectCurrencyInfo(currentCurrencyInfo.value);
  593. showMessageBox.value = false;
  594. showCurrencyPop.value = false;
  595. calcDomZoom();
  596. resetFormIpt();
  597. onIptSetErrorTxt();
  598. };
  599. /**
  600. * 去充值
  601. */
  602. const goTopUp = () => {
  603. Report.reportLog({
  604. pageSource: Report.pageSource.rechargePage,
  605. businessType: Report.businessType.pageView,
  606. });
  607. showComType.value = 'topUp';
  608. }
  609. /**
  610. * 充值done事件
  611. */
  612. const topUpDone = () => {
  613. currentCurrencyInfo.value = tempCurrentCurrencyInfo.value;
  614. asyncIng.value = true;
  615. depositGuide.value = false;
  616. asyncIng.value = false;
  617. showCurrencyPop.value = false;
  618. showComType.value = 'default';
  619. calcDomZoom();
  620. onIptSetErrorTxt()
  621. asyncTokenRechRecord((res) => {
  622. if(res.code == 0 && res.data && res.data.length) {
  623. let currencyInfo = res.data[0];
  624. if(currencyInfo.currencyCode == currentCurrencyInfo.value.currencyCode) {
  625. currentCurrencyInfo.value.balance = currencyInfo.balance;
  626. onIptSetErrorTxt()
  627. }
  628. }
  629. })
  630. }
  631. /**
  632. * 更新货币余额
  633. */
  634. const updateCurrencyBanlce = () => {
  635. if(!refreshRotate.value) {
  636. refreshRotate.value = true;
  637. setTimeout(() => {
  638. refreshRotate.value = false;
  639. }, 1000)
  640. }
  641. asyncTokenRechRecord((res) => {
  642. if(res.code == 0 && res.data && res.data.length) {
  643. let currencyInfo = res.data[0];
  644. if(currencyInfo.currencyCode == currentCurrencyInfo.value.currencyCode) {
  645. currentCurrencyInfo.value.balance = currencyInfo.balance;
  646. }
  647. }
  648. })
  649. }
  650. /**
  651. * 同步链上交易
  652. */
  653. const asyncTokenRechRecord = (cb) => {
  654. syncChainTokenRechargeRecord({
  655. params: {
  656. currencyCode: currentCurrencyInfo.value.currencyCode
  657. }
  658. }).then(res => {
  659. cb && cb(res)
  660. })
  661. }
  662. /**
  663. * 提交表单请求
  664. */
  665. const submitRequest = async () => {
  666. let { amountValue = 0, totalCount = 0 } = baseFormData;
  667. baseFormData.amountCurrencyCode = currentCurrencyInfo.value.currencyCode;
  668. // 组装提交参数
  669. formList[0]["text"] = atUserList.value;
  670. let finishConditions = [];
  671. for (let i = 0; i < formList.length; i++) {
  672. let item = {};
  673. item.type = formList[i]["type"];
  674. if (item.type == 1 && formList[i]["text"]) {
  675. // follow 参数
  676. let relatedUsers = formList[i]["text"];
  677. item.relatedUsers = relatedUsers;
  678. finishConditions.push(item);
  679. } else if (formList[i]["type"] == 7) {
  680. // join discord
  681. if(formList[i]["checked"] && formList[i]["text"]) {
  682. item.bizData = JSON.stringify({inviteUrl: formList[i]["text"]});
  683. finishConditions.push(item);
  684. }
  685. } else if (formList[i]["checked"]) {
  686. finishConditions.push(item);
  687. }
  688. }
  689. let receiveConditions = openAntiBot.value ? "" : [];
  690. // 提交参数
  691. let formData = {
  692. amountCurrencyCode: baseFormData.amountCurrencyCode,
  693. amountValue,
  694. totalCount,
  695. finishConditions,
  696. receiveConditions,
  697. payAmountValue: amountValue
  698. };
  699. submitIng.value = true;
  700. // 法币支付需要计算费率
  701. if(formData.amountCurrencyCode == "USD") {
  702. let payAmountRes = await getPayAmount(amountValue);
  703. formData["payAmountValue"] = payAmountRes.finalAmountValue;
  704. }
  705. let data = {
  706. params: {
  707. postBizData: JSON.stringify(formData),
  708. postSrc: 1, //1 twitter
  709. postType: 1, //1 红包
  710. },
  711. };
  712. postPublish(data).then((res) => {
  713. submitIng.value = false;
  714. if (res.code == 0) {
  715. publishRes = res.data;
  716. postId.value = res.data.postId;
  717. Report.reportLog({
  718. pageSource: Report.pageSource.previewPage,
  719. businessType: Report.businessType.pageView,
  720. });
  721. showComType.value = "preview";
  722. previewFontSize.value = calcFontSize(baseFormData.amountValue, 238, 56);
  723. isBack.value = false;
  724. } else {
  725. console.log(res);
  726. }
  727. })
  728. .catch((err) => {
  729. console.log(err);
  730. });
  731. };
  732. const calcFontSize = (str, domWidth, maxSize) => {
  733. let lenstr = str.length;
  734. let num = parseInt(domWidth / lenstr);
  735. let fontSize = num < maxSize ? num : maxSize
  736. return fontSize;
  737. }
  738. /**
  739. * 初始化提交参数
  740. */
  741. const initParams = () => {
  742. resetFormIpt();
  743. formList[0].text = [];
  744. atUserList.value = [];
  745. submitIng.value = false;
  746. isBack.value = false;
  747. showCurrencyPop.value = false;
  748. openAntiBot.value = false;
  749. tempCurrentCurrencyInfo.value = {};
  750. currentCurrencyInfo.value = {};
  751. };
  752. /**
  753. * 支付完成回调
  754. */
  755. const payPalFinsh = (params) => {
  756. let {payNetwork, payStatus} = params;
  757. // token 支付
  758. if(payNetwork == 'bsc') {
  759. payStatusHandle(payStatus);
  760. } else {
  761. // 法币支付
  762. let transaction = params.transaction;
  763. let loadingInstance = ElLoading.service({
  764. background: "rgba(0,0,0,.3)",
  765. });
  766. verifyPaypalResult({
  767. params: {
  768. paypalTransactionId: transaction.id,
  769. postId: publishRes.postId,
  770. paypalClientId: paypalClientId.value,
  771. },
  772. }).then((res) => {
  773. loadingInstance.close();
  774. if (res.code == 0) {
  775. if (res.data) {
  776. payStatusHandle(res.data.payStatus)
  777. }
  778. }
  779. })
  780. .catch(() => {
  781. loadingInstance.close();
  782. });
  783. }
  784. };
  785. const payStatusHandle = (payStatus) => {
  786. //支付状态 0:未支付,1:支付成功,2:支付失败,3:已关闭,4:已退款
  787. switch (payStatus) {
  788. case 1:
  789. emits("payPalFinsh", { publishRes });
  790. showComType.value = "default";
  791. initParams();
  792. break;
  793. case 2:
  794. // ElMessage({
  795. // message: "Pay Fail",
  796. // type: "warning",
  797. // });
  798. break;
  799. case 3:
  800. // ElMessage({
  801. // message: "Pay Exceptions",
  802. // type: "warning",
  803. // });
  804. break;
  805. case 4:
  806. // ElMessage({
  807. // message: "Pay Exceptions",
  808. // type: "warning",
  809. // });
  810. break;
  811. }
  812. }
  813. /**
  814. * follow组件触发新增关注人
  815. */
  816. const addFollowUser = (params) => {
  817. atUserList.value.push(params);
  818. };
  819. const setFollowUser = (params) => {
  820. atUserList.value[params.index]["name"] = params.name;
  821. };
  822. const delFollowUser = (params) => {
  823. atUserList.value.splice(params.index, 1);
  824. };
  825. const onAmountInput = () => {
  826. let val = baseFormData.amountValue;
  827. // val = val.replace(/[^\d^\.]+/g, "");
  828. val = val.replace(/^\D*(\d*(?:\.\d{0,18})?).*$/g, '$1');
  829. if(val == '00') {
  830. val = '0'
  831. }
  832. if(val.indexOf('.') > -1){ //校验 例:00.12 => 0.12
  833. let arr = val.split('.');
  834. if(arr[0].startsWith('0')) {
  835. let num = +arr[0];
  836. val = num + '.' + arr[1];
  837. }
  838. }
  839. baseFormData.amountValue = val;
  840. setInputErrorMsg({from: 'amount', type:'input'});
  841. return val;
  842. };
  843. const onCountInput = () => {
  844. let val = baseFormData.totalCount;
  845. if (val == 0) {
  846. val = "";
  847. }
  848. // val = val.replace(/[^\d]/g, "");
  849. val = val.replace(/^\D*(\d*(?:\.\d{0,18})?).*$/g, '$1');
  850. baseFormData.totalCount = val;
  851. setInputErrorMsg({from: 'count', type:'input'});
  852. return val;
  853. };
  854. /**
  855. * 金额输入失焦
  856. */
  857. const onAmountBlur = () => {
  858. setInputErrorMsg({from: 'amount', type:'blur'});
  859. };
  860. /**
  861. * count失焦,校验输入结果
  862. */
  863. const onCountBlur = () => {
  864. setInputErrorMsg({from: 'count', type:'blur'});
  865. };
  866. /**
  867. * 输入结果金额和数量 (金额/数量)是否小于最小货币单位
  868. */
  869. const calcIptValue = (cb) => {
  870. let amountValue = baseFormData.amountValue;
  871. let totalCount = baseFormData.totalCount;
  872. let flag = true;
  873. if (!amountValue || !totalCount) {
  874. return {
  875. flag
  876. };
  877. }
  878. if (math.format(math.evaluate(`${baseFormData.amountValue} / ${baseFormData.totalCount}`)) < +currentCurrencyInfo.value.minAmount) {
  879. flag = false;
  880. }
  881. return {
  882. flag,
  883. count: Math.floor(math.format(math.evaluate(`${baseFormData.amountValue} / ${currentCurrencyInfo.value.minAmount}`)))
  884. }
  885. };
  886. /**
  887. * 设置输入提示语
  888. */
  889. const setInputErrorMsg = () => {
  890. onIptSetErrorTxt();
  891. };
  892. /**
  893. * 输入时 检测设置错误信息
  894. */
  895. const onIptSetErrorTxt = () => {
  896. depositGuide.value = false;
  897. if(!currentCurrencyInfo.value.currencyCode) {
  898. iptErrMsgTxt.value = "Select a reward"
  899. } else if (!baseFormData.amountValue || baseFormData.amountValue == '0') {
  900. iptErrMsgTxt.value = "Enter an amount";
  901. } else if (!baseFormData.totalCount || baseFormData.totalCount == '0') {
  902. iptErrMsgTxt.value = "Enter the number of winners";
  903. } else if(+baseFormData.amountValue <= +currentCurrencyInfo.value.balance) {
  904. let res = calcIptValue();
  905. if (!res.flag) {
  906. iptErrMsgTxt.value = `${baseFormData.amountValue} ${currentCurrencyInfo.value.tokenSymbol} Can send up to ${res.count} winners`;
  907. } else {
  908. iptErrMsgTxt.value = "";
  909. }
  910. } else if(currentCurrencyInfo.value.currencyCode != 'USD') {
  911. depositGuide.value = true;
  912. iptErrMsgTxt.value = `Insufficient ${currentCurrencyInfo.value.tokenSymbol} balance, please deposit`;
  913. }
  914. }
  915. const formSwitchChange = (val, params) => {
  916. if(!val) {
  917. if(params.type == 7) {
  918. // 清空discord错误校验
  919. }
  920. }
  921. }
  922. const onIptDiscordAddress = (e, index) => {
  923. let val = formList[index].text;
  924. onIptDiscordDebounce({value: val, checked: formList[index].checked})
  925. }
  926. const onBlurDiscordAddress = (e, index) => {
  927. let val = formList[index].text;
  928. }
  929. const onIptDiscordDebounce = debounce(function({value, checked}) {
  930. if(value && checked) {
  931. let validata = checkInviteUrl(value);
  932. if(validata) {
  933. getDiscordInviteInfo(value, (res) => {
  934. if(res.code != 0) {
  935. // 错误提示
  936. } else {
  937. // 预览 服务器 showDiscordInvitePop
  938. }
  939. });
  940. } else {
  941. // 错误提示
  942. }
  943. }
  944. }, 800)
  945. const checkInviteUrl = (inviteUrl) => {
  946. let flag = true;
  947. const INVITE_URL_PREFIX = 'https://discord.gg/';
  948. const INVITE_URL_PREFIX_OLD = 'https://discord.com/invite/';
  949. if(inviteUrl) {
  950. if(inviteUrl == INVITE_URL_PREFIX || inviteUrl == INVITE_URL_PREFIX_OLD ||
  951. (!inviteUrl.startsWith(INVITE_URL_PREFIX) && !inviteUrl.startsWith(INVITE_URL_PREFIX_OLD))) {
  952. flag = false;
  953. }
  954. }
  955. return flag;
  956. }
  957. const getDiscordInviteInfo = (inviteUrl, cb) => {
  958. if(!inviteUrl) return;
  959. getInviteGuildInfo({
  960. params: {
  961. inviteUrl
  962. }
  963. }).then(res => {
  964. cb && cb(res)
  965. if(res.code == 0) {
  966. discordInviteInfo.value = res.data;
  967. }
  968. })
  969. }
  970. /**
  971. * 获取支付配置(paypalClientId)
  972. */
  973. const setPayConfig = () => {
  974. getPayConfig({
  975. params: {},
  976. }).then((res) => {
  977. if (res.code == 0) {
  978. payConfig.value = res.data;
  979. paypalClientId.value = res.data.paypalClientId;
  980. }
  981. });
  982. };
  983. /**
  984. * 获取配置
  985. */
  986. const setFrontConfig = () => {
  987. getFrontConfig({
  988. params: {},
  989. }).then((res) => {
  990. if (res.code == 0) {
  991. paypalHtml.value = res.data.paypalHtml;
  992. }
  993. });
  994. };
  995. const goTransactionsList = () => {
  996. window.open(`${chrome.runtime.getURL('/iframe/home.html#/transactions')}`)
  997. }
  998. /**
  999. * 默认获取上次选中的货币信息
  1000. */
  1001. const getLocalCurrencyInfoByCode = () => {
  1002. if(!currentCurrencyInfo.value.currencyCode) {
  1003. getChromeStorage('selectCurrencyInfo', (res) => {
  1004. if(res && res.currencyCode) {
  1005. getCurrencyInfoByCode({
  1006. params: {
  1007. currencyCode: res.currencyCode
  1008. }
  1009. }).then(res => {
  1010. if(res.code == 0 && res.data) {
  1011. currentCurrencyInfo.value = res.data;
  1012. tempCurrentCurrencyInfo.value = res.data;
  1013. onIptSetErrorTxt();
  1014. }
  1015. });
  1016. }
  1017. })
  1018. }
  1019. }
  1020. onMounted(() => {
  1021. setFrontConfig();
  1022. setPayConfig();
  1023. getLocalCurrencyInfoByCode();
  1024. document.onkeydown = function (e) {
  1025. var keyNum = window.event ? e.keyCode : e.which;
  1026. let escKey = 27;
  1027. if (keyNum == escKey) {
  1028. if (visible.value) {
  1029. // close();
  1030. }
  1031. }
  1032. };
  1033. window.addEventListener('resize', function () {
  1034. setDialogHeight(true);
  1035. })
  1036. });
  1037. </script>
  1038. <style lang="scss" scoped>
  1039. .overlay {
  1040. position: fixed;
  1041. top: 0;
  1042. right: 0;
  1043. bottom: 0;
  1044. left: 0;
  1045. z-index: 2000;
  1046. height: 100%;
  1047. background-color: rgba(0, 0, 0, 0.5);
  1048. overflow: auto;
  1049. .content {
  1050. height: 620px;
  1051. background: #ffffff;
  1052. border-radius: 20px;
  1053. position: absolute;
  1054. left: 50%;
  1055. top: 50%;
  1056. transform: translate(-50%, -50%);
  1057. box-sizing: border-box;
  1058. z-index: 2000;
  1059. .pop-mask {
  1060. width: 100%;
  1061. height:100%;
  1062. position: absolute;
  1063. z-index:900;
  1064. }
  1065. .head {
  1066. border-bottom: 1px solid #ececec;
  1067. height: 48px;
  1068. box-sizing: border-box;
  1069. display: flex;
  1070. align-items: center;
  1071. justify-content: space-between;
  1072. padding: 0 14px;
  1073. .left {
  1074. display: flex;
  1075. align-items: center;
  1076. .title {
  1077. font-size: 16px;
  1078. font-weight: 500;
  1079. }
  1080. .close-btn {
  1081. display: flex;
  1082. align-items: center;
  1083. width: max-content;
  1084. margin-right: 12px;
  1085. cursor: pointer;
  1086. }
  1087. }
  1088. .right {
  1089. .more {
  1090. cursor: pointer;
  1091. }
  1092. .area-option {
  1093. width: 100%;
  1094. height: 100%;
  1095. position: absolute;
  1096. top: 0;
  1097. left: 0;
  1098. z-index: 111;
  1099. .option {
  1100. position: absolute;
  1101. top: 43px;
  1102. right: 15px;
  1103. background: #fff;
  1104. filter: drop-shadow(0px 3px 20px rgba(0, 0, 0, 0.2));
  1105. width: 240px;
  1106. border-radius: 15px;
  1107. overflow: hidden;
  1108. .item {
  1109. width: 100%;
  1110. height: 50px;
  1111. display: flex;
  1112. align-items: center;
  1113. cursor: pointer;
  1114. border-top: 1px solid #E9E9E9;
  1115. img {
  1116. margin-left: 15px;
  1117. width: 30px;
  1118. height: 30px;
  1119. margin-right: 6px;
  1120. }
  1121. span {
  1122. font-weight: 500;
  1123. font-size: 14px;
  1124. }
  1125. }
  1126. .item:first-child {
  1127. border-top: 0;
  1128. }
  1129. .item:hover {
  1130. background: #F5F5F5;
  1131. }
  1132. }
  1133. }
  1134. }
  1135. }
  1136. .body {
  1137. box-sizing: border-box;
  1138. height: calc(100% - 48px);
  1139. display: flex;
  1140. position: relative;
  1141. .icon-guide-select {
  1142. width: 40px;
  1143. position: absolute;
  1144. top: 78px;
  1145. left: 25px;
  1146. z-index: 1000;
  1147. }
  1148. .body-content {
  1149. display:flex;
  1150. width:100%;
  1151. }
  1152. .currency-pop {
  1153. position: absolute;
  1154. width: 375px;
  1155. height: 480px;
  1156. top: 85px;
  1157. left: 88px;
  1158. z-index: 1000;
  1159. box-shadow: 0px 4px 30px rgba(0, 0, 0, 0.3);
  1160. background-color: #fff;
  1161. border-radius: 20px;
  1162. overflow-y: scroll;
  1163. }
  1164. .left,
  1165. .right {
  1166. height: 100%;
  1167. }
  1168. .left {
  1169. width: 50px;
  1170. display: flex;
  1171. flex-direction: column;
  1172. justify-content: space-between;
  1173. align-items: center;
  1174. .gift-pack-wrapper {
  1175. width: 100%;
  1176. height: 55px;
  1177. background: #f5f5f5;
  1178. display: flex;
  1179. align-items: center;
  1180. justify-content: center;
  1181. }
  1182. .bottom {
  1183. .icon {
  1184. display: block;
  1185. margin-bottom: 26px;
  1186. }
  1187. }
  1188. }
  1189. .right {
  1190. width: calc(100% - 50px);
  1191. box-sizing: border-box;
  1192. position: relative;
  1193. border-left: 1px solid #ececec;
  1194. .form-wrapper {
  1195. padding: 0px 18px 18px 18px;
  1196. height: calc(100% - 80px);
  1197. overflow-y: scroll;
  1198. overflow-x: hidden;
  1199. box-sizing: border-box;
  1200. .img-mode {
  1201. margin-left: -18px;
  1202. }
  1203. .form-base-help {
  1204. display: flex;
  1205. justify-content: space-between;
  1206. margin-top: 10px;
  1207. .currency-operation:before{
  1208. box-sizing: content-box;
  1209. width: 0px;
  1210. height: 0px;
  1211. position: absolute;
  1212. top: -16px;;
  1213. left:46px;
  1214. padding:0;
  1215. border-bottom:8px solid #FFFFFF;
  1216. border-top:8px solid transparent;
  1217. border-left:8px solid transparent;
  1218. border-right:8px solid transparent;
  1219. display: block;
  1220. content:'';
  1221. z-index: 12;
  1222. }
  1223. .currency-operation:after{
  1224. box-sizing: content-box;
  1225. width: 0px;
  1226. height: 0px;
  1227. position: absolute;
  1228. top: -18px;;
  1229. left:45px;
  1230. padding:0;
  1231. border-bottom:9px solid #EAEAEA;
  1232. border-top:9px solid transparent;
  1233. border-left:9px solid transparent;
  1234. border-right:9px solid transparent;
  1235. display: block;
  1236. content:'';
  1237. z-index:10
  1238. }
  1239. .currency-operation {
  1240. position: relative;
  1241. height: 36px;
  1242. border: 1px solid #EAEAEA;
  1243. box-sizing: border-box;
  1244. padding: 10px;
  1245. display: flex;
  1246. align-items: center;
  1247. border-radius: 100px;
  1248. .balance,
  1249. .amount {
  1250. display: flex;
  1251. align-items: center;
  1252. }
  1253. .balance {
  1254. font-weight: 400;
  1255. font-size: 13px;
  1256. img {
  1257. width: 16px;
  1258. height: 16px;
  1259. margin-right: 3px;
  1260. }
  1261. }
  1262. .amount {
  1263. font-weight: 500;
  1264. font-size: 13px;
  1265. color: #4e4e4e;
  1266. margin-left: 5px;
  1267. img {
  1268. margin-left: 5px;
  1269. cursor: pointer;
  1270. }
  1271. }
  1272. .top-up {
  1273. font-weight: 500;
  1274. font-size: 12px;
  1275. color: #ff9839;
  1276. cursor: pointer;
  1277. margin-left: 8px;
  1278. }
  1279. .icon-refresh-rotate {
  1280. transform: rotate(360deg);
  1281. transition-duration: 1s;
  1282. }
  1283. }
  1284. .msg {
  1285. font-weight: 400;
  1286. font-size: 12px;
  1287. color: #acacac;
  1288. }
  1289. }
  1290. .form-base {
  1291. display: flex;
  1292. justify-content: space-between;
  1293. align-items: center;
  1294. margin-top: 14px;
  1295. .item {
  1296. width: 250px;
  1297. height: 50px;
  1298. box-sizing: border-box;
  1299. border-radius: 14px;
  1300. border: 1px solid #D1D9DD;
  1301. display: flex;
  1302. align-items: center;
  1303. justify-content: space-between;
  1304. padding: 16px 14px;
  1305. input {
  1306. width: 102px;
  1307. text-align: right;
  1308. font-weight: 500;
  1309. font-size: 18px;
  1310. border: none;
  1311. outline: none;
  1312. box-sizing: border-box;
  1313. }
  1314. input::placeholder {
  1315. color: #c5c5c5;
  1316. }
  1317. .label {
  1318. font-weight: 500;
  1319. font-size: 15px;
  1320. display: flex;
  1321. align-items: center;
  1322. .icon {
  1323. width: 20px;
  1324. height: 20px;
  1325. margin-right: 8px;
  1326. }
  1327. }
  1328. }
  1329. .item:first-child {
  1330. margin-right: 14px
  1331. }
  1332. .currency-select-wrapper {
  1333. padding: 0 !important;
  1334. input {
  1335. padding-right: 14px;
  1336. }
  1337. .currency-select {
  1338. max-width: 136px;
  1339. cursor: pointer;
  1340. background: #1D9BF0;
  1341. margin-left: 6px;
  1342. padding: 6px 10px;
  1343. border-radius: 12px;
  1344. color: #fff;
  1345. .text {
  1346. white-space: nowrap;
  1347. zoom: 0.85;
  1348. }
  1349. .arrow {
  1350. margin-left: 5px;
  1351. }
  1352. }
  1353. .selected {
  1354. background: #F4F4F4 !important;
  1355. color: #000 !important;
  1356. }
  1357. }
  1358. }
  1359. .form-label {
  1360. margin-top: 14px;
  1361. margin-bottom: 10px;
  1362. font-weight: 500;
  1363. font-size: 14px;
  1364. }
  1365. .form-require {
  1366. box-sizing: border-box;
  1367. border-radius: 15px;
  1368. margin-top: 12px;
  1369. border: 1px solid #D1D9DD;
  1370. .form-item {
  1371. min-height: 50px;
  1372. display: flex;
  1373. align-items: center;
  1374. justify-content: space-between;
  1375. margin: 0 16px;
  1376. border-bottom: 1px solid #ececec;
  1377. padding: 8px 0;
  1378. box-sizing: border-box;
  1379. .item-left {
  1380. display: flex;
  1381. }
  1382. .label {
  1383. min-width: 76px;
  1384. display: flex;
  1385. align-items: center;
  1386. font-size: 15px;
  1387. font-weight: 500;
  1388. .icon {
  1389. margin-right: 10px;
  1390. }
  1391. }
  1392. .control {
  1393. min-width: 280px;
  1394. margin-left: 18px;
  1395. box-sizing: border-box;
  1396. border-left: 1px solid #ECECEC;
  1397. .discord-address {
  1398. border: none;
  1399. outline: none;
  1400. color: #1D9BF0;
  1401. font-weight: 500;
  1402. font-size: 14px;
  1403. width: 100%;
  1404. height: 34px;
  1405. padding-left: 15px;
  1406. }
  1407. .discord-address::placeholder {
  1408. color: #c5c5c5;
  1409. }
  1410. }
  1411. }
  1412. .form-item:last-child {
  1413. border-bottom: none !important;
  1414. }
  1415. }
  1416. }
  1417. .anti-bot-wrapper {
  1418. width: 100%;
  1419. height: 50px;
  1420. display: flex;
  1421. align-items: center;
  1422. justify-content: space-between;
  1423. box-sizing: border-box;
  1424. border-radius: 15px;
  1425. padding: 0 18px;
  1426. margin-top: 14px;
  1427. border: 1px solid #D1D9DD;
  1428. .label {
  1429. display: flex;
  1430. align-items: center;
  1431. font-size: 15px;
  1432. font-weight: 500;
  1433. .icon-bot {
  1434. margin-right: 8px;
  1435. }
  1436. .icon-beta {
  1437. margin-left: 5px;
  1438. margin-right: 8px;
  1439. }
  1440. .icon-question {
  1441. cursor: pointer;
  1442. }
  1443. }
  1444. }
  1445. .tips-wrapper {
  1446. margin: 16px 0 0 12px !important;
  1447. padding: 0px !important;
  1448. .title,
  1449. .row {
  1450. font-weight: 400;
  1451. font-size: 12px;
  1452. color: #A39F9F;
  1453. }
  1454. .row {
  1455. box-sizing: border-box;
  1456. line-height: 16px;
  1457. }
  1458. .more {
  1459. color: #1D9BF0;
  1460. font-size: 13px;
  1461. padding-left: 4px;
  1462. cursor: pointer;
  1463. }
  1464. }
  1465. .submit-btn-wrapper {
  1466. width: 100%;
  1467. background: #fff;
  1468. position: absolute;
  1469. bottom: 18px;
  1470. left: 0;
  1471. box-sizing: border-box;
  1472. padding: 16px 18px 0 18px;
  1473. .submit-btn {
  1474. width: 100%;
  1475. height: 46px;
  1476. text-align: center;
  1477. background: #4a99e9;
  1478. border-radius: 100px;
  1479. color: #fff;
  1480. display: flex;
  1481. align-items: center;
  1482. justify-content: center;
  1483. font-size: 16px;
  1484. font-weight: 500;
  1485. cursor: pointer;
  1486. .icon-loading {
  1487. width: 20px;
  1488. height: 20px;
  1489. margin-right: 3px;
  1490. }
  1491. }
  1492. .disabled-submit {
  1493. background-color: #D9D9D9;
  1494. }
  1495. }
  1496. }
  1497. .fill-right {
  1498. width: 100% !important;
  1499. border-bottom-left-radius: 16px;
  1500. }
  1501. }
  1502. }
  1503. }
  1504. </style>