소스 검색

Merge branch 'feature_220525_publish' into feature_220523_at_task

A\An 2 년 전
부모
커밋
a590f47028

+ 5 - 0
src/assets/svg/icon-add-task.svg

@@ -0,0 +1,5 @@
+<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="22" height="22" rx="6" fill="#1D9BF0"/>
+<line x1="6" y1="10.75" x2="16" y2="10.75" stroke="white" stroke-width="1.5"/>
+<line x1="10.9492" y1="16" x2="10.9492" y2="6" stroke="white" stroke-width="1.5"/>
+</svg>

+ 3 - 0
src/assets/svg/icon-bells.svg

@@ -0,0 +1,3 @@
+<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M15 0C6.69231 0 0 6.69231 0 15C0 23.3077 6.69231 30 15 30C23.3077 30 30 23.3077 30 15C30 6.69231 23.3077 0 15 0ZM15 23.1923C14.1923 23.1923 13.5 22.6154 13.5 21.8077C13.5 21.6923 13.6154 21.5769 13.7308 21.5769H16.3846C16.5 21.5769 16.6154 21.6923 16.6154 21.8077C16.5 22.6154 15.8077 23.3077 15 23.1923ZM21.6923 20.4231C21.6923 20.5385 21.5769 20.6538 21.4615 20.6538H8.53846C8.42308 20.6538 8.30769 20.5385 8.30769 20.4231V19.1538C8.30769 18.3462 9.23077 17.7692 10.5 17.6538C10.3846 17.1923 10.2692 16.7308 10.2692 16.2692V12.5769C10.2692 10.6154 11.6538 9 13.5 8.53846V8.19231C13.6154 7.38462 14.3077 6.69231 15.1154 6.80769C15.8077 6.92308 16.5 7.5 16.5 8.19231V8.53846C18.3462 9 19.6154 10.7308 19.7308 12.5769V16.2692C19.7308 16.7308 19.6154 17.1923 19.5 17.6538C20.7692 17.7692 21.6923 18.3462 21.6923 19.1538V20.4231Z" fill="#FFA800"/>
+</svg>

+ 4 - 0
src/assets/svg/icon-task-close.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<line y1="-0.75" x2="12.8917" y2="-0.75" transform="matrix(-0.698077 0.716023 -0.698077 -0.716023 16.4922 7)" stroke="#D9D9D9" stroke-width="1.5"/>
+<line y1="-0.75" x2="12.8917" y2="-0.75" transform="matrix(0.698074 0.716025 0.698074 -0.716025 8.49219 7)" stroke="#D9D9D9" stroke-width="1.5"/>
+</svg>

+ 9 - 1
src/entry/content.js

@@ -12,7 +12,9 @@ import {
     init,
     initExecuteScript,
     changeQueueNum,
-    replyHandle
+    replyHandle,
+    noticeBindTweet,
+    hideNoticeBindTweet
 } from "@/logic/content/twitter.js";
 
 import {
@@ -44,6 +46,12 @@ window.onmessage = (res) => {
             case "IFRAME_RED_PACKET_REPLY_CLICK":
                 replyHandle(res.data.data || {});
                 break;
+            case "IFRAME_RED_PACKET_SHOW_BIND_TWEET_NOTICE":
+                noticeBindTweet(res.data.data || {});
+                break;
+            case "IFRAME_CLOSE_BIND_TWEET":
+                hideNoticeBindTweet();
+                break;
             // case "IFRAME_DO_TASK":
             //     findTweetByIdDoTask(res.data.task_data, res.data.task_type)
             //     break

+ 10 - 0
src/iframe/bind-tweet.js

@@ -0,0 +1,10 @@
+import { createApp } from 'vue'
+import App from '@/view/iframe/bind-tweet/bind-tweet.vue'
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+
+
+const app = createApp(App);
+
+app.use(ElementPlus);
+app.mount('#app');

+ 10 - 0
src/iframe/publish-tips.js

@@ -0,0 +1,10 @@
+import { createApp } from 'vue'
+import App from '@/view/iframe/publish-tips/publish-tips.vue'
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+
+
+const app = createApp(App);
+
+app.use(ElementPlus);
+app.mount('#app');

+ 45 - 1
src/logic/content/twitter.js

@@ -72,6 +72,7 @@ export function hideIframeHandler() {
 /**
  * 展示twitter原生发布框
  */
+
 export function showTwitterPublishDialogHandler(publishRes) {
     let bigBtn = document.querySelector('a[data-testid="SideNav_NewTweet_Button"]');
     if(bigBtn) {
@@ -81,6 +82,11 @@ export function showTwitterPublishDialogHandler(publishRes) {
         smallBtn && smallBtn.click();
     }
 
+    setChromeStorage({ publishData: JSON.stringify(publishRes) })
+
+    addPublishTipsIframe({
+        srcContent: publishRes.srcContent
+    })
     _setPublishContent(publishRes.srcContent);
     _publishTweetEvent(publishRes.postId, bindTwitterArtMethod);
 }
@@ -282,6 +288,43 @@ function _addIframe() {
     }
 }
 
+function addPublishTipsIframe({srcContent}) {
+    setTimeout(() => {
+        let dialog = document.querySelector('div[role="dialog"]').querySelector('div[role="dialog"]')
+
+        if(dialog) {
+            let right = dialog.offsetLeft - 15 - 266, top = window.innerHeight * 0.05 + dialog.offsetHeight - 60 - 160;
+
+            let iframe = document.createElement('iframe');
+            iframe.id = 'de-publish-tips'
+            iframe.src = chrome.runtime.getURL('/iframe/publish-tips.html');
+            iframe.style.cssText = `border: medium none; width:266px;min-height:178px;position: fixed; right: ${right}px; top: ${top}px;`
+            let iframeContent = document.getElementById('de-publish-tips');
+            if(!iframeContent) {
+                dialog.appendChild(iframe)
+            }
+        }
+    }, 1000)
+}
+
+export function noticeBindTweet(params) {
+    let iframe = document.createElement('iframe');
+    iframe.id = 'de-notice-bind-tweet';
+    iframe.src = chrome.runtime.getURL('/iframe/bind-tweet.html') + `?params=${JSON.stringify(params)}`;
+    iframe.style.cssText = `border: medium none; width:400px;min-height:313px;position: fixed; right: 16px; top: 16px;`
+    let iframeContent = document.getElementById('de-notice-bind-tweet');
+    if(!iframeContent) {
+        document.querySelector('body').appendChild(iframe)
+    }
+}
+
+export function hideNoticeBindTweet() {
+    let iframeContent = document.getElementById('de-notice-bind-tweet');
+    if(iframeContent) {
+        document.querySelector('body').removeChild(iframeContent)
+    }
+}
+
 /**
  * 点击deNet按钮处理
  * @private
@@ -623,7 +666,8 @@ export function init() {
         }
     }, 1000);
     renderDom();
-    checkTwitterTaskState()
+    checkTwitterTaskState();
+
     getChromeStorage("popupShowPublishDialog", (res) => {
         console.log("popupShowPublishDialog", res);
         if (res && res.show) {

+ 3 - 1
src/manifest.json

@@ -54,7 +54,9 @@
             "resources": [
                 "/iframe/publish.html",
                 "/iframe/red-packet.html",
-                "/iframe/home.html"
+                "/iframe/home.html",
+                "/iframe/publish-tips.html",
+                "/iframe/bind-tweet.html"
             ],
             "matches": [
                 "<all_urls>"

+ 146 - 0
src/view/iframe/bind-tweet/bind-tweet.vue

@@ -0,0 +1,146 @@
+<template>
+    <div class="bind-tips-wrapper">
+        <img  :src="require('@/assets/svg/icon-close.svg')" class="icon-close" @click="close">
+        <div class="top">
+            <img :src="require('@/assets/svg/icon-giveaways-notice.svg')" class="icon-give-box">
+            <div class="text">
+                oops, you failed to send giveaway
+            </div>
+        </div>
+        <div class="button-wrapper">
+            <div class="re-send" @click="seSend">Resend</div>
+            <div class="terminate" @click="terminate">Terminate for a refund</div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+/* eslint-disable */
+import { onMounted, ref } from "vue";
+import { ElMessage } from 'element-plus'
+import { getChromeStorage } from '@/uilts/chromeExtension.js'
+import { getQueryString } from '@/uilts/help.js'
+import { terminatedLuckdrop } from "@/http/redPacket";
+
+let submitData = ref({});
+
+const close = () => {
+    window.parent.postMessage({ actionType: "IFRAME_CLOSE_BIND_TWEET",  data: {
+    }}, "*");
+}
+
+const seSend = async () => {
+    let publishData = await getChromeStorage('publishData');
+    callEventPageMethod(
+        "POPUP_PUBLISH_TWITTER_RED_PACK",
+        { 
+            srcContent: publishData.srcContent, 
+            postId: publishData.postId 
+        },
+        function (response) {
+            console.log("res", response);
+        }
+    );
+}
+
+const terminate = () => {
+    console.log(' submitData.value ',  submitData.value.taskLuckdropId )
+    terminatedLuckdrop({
+        params: {
+            luckdropId: submitData.value.taskLuckdropId
+        }
+    }).then(res => {
+        close();
+    });
+}
+
+/**
+ * sendMessage
+ */
+const callEventPageMethod = (actionType, data, callback) => {
+    chrome.runtime.sendMessage(
+        { 
+            actionType: actionType, 
+            data: data 
+        },
+        function (response) {
+            if (typeof callback === "function") callback(response);
+        }
+    );
+};
+
+
+onMounted(() => {
+    let params = getQueryString('params');
+    submitData.value = JSON.parse(params);
+}) 
+
+</script>
+
+<style scoped lang="scss">
+.bind-tips-wrapper {
+    width: 100%;
+    height: 100%;
+    box-sizing: border-box;
+    background: #FFFFFF;
+    border-radius: 20px;
+    padding: 15px;
+    position: relative;
+    box-shadow: 0px 4px 30px 0px #00000033;
+
+
+    .icon-close {
+        position: absolute;
+        left: 14px;
+        top: 14px;
+        width: 24px;
+        height: 24px;
+        cursor: pointer;
+    }
+
+    .top {
+        display: flex;
+        align-items: center;
+        flex-direction: column;
+        margin-top: 35px;
+
+        .icon-give-box {
+            width: 60px;
+            height: 60px;
+            margin-bottom: 20px;
+        }
+
+        .text {
+            font-weight: 590;
+            font-size: 18px;
+        }
+    }
+
+    .button-wrapper {
+        margin-top: 26px;
+
+        .re-send, .terminate {
+            width: 360px;
+            height: 43px;
+            border-radius: 100px;
+            font-weight: 500;
+            font-size: 17px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            cursor: pointer;
+        }
+        
+        .re-send {
+            background: #1D9BF0;
+            margin-bottom: 12px;
+            color: #FFFFFF;
+        }
+
+        .terminate {
+            color: #1D9BF0;
+            border: 1px solid #ECECEC;
+        }
+    }
+}
+</style>

+ 110 - 0
src/view/iframe/publish-tips/publish-tips.vue

@@ -0,0 +1,110 @@
+<template>
+    <div class="tips-wrapper">
+        <div class="top">
+            <img src="@/assets/svg/icon-bells.svg" class="icon-bells">
+            <div class="text-wrapper">
+                <div>
+                    Do not delete the
+                </div>
+                <div>
+                    <span>#DeNet</span>and<span> Giveaway link</span>
+                    otherwise the giveaway will not be available
+                </div>
+            </div>
+        </div>
+        <div class="copy-btn" 
+            :data-clipboard-text="strContent" 
+            @click="copyToken">Copy giveaways link</div>
+    </div>
+</template>
+
+<script setup>
+/* eslint-disable */
+import { onMounted, ref } from "vue";
+import { ElMessage } from 'element-plus'
+import { getChromeStorage } from '@/uilts/chromeExtension.js'
+
+let ClipboardJS = require('clipboard');
+
+let strContent = ref('');
+
+const copyToken = async () => {
+    let publishData = await getChromeStorage('publishData');
+    strContent.value = publishData.srcContent;
+    var clipboard = new ClipboardJS('.copy-btn');
+    clipboard.on('success', function (e) {
+        // ElMessage({
+        //     message: 'copy success',
+        //     grouping: true,
+        //     type: 'success',
+        //     offset: -16,
+        //     appendTo: document.body
+
+        // })
+        console.info('Action:', e.action);
+        console.info('Text:', e.text);
+        console.info('Trigger:', e.trigger);
+
+        e.clearSelection();
+    });
+
+    clipboard.on('error', function (e) {
+        // ElMessage({
+        //     message: 'copy error',
+        //     grouping: true,
+        //     type: 'error',
+        //     offset: -16
+        // })
+        console.error('Action:', e.action);
+        console.error('Trigger:', e.trigger);
+    });
+}
+
+
+onMounted(() => {
+}) 
+
+</script>
+
+<style scoped lang="scss">
+.tips-wrapper {
+    width: 100%;
+    height: 100%;
+    box-sizing: border-box;
+    background: #FFFFFF;
+    border-radius: 12px;
+    padding: 15px;
+    .top {
+        display: flex;
+
+        .icon-bells {
+            width: 30px;
+            height: 30px;
+            margin-right: 8px;
+        }
+
+        .text-wrapper {
+            font-weight: 500;
+            font-size: 14px;
+
+            span {
+                color: red;
+            }
+        }
+    }
+
+    .copy-btn {
+        margin-top: 20px;
+        background: rgba(56, 154, 255, 0.01);
+        border: 1px solid #000000;
+        border-radius: 100px;
+        font-weight: 500;
+        font-size: 14px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 33px;
+        cursor: pointer;
+    }
+}
+</style>

+ 113 - 51
src/view/iframe/publish/give-dialog.vue

@@ -162,64 +162,93 @@
                                     Recommend winners 100~10000
                                 </div>
                             </div>
-                            <div class="form-label">Tasks</div>
+                            <div class="form-label">
+                                <div>
+                                    Tasks
+                                </div>
+                                <div>
+                                    <el-dropdown trigger="click">
+                                        <img src="@/assets/svg/icon-add-task.svg" class="icon-add-task">
+                                        <template #dropdown v-if="formList.some(item => !item.show)">
+                                            <el-dropdown-menu>
+                                                <div  v-for="(item, key) in formList" :key="key"
+                                                     @click="clickDropdown(item, key)">
+                                                    <el-dropdown-item style="height: 50px;width: 240px" v-if="!item.show">
+                                                        <img :src="item.icon" style="width: 20px; height: 20px;margin-right: 12px" />
+                                                        {{item.label}}
+                                                    </el-dropdown-item>
+                                                </div>
+                                            </el-dropdown-menu>
+                                        </template>
+                                    </el-dropdown>
+                                </div>
+                            </div>
 
                             <!-- 转推、like、关注 -->
                             <div class="form-require">
                                 <div
-                                    class="form-item"
                                     v-for="(item, index) in formList"
                                     :key="index"
                                 >
-                                    <div class="item-left">
-                                        <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>
-                                        <!-- join discord -->
-                                        <div
-                                            class="control"
-                                            v-if="item.nodeType == 'input'"
-                                        >
-                                            <div v-if="showDiscordInvitePop" 
-                                                class="discord-invite-info"
-                                                @click="showDiscordInvitePop = false">
-                                                <img class="icon" :src="discordInviteInfo.icon || require('@/assets/svg/icon-discord-mini.svg')" />
-                                                <span class="name">{{discordInviteInfo.name}}</span>
+                                    <div v-if="item.show"  class="form-item">
+                                        <div class="item-left">
+                                            <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>
+                                            <!-- join discord -->
+                                            <div
+                                                class="control"
+                                                v-if="item.nodeType == 'input'"
+                                            >
+                                                <div v-if="showDiscordInvitePop" 
+                                                    class="discord-invite-info"
+                                                    @click="showDiscordInvitePop = false">
+                                                    <img class="icon" :src="discordInviteInfo.icon || require('@/assets/svg/icon-discord-mini.svg')" />
+                                                    <span class="name">{{discordInviteInfo.name}}</span>
+                                                </div>
+                                                <input v-model="item.text" 
+                                                    placeholder="Enter discord invite link"
+                                                    class="discord-address" 
+                                                    @input="onIptDiscordAddress($event, index)"
+                                                    @blur="onBlurDiscordAddress($event, index)" />
                                             </div>
-                                            <input v-model="item.text" 
-                                                placeholder="Enter discord invite link"
-                                                class="discord-address" 
-                                                @input="onIptDiscordAddress($event, index)"
-                                                @blur="onBlurDiscordAddress($event, index)" />
                                         </div>
+                                        
+                                        <div>
+                                            <el-switch
+                                                v-model="item.checked"
+                                                @change="formSwitchChange($event, item, index)"
+                                            />
+                                            <img src="@/assets/svg/icon-task-close.svg" 
+                                                class="icon-task-close"
+                                                @click="hideTask(item, index)">
+                                        </div>
+                                        <!-- 
+                                            v-if="item.type == 2 || item.type == 3 || item.type == 7 || item.type == 8 || item.type == 9"
+
+                                            <img
+                                            v-if="item.type == 3"
+                                            :src="
+                                                require('@/assets/svg/icon-option-checked.svg')
+                                            "
+                                        /> -->
                                     </div>
-                                    <el-switch
-                                        v-if="item.type == 2 || item.type == 7 || item.type == 8 || item.type == 9"
-                                        v-model="item.checked"
-                                        @change="formSwitchChange($event, item, index)"
-                                    />
-                                    <img
-                                        v-if="item.type == 3"
-                                        :src="
-                                            require('@/assets/svg/icon-option-checked.svg')
-                                        "
-                                    />
                                 </div>
                             </div>
                             <!-- 机器人 -->
@@ -412,7 +441,7 @@ import { getFrontConfig } from "@/http/account";
 import {setChromeStorage, getChromeStorage} from "@/uilts/chromeExtension"
 import { debounce, getBit } from "@/uilts/help"
 import Report from "@/log-center/log"
-import { ElMessage, ElLoading } from "element-plus";
+import { ElMessage, ElLoading, ElDropdown, ElDropdownMenu, ElDropdownItem } from "element-plus";
 import "element-plus/es/components/message/style/css";
 
 import {create, all} from "mathjs";
@@ -552,6 +581,7 @@ let formList = reactive([
         type: 1,
         text: [],
         checked: true,
+        show: true
     },
     {
         label: "Retweet",
@@ -559,6 +589,7 @@ let formList = reactive([
         nodeType: "div",
         type: 3,
         checked: true,
+        show: true
     },
     {
         label: "Like Tweet",
@@ -566,6 +597,7 @@ let formList = reactive([
         nodeType: "div",
         type: 2,
         checked: true,
+        show: true
     },
     {
         label: "Comment and tag 3 friends",
@@ -573,6 +605,7 @@ let formList = reactive([
         nodeType: "div",
         type: 9,
         checked: true,
+        show: true
     },
     {
         label: "Repost to Facebook",
@@ -581,6 +614,7 @@ let formList = reactive([
         text: '',
         type: 8,
         checked: true,
+        show: true
     },
     {
         label: "Join Discord",
@@ -589,6 +623,7 @@ let formList = reactive([
         text: '',
         type: 7,
         checked: true,
+        show: true
     },
 ]);
 
@@ -1168,7 +1203,21 @@ const onIptSetErrorTxt = (params = {}) => {
  * 监听开关触发事件
  */
 const formSwitchChange = (val, params, index) => {
-    console.log('formSwitchChange')
+    closeDiscordTask(val, params, index);
+}
+
+
+const hideTask = (params, index) => {
+    formList[index]['checked'] = false;
+    formList[index]['show'] = false;
+    closeDiscordTask(false, {type: 7}, index)
+}
+
+const clickDropdown = (params, index) => {
+    formList[index]['show'] = true;
+}
+
+const closeDiscordTask = (val, params, index) => {
     if(params.type == 7) {
         if(!val) {
             //错误类型 discord 清空discord错误校验
@@ -1183,6 +1232,7 @@ const formSwitchChange = (val, params, index) => {
     }
 }
 
+
 /** 监听 discord 输入 */
 const onIptDiscordAddress = (e, index) => {
     let val = formList[index].text;
@@ -1785,6 +1835,13 @@ onMounted(() => {
                         margin-bottom: 10px;
                         font-weight: 500;
                         font-size: 14px;
+                        display: flex;
+                        align-items: center;
+                        justify-content: space-between;
+
+                        .icon-add-task {
+                            cursor: pointer;
+                        }
                     }
 
                     .form-require {
@@ -1820,7 +1877,7 @@ onMounted(() => {
                             }
 
                             .control {
-                                min-width: 280px;
+                                min-width: 258px;
                                 margin-left: 18px;
                                 box-sizing: border-box;
                                 border-left: 1px solid #ECECEC;
@@ -1872,6 +1929,11 @@ onMounted(() => {
                                     }
                                 }
                             }
+
+                            .icon-task-close {
+                                margin-left: 6px;
+                                cursor: pointer;
+                            }
                         }
                         .form-item:last-child {
                             border-bottom: none !important;

+ 10 - 2
src/view/iframe/red-packet/red-packet.vue

@@ -724,7 +724,7 @@ const reSetBindTwtterId = (_params) => {
           Report.reportLog({
             objectType: Report.objectType.tweetPostBinded
           });
-          init()
+          init({from: 'reSetBindTwtterId'})
         }
       })
     }
@@ -901,7 +901,8 @@ function setFrontConfig() {
     });
 };
 
-function init() {
+function init(initParams) {
+  let {type} = initParams || {};
   onRuntimeMsg();
   onPageVisbile();
   onWindowMessage();
@@ -923,6 +924,13 @@ function init() {
       // 判断推特id,绑定逻辑
       state.srcContentId = res.data.srcContentId
       if (!state.srcContentId) {
+        if(type != 'reSetBindTwtterId') {
+          // 显示提示
+          window.parent.postMessage({ actionType: "IFRAME_RED_PACKET_SHOW_BIND_TWEET_NOTICE",  data: {
+            postId: state.postId,
+            taskLuckdropId: JSON.parse(res.data.postBizData).taskLuckdropId
+          }}, "*");
+        }
         reSetBindTwtterId(res.data)
         return
       }