Browse Source

Merge branch 'dev_1.1.7.2' of DeNet/de-net into master

v1.1.7.2
wenliming 2 years ago
parent
commit
7e2be55548
63 changed files with 2146 additions and 877 deletions
  1. 1 0
      package.json
  2. BIN
      src/assets/img/icon-gold-close-box.png
  3. BIN
      src/assets/img/icon-gold-open-box-big.png
  4. BIN
      src/assets/img/icon-gold-open-box.png
  5. BIN
      src/assets/img/icon-loading-channel.png
  6. BIN
      src/assets/img/icon-purple-close-box.png
  7. BIN
      src/assets/img/icon-purple-open-big.png
  8. BIN
      src/assets/img/icon-purple-open-box.png
  9. BIN
      src/assets/img/icon-silver-close-box.png
  10. BIN
      src/assets/img/icon-silver-open-box-big.png
  11. BIN
      src/assets/img/icon-silver-open-box.png
  12. 3 0
      src/assets/svg/icon-back-2.svg
  13. 2 0
      src/assets/svg/icon-channel-tips.svg
  14. 16 0
      src/assets/svg/icon-copy-url-teasure.svg
  15. 13 0
      src/assets/svg/icon-invited-more.svg
  16. 4 0
      src/assets/svg/icon-loading-channel.svg
  17. 1 1
      src/assets/svg/icon-refresh-treasure.svg
  18. 4 0
      src/assets/svg/icon-sort-amount.svg
  19. 4 0
      src/assets/svg/icon-sort-time.svg
  20. 0 1
      src/assets/svg/icon-three-line.svg
  21. 5 0
      src/assets/svg/icon-user1.svg
  22. 1 1
      src/assets/svg/icon-while-yes.svg
  23. 4 5
      src/entry/background.js
  24. 8 2
      src/http/fetch.js
  25. 14 2
      src/http/request.js
  26. 11 1
      src/http/treasure.js
  27. 2 0
      src/log-center/logEnum.js
  28. 29 19
      src/logic/background/twitter.js
  29. 4 4
      src/logic/content/ParseCard.js
  30. 41 2
      src/logic/content/help/twitter.js
  31. 68 14
      src/logic/content/twitter.js
  32. 2 2
      src/manifest.json
  33. 1 1
      src/uilts/chromeExtension.js
  34. 43 0
      src/uilts/help.js
  35. 2 1
      src/view/components/custom-card-cover.vue
  36. 20 8
      src/view/components/custom-card-horizontal-cover.vue
  37. 27 18
      src/view/iframe/buy-nft/buy/home.vue
  38. 2 2
      src/view/iframe/buy-nft/buy/pay.vue
  39. 2 2
      src/view/iframe/buy-nft/group/tip.vue
  40. 11 11
      src/view/iframe/group-card/card.vue
  41. 2 1
      src/view/iframe/publish/components/get-more.vue
  42. 1 0
      src/view/iframe/publish/components/preview-card.vue
  43. 10 2
      src/view/iframe/publish/give-dialog.vue
  44. 13 12
      src/view/iframe/red-packet/luck-draw.vue
  45. 7 5
      src/view/iframe/red-packet/red-packet.vue
  46. 21 19
      src/view/iframe/tab-group/joined-group-list.vue
  47. 21 14
      src/view/iframe/tool-box/buy-nft.vue
  48. 23 17
      src/view/iframe/tool-box/card.vue
  49. 13 9
      src/view/iframe/tool-box/full.vue
  50. 334 0
      src/view/iframe/treasure-hunt/all-receive-list.vue
  51. 336 0
      src/view/iframe/treasure-hunt/components/boxs.vue
  52. 2 5
      src/view/iframe/treasure-hunt/components/btn.vue
  53. 191 0
      src/view/iframe/treasure-hunt/components/carousel.vue
  54. 2 2
      src/view/iframe/treasure-hunt/components/dialog.vue
  55. 3 2
      src/view/iframe/treasure-hunt/components/head.vue
  56. 195 91
      src/view/iframe/treasure-hunt/components/invite-friends.vue
  57. 86 0
      src/view/iframe/treasure-hunt/components/invite-layer.vue
  58. 380 186
      src/view/iframe/treasure-hunt/components/invite-list.vue
  59. 3 3
      src/view/iframe/treasure-hunt/components/open-box.vue
  60. 72 41
      src/view/iframe/treasure-hunt/cover.vue
  61. 52 20
      src/view/iframe/treasure-hunt/index.vue
  62. 29 349
      src/view/iframe/treasure-hunt/invite.vue
  63. 5 2
      src/view/popup/tabbar-page/wallter/popup.vue

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "build-watch": "vue-cli-service  --env.NODE_ENV=development build-watch --mode development"
   },
   "dependencies": {
+    "@fingerprintjs/fingerprintjs": "^3.3.5",
     "@sentry/tracing": "^7.5.1",
     "@sentry/vue": "^7.5.1",
     "ant-design-vue": "^2.2.8",

BIN
src/assets/img/icon-gold-close-box.png


BIN
src/assets/img/icon-gold-open-box-big.png


BIN
src/assets/img/icon-gold-open-box.png


BIN
src/assets/img/icon-loading-channel.png


BIN
src/assets/img/icon-purple-close-box.png


BIN
src/assets/img/icon-purple-open-big.png


BIN
src/assets/img/icon-purple-open-box.png


BIN
src/assets/img/icon-silver-close-box.png


BIN
src/assets/img/icon-silver-open-box-big.png


BIN
src/assets/img/icon-silver-open-box.png


+ 3 - 0
src/assets/svg/icon-back-2.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M20.1427 11.3184V13.3184H8.14273L13.6427 18.8184L12.2227 20.2384L4.30273 12.3184L12.2227 4.39844L13.6427 5.81844L8.14273 11.3184H20.1427Z" fill="black"/>
+</svg>

File diff suppressed because it is too large
+ 2 - 0
src/assets/svg/icon-channel-tips.svg


+ 16 - 0
src/assets/svg/icon-copy-url-teasure.svg

@@ -0,0 +1,16 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_27199_78278)">
+<rect width="40" height="40" fill="#1D9BF0"/>
+<g clip-path="url(#clip1_27199_78278)">
+<path d="M27.7853 11.4827L27.7101 11.4075C25.9539 9.65127 23.0801 9.65127 21.3239 11.4075L17.2551 15.4763C15.4988 17.2326 15.4988 20.1057 17.2551 21.862L17.3303 21.9372C17.4765 22.0834 17.6318 22.2154 17.7917 22.3377L19.2811 20.8483C19.1074 20.7457 18.9433 20.6233 18.794 20.474L18.7188 20.3988C17.7655 19.4455 17.7655 17.894 18.7188 16.9407L22.7876 12.8712C23.741 11.9179 25.2925 11.9179 26.2458 12.8712L26.321 12.9465C27.2743 13.8998 27.2743 15.4519 26.321 16.4046L24.48 18.2456C24.7994 19.0348 24.951 19.8759 24.9379 20.7152L27.7847 17.8683C29.541 16.1121 29.541 13.2384 27.7853 11.4827ZM21.7716 17.3454C21.6254 17.1992 21.4702 17.0672 21.3102 16.9454L19.8208 18.4348C19.9945 18.5375 20.1587 18.6599 20.3079 18.8091L20.3831 18.8844C21.3364 19.8377 21.3364 21.3892 20.3831 22.3425L16.3143 26.4119C15.3609 27.3653 13.8095 27.3653 12.8561 26.4119L12.7809 26.3367C11.8276 25.3834 11.8276 23.8319 12.7809 22.8786L14.6219 21.0376C14.3025 20.2484 14.1509 19.4073 14.164 18.568L11.3172 21.4148C9.56094 23.1711 9.56094 26.0448 11.3172 27.801L11.3924 27.8763C13.1486 29.6325 16.0224 29.6325 17.7786 27.8763L21.8474 23.8074C23.6037 22.0512 23.6037 19.1775 21.8474 17.4212L21.7716 17.3454Z" fill="white"/>
+</g>
+</g>
+<defs>
+<clipPath id="clip0_27199_78278">
+<rect width="40" height="40" rx="20" fill="white"/>
+</clipPath>
+<clipPath id="clip1_27199_78278">
+<rect width="20" height="20" fill="white" transform="translate(10 10.0801)"/>
+</clipPath>
+</defs>
+</svg>

+ 13 - 0
src/assets/svg/icon-invited-more.svg

@@ -0,0 +1,13 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_27248_33494)">
+<circle opacity="0.2" cx="8" cy="8" r="8" fill="white"/>
+<ellipse cx="4.66406" cy="8" rx="1" ry="1" fill="white"/>
+<circle cx="8" cy="8" r="1" fill="white"/>
+<ellipse cx="11.3281" cy="8" rx="1" ry="1" fill="white"/>
+</g>
+<defs>
+<clipPath id="clip0_27248_33494">
+<rect width="16" height="16" rx="8" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 4 - 0
src/assets/svg/icon-loading-channel.svg

@@ -0,0 +1,4 @@
+<svg width="66" height="66" viewBox="0 0 66 66" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="33" cy="33" r="30" stroke="#424242" stroke-width="5"/>
+<path d="M63 33C63 16.4315 49.5685 3 33 3" stroke="#1D9BF0" stroke-width="5"/>
+</svg>

+ 1 - 1
src/assets/svg/icon-refresh-treasure.svg

@@ -1,3 +1,3 @@
 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4C9.87827 4 7.84344 4.84285 6.34315 6.34315C4.84285 7.84344 4 9.87827 4 12C4 14.1217 4.84285 16.1566 6.34315 17.6569C7.84344 19.1571 9.87827 20 12 20C15.73 20 18.84 17.45 19.73 14H17.65C16.83 16.33 14.61 18 12 18C10.4087 18 8.88258 17.3679 7.75736 16.2426C6.63214 15.1174 6 13.5913 6 12C6 10.4087 6.63214 8.88258 7.75736 7.75736C8.88258 6.63214 10.4087 6 12 6C13.66 6 15.14 6.69 16.22 7.78L13 11H20V4L17.65 6.35Z" fill="#636363"/>
+<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4C9.87827 4 7.84344 4.84285 6.34315 6.34315C4.84285 7.84344 4 9.87827 4 12C4 14.1217 4.84285 16.1566 6.34315 17.6569C7.84344 19.1571 9.87827 20 12 20C15.73 20 18.84 17.45 19.73 14H17.65C16.83 16.33 14.61 18 12 18C10.4087 18 8.88258 17.3679 7.75736 16.2426C6.63214 15.1174 6 13.5913 6 12C6 10.4087 6.63214 8.88258 7.75736 7.75736C8.88258 6.63214 10.4087 6 12 6C13.66 6 15.14 6.69 16.22 7.78L13 11H20V4L17.65 6.35Z" fill="#1D9BF0"/>
 </svg>

+ 4 - 0
src/assets/svg/icon-sort-amount.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1 12V10H11.4667V12H1ZM1 5H17V7H1V5ZM1 17V15H8.6V17H1Z" fill="black"/>
+<path d="M16.9798 20V19.1831C18.9112 19.0121 20 18.0115 20 16.403C20 15.0288 19.2127 14.1865 17.638 13.8319L16.9798 13.6989V11.3368C17.638 11.4318 18.1054 11.9257 18.1239 12.5273H19.8339C19.8093 11.0708 18.7021 10.0322 16.9798 9.87392V9H16.1125V9.86759C14.2671 10.0196 13.1845 11.0201 13.1845 12.5717C13.1845 13.8889 13.978 14.7691 15.4605 15.1238L16.1125 15.2821V17.7519C15.3313 17.6632 14.8023 17.1819 14.7592 16.5233H13C13.0062 18.0748 14.181 19.0754 16.1125 19.1894V20H16.9798ZM18.2592 16.6056C18.2592 17.2769 17.7856 17.7075 16.9798 17.7582V15.4404C17.8533 15.6177 18.2592 15.9914 18.2592 16.6056ZM14.9622 12.4134C14.9622 11.8117 15.442 11.3685 16.1125 11.3305V13.5153C15.362 13.3506 14.9622 12.9706 14.9622 12.4134Z" fill="black"/>
+</svg>

+ 4 - 0
src/assets/svg/icon-sort-time.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1 12V10H8.46667V12H1ZM1 5H15V7H1V5ZM1 17V15H6.6V17H1Z" fill="black"/>
+<path d="M17 8C13.14 8 10 11.13 10 15C10 18.87 13.13 22 17 22C20.86 22 24 18.87 24 15C24 11.13 20.87 8 17 8ZM19.19 17.53L16 15.69V12H17.5V14.82L19.94 16.23L19.19 17.53Z" fill="#609FC9"/>
+</svg>

File diff suppressed because it is too large
+ 0 - 1
src/assets/svg/icon-three-line.svg


+ 5 - 0
src/assets/svg/icon-user1.svg

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g opacity="0.4">
+<path d="M8 3C8.66304 3 9.29893 3.26339 9.76777 3.73223C10.2366 4.20107 10.5 4.83696 10.5 5.5C10.5 6.16304 10.2366 6.79893 9.76777 7.26777C9.29893 7.73661 8.66304 8 8 8C7.33696 8 6.70107 7.73661 6.23223 7.26777C5.76339 6.79893 5.5 6.16304 5.5 5.5C5.5 4.83696 5.76339 4.20107 6.23223 3.73223C6.70107 3.26339 7.33696 3 8 3ZM8 9.25C10.7625 9.25 13 10.3688 13 11.75V13H3V11.75C3 10.3688 5.2375 9.25 8 9.25Z" fill="white"/>
+</g>
+</svg>

+ 1 - 1
src/assets/svg/icon-while-yes.svg

@@ -1,3 +1,3 @@
 <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 15C11.6421 15 15 11.6421 15 7.5C15 3.35786 11.6421 0 7.5 0C3.35786 0 0 3.35786 0 7.5C0 11.6421 3.35786 15 7.5 15ZM3.96965 8.83499L6.50193 11.3675L7.1218 11.9874L7.6383 11.2791L12.219 4.99666L11.007 4.11293L6.94276 9.68696L5.03035 7.77438L3.96965 8.83499Z" fill="white"/>
+<path d="M3 7.5L7.15975 11.4647L12.8755 3.62562" stroke="white" stroke-width="2"/>
 </svg>

+ 4 - 5
src/entry/background.js

@@ -148,19 +148,18 @@ function thenInstalledMethod() {
     try {
 
         onInstalledCreateTab()
-        onInstalledMid()
         onInstalledUserSet()
         // pingpang
         chrome.alarms.create('PingPong', {
-            //1分鐘之後開始(該值不能小於1) 
+            //1分鐘之後開始(該值不能小於1)
             delayInMinutes: 2,
-            //開始後每一分鐘執行一次(該值不能小于1) 
+            //開始後每一分鐘執行一次(該值不能小于1)
             periodInMinutes: 4
         });
         chrome.alarms.create('LuckMessage', {
-            //1分鐘之後開始(該值不能小於1) 
+            //1分鐘之後開始(該值不能小於1)
             delayInMinutes: 1,
-            //開始後每一分鐘執行一次(該值不能小于1) 
+            //開始後每一分鐘執行一次(該值不能小于1)
             periodInMinutes: 1
         });
     } catch (error) {

+ 8 - 2
src/http/fetch.js

@@ -1,9 +1,10 @@
 import { appVersionCode, baseAPIUrl } from '@/http/configAPI.js'
 import { getChromeStorage } from '@/uilts/chromeExtension.js'
+import { guid } from '@/uilts/help'
 
 export async function commonFetch({ url = '', method = 'POST', params = {}, baseInfo = {} }) {
     try {
-
+        let deviceInfo = await getChromeStorage('deviceInfo') || {};
         let storage_mid = await getChromeStorage('mid').catch((error) => {console.log(error) }) || ''
         const { mid } = storage_mid || {}
         if (!baseInfo.token || !baseInfo.uid) {
@@ -17,6 +18,11 @@ export async function commonFetch({ url = '', method = 'POST', params = {}, base
         baseInfo.appType = 1
         baseInfo.loginUid = baseInfo.uid
 
+        baseInfo.fid = deviceInfo.deviceId1;
+        baseInfo.rid = deviceInfo.deviceId2;
+        baseInfo.clientTimestamp = new Date().getTime();
+        baseInfo.requestId = guid();
+
         return new Promise(function (resolve, reject) {
             let _url = baseAPIUrl + url
             if (url.includes('http')) {
@@ -75,4 +81,4 @@ export async function commonFetch({ url = '', method = 'POST', params = {}, base
     } catch (error) {
         console.log('error', error)
     }
-}
+}

+ 14 - 2
src/http/request.js

@@ -1,9 +1,12 @@
 import axios from 'axios'
 import { getChromeStorage } from '@/uilts/chromeExtension.js'
 import { baseAPIUrl, appVersionCode } from '@/http/configAPI.js'
+import { guid } from '@/uilts/help'
+
 
 let userInfo = '';
 let storage_mid = ''
+let deviceInfo = {};
 
 // 创建axios实例
 export const service = axios.create({
@@ -39,7 +42,11 @@ function checkParams(config) {
         uid,
         appType: 1,
         machineCode: mid,
-        pageSource: pageSource || ''
+        pageSource: pageSource || '',
+        fid: deviceInfo.deviceId1 || '',
+        rid: deviceInfo.deviceId2 || '',
+        clientTimestamp: new Date().getTime(),
+        requestId: guid()
       }
     }
     config['params'] = params;
@@ -64,7 +71,11 @@ function checkParams(config) {
         uid,
         appType: 1,
         machineCode: mid,
-        pageSource: pageSource || ''
+        pageSource: pageSource || '',
+        fid: deviceInfo.deviceId1 || '',
+        rid: deviceInfo.deviceId2 || '',
+        clientTimestamp: new Date().getTime(),
+        requestId: guid()
       }
     }
     config['data'] = data;
@@ -75,6 +86,7 @@ function checkParams(config) {
 // request拦截器
 service.interceptors.request.use(async (config) => {
   userInfo = await getChromeStorage('userInfo') || ''
+  deviceInfo = await getChromeStorage('deviceInfo') || {};
   if (!storage_mid) {
     storage_mid = await getChromeStorage('mid') || ''
   }

+ 11 - 1
src/http/treasure.js

@@ -91,4 +91,14 @@ export function bindPostContent(params) {
         method: "post",
         data: params,
     });
-}
+}
+
+export function receiveListV2(params) {
+    return service({
+        url: `/post/treasure/receive/list/v2`,
+        method: "post",
+        data: params,
+    });
+}
+
+

+ 2 - 0
src/log-center/logEnum.js

@@ -9,6 +9,8 @@ export const redPacketType = {
     nftGroupSale: 3,
     treasure: 4,
     postEditor: 5,
+    giveaway: 0,
+    lottery: 1
 }
 
 export const businessType = {

+ 29 - 19
src/logic/background/twitter.js

@@ -222,21 +222,26 @@ export function twitterShortUrl(sender, url) {
 
 
 // 安装插件后获取mid
-export function onInstalledMid() {
+export function onInstalledMid(cb) {
     try {
         getChromeCookie(LANDING_PAGE_MID, (res_arr) => {
             // 没有cookie
             if (res_arr && res_arr.length) {
-                setChromeStorage({ mid: JSON.stringify(res_arr[0]) })
+                setChromeStorage({ mid: JSON.stringify(res_arr[0]) }, () => {
+                  cb && cb()
+                })
             } else {
                 let _params = {
                     mid: guid()
                 }
                 setChromeCookie(LANDING_PAGE, { 'mid': _params.mid })
-                setChromeStorage({ mid: JSON.stringify(_params) })
+                setChromeStorage({ mid: JSON.stringify(_params) }, () => {
+                  cb && cb()
+                })
             }
         })
     } catch (error) {
+        cb && cb();
         Report.reportLog({
             objectType: Report.objectType.background_function_catch,
             funcName: 'onInstalledMid',
@@ -331,17 +336,22 @@ function sendActivetabMessage(message = {}) {
 export function onInstalledCreateTab() {
     try {
         getChromeCookie(LANDING_PAGE_JUMP_INFO, (res = {}) => {
-            setTimeout(() => {
-                if (!res) {
-                    res = {}
-                }
-                // 安装成功埋点
-                Report.reportLog({
-                    objectType: Report.objectType.chrome_extension_installed,
-                    funcName: 'onInstalledCreateTab',
-                    postId: res.postId || ''
-                })
-            }, 5000)
+            onInstalledMid(() => {
+              setTimeout(() => {
+                  if (!res) {
+                      res = {}
+                  }
+                  // 安装成功埋点
+                  Report.reportLog({
+                      objectType: Report.objectType.chrome_extension_installed,
+                      funcName: 'onInstalledCreateTab',
+                      postId: res.postId || '',
+                      shareLinkId: res.shareLinkId || '',
+                      'channel-name': res.channelName
+                  })
+              }, 5000)
+            });
+
             let url = 'https://twitter.com/search?q=%23denet'
             // jump_info
             if (!res || !res.jump_type) {
@@ -442,7 +452,7 @@ export function onInstalledCreateTab() {
 
 /**
  * 在popop重新发送
- * @param {*} req 
+ * @param {*} req
  */
 export function popupRePublish(req) {
     try {
@@ -507,11 +517,11 @@ export async function setMessageCount() {
 function createAlarm() {
     try {
         let alarmInfo = {
-            //1分鐘之後開始(該值不能小於1) 
+            //1分鐘之後開始(該值不能小於1)
             delayInMinutes: 1,
-            //與上方等同的寫法是 
+            //與上方等同的寫法是
             // when : Date.now() + n,
-            //開始後每一分鐘執行一次(該值不能小于1) 
+            //開始後每一分鐘執行一次(該值不能小于1)
             periodInMinutes: 1
         };
 
@@ -730,4 +740,4 @@ const createTabShowGiveaway = (params) => {
     chrome.tabs.create({
         url: params.url,
     });
-}
+}

+ 4 - 4
src/logic/content/ParseCard.js

@@ -343,11 +343,11 @@ class ParseCard {
         _iframe.style.cssText = 'border:medium none; width:505px; min-height:180px;'
         return _iframe
     }
-    createTreasureIframe(params = { page_type, tweet_Id, post_Id, invite_code }) {
+    createTreasureIframe(params = { page_type, tweet_Id, post_Id, invite_code, invite_channel }) {
         let _iframe = document.createElement('iframe')
         _iframe.id = params.post_Id
         _iframe.src = chromeExtensionUrl + ('iframe/treasure-hunt.html') + `?params=${JSON.stringify(params)}&iframeId=${guid()}`;
-        _iframe.style.cssText = 'border:medium none; width:375px; min-height:500px; border: 1px solid #DCDCDC; border-radius: 20px;'
+        _iframe.style.cssText = 'border:medium none; width:375px; min-height:580px; border: 1px solid #DCDCDC; border-radius: 20px;'
         return _iframe
     }
     isHasIframeByArticle(dom_card) {
@@ -538,7 +538,7 @@ class ParseCard {
             dom.appendChild(this.createIframe({ post_Id, tweet_Id, page_type }))
         }
     }
-    replaceDOMTreasureCard({ invite_code, dom_card, tweet_Id, post_Id, time, short_url, page_type = '' }) {
+    replaceDOMTreasureCard({ invite_code, dom_card, tweet_Id, post_Id, time, short_url, page_type = '', invite_channel }) {
         if (!dom_card || !dom_card.parentElement) {
             return
         }
@@ -558,7 +558,7 @@ class ParseCard {
 
         dom.style = 'min-height:500px'
         if (dom) {
-            dom.appendChild(this.createTreasureIframe({ post_Id, tweet_Id, page_type, invite_code }))
+            dom.appendChild(this.createTreasureIframe({ post_Id, tweet_Id, page_type, invite_code, invite_channel }))
         }
     }
     replaceNftDomRedPacket({ dom_card, tweet_Id, post_Id, time, short_url }) {

+ 41 - 2
src/logic/content/help/twitter.js

@@ -1,3 +1,5 @@
+import { getStorage, setStorage, getVisitorId, setCookie, getCookie, guid } from '@/uilts/help'
+import { getChromeStorage, setChromeStorage } from '@/uilts/chromeExtension.js'
 
 // 根据提示dom 跳转到推文详情页面
 export const jumpTwitterDetailByAlert = () => {
@@ -38,6 +40,43 @@ export const showEditTweet = (callback) => {
             clearInterval(timer)
             callback && callback()
         }
-        num-- 
+        num--
     }, 500);
-}
+}
+
+export const setDeviceInfo = async () => {
+  const deviceStorageParams = {
+    name: 'de_net_device_id_1'
+  }
+
+  const deviceCookieParams = {
+    url: 'https://twitter.com/',
+    name: 'de_net_device_id_2'
+  }
+
+  let deviceInfo = {
+    deviceId1: '',
+    deviceId2: ''
+  }
+
+  let storageDeviceInfo = getStorage(deviceStorageParams.name);
+  if(!storageDeviceInfo) {
+    let res = await getVisitorId();
+    let id =  res && res.visitorId || '';
+    setStorage(deviceStorageParams.name, id);
+    deviceInfo.deviceId1 = id;
+  } else {
+    deviceInfo.deviceId1 = storageDeviceInfo;
+  }
+
+  let cookieDeviceInfo = getCookie(deviceCookieParams.name);
+  if(!cookieDeviceInfo) {
+    let rid = guid();
+    setCookie(deviceCookieParams.name, rid, 600);
+    deviceInfo.deviceId2 = rid;
+  } else {
+    deviceInfo.deviceId2 = cookieDeviceInfo;
+  }
+
+  setChromeStorage({'deviceInfo': JSON.stringify(deviceInfo)});
+}

+ 68 - 14
src/logic/content/twitter.js

@@ -12,7 +12,8 @@ import { toolBox } from '@/logic/content/ToolBox'
 import axios from 'axios';
 import messageCenter from '@/uilts/messageCenter';
 import { PlayType } from '@/types';
-import { reSetBindPostContent } from '@/http/help.js'
+import { reSetBindPostContent } from '@/http/help.js';
+import { setDeviceInfo } from '@/logic/content/help/twitter';
 
 let dom = {};
 
@@ -880,7 +881,12 @@ function setIframeCard(type = 'twitter') {
                         for (let i in arr) {
                             index = Number(i) + 1
                             if (arr[i] == 'invite' && arr.length >= index) {
-                                item.invite_code = arr[index]
+                                item.invite_code = arr[index];
+                                if(arr.length > index + 1) {
+                                  item.invite_channel = arr[index+1];
+                                } else {
+                                  item.invite_channel = '';
+                                }
                                 break
                             }
                         }
@@ -932,7 +938,7 @@ export function initExecuteScript(changes) {
             init()
         }
     }
-    if (changes.userInfo) {
+    if (changes.userInfo && changes.userInfo.newValue) {
         let item = JSON.parse(changes.userInfo.newValue)
         if (item) {
             checkUserJoinGroup(() => {
@@ -1030,6 +1036,7 @@ export function init() {
         addJoinedGroupList();
         getSysTheme();
         addGroupTab();
+        setDeviceInfo();
         // 预加载全屏 toobbox
         toolBox.initFull()
     }
@@ -1069,18 +1076,21 @@ export const getTweetUserFollowStatus = (params) => {
         promiseList[i] = TwitterApiUserByScreenNameReq({ screen_name: userList[i]['name'] });
     }
 
-    Promise.all(promiseList).then((res) => {
+    Promise.allSettled(promiseList).then((res) => {
         let list = [];
         if (res && res.length) {
-            for (let i = 0; i < res.length; i++) {
-                let item = res[i];
-                if (item && item.data && item.data.data) {
-                    list.push(item.data.data)
-                }
-            }
+          let resList = res.filter(item => item.status == 'fulfilled');
+          for (let i = 0; i < resList.length; i++) {
+              let item = resList[i];
+              if (item && item.value && item.value.data && item.value.data.data) {
+                  list.push(item.value.data.data)
+              }
+          }
         }
 
         chrome.runtime.sendMessage({ actionType: 'CONTENT_GET_TWEET_USER_FOLLOW_STATUS_RES', data: list, tweetId, type: params.type, iframeId: params.iframeId }, () => { })
+    }).catch(err => {
+      chrome.runtime.sendMessage({ actionType: 'CONTENT_GET_TWEET_USER_FOLLOW_STATUS_RES', data: [], tweetId, type: params.type, iframeId: params.iframeId }, () => { })
     })
 }
 
@@ -1424,7 +1434,7 @@ export function doTaskTwitterAPI({ task_data, task_type, tasks, iframeId }) {
                     case '1':
                         item.relatedUsers.forEach((item) => {
                             if (item.name && item.twitterUserId) {
-                                TwitterFollowAPI(item, task_data.tweet_Id)
+                                TwitterFollowAPI(item, task_data.tweet_Id);
                             }
                         })
                         break
@@ -1452,6 +1462,48 @@ export function showJoinDialog(data) {
     iframe.src = chromeExtensionUrl + (`iframe/buy-nft.html#/group?params=${JSON.stringify(data)}&time=${new Date().getTime()}`)
 }
 
+const TwitterFriendshipsUpdate = (params) => {
+  let {id = '', device = true, name} = params || {};
+  let data = {
+    include_profile_interstitial_type: 1,
+    include_blocking: 1,
+    include_blocked_by: 1,
+    include_followed_by: 1,
+    include_want_retweets: 1,
+    include_mute_edge: 1,
+    include_can_dm: 1,
+    include_can_media_tag: 1,
+    include_ext_has_nft_avatar: 1,
+    skip_status: 1,
+    cursor: -1,
+    id,
+    device
+  }
+  if(!id) {
+    return;
+  }
+  return fetch("https://twitter.com/i/api/1.1/friendships/update.json", {
+      "headers": {
+          "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
+          "content-type": "application/x-www-form-urlencoded",
+          "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\", \"Google Chrome\";v=\"102\"",
+          "sec-ch-ua-mobile": "?0",
+          "sec-ch-ua-platform": "\"macOS\"",
+          "x-csrf-token": getCookie('ct0'),
+          "x-twitter-active-user": "yes",
+          "x-twitter-auth-type": "OAuth2Session",
+          "x-twitter-client-language": "en",
+          "referer": `https://twitter.com/${name}`
+      },
+      "referrer": `https://twitter.com/${name}`,
+      "referrerPolicy": "strict-origin-when-cross-origin",
+      "body": `include_profile_interstitial_type=1&include_blocking=1&include_blocked_by=1&include_followed_by=1&include_want_retweets=1&include_mute_edge=1&include_can_dm=1&include_can_media_tag=1&include_ext_has_nft_avatar=1&skip_status=1&cursor=-1&id=${id}&device=true`,
+      "method": "POST",
+      "mode": "cors",
+      "credentials": "include"
+  })
+}
+
 const TwitterFollowAPI = (item, tweet_Id) => {
     fetch("https://twitter.com/i/api/1.1/friendships/create.json", {
         "headers": {
@@ -1475,6 +1527,8 @@ const TwitterFollowAPI = (item, tweet_Id) => {
         let task_data = {
             follow_name: item.name
         }
+        TwitterFriendshipsUpdate({id: item.twitterUserId, name: item.name})
+
         chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'follow', task_data, task_done: true }, () => { })
     }).catch(() => {
         console.log('DO_TASK3')
@@ -1623,12 +1677,12 @@ const TwitterApiUserByScreenNameReq = (params) => {
 
 
 export const TwitterApiUserByScreenName = (params, cb) => {
-    let { screen_name, tweetId = '', objectType = '' } = params;
+    let { screen_name, tweetId = '', objectType = '', iframeId = '' } = params;
 
     TwitterApiUserByScreenNameReq({ screen_name }).then(function (response) {
-        chrome.runtime.sendMessage({ actionType: "CONTENT_API_GET_TWEET_USER_INFO_RES", data: response.data.data || {}, tweetId, objectType }, () => { })
+        chrome.runtime.sendMessage({ actionType: "CONTENT_API_GET_TWEET_USER_INFO_RES", data: response.data.data || {}, tweetId, objectType, iframeId }, () => { })
     }).catch(function (err) {
-        chrome.runtime.sendMessage({ actionType: "CONTENT_API_GET_TWEET_USER_INFO_RES", data: {}, tweetId, objectType }, () => { })
+        chrome.runtime.sendMessage({ actionType: "CONTENT_API_GET_TWEET_USER_INFO_RES", data: {}, tweetId, objectType, iframeId }, () => { })
     });
 }
 

+ 2 - 2
src/manifest.json

@@ -2,8 +2,8 @@
     "manifest_version": 3,
     "name": "DeNet",
     "description": "Growing more twitter followers with Denet",
-    "version": "1.1.7.1",
-    "denet_app_version_code": "21",
+    "version": "1.1.7.2",
+    "denet_app_version_code": "22",
     "background": {
         "service_worker": "/js/background.js"
     },

+ 1 - 1
src/uilts/chromeExtension.js

@@ -119,7 +119,7 @@ export function removeChromeCookie(params, cb) {
     }
 }
 
-export function sendChromeTabMessage(params, callback) {
+export function sendCurrentTabMessage(params, callback) {
     try {
         chrome.tabs.getCurrent((tab) => {
             chrome.tabs.sendMessage(tab.id, params, callback);

+ 43 - 0
src/uilts/help.js

@@ -1,4 +1,6 @@
 import { appVersionCode } from '@/http/configAPI.js'
+import FingerprintJS from '@fingerprintjs/fingerprintjs'
+var moment = require('moment')
 
 export function getQueryString(name) {
   let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
@@ -112,6 +114,13 @@ export function getTargetElementWhenClick(e) {
   return result
 }
 
+export function setCookie(cname, cvalue, exdays) {
+  var d = new Date();
+  d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
+  var expires = "expires=" + d.toGMTString();
+  document.cookie = cname + "=" + cvalue + "; " + expires;
+}
+
 export function getCookie(name) {
   var strcookie = document.cookie; //获取cookie字符串
   var arrcookie = strcookie.split("; "); //分割
@@ -278,3 +287,37 @@ export const getInnerIframeURL = (url) => {
   }
   return iframeUrl;
 }
+
+export const getVisitorId = async () => {
+  const fpPromise = FingerprintJS.load();
+  let result = {};
+  const fp = await fpPromise
+  result = await fp.get();
+  return result;
+}
+
+export const getBeforeTimeFormat = (timestamp) => {
+  let _d1 = moment(new Date().getTime())
+  let _d2 = moment(timestamp)
+  const plural = (n, s) => {
+    let _str = `${n} ${s} ago`
+    if (n > 1) {
+      _str = `${n} ${s}s ago`
+    }
+    return _str
+  }
+  let _d = moment.duration(_d1.diff(_d2)).days()
+  if (_d) {
+    return plural(_d, 'day')
+  }
+  let _h = moment.duration(_d1.diff(_d2)).hours()
+  if (_h) {
+    return plural(_h, 'hour')
+  }
+  let _m = moment.duration(_d1.diff(_d2)).minutes()
+  if (_m) {
+    return plural(_m, 'min')
+  }
+  let _s = moment.duration(_d1.diff(_d2)).seconds()
+  return plural(_s, 'sec')
+}

+ 2 - 1
src/view/components/custom-card-cover.vue

@@ -92,7 +92,7 @@
             <img class="img-treasure-big" :src="require('@/assets/img/icon-treasure-box.png')">
 
             <div class="treasure-row-4">
-               <img class="img" :src="require('@/assets/svg/icon-card-cover-treasure-tasks.svg')"> to Hunt Treasure
+               <img class="img" :src="require('@/assets/svg/icon-three-line.svg')"> to Hunt Treasure
             </div>
 
             <div class="open-btn" @click="open">
@@ -377,6 +377,7 @@ onMounted(() => {
 
             .img {
                 width: 76px;
+                margin-right: 10px;
             }
         }
 

+ 20 - 8
src/view/components/custom-card-horizontal-cover.vue

@@ -37,7 +37,7 @@
             </div>
 
             <div class="content-text">
-                <template v-if="data.type != PlayType.treasure">
+                <div style="margin-left: 35px" v-if="data.type != PlayType.treasure">
                     <div class="title">
                         <span>{{data.currencyCode == 'USD' ? 'US Dollar' : data.tokenSymbol}} </span>
                         &nbsp;GIVEAWAY
@@ -64,7 +64,7 @@
                             {{data.totalCount}} WINNERS TO SHARE
                         </template>
                     </div>
-                </template>
+                </div>
                 <div class="treasure-layout" v-else>
                     <div class="treasure-row-1">
                         <span class="left">Treasure</span>
@@ -73,10 +73,12 @@
                         </component-zoom>
                     </div>
                     <div class="treasure-desc-data">
-                        <div class="item">
-                            <img class="icon"
-                                :src="require('@/assets/svg/icon-preview-trophy.svg')" />
-                            {{data.totalCount}} Winners
+                        <div class="item up-gain">
+                            You can get up to $
+                            <component-zoom :width="160"
+                            fontSize="24" :txt="data.upGainAmountUsdValue || 0">
+                              <div class="amount">{{data.upGainAmountUsdValue || 0}}</div>
+                            </component-zoom>
                         </div>
                         <div class="item">
                             <img class="icon" :src="data.currencyIconUrl">
@@ -215,7 +217,7 @@ watch(() => props.data, () => {
     .content-text {
         position: absolute;
         top: 53px;
-        left: 35px;
+        left: 0;
         .title {
             font-weight: 800;
             font-size: 16px;
@@ -272,6 +274,7 @@ watch(() => props.data, () => {
                 font-weight: 900;
                 font-size: 35px;
                 color: #fff;
+                margin-left: 35px;
 
                 .left {
                     margin-right: 7px;
@@ -286,7 +289,15 @@ watch(() => props.data, () => {
             }
 
             .treasure-desc-data {
-                margin-top: 18px;
+                margin-top: 12px;
+
+                .up-gain {
+                  background: linear-gradient(90deg, rgba(255, 255, 255, 0.1) 15.54%, rgba(255, 255, 255, 0) 100%);
+                  width: 350px;
+                  color: #fff !important;
+                  padding: 4px 0;
+                  box-sizing: border-box;
+                }
 
                 .item {
                     font-weight: 500;
@@ -295,6 +306,7 @@ watch(() => props.data, () => {
                     margin-bottom: 10px;
                     display: flex;
                     align-items: center;
+                    padding-left: 35px;
 
                     .icon {
                         width: 20px;

+ 27 - 18
src/view/iframe/buy-nft/buy/home.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="dialog"  :style="{'height': dialogStyle.height + 'px'}">
+    <div class="dialog" :style="{ 'height': dialogStyle.height + 'px' }">
         <!-- home -->
         <div class="area-title">
             <img :src="require('@/assets/svg/icon-close.svg')" @click="clickClose" />
@@ -16,11 +16,14 @@
             <!-- 首页 -->
             <div class="mark">
                 <div class="sold">SOLD: {{ state.data.itemSoldCount || 0 }}/{{ state.data.itemTotalCount || 0 }} </div>
-                <div class="limit" v-if="showDesc">Buy Limit: {{ state.data.userBuyCount || 0 }}/{{ state.data.perUserBuyLimit || 0 }}</div>
+                <div class="limit" v-if="showDesc">Buy Limit: {{ state.data.userBuyCount || 0 }}/{{
+                        state.data.perUserBuyLimit || 0
+                }}</div>
             </div>
             <div class="btn-area">
                 <!-- 兑换码 -->
-                <template v-if="(state.data.perUserBuyLimit - state.data.userBuyCount) >= 1 && (state.data.itemTotalCount - state.data.itemSoldCount) >= 1">
+                <template
+                    v-if="(state.data.perUserBuyLimit - state.data.userBuyCount) >= 1 && (state.data.itemTotalCount - state.data.itemSoldCount) >= 1">
                     <div class="redeem" @click="showRedeemLayer">Redeem</div>
                 </template>
                 <template v-else>
@@ -28,10 +31,7 @@
                 </template>
 
                 <template v-for="item in state.data.salePlans.slice(0, 2).reverse()">
-                    <div
-                        class="buy1"
-                        :class="{ grey: payNext }"
-                        @click="clickJump(item)"
+                    <div class="buy1" :class="{ grey: payNext }" @click="clickJump(item)"
                         v-if="item.itemCount == 1 && (state.data.perUserBuyLimit - state.data.userBuyCount) >= 1 && (state.data.itemTotalCount - state.data.itemSoldCount) >= 1">
                         <template v-if="(item.price.length + item.currencyInfo.tokenSymbol.length) > 30">
                             <div class="left">Buy 1</div>
@@ -66,10 +66,7 @@
                         </template>
                     </div>
 
-                    <div
-                        class="buy5"
-                        :class="{ grey: payNext }"
-                        @click="clickJump(item)"
+                    <div class="buy5" :class="{ grey: payNext }" @click="clickJump(item)"
                         v-if="item.itemCount == 5 && (state.data.perUserBuyLimit - state.data.userBuyCount) >= 5 && (state.data.itemTotalCount - state.data.itemSoldCount) >= 5">
                         <div class="left">Buy {{ item.itemCount }}</div>
 
@@ -120,7 +117,7 @@ import Report from "@/log-center/log"
 import { getQueryString } from "@/uilts/help";
 import { calcRechargePayAmount } from "@/http/account";
 import { getCurrencyInfoByCode } from "@/http/publishApi";
-import { sendChromeTabMessage } from '@/uilts/chromeExtension.js';
+import { sendCurrentTabMessage } from '@/uilts/chromeExtension.js';
 let postId = inject('post_Id');
 let pay_info = inject('pay_info');
 let router = useRouter()
@@ -228,7 +225,7 @@ const clickJump = (item) => {
 
 const setDialogStyle = () => {
     let clientHeight = window.innerHeight;
-    if(clientHeight >= 840) {
+    if (clientHeight >= 840) {
         dialogStyle.height = 800;
     } else {
         dialogStyle.height = clientHeight - 40;
@@ -253,7 +250,7 @@ const redeemPost = () => {
         let { code, data } = res;
         if (code == 0 && data) {
             pay_info.buy_items = data
-            sendChromeTabMessage({ actionType: "FINISH_GROUP_BANNNER" }, () => { })
+            sendCurrentTabMessage({ actionType: "FINISH_GROUP_BANNNER" }, () => { })
             router.push({ path: '/open_box' });
             // report
             Report.reportLog({
@@ -340,8 +337,8 @@ const hideRedeemLayer = () => {
 watchEffect(() => {
     let len = 16
     let str = redeemStr.value.replace(/[^a-zA-Z0-9]/g, '')
-        str = str.toUpperCase();
-        str = str.slice(0, len);
+    str = str.toUpperCase();
+    str = str.slice(0, len);
     // set
     redeemStr.value = str;
     redeemNext.value = str !== '' && str.length === len;
@@ -353,7 +350,7 @@ onMounted(() => {
     let nft_project_Id = router.currentRoute.value.query.nftProjectId
     let nft_group_Id = router.currentRoute.value.query.nft_group_Id
     let post_id = router.currentRoute.value.query.postId
-    if(nft_group_Id){
+    if (nft_group_Id) {
         pay_info.nft_group_Id = nft_group_Id
     }
     if (!nft_project_Id) {
@@ -556,8 +553,9 @@ onMounted(() => {
                 cursor: not-allowed;
                 border: unset;
                 color: #FFFFFF;
+
                 .usdt {
-                    color: #FFFFFF!important;
+                    color: #FFFFFF !important;
                 }
             }
 
@@ -576,6 +574,7 @@ onMounted(() => {
                 cursor: pointer;
                 margin-right: 12px;
                 box-sizing: border-box;
+
                 &.grey {
                     background: #CDCDCD;
                     cursor: not-allowed;
@@ -597,11 +596,13 @@ onMounted(() => {
     border-radius: 20px;
     background: #FFFFFF;
     transform: translate(-50%, -50%);
+
     .header {
         display: flex;
         align-items: center;
         height: 48px;
         box-shadow: 0px 0.5px 0px #D1D9DD;
+
         img {
             width: 24px;
             height: 24px;
@@ -609,8 +610,10 @@ onMounted(() => {
             cursor: pointer;
         }
     }
+
     .footer {
         padding: 20px;
+
         .tips {
             font-size: 16px;
             font-weight: 500;
@@ -618,6 +621,7 @@ onMounted(() => {
             letter-spacing: 0.3px;
             margin-bottom: 18px;
         }
+
         .input {
             display: flex;
             align-items: center;
@@ -626,6 +630,7 @@ onMounted(() => {
             border-radius: 100px;
             background: #FFFFFF;
             border: 1px solid #DDDDDD;
+
             input {
                 width: calc(100% - 40px);
                 border: 0;
@@ -635,9 +640,11 @@ onMounted(() => {
                 line-height: 19px;
             }
         }
+
         .confirm {
             margin-top: 45px;
             text-align: right;
+
             .btn {
                 border: 0;
                 width: 170px;
@@ -648,6 +655,7 @@ onMounted(() => {
                 font-weight: 700;
                 border-radius: 100px;
                 background: #1D9BF0;
+
                 &.grey {
                     background: #CDCDCD;
                     cursor: not-allowed;
@@ -658,6 +666,7 @@ onMounted(() => {
         }
     }
 }
+
 .redeemMask {
     position: absolute;
     z-index: 24;

+ 2 - 2
src/view/iframe/buy-nft/buy/pay.vue

@@ -142,7 +142,7 @@ import { calcRechargePayAmount } from "@/http/account";
 import { getChromeStorage, setChromeStorage, chromeExtensionUrl } from "@/uilts/chromeExtension"
 import { ElMessage } from 'element-plus'
 import "element-plus/es/components/message/style/css";
-import { sendChromeTabMessage } from '@/uilts/chromeExtension.js';
+import { sendCurrentTabMessage } from '@/uilts/chromeExtension.js';
 
 let pay_info = inject('pay_info');
 let postId = inject('post_Id');
@@ -214,7 +214,7 @@ const clickPlay = () => {
         state.loading.show = false
         if (res.code == 0) {
             pay_info.buy_items = res.data.buyItems
-            sendChromeTabMessage({ actionType: "FINISH_GROUP_BANNNER" }, () => { })
+            sendCurrentTabMessage({ actionType: "FINISH_GROUP_BANNNER" }, () => { })
             router.push({ path: '/open_box' });
             Report.reportLog({
                 pageSource: Report.pageSource.nftShopPage,

+ 2 - 2
src/view/iframe/buy-nft/group/tip.vue

@@ -52,7 +52,7 @@ import { reactive, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 import { setGroupJoin } from '@/http/group.js'
 import { ElMessage } from 'element-plus'
-import { sendChromeTabMessage } from '@/uilts/chromeExtension.js';
+import { sendCurrentTabMessage } from '@/uilts/chromeExtension.js';
 let state = reactive({
     show: 'tip',
     params: {}
@@ -70,7 +70,7 @@ const clickJoin = () => {
         if (res.code == 0) {
             state.show = 'success'
             state.params.type = 'buy'
-            sendChromeTabMessage({ actionType: "FINISH_GROUP_BANNNER" }, () => { })
+            sendCurrentTabMessage({ actionType: "FINISH_GROUP_BANNNER" }, () => { })
         } else {
             let msg = ''
             switch (String(res.code)) {

+ 11 - 11
src/view/iframe/group-card/card.vue

@@ -51,7 +51,7 @@ import { reactive, onBeforeMount } from 'vue'
 import { getTwitterNftGroupInfo } from "@/http/group";
 import { getQueryString } from '@/uilts/help.js';
 import Report from "@/log-center/log"
-import { sendChromeTabMessage, checkIsLogin } from '@/uilts/chromeExtension.js';
+import { sendCurrentTabMessage, checkIsLogin } from '@/uilts/chromeExtension.js';
 
 let state = reactive({
     show: 'arrow', //join
@@ -62,14 +62,14 @@ let state = reactive({
 
 // 显示加入小组弹框
 async function clickJoin() {
-    sendChromeTabMessage({ actionType: "SWITCH_GROUP_STATUS" }, () => { })
+    sendCurrentTabMessage({ actionType: "SWITCH_GROUP_STATUS" }, () => { })
     let _userInfo = await checkIsLogin()
     if (!_userInfo) {
         return
     }
     // 如果没购买过 弹出购买
     if (state.data.buyNftStatus == 0) {
-        sendChromeTabMessage({
+        sendCurrentTabMessage({
             actionType: "IFRAME_SHOW_JOIN_DIALOG",
             data: {
                 type: 'buy',
@@ -83,7 +83,7 @@ async function clickJoin() {
 
         // 如果购买过 没加入 显示加入按钮
     } else if (state.data.buyNftStatus == 1 && state.data.joinStatus == 0) {
-        sendChromeTabMessage({
+        sendCurrentTabMessage({
             actionType: "IFRAME_SHOW_JOIN_DIALOG",
             data: {
                 type: 'join',
@@ -140,7 +140,7 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
             } else {
                 state.show = state.show2
                 // console.log(11)
-                // sendChromeTabMessage({ actionType: "SWITCH_GROUP_STATUS", data: { type: 'btn' } }, () => { })
+                // sendCurrentTabMessage({ actionType: "SWITCH_GROUP_STATUS", data: { type: 'btn' } }, () => { })
             }
             break
     }
@@ -148,7 +148,7 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
 })
 
 chrome.storage.onChanged.addListener(changes => {
-    if (changes.userInfo) {
+    if (changes.userInfo && changes.userInfo.newValue) {
         let item = JSON.parse(changes.userInfo.newValue)
         if (item) {
             init()
@@ -184,7 +184,7 @@ const sendMessageToContent = (params) => {
     })
 }
 const clickArrow = () => {
-    sendChromeTabMessage({ actionType: "SWITCH_GROUP_STATUS" }, (res) => {
+    sendCurrentTabMessage({ actionType: "SWITCH_GROUP_STATUS" }, (res) => {
         if (!res) {
             Report.reportLog({
                 objectType: Report.objectType.chrome_extension_sendmessage_error
@@ -194,7 +194,7 @@ const clickArrow = () => {
 }
 
 async function clickPost() {
-    sendChromeTabMessage({ actionType: "SWITCH_GROUP_STATUS" }, (res) => {
+    sendCurrentTabMessage({ actionType: "SWITCH_GROUP_STATUS" }, (res) => {
         if (!res) {
             Report.reportLog({
                 objectType: Report.objectType.chrome_extension_sendmessage_error
@@ -207,7 +207,7 @@ async function clickPost() {
     }
     // 没有购买过
     if (state.data.buyNftStatus == 0) {
-        sendChromeTabMessage({
+        sendCurrentTabMessage({
             actionType: "IFRAME_SHOW_JOIN_DIALOG",
             data: {
                 type: 'buy',
@@ -220,7 +220,7 @@ async function clickPost() {
         })
         // 购买过 && 加入过
     } else if (state.data.buyNftStatus == 1 && state.data.joinStatus == 1) {
-        sendChromeTabMessage({
+        sendCurrentTabMessage({
             actionType: "IFRAME_SHOW_POST_DIALOG",
             data: {
                 groupId: state.data.nftGroupId
@@ -235,7 +235,7 @@ async function clickPost() {
 onBeforeMount(() => {
     state.twitterAccount = getQueryString('twitterAccount') || ''
     init(() => {
-        sendChromeTabMessage({ actionType: "IFRAME_SHOW_GROUP_TIP" })
+        sendCurrentTabMessage({ actionType: "IFRAME_SHOW_GROUP_TIP" })
     })
 
 })

+ 2 - 1
src/view/iframe/publish/components/get-more.vue

@@ -52,7 +52,8 @@ const jumpMore = () => {
       pageSource: props.reportData.pageSource,
       businessType: Report.businessType.buttonClick,
       objectType: Report.objectType.getMoreGiveaway,
-      postId: props.reportData.postId
+      postId: props.reportData.postId,
+      redPacketType: props.reportData.redPacketType
     });
     if (moreUrl.value) {
         window.open(moreUrl.value)

+ 1 - 0
src/view/iframe/publish/components/preview-card.vue

@@ -79,6 +79,7 @@
                             },
                             rewardType: baseFormData.rewardType,
                             customizedReward: baseFormData.customizedReward,
+                            upGainAmountUsdValue: upGainAmountUsdValue
                         }">
                     </custom-card-horizontal-cover>
                 </div>

+ 10 - 2
src/view/iframe/publish/give-dialog.vue

@@ -1172,6 +1172,10 @@ const submitRequest = async () => {
 
     let finishConditions = selectModeInfo.type != PlayType.treasure ? getFinishCondition() : getTreasureFinishCondition();
 
+    if(selectModeInfo.type == PlayType.treasure) {
+      customPosterData.value = {};
+    }
+
     let receiveConditions = openAntiBot.value ? "" : [];
 
     let validityDuration = '';
@@ -1693,11 +1697,14 @@ const checkUsdMinNumber = (isInTemplate) => {
         } else {
             let val1 = 0;
             if(currentLuckDropConfig?.minAvgUsdAmount) {
-              val1 = +math.format(math.multiply(math.bignumber(+totalCount), math.bignumber(usdPrice)));
+              val1 = +math.format(math.divide(math.bignumber(+amountValue), math.bignumber(+totalCount)));
             }
 
             const isAmountForbidden = currentLuckDropConfig?.minTotalUsdAmount ? +math.format(math.multiply(math.bignumber(+amountValue), math.bignumber(usdPrice))) < currentLuckDropConfig.minTotalUsdAmount : false;
-            const isAvgForbidden = currentLuckDropConfig?.minAvgUsdAmount ? +math.format(math.divide(math.bignumber(+amountValue), math.bignumber(val1))) < currentLuckDropConfig.minAvgUsdAmount : false;
+
+            const isAvgForbidden = currentLuckDropConfig?.minAvgUsdAmount ? +math.format(math.multiply(math.bignumber(val1), math.bignumber(usdPrice))) < currentLuckDropConfig.minAvgUsdAmount : false;
+
+
             forbiddenText = isAmountForbidden || isAvgForbidden ?
                             `The prize pool must be above ${isInTemplate ? ('<span class="font-color-1D9BF0">$' + currentLuckDropConfig.minTotalUsdAmount + '</span>') : ('$' + currentLuckDropConfig.minTotalUsdAmount)}
                             and the average prize must be above
@@ -2169,6 +2176,7 @@ const selectPublishMode = (params, index) => {
         baseFormData.customizedReward = '';
         showGeneralLottery.value = false;
         previewCustomPosterUrl.value = '';
+        treasureFormData.fansUnitAmount = calcFansUnitAmount();
     } else {
         showGeneralLottery.value = true;
         previewCustomPosterUrl.value = customPosterInfo.value && customPosterInfo.value.after && customPosterInfo.value.after.imagePath || ''

+ 13 - 12
src/view/iframe/red-packet/luck-draw.vue

@@ -202,7 +202,8 @@
             </div>
             <get-more :reportData="{
                 pageSource: Report.pageSource.received_success_page,
-                postId: state.postId
+                postId: state.postId,
+                redPacketType: Report.redPacketType.lottery
             }"></get-more>
         </div>
 
@@ -265,13 +266,11 @@
                         <a-tooltip :title="state.detail.amountValue">
                             {{ getBit(state.detail.amountValue) || '' }}
                         </a-tooltip>
-                    </span> {{
-                            state.detail.currencySymbol || ''
-                    }}
+                    </span> {{ state.detail.currencySymbol || '' }}
                 </div>
             </div>
             <div class="luck-list" @scroll="handleScroll">
-                <div class="luck-item" v-for="item, i in     state.detail.allReceived" v-bind:key="i">
+                <div class="luck-item" v-for="item, i in state.detail.allReceived" v-bind:key="i">
                     <img v-if="item.simpleUserInfoVO.avatarUrl" :src="item.simpleUserInfoVO.avatarUrl" alt
                         @click="openTwitterDetail(item)" />
                     <img v-else :src="require('@/assets/svg/icon-twitter.svg')" alt />
@@ -315,7 +314,7 @@
             <div class="header"
                 :style="{ 'backgroundImage': `url(${require('@/assets/subject/002-back-head-top.svg')})` }"
                 v-show="state.close_status == '已经过期了'">
-                <div class="close-title" v-for="item in state.close_text">{{ item }}</div>
+                <div class="close-title" v-for="item in     state.close_text">{{ item }}</div>
             </div>
 
             <!-- 没有抽中 -->
@@ -352,7 +351,8 @@
                 </div>
                 <get-more :style_type="2" :reportData="{
                     pageSource: Report.pageSource.waitingLotteryPage,
-                    postId: state.postId
+                    postId: state.postId,
+                    redPacketType: Report.redPacketType.lottery
                 }"></get-more>
                 <div class="notification_switch" v-if="state.notification_show">
                     <span>Announcement Notification</span>
@@ -412,7 +412,8 @@
             </div>
             <get-more :reportData="{
                 pageSource: Report.pageSource.missingLotteryPage,
-                postId: state.postId
+                postId: state.postId,
+                redPacketType: Report.redPacketType.lottery
             }" v-if="state.close_status != '等待结果'"></get-more>
         </div>
 
@@ -458,7 +459,7 @@ import FontAmount from '@/view/components/font-amount.vue'
 import FontZoom from '@/view/components/font-zoom.vue'
 import ComponentZoom from '@/view/components/component-zoom.vue'
 import GetMore from '@/view/iframe/publish/components/get-more.vue'
-import { setChromeStorage, getChromeStorage, sendChromeTabMessage, chromeExtensionUrl } from '@/uilts/chromeExtension.js'
+import { setChromeStorage, getChromeStorage, sendCurrentTabMessage, chromeExtensionUrl } from '@/uilts/chromeExtension.js'
 import Report from "@/log-center/log"
 import { srcPublishSuccess } from '@/http/publishApi'
 import { discordAuthUrl, checkGuildJoined } from '@/http/discordApi'
@@ -1074,7 +1075,7 @@ const reSetBindTwtterId = (_params) => {
 const reportBindTweetSuccess = (params) => {
     let { discordTask, srcUserId } = params || {};
     discordTaskDetail = discordTask;
-    sendChromeTabMessage({
+    sendCurrentTabMessage({
         actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
         data: {
             screen_name: srcUserId,
@@ -1641,7 +1642,7 @@ function handleRedPacket() {
 }
 
 chrome.storage.onChanged.addListener(changes => {
-    if (changes.userInfo) {
+    if (changes.userInfo && changes.userInfo.newValue) {
         // let item = JSON.parse(changes.userInfo.newValue)
         state.loading_show = false
         init()
@@ -3387,7 +3388,7 @@ body {
 
 .none {
     display: flex;
-    align-item: center;
+    align-items: center;
     justify-content: center;
     width: 100%;
     height: 100%;

+ 7 - 5
src/view/iframe/red-packet/red-packet.vue

@@ -212,7 +212,8 @@
       </div>
       <get-more :reportData="{
         pageSource: Report.pageSource.received_success_page,
-        postId: state.postId
+        postId: state.postId,
+        redPacketType: Report.redPacketType.giveaway
       }"></get-more>
     </div>
 
@@ -369,7 +370,8 @@
       </div>
       <get-more :reportData="{
         pageSource: Report.pageSource.expiredPage,
-        postId: state.postId
+        postId: state.postId,
+        redPacketType: Report.redPacketType.giveaway
       }"></get-more>
     </div>
 
@@ -413,7 +415,7 @@ import { message } from 'ant-design-vue';
 import FontAmount from '@/view/components/font-amount.vue'
 import FontZoom from '@/view/components/font-zoom.vue'
 import GetMore from '@/view/iframe/publish/components/get-more.vue'
-import { setChromeStorage, getChromeStorage, sendChromeTabMessage, chromeExtensionUrl } from '@/uilts/chromeExtension.js'
+import { setChromeStorage, getChromeStorage, sendCurrentTabMessage, chromeExtensionUrl } from '@/uilts/chromeExtension.js'
 import Report from "@/log-center/log"
 import { srcPublishSuccess } from '@/http/publishApi'
 import { discordAuthUrl, checkGuildJoined } from '@/http/discordApi'
@@ -954,7 +956,7 @@ const reSetBindTwtterId = (_params) => {
 const reportBindTweetSuccess = (params) => {
   let { discordTask, srcUserId } = params || {};
   discordTaskDetail = discordTask;
-  sendChromeTabMessage({
+  sendCurrentTabMessage({
     actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
     data: {
       screen_name: srcUserId,
@@ -1434,7 +1436,7 @@ function handleRedPacket() {
 }
 
 chrome.storage.onChanged.addListener(changes => {
-  if (changes.userInfo) {
+  if (changes.userInfo && changes.userInfo.newValue) {
     // let item = JSON.parse(changes.userInfo.newValue)
     state.loading_show = false
     init()

+ 21 - 19
src/view/iframe/tab-group/joined-group-list.vue

@@ -1,14 +1,11 @@
 <template>
     <div class="group-list-page" ref="pageWrapperDom">
         <div class="title">
-            <img class="icon" :src="require('@/assets/svg/icon-joined-group-logo.svg')" >
+            <img class="icon" :src="require('@/assets/svg/icon-joined-group-logo.svg')">
             NFT Owners Group
         </div>
         <div class="content-wrapper">
-            <nft-group-list style="height: 100%" 
-                ref="groupListDom"
-                :showBadge="true" 
-                @clickCallBack="clickHandler"
+            <nft-group-list style="height: 100%" ref="groupListDom" :showBadge="true" @clickCallBack="clickHandler"
                 @updateList="updateList"></nft-group-list>
         </div>
     </div>
@@ -18,14 +15,16 @@
 import { onMounted, ref, nextTick } from "vue";
 import NftGroupList from '@/view/components/nft-group-list.vue';
 
-import { sendChromeTabMessage, setChromeStorage } from '@/uilts/chromeExtension.js';
+import { sendCurrentTabMessage, setChromeStorage } from '@/uilts/chromeExtension.js';
 
 let groupListDom = ref(null);
 
 const clickHandler = (params) => {
-    setChromeStorage({ groupTabData: JSON.stringify({
-        deTabVal: 'deGroupTab'
-    })})
+    setChromeStorage({
+        groupTabData: JSON.stringify({
+            deTabVal: 'deGroupTab'
+        })
+    })
     let url = `https://twitter.com/${params.defaultTwitterAccount}`;
     sendMessageToContent({
         actionType: 'IFRAME_PAGE_JUMP',
@@ -36,11 +35,11 @@ const clickHandler = (params) => {
 }
 
 const sendMessageToContent = (params) => {
-    let {actionType, data} = params || {};
+    let { actionType, data } = params || {};
     chrome.tabs.getCurrent((tab) => {
         chrome.tabs.sendMessage(tab.id, {
-        actionType,
-        data,
+            actionType,
+            data,
         }, (res) => { console.log(res) });
     })
 }
@@ -52,8 +51,8 @@ const updateList = (data) => {
 const setHeight = (data) => {
     const maxHeight = 321;
     nextTick(() => {
-        if(!data || !data.length) { 
-            sendChromeTabMessage({
+        if (!data || !data.length) {
+            sendCurrentTabMessage({
                 actionType: "IFRAME_JOINED_GROUP_SET_STYLE",
                 data: {
                     height: '0px'
@@ -62,17 +61,17 @@ const setHeight = (data) => {
             return;
         }
         let listDom = document.querySelector('.list-content');
-        if(listDom) {
+        if (listDom) {
             const titleDomHeight = 56, marginBottom = 12;
             let height = maxHeight;
             let contentHeight = listDom.offsetHeight + titleDomHeight + marginBottom;
 
-            if(contentHeight < maxHeight) {
-                height =  contentHeight;
+            if (contentHeight < maxHeight) {
+                height = contentHeight;
             } else {
                 height = maxHeight;
             }
-            sendChromeTabMessage({
+            sendCurrentTabMessage({
                 actionType: "IFRAME_JOINED_GROUP_SET_STYLE",
                 data: {
                     height: height + 'px'
@@ -87,7 +86,9 @@ onMounted(() => {
 </script>
 
 <style  lang="scss">
-html, body, #app {
+html,
+body,
+#app {
     width: 100%;
     height: 100%;
     margin: 0;
@@ -115,6 +116,7 @@ html, body, #app {
         }
 
     }
+
     .content-wrapper {
         height: calc(100% - 60px);
         overflow-y: auto;

+ 21 - 14
src/view/iframe/tool-box/buy-nft.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="nft-layer" v-if="nftAuthINfo">
         <div class="title">
-            <img @click="close" :src=" require('@/assets/svg/icon-close.svg') " />
+            <img @click="close" :src="require('@/assets/svg/icon-close.svg')" />
             <span class="text">Unlock by {{ nftAuthINfo.nftProjectName }} NFT</span>
         </div>
         <div class="content">
@@ -11,16 +11,12 @@
             <div class="tips">
                 <span>only {{ nftAuthINfo.nftProjectName }} NFT holder can view the content</span>
             </div>
-            <div
-                class="btn"
-                v-if="btnStatus"
-                @click="buy"
-                v-click-log="{
-                    pageSource: Report.pageSource.buy_posteditor_nft_dialog,
-                    objectType: Report.objectType.buy_button,
-                    nftProjectId: nftAuthINfo.certNftProjectId || '',
-                    postId: postId,
-                }">
+            <div class="btn" v-if="btnStatus" @click="buy" v-click-log="{
+                pageSource: Report.pageSource.buy_posteditor_nft_dialog,
+                objectType: Report.objectType.buy_button,
+                nftProjectId: nftAuthINfo.certNftProjectId || '',
+                postId: postId,
+            }">
                 <span>Buy NFT to Participate</span>
             </div>
             <div class="btn disabled" v-else>
@@ -36,7 +32,7 @@ import { ref, onBeforeMount } from 'vue';
 import { ElMessage } from 'element-plus';
 import { getQueryString } from '@/uilts/help';
 import { getPostEditorNftCertInfo } from '@/http/toolBoxApi';
-import { getChromeStorage, sendChromeTabMessage } from "@/uilts/chromeExtension";
+import { getChromeStorage, sendCurrentTabMessage } from "@/uilts/chromeExtension";
 import "element-plus/es/components/message/style/css";
 
 const postId = ref('')
@@ -44,7 +40,7 @@ const btnStatus = ref(false)
 const nftAuthINfo = ref(null)
 
 const close = () => {
-    sendChromeTabMessage({
+    sendCurrentTabMessage({
         actionType: 'Hide_ToolBox_By_Nft'
     })
 }
@@ -89,7 +85,7 @@ onBeforeMount(() => {
         }
     }).then(res => {
         let { code, data } = res;
-        if ( code === 0 ) {
+        if (code === 0) {
             btnStatus.value = true;
             nftAuthINfo.value = data;
             // report
@@ -110,6 +106,7 @@ body {
     margin: 0;
     padding: 0;
 }
+
 .nft-layer {
     position: absolute;
     top: 50%;
@@ -119,11 +116,13 @@ body {
     transform: translate(-50%, -50%);
     border-radius: 20px;
     background: #FFFFFF;
+
     .title {
         height: 48px;
         display: flex;
         align-items: center;
         box-shadow: 0px 0.5px 0px #D1D9DD;
+
         img {
             width: 24px;
             height: 24px;
@@ -131,24 +130,28 @@ body {
             margin-right: 12px;
             cursor: pointer;
         }
+
         .text {
             font-size: 16px;
             font-weight: 500;
             line-height: 19px;
         }
     }
+
     .content {
         .img {
             display: flex;
             height: 250px;
             align-items: center;
             justify-content: center;
+
             img {
                 width: 150px;
                 height: 150px;
                 border-radius: 5px;
             }
         }
+
         .tips {
             position: relative;
             font-size: 14px;
@@ -158,6 +161,7 @@ body {
             margin: auto;
             margin-bottom: 28px;
             width: calc(100% - 30px);
+
             &::before {
                 position: absolute;
                 top: 50%;
@@ -168,6 +172,7 @@ body {
                 height: 1px;
                 background-color: rgba($color: #000000, $alpha: .2);
             }
+
             &::after {
                 position: absolute;
                 top: 50%;
@@ -179,6 +184,7 @@ body {
                 background-color: rgba($color: #000000, $alpha: .2);
             }
         }
+
         .btn {
             display: flex;
             align-items: center;
@@ -192,6 +198,7 @@ body {
             font-weight: 600;
             border-radius: 100px;
             background: #1D9BF0;
+
             &.disabled {
                 background: #CDCDCD;
                 cursor: not-allowed;

+ 23 - 17
src/view/iframe/tool-box/card.vue

@@ -13,13 +13,14 @@
         <div class="content" v-else>
             <template v-if="state.showMask && state.status != '固定右上角'">
                 <div class="mask" @click="confirmStatus">
-                    <img class="luck" :src=" require('@/assets/svg/icon-post-lock.svg') " />
+                    <img class="luck" :src="require('@/assets/svg/icon-post-lock.svg')" />
                     <div class="btn">
-                        <img class="img" v-if="state.detail && state.detail.nftProjectIcon" :src=" state.detail.nftProjectIcon " />
-                        <div class="font">Available for holders of {{state.detail.nftProjectName}} NFT</div>
+                        <img class="img" v-if="state.detail && state.detail.nftProjectIcon"
+                            :src="state.detail.nftProjectIcon" />
+                        <div class="font">Available for holders of {{ state.detail.nftProjectName }} NFT</div>
                     </div>
                 </div>
-                <img class="mask_bg" v-if="state.detail.viewBgImagePath" :src=" state.detail.viewBgImagePath " />
+                <img class="mask_bg" v-if="state.detail.viewBgImagePath" :src="state.detail.viewBgImagePath" />
             </template>
             <iframe :src="state.iframe_url" v-show="state.status == 'iframe'" ref="dom_iframe" frameborder="0"
                 scrolling="yes" allow="camera *;microphone *"></iframe>
@@ -72,7 +73,7 @@
     </div>
 </template>
 <script setup>
-import { getChromeStorage, setChromeStorage, defineProps, sendChromeTabMessage } from "@/uilts/chromeExtension";
+import { getChromeStorage, setChromeStorage, defineProps, sendCurrentTabMessage } from "@/uilts/chromeExtension";
 import { getPostDetail } from '@/http/redPacket.js'
 import { getPostEditorNftCertInfo, unlockNftCert } from '@/http/toolBoxApi'
 import { guid, getQueryString } from "@/uilts/help";
@@ -150,7 +151,7 @@ onMounted(() => {
     state.postId = getQueryString('postId')
     state.tweetId = getQueryString('tweetId')
 
-    sendChromeTabMessage({
+    sendCurrentTabMessage({
         actionType: 'Get_ToolBox_Fixed_TweetId'
     }, (res) => {
         if (res == state.tweetId) {
@@ -195,13 +196,13 @@ const getDetail = () => {
                     postId: state.postId,
                     tweetId: state.tweetId
                 }, () => {
-                  Report.reportLog({
-                    objectType: Report.objectType.tweetPostBinded,
-                    redPacketType: 5,
-                    postId: state.postId,
-                  }, {
-                    'post-editor-url': state.detail.convertUrl
-                  });
+                    Report.reportLog({
+                        objectType: Report.objectType.tweetPostBinded,
+                        redPacketType: 5,
+                        postId: state.postId,
+                    }, {
+                        'post-editor-url': state.detail.convertUrl
+                    });
                 })
             }
             console.log('postBizData', state.detail)
@@ -253,7 +254,7 @@ const getNftInfoStatus = () => {
         }
     }).then(res => {
         let { code, data } = res;
-        if ( code === 0 ) {
+        if (code === 0) {
             nftAuthINfo.value = data;
         }
     })
@@ -303,7 +304,7 @@ const confirmStatus = () => {
             if (nftAuthINfo.value && nftAuthINfo.value?.certStatus === 1) {
                 succBack()
             } else {
-                sendChromeTabMessage({
+                sendCurrentTabMessage({
                     actionType: 'Set_ToolBox_By_Nft',
                     data: {
                         postId: state.postId,
@@ -416,7 +417,7 @@ const handleFull = () => {
             // 切换状态
             state.status = '固定右上角'
             state.show_btn = false
-            sendChromeTabMessage({
+            sendCurrentTabMessage({
                 actionType: 'Set_ToolBox_Fixed',
                 data: {
                     type: '全屏',
@@ -439,7 +440,7 @@ const handleFixed = () => {
     // 切换状态
     state.show_btn = false
     state.status = '固定右上角'
-    sendChromeTabMessage({
+    sendCurrentTabMessage({
         actionType: 'Set_ToolBox_Fixed',
         data: {
             type: '固定右上角',
@@ -660,10 +661,12 @@ const msgListener = (req, sender, sendResponse) => {
             width: 100%;
             height: 100%;
             background-color: rgba($color: #000000, $alpha: .5);
+
             .luck {
                 width: 100px;
                 height: 100px;
             }
+
             .btn {
                 display: flex;
                 align-items: center;
@@ -673,6 +676,7 @@ const msgListener = (req, sender, sendResponse) => {
                 margin-top: 12px;
                 border-radius: 100px;
                 background: #1D9BF0;
+
                 .img {
                     overflow: hidden;
                     width: 35px;
@@ -680,6 +684,7 @@ const msgListener = (req, sender, sendResponse) => {
                     margin-right: 16px;
                     border-radius: 4px;
                 }
+
                 .font {
                     width: 188px;
                     color: #fff;
@@ -690,6 +695,7 @@ const msgListener = (req, sender, sendResponse) => {
                 }
             }
         }
+
         .mask_bg {
             position: absolute;
             z-index: 1;

+ 13 - 9
src/view/iframe/tool-box/full.vue

@@ -14,13 +14,13 @@
         <div class="content">
             <template v-if="showMask">
                 <div class="mask" @click="confirmStatus">
-                    <img class="luck" :src=" require('@/assets/svg/icon-post-lock.svg') " />
+                    <img class="luck" :src="require('@/assets/svg/icon-post-lock.svg')" />
                     <div class="btn">
-                        <img class="img" v-if="detail.nftProjectIcon" :src=" detail.nftProjectIcon " />
-                        <div class="font">Available for holders of {{detail.nftProjectName}} NFT</div>
+                        <img class="img" v-if="detail.nftProjectIcon" :src="detail.nftProjectIcon" />
+                        <div class="font">Available for holders of {{ detail.nftProjectName }} NFT</div>
                     </div>
                 </div>
-                <img class="mask_bg" v-if="detail.viewBgImagePath" :src=" detail.viewBgImagePath " />
+                <img class="mask_bg" v-if="detail.viewBgImagePath" :src="detail.viewBgImagePath" />
             </template>
             <iframe :src="state.iframe_url" frameborder="0" allow="camera *;microphone *"></iframe>
         </div>
@@ -30,7 +30,7 @@
 import { reactive, ref } from "vue";
 import { ElMessage } from 'element-plus'
 import { unlockNftCert } from '@/http/toolBoxApi'
-import { getChromeStorage, sendChromeTabMessage } from "@/uilts/chromeExtension";
+import { getChromeStorage, sendCurrentTabMessage } from "@/uilts/chromeExtension";
 import "element-plus/es/components/message/style/css";
 
 let state = reactive({
@@ -81,7 +81,7 @@ const clickFull = () => {
 }
 
 const changeFull = () => {
-    sendChromeTabMessage({
+    sendCurrentTabMessage({
         actionType: 'Set_ToolBox_Fixed',
         data: {
             type: '全屏',
@@ -92,7 +92,7 @@ const changeFull = () => {
 }
 
 const changeFixed = () => {
-    sendChromeTabMessage({
+    sendCurrentTabMessage({
         actionType: 'Set_ToolBox_Fixed',
         data: {
             type: '固定右上角',
@@ -111,7 +111,7 @@ const clickClose = () => {
 }
 
 const sendClose = () => {
-    sendChromeTabMessage({
+    sendCurrentTabMessage({
         actionType: 'Set_ToolBox_Fixed',
         data: {
             type: '关闭',
@@ -140,7 +140,7 @@ const confirmStatus = () => {
             if (nftAuthINfo.value && nftAuthINfo.value?.certStatus === 1) {
                 succBack()
             } else {
-                sendChromeTabMessage({
+                sendCurrentTabMessage({
                     actionType: 'Set_ToolBox_By_Nft',
                     data: {
                         postId: postId.value,
@@ -238,10 +238,12 @@ const hideMask = (data) => {
             width: 100%;
             height: 100%;
             background-color: rgba($color: #000000, $alpha: .5);
+
             .luck {
                 width: 100px;
                 height: 100px;
             }
+
             .btn {
                 display: flex;
                 align-items: center;
@@ -252,6 +254,7 @@ const hideMask = (data) => {
                 margin-top: 12px;
                 border-radius: 100px;
                 background: #1D9BF0;
+
                 .img {
                     overflow: hidden;
                     width: 35px;
@@ -259,6 +262,7 @@ const hideMask = (data) => {
                     margin-right: 16px;
                     border-radius: 4px;
                 }
+
                 .font {
                     width: 188px;
                     color: #fff;

+ 334 - 0
src/view/iframe/treasure-hunt/all-receive-list.vue

@@ -0,0 +1,334 @@
+<template>
+    <div class="invite-list">
+        <div class="head">
+            <div class="left">
+              <img height="20" :src="require('@/assets/svg/icon-back-2.svg')" @click="clickBack" />
+              <span>{{ state.detail.receiveCountWithAmount }} People Get Money</span>
+            </div>
+            <div class="right">
+              <img @click="showOptionSheet = true" :src="sortTypeIcon" alt="">
+            </div>
+        </div>
+        <div class="content">
+            <img v-show="state.receive.loading && state.receive.list.length == 0"
+                :src="require('@/assets/svg/icon-loading-gray.svg')" alt="" class="loading" />
+            <img v-if="state.receive.list.length == 0 && state.receive.end"
+                :src="require('@/assets/svg/icon-empty-list.svg')" alt="" class="empty" />
+            <div class="list" v-else @scroll="handleScroll($event)">
+                <div class="item" v-for="item in state.receive.list" :key="item.userInfo.uid">
+                    <div class="left">
+                        <img :src="item.userInfo.avatarUrl" alt="" @click="clickItem(item)" />
+                    </div>
+                    <div class="right">
+                        <div>
+                            <div class="name" @click="clickItem(item)">{{ item.userInfo.nickName }}</div>
+                            <div class="time">{{ getBeforeTimeFormat(item.timestamp) }}</div>
+                        </div>
+                        <div class="money">${{ item.amountUsdValue }}</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="option-sheet" v-if="showOptionSheet">
+          <div class="item" v-for="(item, index) in optionList" :key="index" @click="clickOption(item)">
+            <img :src="item.icon" >
+            <div class="label">
+              {{item.label}}
+            </div>
+          </div>
+        </div>
+        <div class="option-mask" v-if="showOptionSheet" @click="showOptionSheet = false"></div>
+    </div>
+</template>
+<script setup>
+import { receiveListV2 } from '@/http/treasure'
+import { inject, onMounted, ref } from 'vue'
+import { getBeforeTimeFormat } from "@/uilts/help"
+import Report from "@/log-center/log"
+
+let amountIcon = require('@/assets/svg/icon-sort-amount.svg');
+let timeIcon = require('@/assets/svg/icon-sort-time.svg');
+
+
+let sortTypeIcon = ref(amountIcon);
+
+let state = inject('state')
+state.receive = {
+    end: false,
+    list: []
+}
+
+let optionList = ref([
+  {
+    icon: amountIcon,
+    label: 'Amount',
+    type: 2
+  },
+  {
+    icon: timeIcon,
+    label: 'Time',
+    type: 1
+  }
+])
+
+
+let page_num = 1
+let page_size = 10
+let sortType = 2;
+let list_end = false
+
+let showOptionSheet = ref(false);
+
+const clickBack = () => {
+    state.page_show = ''
+}
+
+onMounted(() => {
+    list()
+})
+
+const clickItem = (item) => {
+    window.open(`https://twitter.com/${item.userInfo.nickName}`)
+}
+
+const clickOption = (params) => {
+  showOptionSheet.value = false;
+  sortTypeIcon.value = params.icon;
+  page_num = 1;
+  sortType = params.type;
+  list()
+}
+
+function handleScroll(e) {
+    if (list_end) {
+        return
+    }
+    e = e.target
+    if ((e.clientHeight + e.scrollTop) / e.scrollHeight > .8) {
+        if (page_num * page_size == state.receive.list.length) {
+            page_num++
+            list()
+        }
+        list_end = true
+    }
+}
+
+const list = () => {
+    state.receive.loading = true
+    receiveListV2({
+        params: {
+            postId: state.postId,
+            pageNum: page_num,
+            pageSize: page_size,
+            sortType
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            state.receive.loading = false
+            if(page_num < 2) {
+              state.receive.list = res.data || [];
+            } else {
+              state.receive.list = state.receive.list.concat(res.data)
+            }
+            state.receive.end = true
+            list_end = false
+        }
+    })
+}
+</script>
+<style lang="scss" scoped>
+.invite-list {
+    width: 375px;
+    height: 580px;
+    position: relative;
+
+    .head {
+        width: 100%;
+        height: 48px;
+        box-sizing: border-box;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+
+        background: #FFFFFF;
+        box-shadow: inset 0px -1px 0px #F2F2F2;
+
+        .left {
+          display: flex;
+          align-items: center;
+        }
+
+        img {
+            width: 24px;
+            height: 24px;
+            margin: 0 12px;
+            cursor: pointer;
+        }
+
+        span {
+            font-style: normal;
+            font-weight: 700;
+            font-size: 17px;
+            line-height: 20px;
+            letter-spacing: 0.3px;
+
+            color: #000000;
+        }
+    }
+
+    .content {
+        position: relative;
+        height: calc(100% - 48px);
+
+        .footer {
+            background: #fff;
+            padding: 10px 16px 25px 16px;
+        }
+
+        .error {
+            height: 204px;
+            color: #BABABA;
+            background-color: #fff;
+            font-weight: 500;
+            font-size: 15px;
+            line-height: 204px;
+            text-align: center;
+
+        }
+
+        .list {
+            background: #fff;
+            overflow-y: auto;
+            height: 100%;
+
+            .item {
+                height: 60px;
+                display: flex;
+                align-items: center;
+
+                .left {
+                    width: 58px;
+                    text-align: center;
+
+                    img {
+                        cursor: pointer;
+                        border-radius: 50px;
+                        width: 30px;
+                        height: 30px;
+                    }
+                }
+
+                .right {
+                    flex: 1;
+                    box-shadow: inset 0px -1px 0px #F2F2F2;
+
+                    display: flex;
+                    align-items: center;
+                    height: 100%;
+                    justify-content: space-between;
+
+                    .name {
+                        color: #000000;
+                        font-weight: 500;
+                        font-size: 15px;
+                        cursor: pointer;
+                    }
+
+                    .time {
+                        color: #A6A6A6;
+                        font-weight: 400;
+                        font-size: 12px;
+                        margin-right: 17px;
+                    }
+
+                    .money {
+                        color: #FCB936;
+                        font-weight: 500;
+                        font-size: 13px;
+                        margin-right: 16px;
+
+                    }
+                }
+            }
+        }
+    }
+
+    .option-mask {
+      width: 100%;
+      height: 100%;
+      position: absolute;
+      top: 0;
+      left: 0;
+      z-index: 800;
+    }
+    .option-sheet {
+      width: 200px;
+      background: #FFFFFF;
+      box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.2);
+      border-radius: 14px;
+      position: absolute;
+      top: 40px;
+      right: 8px;
+      z-index: 1000;
+      cursor: pointer;
+
+      .item {
+        width: 100%;
+        height: 40px;
+        display: flex;
+        align-items: center;
+
+        img {
+          width: 24px;
+          margin: 0 12px;
+        }
+
+        .label {
+          font-weight: 500;
+          font-size: 15px;
+          width: calc(100% - 52px);
+          height: 100%;
+          display: flex;
+          align-items: center;
+        }
+      }
+
+       .item:first-child {
+          .label {
+            box-shadow: inset 0px -1px 0px #F2F2F2;
+          }
+        }
+    }
+}
+
+.loading {
+    width: 100px;
+    height: 100px;
+    position: fixed;
+    top: 50%;
+    left: 50%;
+    margin-left: -50px;
+    margin-top: -50px;
+    animation: rotation 1s linear infinite;
+}
+
+.empty {
+    width: 100px;
+    height: 100px;
+    position: fixed;
+    top: 50%;
+    left: 50%;
+    margin-left: -50px;
+    margin-top: -50px;
+}
+
+@keyframes rotation {
+    from {
+        -webkit-transform: rotate(0deg);
+    }
+
+    to {
+        -webkit-transform: rotate(360deg);
+    }
+}
+</style>

+ 336 - 0
src/view/iframe/treasure-hunt/components/boxs.vue

@@ -0,0 +1,336 @@
+<template>
+    <div class="area-boxs">
+        <!-- 箱子 -->
+        <div class="box-process">
+            <div class="item" v-for="item, i in state.boxs"
+                :key="i"
+                :style="{ 'margin-left': item.icon_margin_left, 'z-index': 10 - i }">
+                <!--悬浮 -->
+                <!-- < hover - tip : txt=" item.txt" v-show="item.show || item.openStatus" :icon="item.hover_icon">
+                </hover-tip> -->
+                <!-- 金额 -->
+                <span class="money" :style="{ 'color': item.money_color, 'top': item.money_top }">
+                    <img :src="require('@/assets/svg/icon-green-yes.svg')" alt="" v-if="item.openStatus == 1" />
+                    {{ item.openStatus == 0 ? item.txt : item.amountUsdValue }}
+                </span>
+                <!-- 宝箱 -->
+                <img :src="item.icon" alt="" @mouseenter="mouseItem(i)" @mouseleave="mouseLeaveItem(i)"
+                    :style="{ 'width': item.icon_width, 'height': item.icon_width }" class="box"
+                    :class="{ 'active': i == 0 && item.openStatus == 0 ? true : item.openStatus == 0 && state.boxs[i-1]['openStatus'] == 1  }" @click="clickBox(item)" />
+                <!-- 发光 -->
+                <img :src="require('@/assets/img/icon-flash-active.png')" alt="" class="flash"
+                    v-if="i == 0 && item.openStatus == 0 ? true : item.openStatus == 0 && state.boxs[i-1]['openStatus'] == 1"
+                    :style="{ 'margin-left': item.flash_margin_top, 'margin-top': item.flash_margin_top, 'width': item.flash_width, 'height': item.flash_width }" />
+
+                <!-- 进度条 -->
+                <div class="line" :style="{ 'width': item.line_width, 'left': item.line_left }">
+                    <div class="full" :style="{ 'width': item.full_width }"></div>
+                </div>
+            </div>
+        </div>
+        <!-- 人数 -->
+        <div class="people">
+            <div class="item" v-for="item, i in state.boxs"
+            :key="i"
+                :style="{ 'margin-left': item.icon_margin_left, 'width': item.icon_width }">
+                <img :src="require('@/assets/svg/icon-user1.svg')" alt="" />
+                <span>{{ item.inviteProgress }}</span>
+            </div>
+
+        </div>
+    </div>
+</template>
+<script setup>
+import { onMounted, inject, watch } from 'vue'
+import { checkIsLogin } from '@/uilts/chromeExtension'
+
+
+let state = inject('state')
+// ---- box 区域
+let silver_close_box = require('@/assets/img/icon-silver-close-box.png')
+let silver_open_box = require('@/assets/img/icon-silver-open-box.png')
+let gold_open_box = require('@/assets/img/icon-gold-open-box.png')
+let gold_close_box = require('@/assets/img/icon-gold-close-box.png')
+let purple_open_box = require('@/assets/img/icon-purple-open-box.png')
+let purple_close_box = require('@/assets/img/icon-purple-close-box.png')
+let global_refresh = inject('global_refresh')
+
+watch(global_refresh, () => {
+    if (global_refresh.value) {
+        init()
+    }
+})
+
+onMounted(() => {
+    init()
+})
+const init = () => {
+    boxsStatus()
+    btnStatus()
+}
+
+async function clickBox(item) {
+    let _userInfo = await checkIsLogin()
+    if (!_userInfo) {
+        return
+    }
+
+    if (item.openStatus == 0 && item.taskFinishStatus == 1 && state.btn_loading == false) {
+        state.btn_loading = true
+        state.treasureOpen()
+    }
+}
+
+state.boxs = [{
+    icon: '',
+    icon_open: silver_open_box,
+    icon_close: silver_close_box,
+    icon_margin_left: '17px',
+    icon_width: '46px',
+
+    show: false,
+    flash_width: '70px',
+    flash_margin_top: `-${70 / 2}px`,
+    line_width: '25px',
+    line_left: `-${25 - 10}px`,
+    money_color: '#BFCCE4',
+    money_top: '-20px'
+}, {
+    icon: '',
+    icon_open: gold_open_box,
+    icon_close: gold_close_box,
+
+    show: false,
+    icon_width: '46px',
+    flash_width: '70px',
+    icon_margin_left: '33px',
+    flash_margin_top: `-${70 / 2}px`,
+    line_width: '55px',
+    line_left: `-${55 - 10}px`,
+    money_color: '#FCB936', money_top: '-20px'
+
+}, {
+    icon: '',
+    icon_open: gold_open_box,
+    icon_close: gold_close_box,
+
+    show: false,
+    icon_width: '66px',
+    flash_width: '90px',
+    icon_margin_left: '31px',
+    flash_margin_top: `-${90 / 2}px`,
+    line_width: '60px',
+    line_left: `-${60 - 15}px`,
+    money_color: '#FCB936', money_top: '-15px'
+
+}, {
+    icon: purple_close_box,
+    icon_open: purple_open_box,
+    icon_close: purple_close_box,
+    show: false,
+    icon_width: '84px',
+    flash_width: '108px',
+    icon_margin_left: '23px',
+    flash_margin_top: `-${108 / 2}px`,
+    line_width: '60px',
+    line_left: `-${60 - 20}px`,
+    money_color: '#FCB936', money_top: '-10px'
+}]
+
+const setLineFull = (box_num = 0, finishNeedInviteCount = 0, successInviteCount = 0) => {
+    state.boxs[box_num].full_width = `${(successInviteCount / finishNeedInviteCount) * 100}%`
+}
+
+const btnStatus = () => {
+    for (let i in state.boxs) {
+        if (state.boxs[i].taskFinishStatus == 0) {
+            let num = state.boxs[i].finishNeedInviteCount - state.boxs[i].successInviteCount
+            if (num == 1) {
+                state.open_btn.txt = 'Invite 1 Friend to Open'
+            } else {
+                state.open_btn.txt = `Invite ${num} Friends to Open`
+            }
+            state.open_btn.disabled = true
+            break
+        }
+    }
+
+    state.treasureId = ''
+    let open_num = 0
+    // 有打开的箱子 Open the chest
+    state.boxs.forEach((item, index) => {
+        if (item.taskFinishStatus == 1 && item.openStatus == 0) {
+            state.open_btn.txt = 'Open the Treasure Chest'
+            state.open_btn.disabled = false
+            if (!state.treasureId) {
+                state.treasureId = item.id
+            }
+        }
+        setLineFull(index, item.finishNeedInviteCount, item.successInviteCount)
+        // 箱子全部打开了
+        if (item.openStatus == 1) {
+            open_num++
+        }
+        if (open_num == state.boxs.length) {
+            state.open_btn.txt = 'All Chests Have Been Opened'
+            state.open_btn.disabled = true
+        }
+    })
+}
+
+
+
+const mouseItem = (i) => {
+    state.boxs[i].show = true
+    state.active_share_channel = true
+}
+const mouseLeaveItem = (i) => {
+    state.boxs[i].show = false
+    state.active_share_channel = false
+}
+
+const boxsStatus = () => {
+    state.detail.treasureRecords.forEach((item, index) => {
+        let box = state.boxs[index]
+        if (item.openStatus == 0) {
+            box.icon = box.icon_close
+        } else {
+            box.icon = box.icon_open
+        }
+        box.txt = `$${item.targetAmountUsdValue}`
+        state.boxs[index] = Object.assign(box, item)
+    })
+}
+
+</script>
+<style lang="scss" scoped>
+.area-boxs {
+    position: relative;
+
+    .people {
+        display: flex;
+        position: absolute;
+        bottom: 0px;
+        left: 10px;
+
+        .item {
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            text-align: center;
+            user-select: none;
+
+            img {
+                user-select: none;
+                width: 16px;
+                height: 16px;
+                margin-right: 3px;
+                cursor: pointer;
+            }
+
+            span {
+                color: #FFFFFF;
+                opacity: 0.4;
+                font-weight: 500;
+                font-size: 12px;
+            }
+
+
+        }
+
+    }
+
+    .box-process {
+        width: 350px;
+        height: 90px;
+        margin: 0 auto;
+        display: flex;
+        align-items: center;
+
+        img {
+            width: 60px;
+            height: 60px;
+            z-index: 2;
+            user-select: none;
+        }
+
+
+
+        .item {
+            z-index: 2;
+            display: flex;
+            justify-content: center;
+            position: relative;
+
+            .box {
+
+                cursor: pointer;
+            }
+
+            .active {
+                animation: bounce-up 0.5s linear infinite;
+            }
+
+            .flash {
+                position: absolute;
+                left: 50%;
+                top: 50%;
+                z-index: 0;
+                width: 100%;
+                height: 100%;
+            }
+
+            .money {
+                display: flex;
+                align-items: center;
+                white-space: nowrap;
+                position: absolute;
+                top: -20px;
+                font-weight: 700;
+                font-size: 16px;
+
+                img {
+                    width: 13px;
+                    height: 13px;
+                    margin-right: 4px;
+                }
+            }
+
+            .line {
+                width: 40px;
+                height: 4px;
+                background: rgba(255, 210, 59, 0.2);
+                position: absolute;
+                border-radius: 100px;
+                overflow: hidden;
+                left: -40px;
+                top: 50%;
+
+                .full {
+                    position: absolute;
+                    left: 0;
+                    top: 0;
+                    height: 4px;
+                    width: 0px;
+                    background: #FFD23B;
+                }
+            }
+        }
+    }
+}
+
+@keyframes bounce-up {
+    25% {
+        -webkit-transform: translateY(1px);
+    }
+
+    50%,
+    100% {
+        -webkit-transform: translateY(0);
+    }
+
+    75% {
+        -webkit-transform: translateY(-1px);
+    }
+}
+</style>

+ 2 - 5
src/view/iframe/treasure-hunt/components/btn.vue

@@ -52,17 +52,14 @@ const clickBtn = () => {
     }
 }
 
+
 const refresh = () => {
     if (!refreshRotate.value) {
         refreshRotate.value = true;
         setTimeout(() => {
             refreshRotate.value = false;
         }, 1000)
-
-        state.init(() => {
-            state.inviteInit()
-            state.inviteListRefresh()
-        })
+        state.refreshInit()
     }
 }
 </script>

+ 191 - 0
src/view/iframe/treasure-hunt/components/carousel.vue

@@ -0,0 +1,191 @@
+<template>
+    <div class="area-carousel">
+        <!-- left -->
+        <div class="area-left" @click="state.page_show = '总邀请者页'">
+            <div>
+                <img :src="require('@/assets/svg/icon-user1.svg')" alt="" />
+                <span>{{ state.detail.receiveCountWithAmount }}</span>
+            </div>
+            <div>Get Money</div>
+        </div>
+        <div class="area-right">
+            <div class="area-success-message" @mouseover="mouseOver" @mouseleave="mouseLeave">
+                <div class="content-success-message" ref="content_success_message">
+                    <div class="success-message" v-for="item, index in state.success_message_list" :key="index"
+                        @click="clickItem(item)">
+                        <img :src="item.userInfo.avatarUrl" alt="" />
+                        <span>Get</span> &nbsp;
+                        <span>${{ item.amountUsdValue }}</span>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+</template>
+<script setup>
+import { inject, ref, onMounted, watch } from 'vue'
+import { receiveListV2 } from '@/http/treasure.js'
+let content_success_message = ref(null)
+let state = inject('state')
+let global_refresh = inject('global_refresh')
+// ---- 走马灯
+state.success_message_list = []
+
+watch(global_refresh, () => {
+    if (global_refresh.value) {
+        init()
+    }
+})
+
+onMounted(() => {
+    init()
+})
+
+const init = () => {
+    receiveListV2({
+        params: {
+            postId: state.postId,
+            pageNum: 1,
+            pageSize: 1000,
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            state.success_message_list = res.data
+            state.success_message_list = state.success_message_list.concat(state.success_message_list)
+
+            while (state.success_message_list.length < 10 && state.success_message_list.length > 0) {
+                state.success_message_list = state.success_message_list.concat(state.success_message_list)
+            }
+
+            if (content_success_message && content_success_message.value) {
+                let dom = content_success_message.value
+                let s = state.success_message_list.length * 4
+                dom.style.animationDuration = s + 's'
+            }
+        }
+    })
+}
+const clickItem = (item) => {
+    window.open(`https://twitter.com/${item.userInfo.nickName}`)
+}
+
+const mouseOver = () => {
+    if (content_success_message && content_success_message.value && content_success_message.value.style) {
+        content_success_message.value.style.animationPlayState = 'paused'
+    }
+}
+const mouseLeave = () => {
+    if (content_success_message && content_success_message.value && content_success_message.value.style) {
+        content_success_message.value.style.animationPlayState = 'running'
+    }
+}
+</script>
+<style lang="scss" scoped>
+.area-carousel {
+    width: 100%;
+    display: flex;
+
+    .area-left {
+        cursor: pointer;
+        user-select: none;
+        width: 78px;
+
+
+        div:nth-child(1) {
+            display: flex;
+            align-items: center;
+
+            img {
+                width: 16px;
+                height: 16px;
+                margin-left: 14px;
+                margin-right: 6px;
+            }
+
+            span {
+                color: #FFFFFF;
+                font-weight: 600;
+                font-size: 12px;
+            }
+        }
+
+        div:nth-child(2) {
+            margin: 6px 0;
+            text-align: center;
+            color: #FFFFFF;
+            opacity: 0.4;
+            font-weight: 400;
+
+        }
+
+    }
+
+    .area-right {
+        flex: 1;
+        overflow: hidden;
+
+        .area-success-message {
+            height: 30px;
+            width: 100%;
+
+            .content-success-message {
+                width: fit-content;
+                display: flex;
+                animation: rolling 18s linear infinite;
+                animation-duration: 10s;
+                animation-play-state: running;
+
+                .success-message {
+                    cursor: pointer;
+                    width: fit-content;
+                    height: 30px;
+                    padding: 0 9px;
+                    border-radius: 100px;
+                    background: rgba(255, 255, 255, 0.1);
+                    display: flex;
+                    align-items: center;
+                    overflow: hidden;
+                    margin-right: 10px;
+
+                    img {
+                        width: 20px;
+                        height: 20px;
+                        border-radius: 100px;
+                        margin-right: 5px;
+
+                    }
+
+                    span {
+                        font-style: normal;
+                        font-weight: 500;
+                        font-size: 12px;
+                        line-height: 14px;
+                        white-space: nowrap;
+                    }
+
+                    span:nth-child(2) {
+                        color: #FFFFFF;
+                        opacity: 0.5;
+
+                    }
+
+                    span:nth-child(3) {
+                        color: #FFFFFF;
+                    }
+                }
+            }
+        }
+    }
+}
+
+@keyframes rolling {
+    from {
+        transform: translateX(0);
+    }
+
+    to {
+        transform: translateX(-50%);
+    }
+}
+</style>

+ 2 - 2
src/view/iframe/treasure-hunt/components/dialog.vue

@@ -25,7 +25,7 @@ const clickBtn = () => {
 <style lang="scss" scoped>
 .content {
     width: 375px;
-    height: 500px;
+    height: 100%;
     display: flex;
     align-items: center;
     justify-content: center;
@@ -39,7 +39,7 @@ const clickBtn = () => {
         opacity: .9;
         position: fixed;
         width: 375px;
-        height: 500px;
+        height: 100%;
     }
 
     .dialog {

+ 3 - 2
src/view/iframe/treasure-hunt/components/head.vue

@@ -48,7 +48,8 @@ const clickItem = () => {
         }
 
         span {
-            color: #B69882;
+            color: #FFFFFF;
+            opacity: 0.6;
             font-weight: 400;
             margin-left: 5px;
             font-size: 11px;
@@ -65,7 +66,7 @@ const clickItem = () => {
 
         span:first-child {
             color: #FFFFFF;
-            opacity: 0.7;
+            opacity: 0.6;
         }
 
         span:last-child {

+ 195 - 91
src/view/iframe/treasure-hunt/components/invite-friends.vue

@@ -1,29 +1,50 @@
 <template>
     <div class="invite-friends">
-        <div class="txt">To open the treasure chest you need to share the URL to your friends. Make sure they finish
-            the
-            tasks.</div>
-        <div class="area-url">
-            <div class="url">{{ state.detail.inviteUrl }}</div>
-            <div class="btn copy-btn" @click="clickCopy" v-click-log="state.log_invite_copy_btn_click"
+      <div class="invite-friends-content">
+        <div class="invite-friends-content-head">
+          <div class="title">Invite Friends to Open the Chest!</div>
+          <div class="info">Invitees Need to be Real New follower of {{followUserStr}} to receive rewards</div>
+        </div>
+        <div class="invite-friends-content-body">
+          <img class="tips" v-if="state.active_share_channel" :src="require('@/assets/svg/icon-channel-tips.svg')" />
+
+          <div class="share-list" :class="{'share-list-active': state.active_share_channel}">
+            <div v-for="(item, index) in state.share_list" :key="index" :data-clipboard-text="item.inviteContent"
+                @click="clickShare(item)" class="share-item">
+              <img :src="item.iconPath"  />
+              <div class="name">
+                {{item.name}}
+              </div>
+            </div>
+            <div class="share-item copy-btn" @click="clickCopy" v-click-log="state.log_invite_copy_btn_click"
                 :data-clipboard-text="state.detail.inviteCopyUrl">
-                Copy
+              <img :src="require('@/assets/svg/icon-copy-url-teasure.svg')" alt="">
+              <div class="name">
+                Copy URL
+              </div>
             </div>
         </div>
-        <div class="share-list">
-            <img :src="item.iconPath" alt="" v-for="item in state.share_list" :data-clipboard-text="item.inviteContent"
-                @click="clickShare(item)" class="share-item" />
         </div>
-        <v-btn :txt="state.open_btn.txt" :font-size="'17px'" class="btn" :icon="false"
+      </div>
+      <v-btn :txt="state.open_btn.txt" :font-size="'17px'" class="btn" :icon="false"
             :disabled="state.open_btn.disabled" v-show-log="state.log_invite_btn_show" :loading="state.btn_loading"
             v-click-log="state.log_invite_btn_click" @onClick="clickBtn" font-weight="600"></v-btn>
-
+      <div class="mask" v-show="showShareTips">
+        <div class="content">
+          <img class="icon-loading" :src="channelLoadingImg" />
+          <div class="text">
+            Link copied to clipboard
+             <br/>
+            Opening {{selectShareApp.name }}
+          </div>
+        </div>
+      </div>
     </div>
 </template>
 <script setup>
 import VBtn from '@/view/iframe/treasure-hunt/components/btn.vue'
 import { inviteChannel } from '@/http/treasure'
-import { inject, onMounted } from 'vue'
+import { inject, onMounted, ref } from 'vue'
 import Report from "@/log-center/log"
 import { getFrontConfig } from "@/http/account";
 import { faceShareRedirectUrl } from '@/http/configAPI'
@@ -31,6 +52,9 @@ import { setChromeStorage } from '@/uilts/chromeExtension.js'
 
 let ClipboardJS = require('clipboard');
 
+let loadingImg = require('@/assets/img/icon-loading-channel.png');
+
+let channelLoadingImg = ref(loadingImg);
 let state = inject('state')
 
 state.log_invite_btn_show = {
@@ -70,12 +94,28 @@ let facebookAppConfig = {
     faceShareRedirectUrl
 };
 
+let selectShareApp = ref({});
+let showShareTips = ref(false);
+let followUserStr = ref('');
+
 onMounted(() => {
     state.btn_loading = false
     setFrontConfig();
-    initInviteChannel()
+    initInviteChannel();
+    getFollowUserStr();
 })
 
+const getFollowUserStr = () => {
+  let arr = [];
+  if(state.follows && state.follows.length) {
+    for(let i = 0; i < state.follows.length; i++) {
+      let item = state.follows[i];
+      arr.push('@'+item.name);
+    }
+  }
+  followUserStr.value = arr.join(" or ");
+}
+
 chrome.management.onDisabled.addListener(() => {
     initInviteChannel()
 })
@@ -129,16 +169,20 @@ async function clickBtn() {
 }
 
 const clickShare = (item) => {
+    channelLoadingImg.value = loadingImg;
     var clipboard = new ClipboardJS('.share-item');
     clipboard.on('success', function (e) {
-        state.toast.txt = 'Copy Successfully'
-        state.toast.has_icon = true
-        state.toast.show = true
-        setTimeout(() => {
-            state.toast.show = false
-        }, 2000)
+        // state.toast.txt = 'Copy Successfully'
+        // state.toast.has_icon = true
+        // state.toast.show = true
+        // setTimeout(() => {
+        //     state.toast.show = false
+        // }, 2000)
         e.clearSelection();
     })
+    showShareTips.value = true;
+    selectShareApp.value = item;
+
     if (item.name == 'facebook') {
         setChromeStorage({
             shareFacebookData: JSON.stringify({
@@ -150,16 +194,24 @@ const clickShare = (item) => {
         }
         let url = `https://www.facebook.com/dialog/share?app_id=${facebookAppConfig.facebookAppId}&display=popup&href=${item.treasureInviteUrl}&redirect_uri=${facebookAppConfig.faceShareRedirectUrl}?params=${JSON.stringify(cbParams)}`;
 
-        chrome.windows.create({
+        setTimeout(() => {
+          showShareTips.value = false;
+          chrome.windows.create({
             width: 800,
-            type: 'normal',
-            url
-        }, function (window) {
-        })
+              type: 'normal',
+              url
+          }, function (window) {
+          })
+        }, 1000)
+
     } else {
-        chrome.tabs.create({
-            url: item.redirectPath
-        });
+        setTimeout(() => {
+          showShareTips.value = false;
+          channelLoadingImg.value = '';
+          chrome.tabs.create({
+              url: item.redirectPath
+          });
+        }, 1000)
     }
     Report.reportLog({
         businessType: Report.businessType.buttonClick,
@@ -168,7 +220,8 @@ const clickShare = (item) => {
         shareLinkId: state.invite_code,
         myShareLinkId: state.detail.inviteCopyUrl,
         currentInvitedNum: state.inviteCount,
-        postId: state.postId
+        postId: state.postId,
+        redPacketType: Report.redPacketType.treasure
     }, {
         'channel-name': item.name
     });
@@ -210,80 +263,131 @@ const clickCopy = () => {
 </script>
 <style lang="scss" scoped>
 .invite-friends {
-    padding: 18px 16px 25px 16px;
+    padding: 9px 14px 14px 14px;
     background: #fff;
+    box-sizing: border-box;
+
+    .invite-friends-content {
+      max-height: 242px;
+      overflow-y: auto;
+      margin-bottom: 10px;
+      box-sizing: border-box;
+
+      .invite-friends-content-head {
+        margin-bottom: 16px;
+        padding: 0 6px;
+        box-sizing: border-box;
+
+        .title {
+          font-weight: 900;
+          font-size: 18px;
+          margin-bottom: 7px;
+        }
+        .info {
+          font-weight: 400;
+          font-size: 12px;
+          color: #7A7A7A;
+          line-height: 15px;
+        }
 
-    .txt {
-        font-style: normal;
-        font-weight: 500;
-        font-size: 13px;
-        line-height: 18px;
-        /* or 129% */
-        margin-bottom: 18.5px;
-
-        letter-spacing: 0.3px;
+      }
 
-        color: #000000;
-    }
+      .invite-friends-content-body {
+        position: relative;
 
-    .area-url {
-        height: 70px;
-        background: rgba(29, 155, 240, 0.01);
-        border: 1px solid #1D9BF0;
-        border-radius: 5px;
-        display: flex;
-        align-items: center;
-        padding-left: 15px;
-        padding-right: 11px;
-        justify-content: space-between;
-
-        .url {
-            display: -webkit-box;
-            -webkit-box-orient: vertical;
-            -webkit-line-clamp: 3;
-            overflow: hidden;
-            width: 194px;
-
-            color: #737373;
-            font-weight: 400;
-            font-size: 13px;
-            white-space: normal;
-
-            word-wrap: break-word;
-
-            word-break: break-all;
+        .tips {
+          position: absolute;
+          top: -42px;
+          left: 0;
+          width: 146px;
         }
 
-        .btn {
-            user-select: none;
-            background: #1D9BF0;
-            border-radius: 35px;
-            width: 100px;
-            text-align: center;
-            line-height: 37px;
-            height: 37px;
-            font-weight: 700;
-            font-size: 15px;
-            color: #fff;
-            cursor: pointer;
+        .share-list-active {
+          background: rgba(29, 155, 240, 0.1);
+          border: 1.5px solid #1D9BF0 !important;
+          border-radius: 10px;
         }
-    }
+        .share-list {
+          display: flex;
+          flex-wrap: wrap;
+          width: 100%;
+          box-sizing: border-box;
+          border: 1.5px solid #fff;
+
+          .share-item {
+            user-select: none;
+            width: 20%;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            padding: 8px 2px;
+            box-sizing: border-box;
+            border-radius: 12px;
 
-    .share-list {
-        margin-top: 20px;
-        text-align: center;
-        margin-bottom: 14px;
 
-        img {
-            user-select: none;
             cursor: pointer;
-            width: 33px;
-            height: 33px;
-            margin-right: 14px;
-            border-radius: 100px;
+            img {
+                width: 40px;
+                height: 40px;
+                border-radius: 100px;
+                margin-bottom: 8px;
+            }
+            .name {
+              font-weight: 400;
+              font-size: 12px;
+              color: #898989;
+              width: 100%;
+              overflow: hidden;
+              text-overflow: ellipsis; //文本溢出显示省略号
+              white-space: nowrap;
+              text-align: center;
+            }
+          }
+
+          .share-item:hover {
+            animation: fade-in-gray 0.25s linear forwards;
+          }
+
         }
+      }
+    }
+    .mask {
+      position: fixed;
+      top: 0;
+      left: 0;
+      width: 375px;
+      height: 100%;
+      background: rgba($color: #000000, $alpha: 0.9);
+      z-index: 1000;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      .content {
+        text-align: center;
+      }
+
+      .icon-loading {
+        width: 60px;
+        height: 60px;
+        margin-bottom: 30px;
+      }
+
+      .text {
+        font-weight: 600;
+        font-size: 17px;
+        color: #FFFFFF;
+      }
+    }
+  @keyframes fade-in-gray {
+    from {
+      background: none;
     }
 
-
+    to {
+      background: #E3E3E4;
+    }
+  }
 }
 </style>

+ 86 - 0
src/view/iframe/treasure-hunt/components/invite-layer.vue

@@ -0,0 +1,86 @@
+<template>
+    <div class="layer down">
+        <div v-if="Number(state.start_task.amountValue) > 0">
+            <div class="n1">
+                You Win <span>${{ state.start_task.usdAmountValue }} !</span>
+            </div>
+            <div class="n2">Invite Friends to Open the Chest!</div>
+        </div>
+        <div v-else>
+            <div class="n1">
+                You are not <span>Real New follower</span>
+            </div>
+            <div class="n2">Invite Friends to Open the Chest!</div>
+        </div>
+    </div>
+</template>
+<script setup>
+import { inject } from 'vue'
+let state = inject('state')
+
+</script>
+<style scoped lang="scss">
+.layer {
+    background: #005A98;
+    opacity: 0.9;
+    width: 100%;
+    height: 83px;
+    text-align: center;
+    z-index: 19;
+    position: fixed;
+    top: -83px;
+    color: #fff;
+
+
+
+
+
+    .n1 {
+        margin-top: 20px;
+        text-align: center;
+        font-weight: 800;
+        font-size: 18px;
+
+
+        span {
+            color: #FCB936;
+        }
+    }
+
+    .n2 {
+        margin-top: 10px;
+        font-weight: 800;
+        font-size: 14px;
+    }
+}
+
+.down {
+    animation-name: frame_down, frame_up;
+    animation-duration: 0.5s, 0.5s;
+    animation-timing-function: ease, ease;
+    animation-delay: 0s, 5s;
+    animation-iteration-count: 1, 1;
+    animation-fill-mode: forwards, forwards;
+}
+
+@keyframes frame_down {
+    0% {
+        top: -83px;
+    }
+
+    100% {
+        top: 0px
+    }
+}
+
+@keyframes frame_up {
+    0% {
+        top: 0px
+    }
+
+    100% {
+        top: -83px;
+
+    }
+}
+</style>

+ 380 - 186
src/view/iframe/treasure-hunt/components/invite-list.vue

@@ -1,251 +1,445 @@
 <template>
-    <div class="content" v-show-log="state.log_invite_list_show">
-        <div class="error" v-if="state.invited_list.length == 0">
-            Invite people to hunt treasure with you!
+  <div class="content">
+    <div class="horizontal-invited-wrapper" v-if="state.invited_list.length">
+      invited({{ state.inviteCount }})
+      <div class="horizontal-invited-list" v-show-log="state.log_invite_list_show " @mouseleave="invitedListMouseleave($event)">
+        <template v-for="(item, index) in state.invited_list" :key="index">
+          <div class="invited-item" v-if="index < 5" @mouseenter="invitedItemMouseenter(item)">
+            <img :src="item.userInfo.avatarUrl" />
+          </div>
+        </template>
+      </div>
+      <img class="more" v-if="state.invited_list.length > 5" :src="require('@/assets/svg/icon-invited-more.svg')"
+        @mouseenter="moreMouseenter" @mouseleave="moreMouseleave" />
+    </div>
+
+    <div class="invited-user-info" @mouseenter="invitedItemMouseenter()" @mouseleave="invitedListMouseleave($event)"
+      v-if="hoverInvitedUserInfo.userInfo">
+      <div class="left">
+        <img class="avatar" @click="clickItem(hoverInvitedUserInfo)" :src="hoverInvitedUserInfo.userInfo.avatarUrl" />
+      </div>
+      <div class="right">
+        <div class="user-info">
+          <div class="name" @click="clickItem(hoverInvitedUserInfo)">
+            @{{ hoverInvitedUserInfo.userInfo.nickName }}
+          </div>
+          <div class="time">
+            {{ getTime(hoverInvitedUserInfo.timestamp) }}
+          </div>
         </div>
-        <div class="list" v-else @scroll="handleScroll($event)">
-            <div class="item" v-for="item in state.invited_list" :key="item.userInfo.uid">
-                <div class="left">
-                    <img :src="item.userInfo.avatarUrl" alt="" @click="clickItem(item)" />
-                </div>
-                <div class="right">
-                    <div>{{ item.userInfo.nickName }}</div>
-                    <div>{{ getTime(item.timestamp) }}</div>
-                </div>
-            </div>
+        <span class="channel" v-if="hoverInvitedUserInfo.channelName">
+          <img class="app-icon" :src="hoverInvitedUserInfo.channelIcon" />
+          {{hoverInvitedUserInfo.channelName}}
+        </span>
+      </div>
+    </div>
+
+    <div class="vertical-invited-wrapper" v-if="showVerticalInvitedList" @mouseenter="moreMouseenter"
+      @mouseleave="moreMouseleave" @scroll="handleScroll($event)">
+      <div class="invited-user-info" v-for="(item, index) in state.invited_list" :key="index">
+        <div class="left">
+          <img @click="clickItem(item)" class="avatar" :src="item.userInfo.avatarUrl" />
         </div>
-        <div class="footer">
-            <v-btn :txt="state.open_btn.txt" :font-size="'17px'" class="btn" :icon="false" :loading="state.btn_loading"
-                :disabled="state.open_btn.disabled" v-click-log="state.log_invite_btn_click" @onClick="clickBtn"
-                font-weight="600"></v-btn>
+        <div class="right">
+          <div class="user-info">
+            <div class="name" @click="clickItem(item)">
+              @{{ item.userInfo.nickName }}
+            </div>
+            <div class="time">
+              {{ getTime(item.timestamp) }}
+            </div>
+          </div>
+          <span class="channel" v-if="item.channelName">
+            <img class="app-icon" :src="item.channelIcon" />
+            {{item.channelName}}
+          </span>
         </div>
+      </div>
     </div>
+  </div>
 </template>
 <script setup>
-import VBtn from '@/view/iframe/treasure-hunt/components/btn.vue'
 import { inviteList, inviteListRefresh } from '@/http/treasure'
-import { inject, onMounted } from 'vue'
+import { inject, onMounted, ref, watch } from 'vue'
 import Report from "@/log-center/log"
 
 var moment = require('moment')
 let state = inject('state')
+let global_refresh = inject('global_refresh')
+
 state.invited_list = []
-let page_num = 1
-let page_size = 10
+
+let page_num = 1;
+let page_size = 200
+let listLoadMore = false
 let list_end = false
 
-state.log_invite_btn_click = {
-    businessType: Report.businessType.buttonClick,
-    pageSource: Report.pageSource.inviteFriendsPage,
-    objectType: Report.objectType.openChestButton,
-    redPacketType: Report.redPacketType.treasure,
-    shareLinkId: state.invite_code,
-    myShareLinkId: state.detail.inviteCopyUrl,
-    currentInvitedNum: state.inviteCount,
-    postId: state.postId
-}
+let hoverInvitedUserInfo = ref({});
+let showVerticalInvitedList = ref(false);
+let timer = null;
+let timer1 = null;
 
 state.log_invite_list_show = {
-    businessType: Report.businessType.pageView,
-    pageSource: Report.pageSource.beenInvitedPage,
-    redPacketType: Report.redPacketType.treasure,
-    shareLinkId: state.invite_code,
-    myShareLinkId: state.detail.inviteCopyUrl,
-    currentInvitedNum: state.inviteCount,
-    postId: state.postId
+  businessType: Report.businessType.pageView,
+  pageSource: Report.pageSource.beenInvitedPage,
+  redPacketType: Report.redPacketType.treasure,
+  shareLinkId: state.invite_code,
+  myShareLinkId: state.detail.inviteCopyUrl,
+  currentInvitedNum: state.inviteCount,
+  postId: state.postId
 }
 
+watch(global_refresh, () => {
+    if (global_refresh.value) {
+      list()
+    }
+})
+
 onMounted(() => {
-    state.btn_loading = false
-    list()
+  state.btn_loading = false;
+  list()
 })
 
+const invitedItemMouseenter = (params) => {
+  if (timer) clearTimeout(timer)
+  if (params) {
+    hoverInvitedUserInfo.value = params;
+  }
+}
+
+const invitedListMouseleave = (params) => {
+  timer = setTimeout(function () {
+    hoverInvitedUserInfo.value = {};
+  }, 600);
+}
+
+const moreMouseenter = () => {
+  if (timer1) clearTimeout(timer1)
+  showVerticalInvitedList.value = true;
+}
+
+const moreMouseleave = () => {
+  timer1 = setTimeout(function () {
+    showVerticalInvitedList.value = false;
+  }, 600);
+}
+
 const clickItem = (item) => {
-    window.open(`https://twitter.com/${item.userInfo.nickName}`)
+  window.open(`https://twitter.com/${item.userInfo.nickName}`)
 }
 
 function handleScroll(e) {
-    if (list_end) {
-        return
-    }
-    e = e.target
-    if ((e.clientHeight + e.scrollTop) / e.scrollHeight > .8) {
-        list_end = true
-        inviteListScroll()
-    }
+  if (list_end) {
+    return
+  }
+  e = e.target
+  if ((e.clientHeight + e.scrollTop) / e.scrollHeight > .8) {
+    list_end = true
+    inviteListScroll()
+  }
 }
 
 const list = () => {
-    state.inviteListRefresh()
+  state.inviteListRefresh()
 }
 
 // 刷新时调用
 state.inviteListRefresh = () => {
-    let last_timestamp = 0
-    if (state.invited_list.length > 0) {
-        last_timestamp = state.invited_list[0].timestamp
-    }
+  let last_timestamp = 0
+  if (state.invited_list.length > 0) {
+    last_timestamp = state.invited_list[0].timestamp
+  }
 
-    inviteListRefresh({
-        params: {
-            postId: state.postId,
-            lastTimestamp: last_timestamp,
-        }
-    }).then((res) => {
-        if (res.code == 0) {
-            handleCommon(res.data)
-        }
-    })
+  inviteListRefresh({
+    params: {
+      postId: state.postId,
+      lastTimestamp: last_timestamp,
+    }
+  }).then((res) => {
+    if (res.code == 0) {
+      handleCommon(res.data)
+    }
+  })
 }
 
 const handleCommon = (data) => {
-    state.inviteCount = data.inviteCount
-    if (state.inviteCount > 0) {
-        state.tabs[1].txt = `invited(${state.inviteCount})`
-    }
-    if (data.inviteUsers.length > 0) {
-        data.inviteUsers.forEach(item => {
-            if (state.invited_list.filter((item2) => { return item2.userInfo.uid == item.userInfo.uid }).length == 0) {
-                state.invited_list.push(item)
-            }
-        })
-        state.invited_list = state.invited_list.sort((a, b) => {
-            return b.timestamp - a.timestamp
-        })
-
-        list_end = false
-    } else {
-        list_end = false
-    }
+  state.inviteCount = data.inviteCount
+   if (data.inviteUsers.length > 0) {
+    data.inviteUsers.forEach(item => {
+      if (state.invited_list.filter((item2) => { return item2.userInfo.uid == item.userInfo.uid }).length == 0) {
+        state.invited_list.push(item)
+      }
+    })
+    state.invited_list = state.invited_list.sort((a, b) => {
+      return b.timestamp - a.timestamp
+    })
+
+    list_end = false
+  } else {
+    list_end = false
+  }
 }
 
 // 滚动
 let inviteListScroll = () => {
-    // state.invited_list
-    let last_timestamp = 0
-    let len = state.invited_list.length
-    if (len > 0) {
-        last_timestamp = state.invited_list[len - 1].timestamp
-    }
+  let last_timestamp = 0
+  let len = state.invited_list.length
+  if (len > 0) {
+    last_timestamp = state.invited_list[len - 1].timestamp
+  }
 
-    inviteList({
-        params: {
-            inviteCode: state.invite_code,
-            postId: state.postId,
-            lastTimestamp: last_timestamp,
-            pageSize: page_size
-        }
-    }).then((res) => {
-        if (res.code == 0) {
+  inviteList({
+    params: {
+      inviteCode: state.invite_code,
+      postId: state.postId,
+      lastTimestamp: last_timestamp,
+      pageSize: page_size
+    }
+  }).then((res) => {
+    if (res.code == 0) {
 
-            handleCommon(res.data)
-        }
-    })
+      handleCommon(res.data)
+    }
+  })
 }
 
 const getTime = (timestamp) => {
-    let _d1 = moment(new Date().getTime())
-    let _d2 = moment(timestamp)
-    const plural = (n, s) => {
-        let _str = `${n} ${s} ago`
-        if (n > 1) {
-            _str = `${n} ${s}s ago`
-        }
-        return _str
-    }
-    let _d = moment.duration(_d1.diff(_d2)).days()
-    if (_d) {
-        return plural(_d, 'day')
+  let _d1 = moment(new Date().getTime())
+  let _d2 = moment(timestamp)
+  const plural = (n, s) => {
+    let _str = `${n} ${s} ago`
+    if (n > 1) {
+      _str = `${n} ${s}s ago`
     }
-    let _h = moment.duration(_d1.diff(_d2)).hours()
-    if (_h) {
-        return plural(_h, 'hour')
-    }
-    let _m = moment.duration(_d1.diff(_d2)).minutes()
-    if (_m) {
-        return plural(_m, 'min')
-    }
-    let _s = moment.duration(_d1.diff(_d2)).seconds()
-    return plural(_s, 'sec')
+    return _str
+  }
+  let _d = moment.duration(_d1.diff(_d2)).days()
+  if (_d) {
+    return plural(_d, 'day')
+  }
+  let _h = moment.duration(_d1.diff(_d2)).hours()
+  if (_h) {
+    return plural(_h, 'hour')
+  }
+  let _m = moment.duration(_d1.diff(_d2)).minutes()
+  if (_m) {
+    return plural(_m, 'min')
+  }
+  let _s = moment.duration(_d1.diff(_d2)).seconds()
+  return plural(_s, 'sec')
 }
 
 async function clickBtn() {
-    let _userInfo = await state.checkIsLogin()
-    if (!_userInfo) {
-        return
-    }
-    state.btn_loading = true
-    state.treasureOpen()
+  let _userInfo = await state.checkIsLogin()
+  if (!_userInfo) {
+    return
+  }
+  state.btn_loading = true
+  state.treasureOpen()
 }
 
 </script>
 <style lang="scss" scoped>
 .content {
-    position: relative;
-    height: 292px;
+  position: absolute;
+  bottom: 0px;
+  width: 100%;
+
+  .horizontal-invited-wrapper {
+    width: 100%;
+    padding: 12px 14px;
+    box-sizing: border-box;
+    display: flex;
+    align-items: center;
+    font-weight: 400;
+    font-size: 12px;
+    color: #A7A39F;
+
+    .horizontal-invited-list {
+      display: flex;
+      align-items: center;
+      cursor: pointer;
+
+      .invited-item {
+        width: 16px;
+        height: 16px;
+        padding: 0 5px;
 
-    .footer {
-        background: #fff;
-        padding: 10px 16px 25px 16px;
+        img {
+          width: 16px;
+          height: 16px;
+          border-radius: 50%;
+        }
+      }
     }
 
-    .error {
-        height: 204px;
-        color: #BABABA;
-        background-color: #fff;
-        font-weight: 500;
-        font-size: 15px;
-        line-height: 204px;
-        text-align: center;
+    .more {
+      margin-left: 5px;
+      cursor: pointer;
+    }
+  }
+
+  .vertical-invited-wrapper {
+    width: 343px;
+    height: 308px;
+    background: #FFFFFF;
+    box-shadow: 0px 4px 14px rgba(0, 0, 0, 0.25);
+    border-radius: 16px;
+    overflow-y: scroll;
+    position: absolute;
+    bottom: -316px;
+    left: 16px;
+    z-index: 1000;
+    animation: fade-in 0.25s linear forwards;
+    background: #fff;
+
+    .invited-user-info {
+      position: static !important;
+      border-radius: 0px !important;
+      box-shadow: none !important;
+      padding: 0 !important;
+      animation: none !important;
+
+      .left,
+      .right {
+        padding: 9px 0;
+      }
+
+      .left {
+        padding-left: 16px;
+      }
+
+      .right {
+        padding-right: 16px;
+        box-shadow: inset 0px -1px 0px #F2F2F2;
+        box-sizing: border-box;
+      }
+    }
+  }
+
+  .invited-user-info {
+    width: 343px;
+    padding: 9px 16px;
+    box-sizing: border-box;
+    background: #FFFFFF;
+    box-shadow: 0px 4px 14px rgba(0, 0, 0, 0.25);
+    border-radius: 16px;
+    position: absolute;
+    bottom: -62px;
+    left: 16px;
+    display: flex;
+    justify-content: space-between;
+    animation: fade-in 0.25s linear forwards;
+
+    .left {
+      display: flex;
+      align-items: center;
+
+      .avatar {
+        width: 30px;
+        height: 30px;
+        margin-right: 16px;
+        border-radius: 50%;
+        cursor: pointer;
+      }
+    }
+
+    .right {
+      display: flex;
+      justify-content: space-between;
+      width: 100%;
+
+      .user-info {
+        .name {
+          margin-bottom: 5px;
+          font-weight: 500;
+          font-size: 15px;
+          cursor: pointer;
+        }
+
+        .time {
+          font-weight: 400;
+          font-size: 12px;
+          color: #A9A9A9;
+        }
+      }
 
+      .channel {
+        height: min-content;
+        display: flex;
+        align-items: center;
+        font-weight: 400;
+        font-size: 12px;
+        color: #A9A9A9;
+
+        .app-icon {
+          width: 14px;
+          height: 14px;
+          margin-right: 4px;
+          border-radius: 50%;
+        }
+      }
     }
+  }
+
+
+
+  .list {
+    background: #fff;
+    height: 204px;
+    overflow-y: auto;
+
+    .item {
+      height: 60px;
+      display: flex;
+      align-items: center;
+
+      .left {
+        width: 58px;
+        text-align: center;
 
-    .list {
-        background: #fff;
-        height: 204px;
-        overflow-y: auto;
-
-        .item {
-            height: 60px;
-            display: flex;
-            align-items: center;
-
-            .left {
-                width: 58px;
-                text-align: center;
-
-                img {
-                    cursor: pointer;
-                    border-radius: 50px;
-                    width: 30px;
-                    height: 30px;
-                }
-            }
-
-            .right {
-                flex: 1;
-                border-bottom: 1px solid #D9D9D9;
-                display: flex;
-                align-items: center;
-                height: 100%;
-                justify-content: space-between;
-
-                div:nth-child(1) {
-                    color: #000000;
-                    font-weight: 500;
-                    font-size: 15px;
-                    cursor: pointer;
-                }
-
-                div:nth-child(2) {
-                    color: #A6A6A6;
-                    font-weight: 400;
-                    font-size: 12px;
-                    margin-right: 17px;
-
-                }
-            }
+        img {
+          cursor: pointer;
+          border-radius: 50px;
+          width: 30px;
+          height: 30px;
         }
+      }
+
+      .right {
+        flex: 1;
+        border-bottom: 1px solid #D9D9D9;
+        display: flex;
+        align-items: center;
+        height: 100%;
+        justify-content: space-between;
+
+        div:nth-child(1) {
+          color: #000000;
+          font-weight: 500;
+          font-size: 15px;
+          cursor: pointer;
+        }
+
+        div:nth-child(2) {
+          color: #A6A6A6;
+          font-weight: 400;
+          font-size: 12px;
+          margin-right: 17px;
+
+        }
+      }
+    }
+  }
+
+  @keyframes fade-in {
+    from {
+      opacity: 0;
+    }
+
+    to {
+      opacity: 1;
     }
+  }
 }
 </style>

+ 3 - 3
src/view/iframe/treasure-hunt/components/open-box.vue

@@ -50,7 +50,7 @@ const clickBtn = () => {
     .content {
         z-index: 2;
         width: 375px;
-        height: 500px;
+        height: 580px;
         text-align: center;
         position: relative;
 
@@ -62,7 +62,7 @@ const clickBtn = () => {
         }
 
         img {
-            margin-top: 15px;
+            margin-top: 75px;
             width: 250px;
             height: 250px;
             animation: show 0.5s;
@@ -70,7 +70,7 @@ const clickBtn = () => {
 
         .mark {
             position: absolute;
-            top: 246px;
+            top: 300px;
             width: 375px;
 
             p {

+ 72 - 41
src/view/iframe/treasure-hunt/cover.vue

@@ -42,8 +42,10 @@
             <img :src="require('@/assets/svg/icon-three-line.svg')" alt="" />
             <span>to Hunt Treasure</span>
         </div>
-        <v-btn :txt="state.open_btn.txt" :font-size="'17px'" :icon="true" :disabled="false" @onClick="clickBtn"
-            :loading="state.btn_loading"></v-btn>
+        <div class="footer">
+            <v-btn :txt="state.open_btn.txt" :font-size="'17px'" :icon="true" :disabled="false" @onClick="clickBtn"
+                :loading="state.btn_loading"></v-btn>
+        </div>
     </div>
 
 </template>
@@ -55,7 +57,7 @@ import ComponentZoom from "@/view/components/component-zoom.vue";
 import { pageUrl } from "@/http/configAPI.js"
 import Report from "@/log-center/log"
 import { prepareStart, treasureStart } from '@/http/treasure.js'
-import { getChromeCookie, removeChromeCookie, getChromeStorage, sendChromeTabMessage } from '@/uilts/chromeExtension.js'
+import { getChromeCookie, removeChromeCookie, getChromeStorage, sendCurrentTabMessage } from '@/uilts/chromeExtension.js'
 import { reSetBindRepost } from '@/http/help.js'
 import { guid } from '@/uilts/help.js'
 
@@ -70,7 +72,7 @@ state.log_show = {
 }
 
 chrome.storage.onChanged.addListener(changes => {
-    if (changes.userInfo) {
+    if (changes.userInfo && changes.userInfo.newValue) {
         // let item = JSON.parse(changes.userInfo.newValue)
         state.btn_loading = false
         state.init()
@@ -91,14 +93,19 @@ const toStart = (req) => {
             inviteCode: state.invite_code || '',
             frontFollowRelJSON: JSON.stringify(state.usersFollowStatusList),
             time: new Date().getTime(),
-            guid: guid()
+            guid: guid(),
+            channelCode: state.invite_channel
         }
     }).then((res) => {
         state.usersFollowStatusList = [];
         if (res.code == 0) {
-            state.page = '开奖页'
+            // state.page = '开奖页'
+            state.init(() => {
+                state.page = '邀请页'
+                state.page_status = '显示开奖'
+                state.btn_loading = false
+            })
             state.start_task = res.data
-            state.btn_loading = false
             if (req.response) {
                 let repost_tweetId = req.response.data.data.create_tweet.tweet_results.result.rest_id
                 reSetBindRepost({
@@ -135,12 +142,13 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
                 toStart(req);
                 getChromeStorage('userInfo', (_userInfo) => {
                     if (_userInfo) {
-                        sendChromeTabMessage({
+                        sendCurrentTabMessage({
                             actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
                             data: {
                                 screen_name: _userInfo.nickName,
                                 tweetId: state.tweetId,
-                                objectType: Report.objectType.repostSuccess
+                                objectType: Report.objectType.repostSuccess,
+                                iframeId: state.iframeId
                             }
                         })
                     }
@@ -148,6 +156,9 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
             }
             break
         case 'CONTENT_API_GET_TWEET_USER_INFO_RES':
+            if (state.iframeId != req.iframeId) {
+                return;
+            }
             let twitterFans = 0;
             let { user } = req.data || {};
             if (user && user.result && user.result.legacy) {
@@ -193,25 +204,25 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
                     // 上报埋点
                     logPreRepost()
                     // 做任务
-                    chrome.tabs.getCurrent((tab) => {
-                        // // 一键三连
-                        chrome.tabs.sendMessage(tab.id, {
-                            actionType: "IFRAME_TWITTER_API_DO_TASK",
-                            task_data: {
-                                tweet_Id: state.tweetId,
-                                tweet_text: state.rePostTweetContent
-                            },
-                            task_type: 'tasks',
-                            tasks: state.tasks,
-                            iframeId: state.iframeId
-                        })
-                        // double like
-                        chrome.tabs.sendMessage(tab.id, {
-                            actionType: "IFRAME_TWITTER_API_DO_TASK", task_data: {
-                                tweet_Id: state.detail.srcContentId
-                            }, task_type: 'like',
-                            iframeId: state.iframeId
-                        })
+
+                    // 一键三连
+                    sendCurrentTabMessage({
+                        actionType: "IFRAME_TWITTER_API_DO_TASK",
+                        task_data: {
+                            tweet_Id: state.tweetId,
+                            tweet_text: state.rePostTweetContent
+                        },
+                        task_type: 'tasks',
+                        tasks: state.tasks,
+                        iframeId: state.iframeId
+                    })
+
+                    // double like
+                    sendCurrentTabMessage({
+                        actionType: "IFRAME_TWITTER_API_DO_TASK", task_data: {
+                            tweet_Id: state.detail.srcContentId
+                        }, task_type: 'like',
+                        iframeId: state.iframeId
                     })
                 }
             }
@@ -245,7 +256,7 @@ const logPreRepost = () => {
 
     // rootTwitterName  上报原始发布者的name
     // fatherTwitterName 上报分享者的name or 原始发布者的name
-    // isFatherTwitterFans 在原始链接或分享链接 邀请者非自己 
+    // isFatherTwitterFans 在原始链接或分享链接 邀请者非自己
     // isRootTwitterFans 在原始链接或分享链接 发布者非自己
 
     let params = {}
@@ -285,7 +296,7 @@ const logPreRepost = () => {
         })
     }
 
-    sendChromeTabMessage({
+    sendCurrentTabMessage({
         actionType: "IFRAME_API_GET_TWEET_USER_FOLLOW_STATUS",
         data: {
             userList: names,
@@ -314,11 +325,15 @@ async function clickBtn() {
     }
     if (state.cover_status == '奖励已被领光') {
         Report.reportLog({
-            pageSource: Report.pageSource.pending_page,
+            pageSource: Report.pageSource.expiredPage,
             businessType: Report.businessType.buttonClick,
             objectType: Report.objectType.getMoreGiveaway,
-            postId: state.postId
+            postId: state.postId,
+            shareLinkId: state.invite_code,
+            currentInvitedNum: state.inviteCount,
+            redPacketType: Report.redPacketType.treasure
         });
+
         window.open('https://twitter.com/search?q=%23denet');
         return
     }
@@ -346,6 +361,7 @@ async function clickBtn() {
     }, (res) => {
         if (res && res.inviteCode) {
             state.invite_code = res.inviteCode
+            state.invite_channel = res.channel ? window.atob(res.channel) : '';
         }
         startBtn()
     })
@@ -377,7 +393,7 @@ const getUsersFollowStatus = () => {
     let userList = state.follows;
 
     if (userList && userList.length) {
-        sendChromeTabMessage({
+        sendCurrentTabMessage({
             actionType: "IFRAME_API_GET_TWEET_USER_FOLLOW_STATUS",
             data: {
                 userList: userList,
@@ -391,8 +407,9 @@ const getUsersFollowStatus = () => {
 </script>
 <style lang="scss" scoped>
 .cover {
+    position: relative;
     width: 375px;
-    height: 500px;
+    height: 580px;
     background: linear-gradient(179.96deg, #25180D 38.82%, #5E4025 55.4%, #876635 61.6%, #24180C 71.59%);
     border-radius: 20px;
 
@@ -417,7 +434,7 @@ const getUsersFollowStatus = () => {
     }
 
     .waring {
-        margin-top: 54px;
+        margin-top: 94px;
         font-weight: 900;
         font-size: 34px;
         color: #FFFFFF;
@@ -432,12 +449,12 @@ const getUsersFollowStatus = () => {
 
     .in-invite {
         height: 28px;
-        margin-top: 20px;
+        margin-top: 30px;
         margin-bottom: 10px;
     }
 
     .invite {
-        background: rgba(255, 255, 255, 0.1);
+        /* background: rgba(255, 255, 255, 0.1); */
         height: 28px;
         display: flex;
         align-items: center;
@@ -458,7 +475,8 @@ const getUsersFollowStatus = () => {
         }
 
         span {
-            color: #BE9F89;
+            color: #FFFFFF;
+            opacity: 0.6;
         }
     }
 
@@ -534,12 +552,15 @@ const getUsersFollowStatus = () => {
             line-height: 15px;
             color: #FFFFFF;
 
-            opacity: 0.7;
+            opacity: 0.6;
         }
     }
 
     .box {
         text-align: center;
+        position: absolute;
+        width: 100%;
+        bottom: 155px;
 
         img {
             width: 160px;
@@ -549,11 +570,16 @@ const getUsersFollowStatus = () => {
     }
 
     .mark {
+        position: absolute;
+        bottom: 84px;
         display: flex;
         align-items: center;
         justify-content: center;
-        margin-top: 24px;
-        margin-bottom: 15px;
+        width: 100%;
+
+        img {
+            margin-right: 9px;
+        }
 
         span {
             font-weight: 500;
@@ -564,5 +590,10 @@ const getUsersFollowStatus = () => {
         }
     }
 
+    .footer {
+        width: 100%;
+        position: absolute;
+        bottom: 16px;
+    }
 }
 </style>

+ 52 - 20
src/view/iframe/treasure-hunt/index.vue

@@ -1,22 +1,24 @@
 <template>
-    <v-cover v-show="state.page == '封面页'"></v-cover>
+    <v-cover v-if="state.page == '封面页'"></v-cover>
     <v-invite v-if="state.page == '邀请页'"></v-invite>
     <v-result v-if="state.page == '开奖页'"></v-result>
+
     <open-box v-show="state.open_box.show"></open-box>
     <v-toast :show="state.toast.show" :txt="state.toast.txt" :has_icon="state.toast.has_icon"></v-toast>
     <div v-show="state.loading_redbag" class="redbag">
         <img :src="require('@/assets/img/icon-loading-redbag.png')" alt />
     </div>
+
 </template>
 <script setup>
-import { reactive, provide, onMounted } from 'vue'
+import { reactive, provide, onMounted, ref } from 'vue'
 import VCover from '@/view/iframe/treasure-hunt/cover.vue'
 import VInvite from '@/view/iframe/treasure-hunt/invite.vue'
 import VResult from '@/view/iframe/treasure-hunt/result.vue'
 import { inviteDetail, treasureDetail, treasureOpen } from '@/http/treasure.js'
 import { reSetBindTwtterId, reSetBindPostContent, reSetBindRepost } from '@/http/help.js'
 import { getQueryString } from '@/uilts/help'
-import { getChromeStorage, sendChromeTabMessage } from '@/uilts/chromeExtension.js'
+import { getChromeStorage, sendCurrentTabMessage } from '@/uilts/chromeExtension.js'
 import VToast from '@/view/iframe/treasure-hunt/components/toast.vue'
 import OpenBox from '@/view/iframe/treasure-hunt/components/open-box.vue'
 import Report from "@/log-center/log"
@@ -24,9 +26,11 @@ import Report from "@/log-center/log"
 let state = reactive({
     loading_redbag: true,
     page: '',
+    page_status: '',
     detail: {},
     oldDetail: {},
     btn_loading: false,
+    timer: null,
     open_box: {
         showed: false,
         show: false,
@@ -44,6 +48,8 @@ let state = reactive({
     toast: {},
     iframeId: ''
 })
+let global_refresh = ref(false)
+provide('global_refresh', global_refresh)
 provide('state', state)
 
 let params = {}
@@ -54,6 +60,7 @@ onMounted(() => {
     state.tweetId = params.tweet_Id || ''
     state.invite_code = params.invite_code || ''
     state.page_type = params.page_type || ''
+
     state.init();
     onRuntimeMsg();
 })
@@ -108,7 +115,7 @@ state.init = (callback) => {
                 handleCommon(res, callback)
                 // 原始链接绑定post content
                 if (!res.data.postSrcContent) {
-                    sendChromeTabMessage({
+                    sendCurrentTabMessage({
                         actionType: "GET_CONTENT_BY_TWITTER_ID",
                         data: {
                             tweet_Id: state.tweetId
@@ -167,12 +174,13 @@ const handleCommon = (res, callback) => {
             postId: state.postId || '',
             tweetId: state.tweetId || ''
         }, () => {
-            sendChromeTabMessage({
+            sendCurrentTabMessage({
                 actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
                 data: {
                     screen_name: state.detail.postUserInfo.nickName,
                     tweetId: state.tweetId,
-                    objectType: Report.objectType.tweetPostBinded
+                    objectType: Report.objectType.tweetPostBinded,
+                    iframeId: state.iframeId
                 }
             })
             state.init()
@@ -182,6 +190,16 @@ const handleCommon = (res, callback) => {
 }
 let silver_open_box_big = require('@/assets/img/icon-silver-open-box-big.png')
 let gold_open_box_big = require('@/assets/img/icon-gold-open-box-big.png')
+let purple_open_box_big = require('@/assets/img/icon-purple-open-big.png')
+
+state.refreshInit = () => {
+    state.init(() => {
+        global_refresh.value = true
+        setTimeout(() => {
+            global_refresh.value = false
+        }, 1000)
+    })
+}
 
 state.treasureOpen = () => {
     treasureOpen({
@@ -195,10 +213,12 @@ state.treasureOpen = () => {
             // icon
             for (let i in state.boxs) {
                 if (state.boxs[i].id == state.treasureId) {
-                    if (i > 0) {
-                        state.open_box.icon = gold_open_box_big
-                    } else {
+                    if (i == 0) {
                         state.open_box.icon = silver_open_box_big
+                    } else if (i == 1 || i == 2) {
+                        state.open_box.icon = gold_open_box_big
+                    } else if (i == 3) {
+                        state.open_box.icon = purple_open_box_big
                     }
                     break
                 }
@@ -207,10 +227,7 @@ state.treasureOpen = () => {
             state.open_box.showed = true
             state.open_box.data = res.data
 
-            state.init(() => {
-                state.inviteInit()
-                state.inviteListRefresh()
-            })
+            state.refreshInit()
         } else {
             switch (String(res.code)) {
                 case '2037':
@@ -234,10 +251,7 @@ state.treasureOpen = () => {
                 state.toast.show = false
             }, 2000)
 
-            state.init(() => {
-                state.inviteInit()
-                state.inviteListRefresh()
-            })
+            state.refreshInit()
         }
     }).catch(() => {
         state.btn_loading = false
@@ -274,7 +288,9 @@ const handleStatus = (callback) => {
         }
         // 如果 夺宝参与状态 = 已参与夺宝
         else if (joinStatus == 1) {
-            state.page = '邀请页'
+            if (state.page_show != '总邀请者页') {
+                state.page = '邀请页'
+            }
         }
     }
     // 如果 夺宝状态 = 已结束
@@ -283,6 +299,15 @@ const handleStatus = (callback) => {
         state.page = '封面页'
         state.cover_status = '奖励已被领光'
         state.btn_loading = false
+        Report.reportLog({
+          pageSource: Report.pageSource.expiredPage,
+          businessType: Report.businessType.pageView,
+          postId: state.postId,
+          shareLinkId: state.invite_code,
+          myShareLinkId: state.detail.inviteCopyUrl,
+          currentInvitedNum: state.inviteCount,
+          redPacketType: Report.redPacketType.treasure
+        });
         return
     }
     callback && callback()
@@ -301,6 +326,9 @@ function onRuntimeMsg() {
                 }
                 break
             case 'CONTENT_API_GET_TWEET_USER_INFO_RES':
+                if (state.iframeId != req.iframeId) {
+                    return;
+                }
                 let twitterFans = 0;
                 let { user } = req.data || {};
                 if (user && user.result && user.result.legacy) {
@@ -334,14 +362,18 @@ body {
         z-index: 222;
         text-align: center;
         width: 375px;
-        height: 500px;
+        height: 580px;
         position: fixed;
         top: 0;
         left: 0;
         user-select: none;
 
         img {
-            margin-top: 172px;
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            margin-top: -65px;
+            margin-left: -65px;
             width: 130px;
             height: 130px;
         }

+ 29 - 349
src/view/iframe/treasure-hunt/invite.vue

@@ -1,58 +1,40 @@
 <template>
-    <!-- 邀请页 -->
-    <div class="area-process" v-show-log="state.log_invite_show">
-        <v-head :left-data="state.detail.postUserInfo || null" :rightData="state.detail.remainAmountUsdValue"></v-head>
-        <div class="box-process">
-            <div class="item" v-for="item, i in state.boxs">
-                <hover-tip :txt="item.txt" v-show="item.show || item.openStatus" :icon="item.hover_icon"></hover-tip>
-                <img :src="item.icon" alt="" @mouseenter="mouseItem(i)" @mouseleave="mouseLeaveItem(i)" />
-                <img :src="require('@/assets/img/icon-flash-active.png')" alt="" class="flash"
-                    v-if="item.openStatus == 0 && item.taskFinishStatus == 1" />
-            </div>
-            <div class="line">
-                <div class="full" ref="line_full"></div>
-            </div>
-        </div>
-        <div class="area-success-message" @mouseover="mouseOver" @mouseleave="mouseLeave">
-            <div class="content-success-message" ref="content_success_message">
-                <div class="success-message" v-for="item, index in state.success_message_list" :key="index"
-                    @click="clickItem(item)">
-                    <img :src="item.userInfo.avatarUrl" alt="" />
-                    <span>{{ item.userInfo.nickName }} </span> &nbsp;
-                    <span>Opened Treasure Chest</span>
-                </div>
+    <invite-layer v-if="state.page_status == '显示开奖'"></invite-layer>
+    <all-receive-list v-if="state.page_show == '总邀请者页'"></all-receive-list>
+    <div v-show="state.page_show != '总邀请者页'">
+        <!-- 邀请页 -->
+        <div class="area-process" v-show-log="state.log_invite_show">
+            <div class="area1">
+                <v-head :left-data="state.detail.postUserInfo || null" :rightData="state.detail.remainAmountUsdValue">
+                </v-head>
+                <v-carousel></v-carousel>
             </div>
+            <v-boxs style="margin-top: 40px;"></v-boxs>
+            <invite-list></invite-list>
         </div>
-    </div>
 
-    <div class="area-nav">
-        <div class="item" :class="{ active: state.tab_index == i }" @click="state.tab_index = i"
-            v-for="item, i in state.tabs">
-            <img :src="require('@/assets/svg/icon-invite.svg')" alt=""
-                :style="{ opacity: state.tab_index == 0 ? '1' : '0.55' }" v-if="i == 0" />
-            <img :src="require('@/assets/svg/icon-invite-list.svg')" alt=""
-                :style="{ opacity: state.tab_index == 1 ? '1' : '0.55' }" v-if="i == 1" />
-            {{ item.txt }}
+        <div class="area-info">
+            <invite-friends></invite-friends>
+            <!-- -->
         </div>
     </div>
-    <div class="area-info">
-        <invite-friends v-show="state.tab_index == 0"></invite-friends>
-        <invite-list v-show="state.tab_index == 1"></invite-list>
-    </div>
     <v-dialog v-show="state.dialog.show"></v-dialog>
 </template>
 <script setup>
 import { ref, onMounted, watch, inject } from 'vue'
-import { receiveList } from '@/http/treasure.js'
+import AllReceiveList from '@/view/iframe/treasure-hunt/all-receive-list.vue'
 import VHead from '@/view/iframe/treasure-hunt/components/head.vue'
 import InviteList from '@/view/iframe/treasure-hunt/components/invite-list.vue'
 import HoverTip from '@/view/iframe/treasure-hunt/components/hover-tip.vue'
 import InviteFriends from '@/view/iframe/treasure-hunt/components/invite-friends.vue'
 import VDialog from '@/view/iframe/treasure-hunt/components/dialog.vue'
+import VBoxs from '@/view/iframe/treasure-hunt/components/boxs.vue'
+import VCarousel from '@/view/iframe/treasure-hunt/components/carousel.vue'
+import InviteLayer from '@/view/iframe/treasure-hunt/components/invite-layer.vue'
 
 import Report from "@/log-center/log"
 
-let content_success_message = ref(null)
+
 let state = inject('state')
 
 state.log_invite_show = {
@@ -65,15 +47,6 @@ state.log_invite_show = {
     postId: state.postId
 }
 
-// ---- 走马灯
-state.success_message_list = []
-
-// ---- box 区域
-let silver_close_box = require('@/assets/img/icon-silver-close-box.png')
-let silver_open_box = require('@/assets/img/icon-silver-open-box.png')
-let gold_open_box = require('@/assets/img/icon-gold-open-box.png')
-let gold_close_box = require('@/assets/img/icon-gold-close-box.png')
-
 
 // ---- tab区域 ----
 state.tab_index = 0
@@ -83,327 +56,34 @@ state.tabs = [{
     txt: 'Invited'
 }]
 
-state.boxs = []
-
-let line_full = ref(null)
 onMounted(() => {
-    state.inviteInit()
-    setInterval(() => {
-        state.init(() => {
-            state.inviteInit()
-            state.inviteListRefresh()
-        })
+    if (state.timer) {
+        return
+    }
+    state.timer = setInterval(() => {
+        state.refreshInit()
     }, 30000)
 })
 
-const clickItem = (item) => {
-    window.open(`https://twitter.com/${item.userInfo.nickName}`)
-}
-state.inviteInit = () => {
-    state.boxs = []
-    state.detail.treasureRecords.forEach((item, index) => {
-        if (item.openStatus == 0) {
-            item.hover_icon = require('@/assets/svg/icon-user.svg')
-            if (index > 0) {
-                item.icon = gold_close_box
-            } else {
-                item.icon = silver_close_box
-            }
-            item.txt = item.inviteProgress
-        } else {
-            item.icon = silver_open_box
-            item.hover_icon = require('@/assets/svg/icon-green-yes.svg')
-            // 最后一条
-            if (index > 0) {
-                item.icon = gold_open_box
-            } else {
-                item.icon = silver_open_box
-            }
-            item.txt = '$' + item.amountUsdValue
-        }
-
-        state.boxs.push(item)
-    })
 
-    receiveList({
-        params: {
-            postId: state.postId,
-            pageNum: 1,
-            pageSize: 100,
-        }
-    }).then((res) => {
-        if (res.code == 0) {
-            state.success_message_list = res.data
-            state.success_message_list = state.success_message_list.concat(state.success_message_list)
-            state.success_message_list = state.success_message_list.concat(state.success_message_list)
-
-            if (content_success_message && content_success_message.value) {
-                let dom = content_success_message.value
-                let s = state.success_message_list.length * 4
-                dom.style.animationDuration = s + 's'
-            }
-        }
-    })
-    btnStatus()
-
-}
-let line_width = 0
-const setLineFull = (box_num = 0, finishNeedInviteCount = 0, successInviteCount = 0) => {
-    if (box_num == 0) {
-        // 第一个宝箱起点是0,终点是55
-        line_width = (successInviteCount / finishNeedInviteCount) * 55
-    } else if (box_num == 1) {
-        if (line_width == 55) {
-            // 第二个宝箱起点88,终点是155
-            line_width = 88
-            line_width = (successInviteCount / finishNeedInviteCount) * (155 - line_width) + line_width
-        }
-    } else if (box_num == 2) {
-        if (line_width == 155) {
-            line_width = 192
-            // 第二个宝箱起点是192,终点是260
-            line_width = (successInviteCount / finishNeedInviteCount) * (260 - line_width) + line_width
-        }
-    }
-    line_full.value.style.width = line_width + 'px'
-}
-
-const btnStatus = () => {
-    for (let i in state.boxs) {
-        if (state.boxs[i].taskFinishStatus == 0) {
-            let num = state.boxs[i].finishNeedInviteCount - state.boxs[i].successInviteCount
-            if (num == 1) {
-                state.open_btn.txt = 'Invite 1 Friend to Open'
-            } else {
-                state.open_btn.txt = `Invite ${num} Friends to Open`
-            }
-            state.open_btn.disabled = true
-            break
-        }
-    }
-
-    state.treasureId = ''
-    let open_num = 0
-    // 有打开的箱子 Open the chest
-    state.boxs.forEach((item, index) => {
-        if (item.taskFinishStatus == 1 && item.openStatus == 0) {
-            state.open_btn.txt = 'Open the Treasure Chest'
-            state.open_btn.disabled = false
-            if (!state.treasureId) {
-                state.treasureId = item.id
-            }
-        }
-        setLineFull(index, item.finishNeedInviteCount, item.successInviteCount)
-        // 三个箱子全部打开了
-        if (item.openStatus == 1) {
-            open_num++
-        }
-        if (open_num == state.boxs.length) {
-            state.open_btn.txt = 'All Chests Have Been Opened'
-            state.open_btn.disabled = true
-        }
-    })
-}
-
-const mouseItem = (i) => {
-    state.boxs[i].show = true
-}
-const mouseLeaveItem = (i) => {
-    state.boxs[i].show = false
-}
-
-const mouseOver = () => {
-    if (content_success_message && content_success_message.value && content_success_message.value.style) {
-        content_success_message.value.style.animationPlayState = 'paused'
-    }
-}
-const mouseLeave = () => {
-    if (content_success_message && content_success_message.value && content_success_message.value.style) {
-        content_success_message.value.style.animationPlayState = 'running'
-    }
-}
 
 </script>
 <style lang="scss"  scoped>
 .area-process {
     width: 375px;
-    height: 170px;
-    background: linear-gradient(179.96deg, #735931 0.04%, #0E0803 53.64%);
+    height: 260px;
+    background: linear-gradient(179.96deg, #25180D 48.1%, #6A4C1F 62.7%, #24180C 77.69%);
     position: relative;
 
-    .box-process {
-        width: 350px;
-        height: 90px;
-        margin: 0 auto;
-        display: flex;
-        align-items: center;
-        position: absolute;
-        top: 32px;
-        left: 13px;
-
-        img {
-            width: 60px;
-            height: 60px;
-            z-index: 2;
-        }
-
-        .item {
-            z-index: 2;
-            display: flex;
-            justify-content: center;
-            position: relative;
-
-            .flash {
-                position: absolute;
-                top: 0;
-                left: 0;
-                z-index: 0;
-                width: 100%;
-                height: 100%;
-            }
-        }
-
-        .item:nth-child(1) {
-
-            margin-left: 56px;
-        }
-
-        .item:nth-child(2) {
-            width: 60px;
-            height: 60px;
-            margin-left: 40px;
-        }
-
-        .item:nth-child(3) {
-            img {
-                width: 90px;
-                height: 90px;
-            }
-
-            margin-left: 40px;
-        }
-
-        .line {
-            width: 300px;
-            height: 4px;
-            background: rgba(255, 210, 59, 0.2);
-            position: absolute;
-            border-radius: 100px;
-            overflow: hidden;
-            left: 13px;
-            top: 45px;
-
-            .full {
-                position: absolute;
-                left: 0;
-                top: 0;
-                height: 4px;
-                width: 0px;
-                background: #FFD23B;
-            }
-        }
-
+    .area1 {
+        background: rgba(255, 255, 255, 0.1);
     }
 
-    .area-success-message {
-        height: 30px;
-        width: 100%;
-        position: absolute;
-        bottom: 13px;
-        overflow: hidden;
-
-        .content-success-message {
-            width: fit-content;
-            display: flex;
-            animation: rolling 18s linear infinite;
-            animation-duration: 10s;
-            animation-play-state: running;
-
-            .success-message {
-                cursor: pointer;
-                width: fit-content;
-                height: 30px;
-                padding: 0 9px;
-                border-radius: 100px;
-                background: rgba(255, 255, 255, 0.1);
-                display: flex;
-                align-items: center;
-                overflow: hidden;
-                margin-right: 15px;
-
-                img {
-                    width: 20px;
-                    height: 20px;
-                    border-radius: 100px;
-                    margin-right: 8px;
+    .area2 {}
 
-                }
-
-                span {
-                    font-style: normal;
-                    font-weight: 500;
-                    font-size: 12px;
-                    line-height: 14px;
-                    white-space: nowrap;
-                }
-
-                span:nth-child(2) {
-                    color: #1D9BF0;
-                }
-
-                span:nth-child(3) {
-                    color: #A8A8A8;
-                }
-            }
-        }
-    }
-}
-
-@keyframes rolling {
-    from {
-        transform: translateX(0);
-    }
-
-    to {
-        transform: translateX(-50%);
-    }
-}
-
-.area-nav {
-    width: 375px;
-    height: 38px;
-    display: flex;
-
-    .item {
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        user-select: none;
-        color: #757575;
-        background: #F0F0F0;
-        text-align: center;
-        width: 50%;
-        font-weight: 500;
-        font-size: 14px;
-        line-height: 38px;
-        cursor: pointer;
-
-        img {
-            margin-right: 8px;
-            width: 20px;
-            height: 20px;
-        }
-    }
-
-    .active {
-        background: #FFFFFF;
-        color: #000000;
-    }
 }
 
 .area-info {
     width: 375px;
-
-
 }
 </style>

+ 5 - 2
src/view/popup/tabbar-page/wallter/popup.vue

@@ -25,7 +25,7 @@
             </div>
         </div>
 
-        <currency-list 
+        <currency-list
             v-if="userInfo.accessToken"
             style="height: calc(100% - 103px);"
             ref="currencyListDom"
@@ -90,13 +90,16 @@ const init = () => {
     checkLoginState((res) => {
         if (res) {
             getAccountBalance();
+            setMessageCount();
+            if(window.location.pathname.indexOf('popup-page.html') > -1) {
+              return
+            }
             Report.reportLog({
                 pageSource: Report.pageSource.denetHomePage,
                 businessType: Report.businessType.pageView,
             }, {
                 type: window.location.href.indexOf('home.html') > -1 ? 'web' : 'extensions'
             });
-            setMessageCount();
         } else {
             Report.reportLog({
                 pageSource: Report.pageSource.denetLogin,

Some files were not shown because too many files changed in this diff