give-dialog.vue 74 KB

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