| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719 | <template>    <div class="overlay" v-if="visible">        <div class="content"            :style="{height: showPreview ? previewDialogHeight + 'px' : dialogHeight +'px' }">            <div class="head">                <div class="left">                    <div class="close-btn" @click="close">                        <img class="icon-close" v-if="!showPreview" :src="require('../../assets/svg/icon-close.svg')" />                        <img class="icon-close" v-else :src="require('../../assets/svg/icon-back.svg')" />                    </div>                    <div class="title">                        Giveaways                    </div>                </div>                <!-- <img class="icon-question" :src="require('../../assets/svg/icon-question.svg')"> -->            </div>            <div class="body">                <div class="left">                    <div class="gift-pack-wrapper">                        <img class="icon" :src="require('../../assets/svg/icon-gift-pack.svg')">                    </div>                    <div class="bottom">                        <!-- <img class="icon" :src="require('../../assets/svg/icon-wallet.svg')">                        <img class="icon" :src="require('../../assets/svg/icon-setting.svg')"> -->                    </div>                </div>                <div class="right">                    <template v-if="!showPreview">                        <div class="form-wrapper">                            <div class="error-msg">                                {{iptErrMsgTxt}}                            </div>                            <div class="form-base">                                <div class="item">                                    <div class="label">                                        <img class="icon"                                            :src="require('../../assets/svg/icon-usd.svg')" />                                        USD                                    </div>                                    <el-input                                        v-model="baseFormData.amountValue"                                        placeholder="Amount entered"                                        autofocus                                        @input = "onUsdInput"                                        @blur = "onUsdBlur"                                        :input-style="{ 'box-shadow': 'none','padding': '1px', 'width': '110px', 'text-align': 'right', 'font-size' : '15px', 'color': '#000' }"/>                                </div>                                <div class="item">                                    <div class="label">                                        <img class="icon"                                            :src="require('../../assets/svg/icon-quantity.svg')" />                                        Quantity                                        </div>                                    <el-input                                        v-model="baseFormData.totalCount"                                        placeholder="Quantity entered"                                        @input = "onCountInput"                                        @blur = "onCountBlur"                                        :input-style="{ 'box-shadow': 'none','padding': '1px', 'width': '120px',                                        'text-align': 'right', 'font-size' : '15px', 'color': '#000'}"/>                                </div>                            </div>                            <div class="form-label">                                Requirement                            </div>                            <div class="form-require">                                <div                                    class="form-item"                                    v-for="(item, index) in formList"                                    :key="index">                                    <div class="label">                                        <img class="icon"                                            :src="item.icon" />                                        {{ item.label }}                                    </div>                                    <div class="control"  v-if="item.nodeType == 'textarea'">                                        <follow-input                                         :isAddSelf="!isBack"                                        :atUserList="atUserList"                                        @addUser="addFollowUser" @setUser="setFollowUser"                                        @delUser="delFollowUser"></follow-input>                                    </div>                                    <el-switch v-if="item.type == 2" v-model="item.checked" />                                </div>                            </div>                            <div class="anti-bot-wrapper">                                <div class="label">                                    <img :src="require('../../assets/svg/icon-anti-bot.svg')" class="icon-bot">                                    Anti Bot                                    <img :src="require('../../assets/svg/icon-beta.svg')" class="icon-beta">                                    <img :src="require('../../assets/svg/icon-question.svg')" class="icon-question">                                </div>                                <el-switch v-model="openAntiBot" />                            </div>                            <div class="tips-wrapper">                                <div class="title">                                    TIPS                                </div>                                <div class="row">                                    1. Only after the user completes the tasks you set, they can claim your red envelopes                                </div>                                <div class="row">                                    2. Each user can only receive one red envelope                                </div>                                <div class="row">                                    3. The red envelope issued is valid for 7 days. Please promote your red envelope as much as possible within the validity period. After the red envelope expires, the red envelope will be returned to your DeNet wallet.                                </div>                                <div class="more">                                    More                                </div>                            </div>                            <div class="submit-btn-wrapper">                                <div class="submit-btn" @click="confirm">                                    <img class="icon-loading" v-if="submitIng" :src="require('../../assets/svg/icon-btn-loading.svg')"  />                                    NEXT                                </div>                            </div>                        </div>                    </template>                    <template v-if="showPreview">                        <preview-card :postData="publishRes" :baseFormData="baseFormData"></preview-card>                    </template>                    <div v-show="showPreview">                        <paypal-button :finalAmountData="finalAmountData" @payPalFinsh="payPalFinsh"></paypal-button>                    </div>                </div>            </div>        </div>    </div></template><script setup>import { ref, watch, reactive, defineProps, defineEmits, onMounted } from "vue";import {postPublish, verifyPaypalResult} from "../../http/publishApi"import {payCalcFee} from "../../http/pay"import { ElMessage } from 'element-plus';import 'element-plus/es/components/message/style/css'import previewCard from "./preview-card";import paypalButton from "./paypal-button";import followInput from "./follow-input";const paypalClientId = 'ASn7k0zqyS5AWYikVSfmamR-RFpjyU_QFJWSxOHHoWE04-RgHNO6nahn0GyHUaUAEBxj-aKgtSrq4O4G';let publishRes = reactive({})let visible = ref(false);let showPreview = ref(false);let openAntiBot = ref(false);let dialogHeight = ref(680);let previewDialogHeight = ref(680);let submitIng = ref(false);let atUserList = ref([]);let iptErrMsgTxt = ref('');let isBack = ref(false);let finalAmountData = ref({    currencyCode: "USD",    feeAmountValue: 0,    finalAmountValue: 0,    requestAmountValue: 0})let baseFormData = reactive({    amountCurrencyCode: "USD",    amountValue: "",    totalCount: "",});let formList = reactive([    {        label: "Follow",        icon: require('../../assets/svg/icon-follow.svg'),        nodeType: 'textarea',        type: 1,        text: [],        checked: true    },    {        label: "Retweet",        icon: require('../../assets/svg/icon-retweet.svg'),        nodeType: 'div',        type: 3,        checked: true    },    {        label: "Like tweet",        icon: require('../../assets/svg/icon-like.svg'),        nodeType: 'div',        type: 2,        checked: true    },]);const props = defineProps({    dialogVisible: {        type: Boolean,        default: false,    },});watch(    () => props.dialogVisible,    (newVal) => {        console.log("watch", newVal);        visible.value = newVal;    });const emits = defineEmits(["close", "confirm", "payPalFinsh"]);const close = () => {    if (showPreview.value) {        showPreview.value = false;        isBack.value = true;    } else {        initParams();        emits("close", false);    }};const setPreviewDialogHeight = () => {    let clientHeight = document.documentElement.clientHeight;    let gapSafe = 40;    if(previewDialogHeight.value > clientHeight - gapSafe) {        previewDialogHeight.value = clientHeight - gapSafe;    }};const getPayAmount = (amountValue, cb) => {    payCalcFee({        params : {            amountValue,            currencyCode: "USD",            payChannel: 1        }    }).then(res => {        if(res.code == 0) {            cb && cb(res.data);            let {finalAmountValue} = res.data;            if(finalAmountValue >= 100) {                res.data.finalAmountValue = finalAmountValue / 100;                finalAmountData.value = res.data            }        }    })}const confirm = () => {    if(submitIng.value) {        return;    }    let {amountValue = 0, totalCount = 0, amountCurrencyCode} = baseFormData;    if(!totalCount) {        return;    }    amountValue = amountValue * 100; // 元转分    formList[0]['text'] = atUserList.value;    let finishConditions = [];    for(let i = 0; i < formList.length; i++) {        let item = {};        item.type = formList[i]['type'];        if(item.type == 1 && formList[i]['text']) { // follow 参数            let relatedUsers = formList[i]['text'];            item.relatedUsers = relatedUsers;            finishConditions.push(item);        } else if(formList[i]['checked']){            finishConditions.push(item);        }    }    let receiveConditions = openAntiBot.value ? '' : [];    console.log('finishConditions', finishConditions);    let formData = {        amountCurrencyCode,        amountValue,        totalCount,        finishConditions,        receiveConditions    }    if(!calcIptValue()) {        return;    }    submitIng.value = true;    getPayAmount(amountValue, (res) => {        formData['payAmountValue'] = res.finalAmountValue;        let data = {            params: {                postBizData: JSON.stringify(formData),                postSrc: 1,  //1 twitter                postType: 1, //1 红包            }        }        postPublish(data).then((res) => {            submitIng.value = false;                if(res.code == 0) {                    publishRes = res.data;                    // setPreviewDialogHeight();                    showPreview.value = true;                    isBack.value = false;                } else {                    console.log(res);                }            }).catch(err => {                console.log(err);            })        });};const calcIptValue = (cb) => {    let amountValue = baseFormData.amountValue;    let totalCount = baseFormData.totalCount;    let flag = true;    if(!amountValue || !totalCount) {        return flag;    }    //每人平均要分到大于 0.01美元(1美分)    if(amountValue / totalCount < 1) {        flag = false;    }    cb && cb(flag);    return flag}const initParams = () => {    baseFormData.amountValue = '';    baseFormData.totalCount = '';    formList[0].text = [];    atUserList.value = [];}const payPalFinsh = (params) => {    let transaction = params.transaction;    console.log('transaction', transaction)    verifyPaypalResult({        params: {            paypalTransactionId: transaction.id,            postId: publishRes.postId,            paypalClientId: paypalClientId        }    }).then((res) => {        if(res.code == 0) {            //支付状态 0:未支付,1:支付成功,2:支付失败,3:已关闭,4:已退款            if(res.data && res.data.payStatus == 1) {                emits("payPalFinsh", {publishRes});                showPreview.value = false;                initParams();            } else {                ElMessage({                    message: 'pay error',                    type: 'warning',                })            }        }    })}const addFollowUser = (params) => {    atUserList.value.push(params)}const setFollowUser = (params) => {    atUserList.value[params.index]['name'] = params.name;}const delFollowUser = (params) => {    atUserList.value.splice(params.index, 1);}const onUsdInput = (val) => {    val = val.replace(/[^\d]/g,'');    baseFormData.amountValue = val;    setIptAmountErrorMsg();    return val;}const onCountInput = (val) => {    if(val == 0) {        val = ''    }    val = val.replace(/[^\d]/g,'');    if(val > 9999) {        val = 9999;    }    baseFormData.totalCount = val;    setIptAmountErrorMsg();    return val;}const onUsdBlur = () => {    if(!baseFormData.amountValue) {        iptErrMsgTxt.value = 'Please enter the giveaways amount in USD input box.';    } else {        setIptAmountErrorMsg((res) => {            if(res) {                iptErrMsgTxt.value = '';            }        })    }}const onCountBlur = () => {    if(!baseFormData.amountValue) {        iptErrMsgTxt.value = 'Please enter the number of giveaways in Quantity input box.';    } else {        setIptAmountErrorMsg((res) => {            if(res) {                iptErrMsgTxt.value = '';            }        })    }}const setIptAmountErrorMsg = (cb) => {    let res = calcIptValue();    if(!res) {        iptErrMsgTxt.value = 'If you wish to send {100} red packets, please send USD amount > {$1.00}';    } else {        iptErrMsgTxt.value = '';    }    cb && cb(res);}onMounted(() => {    setPreviewDialogHeight();    document.onkeydown = function(e){            var keyNum=window.event ? e.keyCode :e.which;        let escKey = 27;        if(keyNum == escKey) {            if(visible.value) {                close();            }        }        console.log(keyNum)    }})</script><style lang="scss" scoped>.ql-container {    height: 100px;}.overlay {    position: fixed;    top: 0;    right: 0;    bottom: 0;    left: 0;    z-index: 1000;    height: 100%;    background-color: rgba(0, 0, 0, 0.5);    overflow: auto;    .content {        width: 650px;        height: 620px;        background: #ffffff;        border-radius: 20px;        position: absolute;        left: 50%;        top: 50%;        transform: translate(-50%, -50%);        box-sizing: border-box;        .head {            border-bottom: 1px solid #ececec;            height: 48px;            box-sizing: border-box;            display: flex;            align-items: center;            justify-content: space-between;            padding: 0 14px;            .left {                display: flex;                .title {                    font-size: 16px;                    font-weight: 500;                }                .close-btn {                    display: flex;                    align-items: center;                    width: max-content;                    margin-right: 12px;                    cursor: pointer;                }            }            .icon-question {                cursor: pointer;            }        }        .body {            box-sizing: border-box;            height: calc(100% - 48px);            display: flex;            .left,            .right {                height: 100%;            }            .left {                width: 50px;                display: flex;                flex-direction: column;                justify-content: space-between;                align-items: center;                .gift-pack-wrapper {                    width: 100%;                    height: 54px;                    background: #F5F5F5;                    display: flex;                    align-items: center;                    justify-content: center;                }                .bottom {                    .icon {                        display: block;                        margin-bottom: 26px;                    }                }            }            .right {                width: calc(100% - 50px);                box-sizing: border-box;                position: relative;                border-left: 1px solid #ececec;                .form-wrapper {                    padding: 8px 18px 26px 18px;                    height: calc(100% - 80px);                    overflow-y: scroll;                    box-sizing: border-box;                    .error-msg {                        font-size: 12px;                        color: #FF0000;                        margin-bottom: 8px;                        height: 16px;                    }                    .form-base {                        display: flex;                        justify-content: space-between;                        align-items: center;                        .item {                            width: 270px;                            height: 60px;                            box-sizing: border-box;                            border-radius: 15px;                            display: flex;                            align-items: center;                            justify-content: space-between;                            padding: 16px 14px;                            box-shadow: 0px 3px 27px 0px #0000001A;                            .label {                                font-weight: 500;                                font-size: 15px;                                display: flex;                                align-items: center;                                .icon {                                    width: 20px;                                    height: 20px;                                    margin-right: 8px;                                }                            }                        }                    }                    .form-label {                        color: rgba(0, 0, 0, 0.4);                        margin-top: 23px;                        margin-bottom: 10px;                        font-weight: 500;                        font-size: 15px;                    }                    .form-require {                        box-sizing: border-box;                        border-radius: 15px;                        margin-top: 12px;                        box-shadow: 0px 3px 27px 0px #0000001A;                        .form-item {                            min-height: 60px;                            display: flex;                            align-items: center;                            justify-content: space-between;                            margin: 0 16px;                            border-bottom: 1px solid #ececec;                            .label {                                min-width: 88px;                                display: flex;                                align-items: center;                                font-size: 15px;                                font-weight: 500;                                .icon {                                    margin-right: 10px;                                }                            }                            .control {                                width: 100%;                                min-height: 60px;                                margin-left: 18px;                                padding: 4px 0;                                box-sizing: border-box;                            }                        }                    }                }                .anti-bot-wrapper {                    width: 100%;                    height: 60px;                    display: flex;                    align-items: center;                    justify-content: space-between;                    box-sizing: border-box;                    border-radius: 15px;                    padding: 0 18px;                    margin-top: 14px;                    box-shadow: 0px 3px 27px 0px #0000001A;                    .label {                        display: flex;                        align-items: center ;                        font-size: 15px;                        font-weight: 500;                        .icon-bot {                            margin-right: 8px;                        }                        .icon-beta {                            margin-left: 5px;                            margin-right: 8px;                        }                        .icon-question {                            cursor: pointer;                        }                    }                }                .tips-wrapper {                    margin-top: 23px;                    .title, .row {                        font-weight: 400;                        font-size: 13px;                        color: rgba(0, 0, 0, 0.3);                    }                    .row {                        box-sizing: border-box;                        padding-left: 4px;                    }                    .more {                        color: #389AFF;                        font-size: 13px;                        padding-left: 4px;                        cursor: pointer;                    }                }                .submit-btn-wrapper {                    width: 100%;                    background: #fff;                    position: absolute;                    bottom: 32px;                    left: 0;                    box-sizing: border-box;                    padding-top: 16px;                    .submit-btn {                        width: calc(100% - 36px);                        height: 46px;                        text-align: center;                        line-height: 46px;                        background: #4a99e9;                        border-radius: 100px;                        color: #fff;                        margin-left: 18px;                        display: flex;                        align-items: center;                        justify-content: center;                        font-size: 16px;                        font-weight: 500;                        cursor: pointer;                                                .icon-loading {                            width: 20px;                            height: 20px;                            margin-right: 3px;                        }                    }                }            }        }    }}</style>
 |