give-dialog.vue 45 KB

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