give-dialog.vue 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218
  1. <template>
  2. <div class="overlay" v-if="visible">
  3. <div class="content"
  4. :style="{
  5. height: dialogHeight + 'px',
  6. width: showComType != 'preview' ? '600px' : '880px'}">
  7. <div class="pop-mask"
  8. v-show="showCurrencyPop || showCurrencySelect"
  9. @click.stop="showCurrencyPop = false; showCurrencySelect=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. :list="tempCurrentCurrencyList"
  54. @selectCurrency="selectCurrencyAfter"
  55. @topUpDone="topUpDone"></top-up>
  56. <!-- 表单填写容器 -->
  57. <div class="body-content" v-if="showComType != 'topUp'">
  58. <!-- 货币列表 -->
  59. <div class="currency-pop" v-show="showCurrencyPop">
  60. <currency-list
  61. ref="currencyListDom"
  62. @selectCurrency="selectCurrency"
  63. @setCurrencyList="setCurrentCurrencyInfo"></currency-list>
  64. </div>
  65. <div class="currency-pop-select" v-show="showCurrencySelect">
  66. <currency-select
  67. ref="currencySelectDom"
  68. :list="tempCurrentCurrencyList"
  69. @selectCurrency="selectCurrencyAfter">
  70. </currency-select>
  71. </div>
  72. <div class="left" v-if="showComType != 'preview'">
  73. <div class="gift-pack-wrapper">
  74. <img class="icon"
  75. :src="require('@/assets/svg/icon-gift-pack.svg')"/>
  76. </div>
  77. <div class="bottom">
  78. </div>
  79. </div>
  80. <div class="right"
  81. :class="{'fill-right': showComType == 'preview'}">
  82. <global-tip :type="'2'"></global-tip>
  83. <div class="form-wrapper" v-if="showComType == 'default'">
  84. <img
  85. class="img-mode"
  86. :src="require('@/assets/svg/img-mode.svg')"
  87. />
  88. <!-- 金额、数量 -->
  89. <div class="form-base">
  90. <div class="item currency-select-wrapper">
  91. <div
  92. class="label currency-select"
  93. :class="{'selected': currentCurrencyInfo.currencyCode}"
  94. @click="selectCurrencyPopHandle"
  95. >
  96. <img v-if="currentCurrencyInfo.iconPath"
  97. class="icon"
  98. :src="currentCurrencyInfo.iconPath"
  99. />
  100. <div class="text">
  101. {{currentCurrencyInfo.currencyCode == 'USD' ? 'USD' : currentCurrencyInfo.tokenSymbol || 'Select a reward'}}
  102. </div>
  103. <img
  104. class="arrow"
  105. :src="currentCurrencyInfo.currencyCode ?
  106. require('@/assets/svg/icon-form-arrow-down.svg') : require('@/assets/svg/icon-form-white-arrow-down.svg')
  107. "
  108. />
  109. </div>
  110. <input
  111. v-model="baseFormData.amountValue"
  112. placeholder="0"
  113. autofocus
  114. @input="onAmountInput"
  115. @blur="onAmountBlur"
  116. />
  117. </div>
  118. <div class="item">
  119. <div class="label">
  120. <img
  121. class="icon"
  122. :src="
  123. require('@/assets/svg/icon-winners.svg')
  124. "
  125. />
  126. Winners
  127. </div>
  128. <input
  129. v-model="baseFormData.totalCount"
  130. placeholder="0"
  131. @input="onCountInput"
  132. @blur="onCountBlur"
  133. />
  134. </div>
  135. </div>
  136. <!-- 刷新按钮、充值 -->
  137. <div class="form-base-help" v-show="currentCurrencyInfo.currencyCode">
  138. <div class="currency-operation">
  139. <div class="balance">
  140. <img
  141. :src="
  142. require('@/assets/svg/icon-balance.svg')
  143. "
  144. />
  145. Balance
  146. </div>
  147. <div class="amount">
  148. <a-tooltip :title="currentCurrencyInfo.balance">
  149. {{ getBit(currentCurrencyInfo.balance) }}
  150. </a-tooltip>
  151. <img
  152. :class="{ 'icon-refresh-rotate': refreshRotate }"
  153. @click="updateCurrencyBanlce"
  154. :src="
  155. require('@/assets/svg/icon-form-refresh.svg')
  156. "
  157. />
  158. </div>
  159. <div v-if="currentCurrencyInfo.currencyCode != 'USD'" class="top-up" @click="goTopUp">Deposit</div>
  160. </div>
  161. <div class="msg">
  162. Recommend winners 100~10000
  163. </div>
  164. </div>
  165. <div class="form-label">
  166. <div>
  167. Tasks
  168. </div>
  169. <!-- <div>
  170. <el-dropdown trigger="click">
  171. <img src="@/assets/svg/icon-add-task.svg"
  172. class="icon-add-task"
  173. v-show="formList.some(item => !item.show)">
  174. <template #dropdown>
  175. <el-dropdown-menu>
  176. <div v-for="(item, key) in formList" :key="key"
  177. @click="clickDropdown(item, key)">
  178. <el-dropdown-item style="height: 50px;width: 240px" v-if="!item.show">
  179. <img :src="item.icon" style="width: 20px; height: 20px;margin-right: 12px" />
  180. {{item.label}}
  181. </el-dropdown-item>
  182. </div>
  183. </el-dropdown-menu>
  184. </template>
  185. </el-dropdown>
  186. </div> -->
  187. </div>
  188. <!-- 转推、like、关注 -->
  189. <div class="form-require">
  190. <div
  191. v-for="(item, index) in formList"
  192. :key="index"
  193. >
  194. <div v-if="item.show" class="form-item"
  195. :class="{ 'border-hide': formList.length - 1 == index }">
  196. <div class="item-left">
  197. <div class="label">
  198. <img
  199. class="icon"
  200. :src="item.icon"
  201. />
  202. {{ item.label }}
  203. </div>
  204. <div
  205. class="control"
  206. v-if="item.nodeType == 'textarea'"
  207. >
  208. <follow-input
  209. :isAddSelf="!isBack"
  210. :atUserList="atUserList"
  211. @addUser="addFollowUser"
  212. @setUser="setFollowUser"
  213. @delUser="delFollowUser"
  214. ></follow-input>
  215. </div>
  216. <!-- join discord -->
  217. <div
  218. class="control"
  219. v-if="item.nodeType == 'input'"
  220. >
  221. <div v-if="showDiscordInvitePop"
  222. class="discord-invite-info"
  223. @click="showDiscordInvitePop = false">
  224. <img class="icon" :src="discordInviteInfo.icon || require('@/assets/svg/icon-discord-mini.svg')" />
  225. <span class="name">{{discordInviteInfo.name}}</span>
  226. </div>
  227. <input v-model="item.text"
  228. placeholder="Enter discord invite link"
  229. class="discord-address"
  230. @input="onIptDiscordAddress($event, index)"
  231. @blur="onBlurDiscordAddress($event, index)" />
  232. </div>
  233. </div>
  234. <div>
  235. <el-switch
  236. v-if="item.type > 3"
  237. v-model="item.checked"
  238. @change="formSwitchChange($event, item, index)"
  239. />
  240. <!-- <img src="@/assets/svg/icon-task-close.svg"
  241. class="icon-task-close"
  242. @click="hideTask(item, index)"> -->
  243. </div>
  244. <!--
  245. v-if="item.type == 2 || item.type == 3 || item.type == 7 || item.type == 8 || item.type == 9"
  246. <img
  247. v-if="item.type == 3"
  248. :src="
  249. require('@/assets/svg/icon-option-checked.svg')
  250. "
  251. /> -->
  252. </div>
  253. </div>
  254. </div>
  255. <!-- 机器人 -->
  256. <!-- <div class="anti-bot-wrapper">
  257. <div class="label">
  258. <img
  259. :src="
  260. require('@/assets/svg/icon-anti-bot.svg')
  261. "
  262. class="icon-bot"
  263. />
  264. Anti Bot
  265. <img
  266. :src="
  267. require('@/assets/svg/icon-beta.svg')
  268. "
  269. class="icon-beta"
  270. />
  271. <img
  272. :src="
  273. require('@/assets/svg/icon-question.svg')
  274. "
  275. class="icon-question"
  276. />
  277. </div>
  278. <el-switch v-model="openAntiBot" />
  279. </div> -->
  280. <!-- 提示 -->
  281. <ul class="tips-wrapper">
  282. <li class="row">
  283. Rewards can only be claimed after the target user completes all tasks you set.
  284. </li>
  285. <li class="row">
  286. Each user can only receive a reward once per task.
  287. </li>
  288. <li class="row">
  289. 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.
  290. </li>
  291. </ul>
  292. <div class="submit-btn-wrapper">
  293. <div class="submit-btn"
  294. :class="{ 'disabled-submit': iptErrMsgTxt != '' && !depositGuide }"
  295. @click="confirm">
  296. <img class="icon-loading"
  297. v-if="submitIng"
  298. :src="require('@/assets/svg/icon-btn-loading.svg')"
  299. />
  300. {{iptErrMsgTxt ? iptErrMsgTxt : 'NEXT'}}
  301. </div>
  302. </div>
  303. </div>
  304. <!-- 预览 -->
  305. <template v-else-if="showComType == 'preview'">
  306. <div class="preview">
  307. <div
  308. class="card"
  309. :class="{ center: Number(baseFormData.amountValue) <= Number(currentCurrencyInfo.balance) }">
  310. <div class="card-title">
  311. <img
  312. class="img"
  313. v-if="Number(baseFormData.amountValue) > Number(currentCurrencyInfo.balance)"
  314. :src=" require('@/assets/subject/top-01.svg') " />
  315. <div class="font">
  316. Preview: <span>{{installStatus ? 'After' : 'Before' }}</span> DeNet Installed
  317. </div>
  318. </div>
  319. <div class="flash">
  320. <preview-card
  321. :currentCurrencyInfo="currentCurrencyInfo"
  322. :postData="publishRes"
  323. :baseFormData="baseFormData"
  324. :amountFontSize="previewFontSize"
  325. ></preview-card>
  326. </div>
  327. </div>
  328. <!-- 需充值 -->
  329. <div class="card-content" v-if="Number(baseFormData.amountValue) > Number(currentCurrencyInfo.balance)">
  330. <template v-if="currentCurrencyInfo.currencyCode === 'USD'">
  331. <div class="card-title">
  332. <img class="img" :src=" require('@/assets/subject/top-02.svg') " />
  333. <div class="font">Deposit to Send Giveaway</div>
  334. </div>
  335. <div class="card-list">
  336. <div class="item">
  337. <div class="l">Giveaway Amount</div>
  338. <div class="r"></div>
  339. </div>
  340. <div class="item">
  341. <div class="l">Balance</div>
  342. <div class="r"></div>
  343. </div>
  344. <div class="item">
  345. <div class="l">Paypal charges fee ()</div>
  346. <div class="r"></div>
  347. </div>
  348. <div class="item">
  349. <div class="l">Deposit Amount</div>
  350. <div class="r"></div>
  351. </div>
  352. </div>
  353. </template>
  354. <template v-else>
  355. <div class="card-title">
  356. <img class="img" :src=" require('@/assets/subject/top-02.svg') " />
  357. <div class="font">Deposit to Send Giveaway</div>
  358. </div>
  359. <top-up2
  360. :asyncIng="asyncIng"
  361. :currentCurrencyInfo="tempCurrentCurrencyInfo"
  362. :list="tempCurrentCurrencyList"
  363. @selectCurrency="selectCurrencyAfter"
  364. @topUpDone="topUpDone">
  365. </top-up2>
  366. <div class="card-title">
  367. <img class="img" :src=" require('@/assets/subject/top-03.svg') " />
  368. <div class="font">Wait for the amount to arrive</div>
  369. </div>
  370. <div class="card-amount">
  371. <img class="icon" src="@/assets/subject/icon-balance.png" />
  372. <div class="con">
  373. <div class="desc">Balance</div>
  374. <div class="price">{{currentCurrencyInfo.balance}} {{currentCurrencyInfo.tokenSymbol}}</div>
  375. </div>
  376. <img
  377. class="refresh"
  378. :class="{ 'icon-refresh-rotate': refreshRotate }"
  379. @click="updateCurrencyBanlce"
  380. :src=" require('@/assets/svg/icon-form-refresh.svg') "
  381. />
  382. </div>
  383. </template>
  384. </div>
  385. </div>
  386. </template>
  387. <!-- paypal支付按钮 -->
  388. <div class="payment" v-show="showComType == 'preview'">
  389. <paypal-button
  390. :finalAmountData="finalAmountData"
  391. :payConfig="{
  392. paypalClientId,
  393. feeDesc: payConfig.feeDesc,
  394. paypalHtml,
  395. amount: baseFormData.amountValue,
  396. postId
  397. }"
  398. :currentCurrencyInfo="currentCurrencyInfo"
  399. @payPalFinsh="payPalFinsh"
  400. >
  401. <template v-slot:balance>
  402. <div class="balance" v-if="Number(baseFormData.amountValue) <= Number(currentCurrencyInfo.balance)">
  403. <img class="icon" src="@/assets/subject/icon-balance.png" />
  404. <div class="con">
  405. <div class="desc">Balance</div>
  406. <div class="price">{{currentCurrencyInfo.balance}} {{currentCurrencyInfo.tokenSymbol}}</div>
  407. </div>
  408. <img
  409. class="refresh"
  410. :class="{ 'icon-refresh-rotate': refreshRotate }"
  411. @click="updateCurrencyBanlce"
  412. :src=" require('@/assets/svg/icon-form-refresh.svg') "
  413. />
  414. </div>
  415. </template>
  416. </paypal-button>
  417. </div>
  418. </div>
  419. </div>
  420. </div>
  421. </div>
  422. <!-- 提示 -->
  423. <message-box
  424. :dialogVisible="showMessageBox"
  425. :title="messageBoxData.title"
  426. :content="messageBoxData.content"
  427. @cancel="messageBoxCancel"
  428. @confirm="messageBoxConfirm"
  429. ></message-box>
  430. </div>
  431. </template>
  432. <script setup>
  433. import { ref, watch, reactive, defineProps, defineEmits, onMounted, nextTick, provide } from "vue";
  434. import { postPublish, verifyPaypalResult, syncChainTokenRechargeRecord, getCurrencyInfoByCode } from "@/http/publishApi";
  435. import { getInviteGuildInfo, saveInviteGuildInfo } from "@/http/discordApi";
  436. import { payCalcFee, getPayConfig } from "@/http/pay";
  437. import { getFrontConfig } from "@/http/account";
  438. import {setChromeStorage, getChromeStorage} from "@/uilts/chromeExtension"
  439. import { debounce, getBit } from "@/uilts/help"
  440. import Report from "@/log-center/log"
  441. import { ElMessage, ElLoading, ElDropdown, ElDropdownMenu, ElDropdownItem } from "element-plus";
  442. import "element-plus/es/components/message/style/css";
  443. import {create, all} from "mathjs";
  444. import messageBox from "@/view/components/message-box.vue";
  445. import currencyList from "@/view/components/currency-list.vue";
  446. import currencySelect from "@/view/components/currency-select.vue";
  447. import previewCard from "@/view/iframe/publish/components/preview-card";
  448. import followInput from "@/view/iframe/publish/components/follow-input";
  449. import paypalButton from "@/view/iframe/publish/components/paypal-button";
  450. import topUp from "@/view/iframe/publish/components/top-up.vue";
  451. import topUp2 from "@/view/iframe/publish/components/top-up2.vue";
  452. import GlobalTip from '@/view/components/global-tip.vue'
  453. const config = {
  454. number: 'BigNumber',
  455. }
  456. const math = create(all, config);
  457. //临时货币信息
  458. let tempCurrentCurrencyInfo = ref({});
  459. let tempCurrentCurrencyList = ref([]);
  460. let paypalClientId = ref("");
  461. let payConfig = ref({});
  462. let paypalHtml = ref("");
  463. let installStatus = ref(false);
  464. let timer = ref(null);
  465. provide('installStatus', installStatus)
  466. // 发布后返回的结果
  467. let publishRes = reactive({});
  468. //弹窗是否展示
  469. let visible = ref(false);
  470. //弹窗高度
  471. let dialogHeight = ref(680);
  472. // 当前展示组件内容 default(表单) preview(预览) topUp(充值)
  473. let showComType = ref("default");
  474. let currentComData = {
  475. default: {
  476. title: "Giveaway",
  477. },
  478. preview: {
  479. title: "Giveaway",
  480. },
  481. topUp: {
  482. title: "Deposit",
  483. },
  484. };
  485. // 机器人开关
  486. let openAntiBot = ref(false);
  487. // 是否正在提交
  488. let submitIng = ref(false);
  489. // 艾特关注人列表
  490. let atUserList = ref([]);
  491. // 表单错误提示
  492. let iptErrMsgTxt = ref("Select a reward");
  493. // 是否返回
  494. let isBack = ref(false);
  495. // 展示消息提示
  496. let showMessageBox = ref(false);
  497. // 展示货币列表pop
  498. let showCurrencyPop = ref(false);
  499. let showCurrencySelect = ref(false);
  500. // 展示更多按钮下的选项
  501. let showMoreOption = ref(false);
  502. // 货币列表的dom
  503. let currencyListDom = ref('');
  504. // 刷新按钮旋转
  505. let refreshRotate = ref(false);
  506. // 预览字体大小
  507. let previewFontSize = ref(56);
  508. let postId = ref('');
  509. // 余额是否同步中
  510. let asyncIng = ref(false);
  511. // 提交按钮-充值引导提示
  512. let depositGuide = ref(false);
  513. let messageBoxData = ref({
  514. title: "",
  515. content: "",
  516. });
  517. // 真实支付金额数据
  518. let finalAmountData = ref({
  519. currencyCode: '',
  520. feeAmountValue: 0,
  521. finalAmountValue: 0,
  522. requestAmountValue: 0,
  523. });
  524. // 表单数据
  525. let baseFormData = reactive({
  526. amountCurrencyCode: '',
  527. amountValue: "",
  528. totalCount: "",
  529. });
  530. // 当前选择的货币信息
  531. let currentCurrencyInfo = ref({
  532. currencyCode: "",
  533. currencyName: "",
  534. balance: "",
  535. currencyType: "",
  536. iconPath: "",
  537. minAmount: "",
  538. tokenChain: "",
  539. tokenSymbol: "",
  540. usdEstimateBalance: ""
  541. });
  542. const discordIptErrTxt = 'Discord invite link is wrong';
  543. const discordIptEmptyErrTxt = 'Enter discord invite link';
  544. const discordIptNerverExpiresErrTxt = 'Make sure the Discord link never expires'
  545. let iptErrType = ''; //discord
  546. let formList = reactive([
  547. {
  548. label: "Follow",
  549. icon: require("@/assets/svg/icon-task-twitter.svg"),
  550. nodeType: "textarea",
  551. type: 1,
  552. text: [],
  553. checked: true,
  554. show: true
  555. },
  556. {
  557. label: "Retweet & Like",
  558. icon: require("@/assets/svg/icon-task-twitter.svg"),
  559. nodeType: "div",
  560. type: 3,
  561. checked: true,
  562. show: true
  563. },
  564. {
  565. label: "Like Tweet",
  566. icon: require("@/assets/svg/icon-task-twitter.svg"),
  567. nodeType: "div",
  568. type: 2,
  569. checked: true,
  570. show: false
  571. },
  572. {
  573. label: "Comment and Tag 3 friends",
  574. icon: require("@/assets/svg/icon-task-twitter.svg"),
  575. nodeType: "div",
  576. type: 9,
  577. checked: true,
  578. show: true
  579. },
  580. {
  581. label: "Repost to Facebook",
  582. icon: require("@/assets/svg/icon-task-facebook.svg"),
  583. nodeType: "div",
  584. text: '',
  585. type: 8,
  586. checked: true,
  587. show: true
  588. },
  589. {
  590. label: "Join Discord",
  591. icon: require("@/assets/svg/icon-discord-mini.svg"),
  592. nodeType: "input",
  593. text: '',
  594. type: 7,
  595. checked: true,
  596. show: true
  597. },
  598. ]);
  599. const discordInviteInfo = ref({});
  600. let showDiscordInvitePop = ref(false);
  601. const props = defineProps({
  602. dialogVisible: {
  603. type: Boolean,
  604. default: false,
  605. },
  606. });
  607. watch(
  608. () => props.dialogVisible,
  609. (newVal) => {
  610. console.log("watch", newVal);
  611. visible.value = newVal;
  612. if (newVal) {
  613. Report.reportLog({
  614. pageSource: Report.pageSource.publisherDialog,
  615. businessType: Report.businessType.pageView,
  616. });
  617. getLocalCurrencyInfoByCode();
  618. setTimeout(() => {
  619. setDialogHeight();
  620. }, 300);
  621. // 更新余额
  622. clearInterval(timer.value);
  623. timer.value = setInterval(() => {
  624. getCurrencyInfo();
  625. }, 10000)
  626. } else {
  627. clearInterval(timer.value);
  628. }
  629. }
  630. );
  631. const emits = defineEmits(["close", "confirm", "payPalFinsh"]);
  632. const close = () => {
  633. if (showComType.value != "default") {
  634. showComType.value = "default";
  635. calcDomZoom();
  636. isBack.value = true;
  637. } else {
  638. initParams();
  639. emits("close", false);
  640. }
  641. };
  642. /**
  643. * 设置弹窗高度
  644. */
  645. const setDialogHeight = (resize = false) => {
  646. nextTick(() => {
  647. let clientHeight = window.innerHeight;
  648. let gapSafe = 40;
  649. console.log('resize',resize)
  650. if (dialogHeight.value > clientHeight - gapSafe) {
  651. dialogHeight.value = clientHeight - gapSafe;
  652. } else {
  653. if(resize) {
  654. dialogHeight.value = 680;
  655. }
  656. }
  657. })
  658. };
  659. const selectCurrencyPopHandle = () => {
  660. Report.reportLog({
  661. pageSource: Report.pageSource.currencySelectorPage,
  662. businessType: Report.businessType.pageView,
  663. });
  664. showCurrencyPop.value = true;
  665. nextTick(() => {
  666. if(currencyListDom.value) {
  667. currencyListDom.value.getCurrencyInfoList && currencyListDom.value.getCurrencyInfoList();
  668. }
  669. })
  670. }
  671. /**
  672. * 获取实际支付金额
  673. */
  674. const getPayAmount = async (amountValue) => {
  675. let res = await payCalcFee({
  676. params: {
  677. amountValue,
  678. currencyCode: currentCurrencyInfo.value.currencyCode,
  679. payChannel: 'paypal',
  680. },
  681. });
  682. if (res.code == 0) {
  683. let { finalAmountValue, feeDesc } = res.data;
  684. payConfig.value.feeDesc = feeDesc;
  685. if (finalAmountValue > 0) {
  686. finalAmountData.value = res.data;
  687. }
  688. }
  689. return res.data;
  690. };
  691. const saveDiscordGuildInfo = () => {
  692. let {guildId, inviteCode, inviteUrl} = discordInviteInfo.value;
  693. if(guildId && inviteCode && inviteUrl) {
  694. saveInviteGuildInfo({
  695. params: {
  696. guildId,
  697. inviteCode,
  698. inviteUrl
  699. }
  700. })
  701. }
  702. }
  703. const confirm = () => {
  704. if(depositGuide.value) { //余额不够去充值
  705. goTopUp();
  706. return;
  707. }
  708. if (submitIng.value || iptErrMsgTxt.value) {
  709. return;
  710. }
  711. let { totalCount = 0 } = baseFormData;
  712. if (!totalCount) {
  713. return;
  714. }
  715. saveDiscordGuildInfo();
  716. submitRequest();
  717. };
  718. /**
  719. * 货币列表-选中货币
  720. */
  721. const selectCurrency = (params) => {
  722. tempCurrentCurrencyList.value = params;
  723. depositGuide.value = false;
  724. if (params.length > 1) {
  725. showCurrencyPop.value = false;
  726. showCurrencySelect.value = true;
  727. } else {
  728. selectCurrencyAfter(params[0])
  729. }
  730. };
  731. const selectCurrencyAfter = (params, openWindow = true) => {
  732. tempCurrentCurrencyInfo.value = params;
  733. depositGuide.value = false;
  734. showCurrencySelect.value = false;
  735. currentCurrencyInfo.value = params;
  736. setLocalSelectCurrencyInfo(currentCurrencyInfo.value);
  737. if (openWindow === false) {
  738. return
  739. };
  740. if (params.currencyCode != "USD" && params.balance < params.minAmount) {
  741. let tokenSymbol = params.currencyCode == 'USD' ? 'USD' : params.tokenSymbol;
  742. messageBoxBlock({
  743. title: `Whether to deposit ${tokenSymbol}`,
  744. content: `Insufficient ${tokenSymbol} balance`,
  745. });
  746. } else {
  747. setCurrentCurrencyListInfo(tempCurrentCurrencyList.value);
  748. showCurrencyPop.value = false;
  749. finalAmountData.value.currencyCode = currentCurrencyInfo.value.currencyCode;
  750. calcDomZoom();
  751. resetFormIpt();
  752. onIptSetErrorTxt();
  753. }
  754. }
  755. const calcDomZoom = () => {
  756. nextTick(() => {
  757. let maxWidth = 68;
  758. var textWidth = document.querySelector('.text').offsetWidth;
  759. if(textWidth > 68) {
  760. var scale = maxWidth / textWidth;
  761. document.querySelector('.text').style.zoom = scale;
  762. }
  763. })
  764. }
  765. const resetFormIpt = () => {
  766. baseFormData.amountValue = "";
  767. baseFormData.totalCount = "";
  768. }
  769. const setLocalSelectCurrencyInfo = (params = {}) => {
  770. setChromeStorage({ selectCurrencyInfo : JSON.stringify(params)})
  771. }
  772. const setCurrentCurrencyListInfo = (params = {}) => {
  773. setChromeStorage({ selectCurrencyList : JSON.stringify(params)})
  774. }
  775. /**
  776. * 获取完货币列表
  777. */
  778. const setCurrentCurrencyInfo = (params) => {
  779. }
  780. const messageBoxBlock = ({ title = "", content = "" }) => {
  781. showMessageBox.value = true;
  782. messageBoxData.value.title = title;
  783. messageBoxData.value.content = content;
  784. };
  785. /**
  786. * 确定
  787. */
  788. const messageBoxConfirm = () => {
  789. showMessageBox.value = false;
  790. goTopUp();
  791. };
  792. /**
  793. * 取消
  794. */
  795. const messageBoxCancel = () => {
  796. currentCurrencyInfo.value = tempCurrentCurrencyInfo.value;
  797. setLocalSelectCurrencyInfo(currentCurrencyInfo.value);
  798. setCurrentCurrencyListInfo(tempCurrentCurrencyList.value);
  799. showMessageBox.value = false;
  800. showCurrencyPop.value = false;
  801. showCurrencySelect.value = false;
  802. calcDomZoom();
  803. resetFormIpt();
  804. onIptSetErrorTxt();
  805. };
  806. /**
  807. * 去充值
  808. */
  809. const goTopUp = () => {
  810. Report.reportLog({
  811. pageSource: Report.pageSource.rechargePage,
  812. businessType: Report.businessType.pageView,
  813. });
  814. showComType.value = 'topUp';
  815. }
  816. /**
  817. * 充值done事件
  818. */
  819. const topUpDone = () => {
  820. currentCurrencyInfo.value = tempCurrentCurrencyInfo.value;
  821. asyncIng.value = true;
  822. depositGuide.value = false;
  823. asyncIng.value = false;
  824. showCurrencyPop.value = false;
  825. showCurrencySelect.value = false;
  826. showComType.value = 'default';
  827. calcDomZoom();
  828. onIptSetErrorTxt()
  829. asyncTokenRechRecord((res) => {
  830. if(res.code == 0 && res.data && res.data.length) {
  831. let currencyInfo = res.data[0];
  832. if(currencyInfo.currencyCode == currentCurrencyInfo.value.currencyCode) {
  833. currentCurrencyInfo.value.balance = currencyInfo.balance;
  834. onIptSetErrorTxt()
  835. }
  836. }
  837. })
  838. }
  839. /**
  840. * 更新货币余额
  841. */
  842. const updateCurrencyBanlce = () => {
  843. if(!refreshRotate.value) {
  844. refreshRotate.value = true;
  845. setTimeout(() => {
  846. refreshRotate.value = false;
  847. }, 1000)
  848. }
  849. asyncTokenRechRecord((res) => {
  850. if(res.code == 0 && res.data && res.data.length) {
  851. let currencyInfo = res.data[0];
  852. if(currencyInfo.currencyCode == currentCurrencyInfo.value.currencyCode) {
  853. currentCurrencyInfo.value.balance = currencyInfo.balance;
  854. }
  855. }
  856. })
  857. }
  858. /**
  859. * 同步链上交易
  860. */
  861. const asyncTokenRechRecord = (cb) => {
  862. syncChainTokenRechargeRecord({
  863. params: {
  864. currencyCode: currentCurrencyInfo.value.currencyCode
  865. }
  866. }).then(res => {
  867. cb && cb(res)
  868. })
  869. }
  870. /**
  871. * 提交表单请求
  872. */
  873. const submitRequest = async () => {
  874. let { amountValue = 0, totalCount = 0 } = baseFormData;
  875. baseFormData.amountCurrencyCode = currentCurrencyInfo.value.currencyCode;
  876. // 组装提交参数
  877. let finishConditions = [];
  878. for (let i = 0; i < formList.length; i++) {
  879. let item = {};
  880. item.type = formList[i]["type"];
  881. if (item.type == 1 && atUserList.value.length) {
  882. // follow 参数
  883. let relatedUsers = atUserList.value;
  884. item.relatedUsers = relatedUsers;
  885. finishConditions.push(item);
  886. } else if (formList[i]["type"] == 7) {
  887. // join discord
  888. if(formList[i]["checked"] && formList[i]["text"]) {
  889. item.bizData = JSON.stringify({inviteUrl: formList[i]["text"]});
  890. finishConditions.push(item);
  891. }
  892. } else if (formList[i]["checked"]) {
  893. // 其余任务
  894. finishConditions.push(item);
  895. }
  896. }
  897. let receiveConditions = openAntiBot.value ? "" : [];
  898. // 提交参数
  899. let formData = {
  900. amountCurrencyCode: baseFormData.amountCurrencyCode,
  901. amountValue,
  902. totalCount,
  903. finishConditions,
  904. receiveConditions,
  905. payAmountValue: amountValue
  906. };
  907. submitIng.value = true;
  908. // 法币支付需要计算费率
  909. if(formData.amountCurrencyCode == "USD") {
  910. let payAmountRes = await getPayAmount(amountValue);
  911. formData["payAmountValue"] = payAmountRes.finalAmountValue;
  912. }
  913. let data = {
  914. params: {
  915. postBizData: JSON.stringify(formData),
  916. postSrc: 1, //1 twitter
  917. postType: 1, //1 红包
  918. },
  919. };
  920. postPublish(data).then((res) => {
  921. submitIng.value = false;
  922. if (res.code == 0) {
  923. publishRes = res.data;
  924. postId.value = res.data.postId;
  925. Report.reportLog({
  926. pageSource: Report.pageSource.previewPage,
  927. businessType: Report.businessType.pageView,
  928. });
  929. showComType.value = "preview";
  930. previewFontSize.value = calcFontSize(baseFormData.amountValue, 238, 56);
  931. isBack.value = false;
  932. } else {
  933. console.log(res);
  934. }
  935. })
  936. .catch((err) => {
  937. console.log(err);
  938. });
  939. };
  940. const calcFontSize = (str, domWidth, maxSize) => {
  941. let lenstr = str.length;
  942. let num = parseInt(domWidth / lenstr);
  943. let fontSize = num < maxSize ? num : maxSize
  944. return fontSize;
  945. }
  946. /**
  947. * 初始化提交参数
  948. */
  949. const initParams = () => {
  950. resetFormIpt();
  951. // clear follow value
  952. atUserList.value = [];
  953. submitIng.value = false;
  954. isBack.value = false;
  955. showCurrencyPop.value = false;
  956. showCurrencySelect.value = false;
  957. openAntiBot.value = false;
  958. tempCurrentCurrencyInfo.value = {};
  959. currentCurrencyInfo.value = {};
  960. // clear discord value
  961. setDiscordIptTxt({text: ''});
  962. discordInviteInfo.value = {};
  963. };
  964. const setDiscordIptTxt = ({text}) => {
  965. const index = formList.findIndex(item => item.type == 7);
  966. formList[index]['text'] = text;
  967. }
  968. /**
  969. * 支付完成回调
  970. */
  971. const payPalFinsh = (params) => {
  972. let {payNetwork, payStatus} = params;
  973. // token 支付
  974. if(payNetwork == 'bsc') {
  975. payStatusHandle(payStatus);
  976. } else {
  977. // 法币支付
  978. let transaction = params.transaction;
  979. let loadingInstance = ElLoading.service({
  980. background: "rgba(0,0,0,.3)",
  981. });
  982. verifyPaypalResult({
  983. params: {
  984. paypalTransactionId: transaction.id,
  985. postId: publishRes.postId,
  986. paypalClientId: paypalClientId.value,
  987. },
  988. }).then((res) => {
  989. loadingInstance.close();
  990. if (res.code == 0) {
  991. if (res.data) {
  992. payStatusHandle(res.data.payStatus)
  993. }
  994. }
  995. })
  996. .catch(() => {
  997. loadingInstance.close();
  998. });
  999. }
  1000. };
  1001. const payStatusHandle = (payStatus) => {
  1002. //支付状态 0:未支付,1:支付成功,2:支付失败,3:已关闭,4:已退款
  1003. switch (payStatus) {
  1004. case 1:
  1005. emits("payPalFinsh", { publishRes });
  1006. showComType.value = "default";
  1007. initParams();
  1008. break;
  1009. case 2:
  1010. // ElMessage({
  1011. // message: "Pay Fail",
  1012. // type: "warning",
  1013. // });
  1014. break;
  1015. case 3:
  1016. // ElMessage({
  1017. // message: "Pay Exceptions",
  1018. // type: "warning",
  1019. // });
  1020. break;
  1021. case 4:
  1022. // ElMessage({
  1023. // message: "Pay Exceptions",
  1024. // type: "warning",
  1025. // });
  1026. break;
  1027. }
  1028. }
  1029. /**
  1030. * follow组件触发新增关注人
  1031. */
  1032. const addFollowUser = (params) => {
  1033. atUserList.value.push(params);
  1034. };
  1035. const setFollowUser = (params) => {
  1036. atUserList.value[params.index]["name"] = params.name;
  1037. };
  1038. const delFollowUser = (params) => {
  1039. atUserList.value.splice(params.index, 1);
  1040. };
  1041. const onAmountInput = () => {
  1042. let val = baseFormData.amountValue;
  1043. // val = val.replace(/[^\d^\.]+/g, "");
  1044. val = val.replace(/^\D*(\d*(?:\.\d{0,18})?).*$/g, '$1');
  1045. if(val == '00') {
  1046. val = '0'
  1047. }
  1048. if(val.indexOf('.') > -1){ //校验 例:00.12 => 0.12
  1049. let arr = val.split('.');
  1050. if(arr[0].startsWith('0')) {
  1051. let num = +arr[0];
  1052. val = num + '.' + arr[1];
  1053. }
  1054. }
  1055. baseFormData.amountValue = val;
  1056. setInputErrorMsg({from: 'amount', type:'input'});
  1057. return val;
  1058. };
  1059. const onCountInput = () => {
  1060. let val = baseFormData.totalCount;
  1061. if (val == 0) {
  1062. val = "";
  1063. }
  1064. // val = val.replace(/[^\d]/g, "");
  1065. val = val.replace(/^\D*(\d*(?:\.\d{0,18})?).*$/g, '$1');
  1066. baseFormData.totalCount = val;
  1067. setInputErrorMsg({from: 'count', type:'input'});
  1068. return val;
  1069. };
  1070. /**
  1071. * 金额输入失焦
  1072. */
  1073. const onAmountBlur = () => {
  1074. setInputErrorMsg({from: 'amount', type:'blur'});
  1075. };
  1076. /**
  1077. * count失焦,校验输入结果
  1078. */
  1079. const onCountBlur = () => {
  1080. setInputErrorMsg({from: 'count', type:'blur'});
  1081. };
  1082. /**
  1083. * 输入结果金额和数量 (金额/数量)是否小于最小货币单位
  1084. */
  1085. const calcIptValue = (cb) => {
  1086. let amountValue = baseFormData.amountValue;
  1087. let totalCount = baseFormData.totalCount;
  1088. let flag = true;
  1089. if (!amountValue || !totalCount) {
  1090. return {
  1091. flag
  1092. };
  1093. }
  1094. if (math.format(math.evaluate(`${baseFormData.amountValue} / ${baseFormData.totalCount}`)) < +currentCurrencyInfo.value.minAmount) {
  1095. flag = false;
  1096. }
  1097. return {
  1098. flag,
  1099. count: Math.floor(math.format(math.evaluate(`${baseFormData.amountValue} / ${currentCurrencyInfo.value.minAmount}`)))
  1100. }
  1101. };
  1102. /**
  1103. * 设置输入提示语
  1104. */
  1105. const setInputErrorMsg = () => {
  1106. onIptSetErrorTxt();
  1107. };
  1108. /**
  1109. * 输入时 检测设置错误信息
  1110. */
  1111. const onIptSetErrorTxt = (params = {}) => {
  1112. depositGuide.value = false;
  1113. if(!currentCurrencyInfo.value.currencyCode) {
  1114. iptErrMsgTxt.value = "Select a reward"
  1115. } else if (!baseFormData.amountValue || baseFormData.amountValue == '0') {
  1116. iptErrMsgTxt.value = "Enter an amount";
  1117. } else if (!baseFormData.totalCount || baseFormData.totalCount == '0') {
  1118. iptErrMsgTxt.value = "Enter the number of winners";
  1119. } else if(+baseFormData.amountValue <= +currentCurrencyInfo.value.balance) {
  1120. let res = calcIptValue();
  1121. if (!res.flag) {
  1122. iptErrMsgTxt.value = `${baseFormData.amountValue} ${currentCurrencyInfo.value.tokenSymbol} Can send up to ${res.count} winners`;
  1123. } else {
  1124. iptErrMsgTxt.value = "";
  1125. if(params.actionType != 'discord_blur') {
  1126. setDiscordErrTxt({getDuildId: true});
  1127. }
  1128. }
  1129. } else {
  1130. setDiscordErrTxt({getDuildId: true}, () => {
  1131. iptErrMsgTxt.value = '';
  1132. });
  1133. }
  1134. }
  1135. /**
  1136. * 监听开关触发事件
  1137. */
  1138. const formSwitchChange = (val, params, index) => {
  1139. closeDiscordTask(val, params, index);
  1140. }
  1141. const hideTask = (params, index) => {
  1142. formList[index]['checked'] = false;
  1143. formList[index]['show'] = false;
  1144. closeDiscordTask(false, {type: 7}, index)
  1145. }
  1146. const clickDropdown = (params, index) => {
  1147. formList[index]['show'] = true;
  1148. formList[index]['checked'] = true;
  1149. }
  1150. const closeDiscordTask = (val, params, index) => {
  1151. if(params.type == 7) {
  1152. if(!val) {
  1153. //错误类型 discord 清空discord错误校验
  1154. if(iptErrType == 'discord') {
  1155. iptErrMsgTxt.value = '';
  1156. formList[index]['text'] = '';
  1157. onIptSetErrorTxt();
  1158. }
  1159. } else {
  1160. onIptSetErrorTxt();
  1161. }
  1162. }
  1163. }
  1164. /** 监听 discord 输入 */
  1165. const onIptDiscordAddress = (e, index) => {
  1166. let val = formList[index].text;
  1167. let checked = formList[index].checked;
  1168. if(val && !checked) {
  1169. checked = true;
  1170. formList[index].checked = checked;
  1171. formList[index].text = formList[index].text.replace(/\s/g,'');
  1172. } else if(!val){
  1173. discordInviteInfo.value = {};
  1174. }
  1175. onIptDiscordDebounce()
  1176. }
  1177. const onBlurDiscordAddress = (e, index) => {
  1178. setDiscordErrTxt({fromType: 'discord', showPop: false, actionType: 'discord_blur'});
  1179. }
  1180. const getDiscordIptData = () => {
  1181. let discordItem = formList.find(item => item.type == 7);
  1182. return discordItem;
  1183. }
  1184. /**
  1185. * 设置输入discord错误提示信息
  1186. */
  1187. const setDiscordErrTxt = (params = {showPop: false}, cb) => {
  1188. let discordData = getDiscordIptData() || {};
  1189. if(discordData.checked) {
  1190. if(discordData.text) {
  1191. let validata = checkInviteUrl(discordData.text);
  1192. if(validata) {
  1193. getDiscordInviteInfo({inviteUrl: discordData.text, getDuildId: params.getDuildId}, (res) => {
  1194. console.log('discordData',res)
  1195. // 未知的邀请链接
  1196. if(res.inviteCode != res.data.code || !res.data.guildId) {
  1197. iptErrMsgTxt.value = discordIptErrTxt;
  1198. iptErrType = 'discord';
  1199. } else {
  1200. if(res.data.expires !== null) {
  1201. // 不是永久邀请链接
  1202. iptErrMsgTxt.value = discordIptNerverExpiresErrTxt;
  1203. iptErrType = '';
  1204. } else {
  1205. if(iptErrMsgTxt.value) {
  1206. iptErrMsgTxt.value = '';
  1207. iptErrType = '';
  1208. }
  1209. if(params.showPop && res.data) {
  1210. showDiscordInvitePop.value = true;
  1211. setTimeout(() => {
  1212. showDiscordInvitePop.value = false;
  1213. }, 2000)
  1214. }
  1215. if(params.fromType == 'discord') {
  1216. onIptSetErrorTxt();
  1217. }
  1218. }
  1219. }
  1220. cb && cb(res)
  1221. })
  1222. } else {
  1223. iptErrMsgTxt.value = discordIptErrTxt;
  1224. iptErrType = 'discord';
  1225. }
  1226. } else {
  1227. if(params.actionType == 'discord_blur') {
  1228. onIptSetErrorTxt({acitonType: 'discord_blur'});
  1229. } else {
  1230. // 设置空提示
  1231. iptErrMsgTxt.value = discordIptEmptyErrTxt;
  1232. iptErrType = 'discord';
  1233. }
  1234. }
  1235. } else {
  1236. cb && cb();
  1237. }
  1238. }
  1239. const onIptDiscordDebounce = debounce(function() {
  1240. setDiscordErrTxt({fromType: 'discord', showPop: true});
  1241. }, 800)
  1242. /**
  1243. * 校验 discord邀请url
  1244. */
  1245. const checkInviteUrl = (inviteUrl) => {
  1246. let flag = false;
  1247. const INVITE_URL_PREFIX_1 = 'https://discord.gg/';
  1248. const INVITE_URL_PREFIX_2 = 'https://discord.com/invite/';
  1249. const INVITE_URL_PREFIX_3 = 'http://discord.gg/';
  1250. const INVITE_URL_PREFIX_4 = 'http://discord.com/invite/';
  1251. const INVITE_URL_PREFIX_5 = 'discord.gg/';
  1252. const INVITE_URL_PREFIX_6 = 'discord.com/invite/';
  1253. const arr = [INVITE_URL_PREFIX_1, INVITE_URL_PREFIX_2, INVITE_URL_PREFIX_3, INVITE_URL_PREFIX_4, INVITE_URL_PREFIX_5, INVITE_URL_PREFIX_6]
  1254. if(inviteUrl) {
  1255. if(arr.indexOf(inviteUrl) > -1) {
  1256. flag = false;
  1257. } else {
  1258. let isPass = false;
  1259. for(let i = 0; i < arr.length; i++) {
  1260. let item = arr[i];
  1261. if(inviteUrl.startsWith(item)) {
  1262. isPass = true;
  1263. break;
  1264. }
  1265. }
  1266. flag = isPass;
  1267. }
  1268. }
  1269. return flag;
  1270. }
  1271. /**获取discord 邀请信息 */
  1272. const getDiscordInviteInfo = ({inviteUrl, getDuildId}, cb) => {
  1273. if(!inviteUrl) return;
  1274. let inviteCode = '';
  1275. let arr = inviteUrl.split('/');
  1276. if(arr.length > 0) {
  1277. inviteCode = arr[arr.length - 1];
  1278. }
  1279. if(!getDuildId && discordInviteInfo.value.guildId && discordInviteInfo.value.inviteCode == inviteCode) {
  1280. return;
  1281. }
  1282. getInviteGuildInfo({
  1283. inviteCode
  1284. }).then(res => {
  1285. if(!res) {
  1286. res = {};
  1287. }
  1288. let {name, icon, id} = res.guild || {};
  1289. icon = icon && id ? `https://cdn.discordapp.com/icons/${id}/${icon}.png` : '';
  1290. let resData = {
  1291. inviteCode,
  1292. data: {
  1293. code: res.code,
  1294. guildId: id,
  1295. inviteUrl,
  1296. inviteCode,
  1297. expires: res.expires_at,
  1298. name,
  1299. icon,
  1300. }
  1301. }
  1302. discordInviteInfo.value = resData.data;
  1303. cb && cb(resData);
  1304. }).catch((err) => {
  1305. if(iptErrMsgTxt.value && iptErrType == 'discord') {
  1306. iptErrMsgTxt.value = '';
  1307. iptErrType = '';
  1308. }
  1309. });
  1310. }
  1311. /**
  1312. * 获取支付配置(paypalClientId)
  1313. */
  1314. const setPayConfig = () => {
  1315. getPayConfig({
  1316. params: {},
  1317. }).then((res) => {
  1318. if (res.code == 0) {
  1319. payConfig.value = res.data;
  1320. paypalClientId.value = res.data.paypalClientId;
  1321. }
  1322. });
  1323. };
  1324. /**
  1325. * 获取配置
  1326. */
  1327. const setFrontConfig = () => {
  1328. getFrontConfig({
  1329. params: {},
  1330. }).then((res) => {
  1331. if (res.code == 0) {
  1332. paypalHtml.value = res.data.paypalHtml;
  1333. }
  1334. });
  1335. };
  1336. const goTransactionsList = () => {
  1337. window.open(`${chrome.runtime.getURL('/iframe/home.html#/transactions')}`)
  1338. }
  1339. /**
  1340. * 默认获取上次选中的货币信息
  1341. */
  1342. const getLocalCurrencyInfoByCode = () => {
  1343. if(!currentCurrencyInfo.value.currencyCode) {
  1344. getCurrencyInfo();
  1345. }
  1346. }
  1347. const getCurrencyInfo = async () => {
  1348. let {accessToken = ''} = await getChromeStorage('userInfo') || {};
  1349. if (accessToken) {
  1350. getChromeStorage('selectCurrencyInfo', (res) => {
  1351. if(res && res.currencyCode) {
  1352. getCurrencyInfoByCode({
  1353. params: {
  1354. currencyCode: res.currencyCode
  1355. }
  1356. }).then(res => {
  1357. if(res.code == 0 && res.data) {
  1358. currentCurrencyInfo.value = res.data;
  1359. tempCurrentCurrencyInfo.value = res.data;
  1360. onIptSetErrorTxt();
  1361. }
  1362. });
  1363. }
  1364. })
  1365. getChromeStorage('selectCurrencyList', (res) => {
  1366. tempCurrentCurrencyList.value = res;
  1367. })
  1368. }
  1369. }
  1370. onMounted(() => {
  1371. setFrontConfig();
  1372. setPayConfig();
  1373. getLocalCurrencyInfoByCode();
  1374. document.onkeydown = function (e) {
  1375. var keyNum = window.event ? e.keyCode : e.which;
  1376. let escKey = 27;
  1377. if (keyNum == escKey) {
  1378. if (visible.value) {
  1379. // close();
  1380. }
  1381. }
  1382. };
  1383. window.addEventListener('resize', function () {
  1384. setDialogHeight(true);
  1385. })
  1386. });
  1387. </script>
  1388. <style lang="scss" scoped>
  1389. .overlay {
  1390. position: fixed;
  1391. top: 0;
  1392. right: 0;
  1393. bottom: 0;
  1394. left: 0;
  1395. z-index: 1000;
  1396. height: 100%;
  1397. background-color: rgba(0, 0, 0, 0.5);
  1398. overflow: auto;
  1399. .content {
  1400. height: 620px;
  1401. background: #ffffff;
  1402. border-radius: 20px;
  1403. position: absolute;
  1404. left: 50%;
  1405. top: 50%;
  1406. transform: translate(-50%, -50%);
  1407. box-sizing: border-box;
  1408. z-index: 2000;
  1409. .pop-mask {
  1410. width: 100%;
  1411. height:100%;
  1412. position: absolute;
  1413. z-index:900;
  1414. }
  1415. .head {
  1416. border-bottom: 1px solid #ececec;
  1417. height: 48px;
  1418. box-sizing: border-box;
  1419. display: flex;
  1420. align-items: center;
  1421. justify-content: space-between;
  1422. padding: 0 14px;
  1423. .left {
  1424. display: flex;
  1425. align-items: center;
  1426. .title {
  1427. font-size: 16px;
  1428. font-weight: 500;
  1429. }
  1430. .close-btn {
  1431. display: flex;
  1432. align-items: center;
  1433. width: max-content;
  1434. margin-right: 12px;
  1435. cursor: pointer;
  1436. }
  1437. }
  1438. .right {
  1439. .more {
  1440. cursor: pointer;
  1441. }
  1442. .area-option {
  1443. width: 100%;
  1444. height: 100%;
  1445. position: absolute;
  1446. top: 0;
  1447. left: 0;
  1448. z-index: 111;
  1449. .option {
  1450. position: absolute;
  1451. top: 43px;
  1452. right: 15px;
  1453. background: #fff;
  1454. filter: drop-shadow(0px 3px 20px rgba(0, 0, 0, 0.2));
  1455. width: 240px;
  1456. border-radius: 15px;
  1457. overflow: hidden;
  1458. .item {
  1459. width: 100%;
  1460. height: 50px;
  1461. display: flex;
  1462. align-items: center;
  1463. cursor: pointer;
  1464. border-top: 1px solid #E9E9E9;
  1465. img {
  1466. margin-left: 15px;
  1467. width: 30px;
  1468. height: 30px;
  1469. margin-right: 6px;
  1470. }
  1471. span {
  1472. font-weight: 500;
  1473. font-size: 14px;
  1474. }
  1475. }
  1476. .item:first-child {
  1477. border-top: 0;
  1478. }
  1479. .item:hover {
  1480. background: #F5F5F5;
  1481. }
  1482. }
  1483. }
  1484. }
  1485. }
  1486. .body {
  1487. box-sizing: border-box;
  1488. height: calc(100% - 48px);
  1489. display: flex;
  1490. position: relative;
  1491. .icon-guide-select {
  1492. width: 40px;
  1493. position: absolute;
  1494. top: 78px;
  1495. left: 25px;
  1496. z-index: 1000;
  1497. }
  1498. .body-content {
  1499. display:flex;
  1500. width:100%;
  1501. }
  1502. .currency-pop {
  1503. position: absolute;
  1504. width: 375px;
  1505. height: 480px;
  1506. top: 85px;
  1507. left: 88px;
  1508. z-index: 1000;
  1509. box-shadow: 0px 4px 30px rgba(0, 0, 0, 0.3);
  1510. background-color: #fff;
  1511. border-radius: 20px;
  1512. overflow-y: scroll;
  1513. }
  1514. .currency-pop-select {
  1515. position: absolute;
  1516. width: 375px;
  1517. max-height: 480px;
  1518. top: 85px;
  1519. left: 88px;
  1520. z-index: 1000;
  1521. box-shadow: 0px 4px 30px rgba(0, 0, 0, 0.3);
  1522. background-color: #fff;
  1523. border-radius: 20px;
  1524. overflow-y: scroll;
  1525. }
  1526. .left,
  1527. .right {
  1528. height: 100%;
  1529. }
  1530. .left {
  1531. width: 50px;
  1532. display: flex;
  1533. flex-direction: column;
  1534. justify-content: space-between;
  1535. align-items: center;
  1536. .gift-pack-wrapper {
  1537. width: 100%;
  1538. height: 55px;
  1539. background: #f5f5f5;
  1540. display: flex;
  1541. align-items: center;
  1542. justify-content: center;
  1543. }
  1544. .bottom {
  1545. .icon {
  1546. display: block;
  1547. margin-bottom: 26px;
  1548. }
  1549. }
  1550. }
  1551. .right {
  1552. width: calc(100% - 50px);
  1553. box-sizing: border-box;
  1554. position: relative;
  1555. border-left: 1px solid #ececec;
  1556. .form-wrapper {
  1557. padding: 0px 18px 18px 18px;
  1558. height: calc(100% - 80px);
  1559. overflow-y: scroll;
  1560. overflow-x: hidden;
  1561. box-sizing: border-box;
  1562. .img-mode {
  1563. margin-left: -18px;
  1564. }
  1565. .form-base-help {
  1566. display: flex;
  1567. justify-content: space-between;
  1568. margin-top: 10px;
  1569. .currency-operation:before{
  1570. box-sizing: content-box;
  1571. width: 0px;
  1572. height: 0px;
  1573. position: absolute;
  1574. top: -16px;;
  1575. left:46px;
  1576. padding:0;
  1577. border-bottom:8px solid #FFFFFF;
  1578. border-top:8px solid transparent;
  1579. border-left:8px solid transparent;
  1580. border-right:8px solid transparent;
  1581. display: block;
  1582. content:'';
  1583. z-index: 12;
  1584. }
  1585. .currency-operation:after{
  1586. box-sizing: content-box;
  1587. width: 0px;
  1588. height: 0px;
  1589. position: absolute;
  1590. top: -18px;;
  1591. left:45px;
  1592. padding:0;
  1593. border-bottom:9px solid #EAEAEA;
  1594. border-top:9px solid transparent;
  1595. border-left:9px solid transparent;
  1596. border-right:9px solid transparent;
  1597. display: block;
  1598. content:'';
  1599. z-index:10
  1600. }
  1601. .currency-operation {
  1602. position: relative;
  1603. height: 36px;
  1604. border: 1px solid #EAEAEA;
  1605. box-sizing: border-box;
  1606. padding: 10px;
  1607. display: flex;
  1608. align-items: center;
  1609. border-radius: 100px;
  1610. .balance,
  1611. .amount {
  1612. display: flex;
  1613. align-items: center;
  1614. }
  1615. .balance {
  1616. font-weight: 400;
  1617. font-size: 13px;
  1618. img {
  1619. width: 16px;
  1620. height: 16px;
  1621. margin-right: 3px;
  1622. }
  1623. }
  1624. .amount {
  1625. font-weight: 500;
  1626. font-size: 13px;
  1627. color: #4e4e4e;
  1628. margin-left: 5px;
  1629. img {
  1630. margin-left: 5px;
  1631. cursor: pointer;
  1632. }
  1633. }
  1634. .top-up {
  1635. font-weight: 500;
  1636. font-size: 12px;
  1637. color: #ff9839;
  1638. cursor: pointer;
  1639. margin-left: 8px;
  1640. }
  1641. }
  1642. .msg {
  1643. font-weight: 400;
  1644. font-size: 12px;
  1645. color: #acacac;
  1646. }
  1647. }
  1648. .form-base {
  1649. display: flex;
  1650. justify-content: space-between;
  1651. align-items: center;
  1652. margin-top: 14px;
  1653. .item {
  1654. width: 250px;
  1655. height: 50px;
  1656. box-sizing: border-box;
  1657. border-radius: 14px;
  1658. border: 1px solid #D1D9DD;
  1659. display: flex;
  1660. align-items: center;
  1661. justify-content: space-between;
  1662. padding: 16px 14px;
  1663. input {
  1664. width: 102px;
  1665. text-align: right;
  1666. font-weight: 500;
  1667. font-size: 18px;
  1668. border: none;
  1669. outline: none;
  1670. box-sizing: border-box;
  1671. }
  1672. input::placeholder {
  1673. color: #c5c5c5;
  1674. }
  1675. .label {
  1676. font-weight: 500;
  1677. font-size: 15px;
  1678. display: flex;
  1679. align-items: center;
  1680. .icon {
  1681. width: 20px;
  1682. height: 20px;
  1683. margin-right: 8px;
  1684. }
  1685. }
  1686. }
  1687. .item:first-child {
  1688. margin-right: 14px
  1689. }
  1690. .currency-select-wrapper {
  1691. padding: 0 !important;
  1692. input {
  1693. padding-right: 14px;
  1694. }
  1695. .currency-select {
  1696. max-width: 136px;
  1697. cursor: pointer;
  1698. background: #1D9BF0;
  1699. margin-left: 6px;
  1700. padding: 6px 10px;
  1701. border-radius: 12px;
  1702. color: #fff;
  1703. .text {
  1704. white-space: nowrap;
  1705. zoom: 0.85;
  1706. }
  1707. .arrow {
  1708. margin-left: 5px;
  1709. }
  1710. }
  1711. .selected {
  1712. background: #F4F4F4 !important;
  1713. color: #000 !important;
  1714. }
  1715. }
  1716. }
  1717. .form-label {
  1718. margin-top: 14px;
  1719. margin-bottom: 10px;
  1720. font-weight: 500;
  1721. font-size: 14px;
  1722. display: flex;
  1723. align-items: center;
  1724. justify-content: space-between;
  1725. .icon-add-task {
  1726. cursor: pointer;
  1727. }
  1728. }
  1729. .form-require {
  1730. box-sizing: border-box;
  1731. border-radius: 15px;
  1732. margin-top: 12px;
  1733. border: 1px solid #D1D9DD;
  1734. .form-item {
  1735. min-height: 50px;
  1736. display: flex;
  1737. align-items: center;
  1738. justify-content: space-between;
  1739. margin: 0 16px;
  1740. border-bottom: 1px solid #ececec;
  1741. padding: 8px 0;
  1742. box-sizing: border-box;
  1743. .item-left {
  1744. display: flex;
  1745. }
  1746. .label {
  1747. min-width: 76px;
  1748. display: flex;
  1749. align-items: center;
  1750. font-size: 15px;
  1751. font-weight: 500;
  1752. .icon {
  1753. margin-right: 10px;
  1754. }
  1755. }
  1756. .control {
  1757. min-width: 258px;
  1758. margin-left: 18px;
  1759. box-sizing: border-box;
  1760. border-left: 1px solid #ECECEC;
  1761. position: relative;
  1762. .discord-address {
  1763. border: none;
  1764. outline: none;
  1765. color: #1D9BF0;
  1766. font-weight: 500;
  1767. font-size: 14px;
  1768. width: 100%;
  1769. height: 34px;
  1770. padding-left: 15px;
  1771. }
  1772. .discord-address::placeholder {
  1773. color: #c5c5c5;
  1774. }
  1775. .discord-invite-info {
  1776. position: absolute;
  1777. top: 40px;
  1778. left: 0;
  1779. box-shadow: 0px 4px 30px rgba(0, 0, 0, 0.3);
  1780. background: #fff;
  1781. border-radius: 16px;
  1782. padding: 16px;
  1783. box-sizing: border-box;
  1784. display: flex;
  1785. align-items: center;
  1786. cursor: pointer;
  1787. .icon {
  1788. width: 40px;
  1789. height: 40px;
  1790. margin-right: 10px;
  1791. border-radius: 50%;
  1792. }
  1793. .name {
  1794. font-weight: 600;
  1795. font-size: 16px;
  1796. color: #101419;
  1797. width: 193px;
  1798. height: 20px;
  1799. overflow: hidden;
  1800. white-space: nowrap;
  1801. text-overflow: ellipsis;
  1802. display: inline-block;
  1803. }
  1804. }
  1805. }
  1806. .icon-task-close {
  1807. margin-left: 6px;
  1808. cursor: pointer;
  1809. }
  1810. }
  1811. .border-hide {
  1812. border-bottom: none !important;
  1813. }
  1814. }
  1815. }
  1816. .anti-bot-wrapper {
  1817. width: 100%;
  1818. height: 50px;
  1819. display: flex;
  1820. align-items: center;
  1821. justify-content: space-between;
  1822. box-sizing: border-box;
  1823. border-radius: 15px;
  1824. padding: 0 18px;
  1825. margin-top: 14px;
  1826. border: 1px solid #D1D9DD;
  1827. .label {
  1828. display: flex;
  1829. align-items: center;
  1830. font-size: 15px;
  1831. font-weight: 500;
  1832. .icon-bot {
  1833. margin-right: 8px;
  1834. }
  1835. .icon-beta {
  1836. margin-left: 5px;
  1837. margin-right: 8px;
  1838. }
  1839. .icon-question {
  1840. cursor: pointer;
  1841. }
  1842. }
  1843. }
  1844. .tips-wrapper {
  1845. margin: 16px 0 0 12px !important;
  1846. padding: 0px !important;
  1847. .title,
  1848. .row {
  1849. font-weight: 400;
  1850. font-size: 12px;
  1851. color: #A39F9F;
  1852. }
  1853. .row {
  1854. box-sizing: border-box;
  1855. line-height: 16px;
  1856. }
  1857. .more {
  1858. color: #1D9BF0;
  1859. font-size: 13px;
  1860. padding-left: 4px;
  1861. cursor: pointer;
  1862. }
  1863. }
  1864. .submit-btn-wrapper {
  1865. width: 100%;
  1866. background: #fff;
  1867. position: absolute;
  1868. bottom: 18px;
  1869. left: 0;
  1870. box-sizing: border-box;
  1871. padding: 16px 18px 0 18px;
  1872. .submit-btn {
  1873. width: 100%;
  1874. height: 46px;
  1875. text-align: center;
  1876. background: #4a99e9;
  1877. border-radius: 100px;
  1878. color: #fff;
  1879. display: flex;
  1880. align-items: center;
  1881. justify-content: center;
  1882. font-size: 16px;
  1883. font-weight: 500;
  1884. cursor: pointer;
  1885. .icon-loading {
  1886. width: 20px;
  1887. height: 20px;
  1888. margin-right: 3px;
  1889. }
  1890. }
  1891. .disabled-submit {
  1892. background-color: #D9D9D9;
  1893. }
  1894. }
  1895. }
  1896. .fill-right {
  1897. width: 100% !important;
  1898. border-bottom-left-radius: 16px;
  1899. }
  1900. }
  1901. }
  1902. }
  1903. .preview {
  1904. padding: 30px 40px;
  1905. .card {
  1906. float: left;
  1907. position: relative;
  1908. .flash {
  1909. overflow: hidden;
  1910. height: 460px;
  1911. border-radius: 26px;
  1912. border: solid 1px #ECECEC;
  1913. }
  1914. &.center {
  1915. margin-left: 50%;
  1916. transform: translateX(-50%);
  1917. }
  1918. }
  1919. .card-title {
  1920. height: 32px;
  1921. .img {
  1922. float: left;
  1923. width: 20px;
  1924. height: 20px;
  1925. margin-right: 8px;
  1926. }
  1927. .font {
  1928. float: left;
  1929. font-size: 17px;
  1930. font-weight: 500;
  1931. span {
  1932. color: #0091e9;
  1933. }
  1934. }
  1935. }
  1936. .card-content {
  1937. float: right;
  1938. width: 430px;
  1939. }
  1940. .card-amount {
  1941. overflow: hidden;
  1942. display: flex;
  1943. height: 80px;
  1944. padding: 20px;
  1945. border-radius: 20px;
  1946. border: 1px solid #E6E6E6;
  1947. .icon {
  1948. width: 40px;
  1949. height: 40px;
  1950. }
  1951. .con {
  1952. flex: 1;
  1953. padding: 0 10px;
  1954. .desc {
  1955. color: rgba($color: #000000, $alpha: 0.5);
  1956. font-size: 12px;
  1957. margin-bottom: 4px;
  1958. }
  1959. .price {
  1960. font-size: 16px;
  1961. font-weight: bold;
  1962. }
  1963. }
  1964. .refresh {
  1965. cursor: pointer;
  1966. width: 50px;
  1967. height: 50px;
  1968. margin-top: -5px;
  1969. }
  1970. }
  1971. .card-list {
  1972. padding: 20px;
  1973. border-radius: 20px;
  1974. border: 1px solid #E6E6E6;
  1975. .item {
  1976. display: flex;
  1977. justify-content: space-between;
  1978. align-items: center;
  1979. height: 47px;
  1980. font-size: 14px;
  1981. font-weight: 500;
  1982. box-shadow: inset 0px -1px 0px #EAEAEA;
  1983. }
  1984. }
  1985. }
  1986. .icon-refresh-rotate {
  1987. transform: rotate(360deg);
  1988. transition-duration: 1s;
  1989. }
  1990. .payment {
  1991. .balance {
  1992. display: flex;
  1993. margin-right: 20px;
  1994. .icon {
  1995. width: 40px;
  1996. height: 40px;
  1997. }
  1998. .con {
  1999. padding: 0 5px;
  2000. .desc {
  2001. color: rgba($color: #000000, $alpha: 0.5);
  2002. font-size: 12px;
  2003. margin-bottom: 4px;
  2004. }
  2005. .price {
  2006. font-size: 14px;
  2007. font-weight: bold;
  2008. }
  2009. }
  2010. .refresh {
  2011. width: 40px;
  2012. cursor: pointer;
  2013. margin-left: -5px;
  2014. }
  2015. }
  2016. }
  2017. </style>