Pārlūkot izejas kodu

Merge branch 'master' of https://git.yishihui.com/DeNet/de-net

zhangwei 2 gadi atpakaļ
vecāks
revīzija
68a6f2cfc7
100 mainītis faili ar 4020 papildinājumiem un 1197 dzēšanām
  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-loading-redbag.png
  7. BIN
      src/assets/img/icon-purple-close-box.png
  8. BIN
      src/assets/img/icon-purple-open-big.png
  9. BIN
      src/assets/img/icon-purple-open-box.png
  10. BIN
      src/assets/img/icon-silver-close-box.png
  11. BIN
      src/assets/img/icon-silver-open-box-big.png
  12. BIN
      src/assets/img/icon-silver-open-box.png
  13. 9 0
      src/assets/subject/004-back-head-top.svg
  14. 3 0
      src/assets/svg/icon-back-2.svg
  15. 2 0
      src/assets/svg/icon-channel-tips.svg
  16. 16 0
      src/assets/svg/icon-copy-url-teasure.svg
  17. 2 0
      src/assets/svg/icon-gold-box-close.svg
  18. 13 0
      src/assets/svg/icon-invited-more.svg
  19. 4 0
      src/assets/svg/icon-loading-channel.svg
  20. 3 0
      src/assets/svg/icon-loading-gray2.svg
  21. 1 1
      src/assets/svg/icon-refresh-treasure.svg
  22. 4 0
      src/assets/svg/icon-sort-amount.svg
  23. 4 0
      src/assets/svg/icon-sort-time.svg
  24. 0 1
      src/assets/svg/icon-three-line.svg
  25. 5 0
      src/assets/svg/icon-user1.svg
  26. 1 1
      src/assets/svg/icon-while-yes.svg
  27. 25 0
      src/denet/chrome/content.js
  28. 7 0
      src/denet/chrome/index.js
  29. 25 0
      src/denet/chrome/sw.js
  30. 94 0
      src/denet/content/doTask.js
  31. 30 0
      src/denet/content/dom.js
  32. 29 0
      src/denet/content/getData.js
  33. 9 0
      src/denet/content/index.js
  34. 9 0
      src/denet/index.js
  35. 107 85
      src/entry/background.js
  36. 143 51
      src/entry/content.js
  37. 8 2
      src/http/fetch.js
  38. 16 1
      src/http/help.js
  39. 14 2
      src/http/request.js
  40. 17 1
      src/http/toolBoxApi.js
  41. 29 2
      src/http/treasure.js
  42. 3 2
      src/iframe/ach-cashier.js
  43. 2 1
      src/iframe/tool-box-buy-nft.js
  44. 3 2
      src/iframe/tool-box-guide.js
  45. 3 1
      src/iframe/tool-box.js
  46. 3 0
      src/iframe/treasure-hunt.js
  47. 14 7
      src/log-center/logEnum.js
  48. 16 14
      src/logic/background/facebook.js
  49. 31 20
      src/logic/background/twitter.js
  50. 117 41
      src/logic/content/ParseCard.js
  51. 6 4
      src/logic/content/ToolBox.js
  52. 2 2
      src/logic/content/facebook.js
  53. 155 0
      src/logic/content/help/doTask.js
  54. 33 0
      src/logic/content/help/getData.js
  55. 74 35
      src/logic/content/help/twitter.js
  56. 38 38
      src/logic/content/nft.js
  57. 452 141
      src/logic/content/twitter.js
  58. 2 2
      src/manifest.json
  59. 2 1
      src/uilts/chromeExtension.js
  60. 64 1
      src/uilts/help.js
  61. 129 0
      src/uilts/messageCenter/chrome/index.js
  62. 13 0
      src/uilts/messageCenter/chrome/messageEnum.js
  63. 60 0
      src/uilts/messageCenter/content/index.js
  64. 22 0
      src/uilts/messageCenter/content/messageEnum.js
  65. 106 0
      src/uilts/messageCenter/iframe/index.js
  66. 34 0
      src/uilts/messageCenter/iframe/messageEnum.js
  67. 0 50
      src/uilts/messageCenter/index.js
  68. 12 1
      src/view/components/currency-list.vue
  69. 6 5
      src/view/components/custom-card-cover.vue
  70. 20 8
      src/view/components/custom-card-horizontal-cover.vue
  71. 39 0
      src/view/components/loading.vue
  72. 12 9
      src/view/content/message/index.vue
  73. 27 18
      src/view/iframe/buy-nft/buy/home.vue
  74. 28 29
      src/view/iframe/buy-nft/buy/pay.vue
  75. 2 2
      src/view/iframe/buy-nft/group/tip.vue
  76. 11 11
      src/view/iframe/group-card/card.vue
  77. 18 0
      src/view/iframe/nft/card.vue
  78. 24 13
      src/view/iframe/publish/components/get-more.vue
  79. 13 21
      src/view/iframe/publish/components/give-dialog-head.vue
  80. 4 4
      src/view/iframe/publish/components/giveaway-poster.vue
  81. 1 1
      src/view/iframe/publish/components/nft-setting.vue
  82. 22 22
      src/view/iframe/publish/components/pay-button.vue
  83. 3 2
      src/view/iframe/publish/components/preview-card.vue
  84. 80 16
      src/view/iframe/publish/give-dialog.vue
  85. 55 77
      src/view/iframe/publish/tool-box/child/editor.vue
  86. 107 12
      src/view/iframe/publish/tool-box/child/preview.vue
  87. 90 5
      src/view/iframe/publish/tool-box/index.vue
  88. 83 96
      src/view/iframe/red-packet/luck-draw.vue
  89. 78 91
      src/view/iframe/red-packet/red-packet.vue
  90. 21 19
      src/view/iframe/tab-group/joined-group-list.vue
  91. 24 17
      src/view/iframe/tool-box/buy-nft.vue
  92. 24 18
      src/view/iframe/tool-box/card.vue
  93. 14 10
      src/view/iframe/tool-box/full.vue
  94. 265 0
      src/view/iframe/treasure-hunt/all-receive-list.vue
  95. 336 0
      src/view/iframe/treasure-hunt/components/boxs.vue
  96. 20 10
      src/view/iframe/treasure-hunt/components/btn.vue
  97. 192 0
      src/view/iframe/treasure-hunt/components/carousel.vue
  98. 2 2
      src/view/iframe/treasure-hunt/components/dialog.vue
  99. 3 2
      src/view/iframe/treasure-hunt/components/head.vue
  100. 370 167
      src/view/iframe/treasure-hunt/components/invite-friends.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-loading-redbag.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


+ 9 - 0
src/assets/subject/004-back-head-top.svg

@@ -0,0 +1,9 @@
+<svg width="375" height="150" viewBox="0 0 375 150" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M0 0H375V117.057C375 117.057 320.624 150 187.5 150C54.376 150 0 117.057 0 117.057V0Z" fill="url(#paint0_linear_27657_247702)"/>
+<defs>
+<linearGradient id="paint0_linear_27657_247702" x1="187" y1="-2.34963e-09" x2="187.045" y2="150" gradientUnits="userSpaceOnUse">
+<stop offset="0.367196" stop-color="#26180E"/>
+<stop offset="0.953767" stop-color="#51361D"/>
+</linearGradient>
+</defs>
+</svg>

+ 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>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 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>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 2 - 0
src/assets/svg/icon-gold-box-close.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>

+ 3 - 0
src/assets/svg/icon-loading-gray2.svg

@@ -0,0 +1,3 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19.9992 3.33203V7.49869C17.2553 7.49927 14.5878 8.40267 12.4083 10.0695C10.2287 11.7364 8.65819 14.0741 7.93892 16.722C7.21965 19.3699 7.39163 22.1809 8.42832 24.7214C9.46501 27.2619 11.3088 29.3907 13.6753 30.7795C16.0418 32.1682 18.7995 32.7397 21.5229 32.4058C24.2464 32.0719 26.7844 30.8511 28.7453 28.9318C30.7062 27.0125 31.9811 24.5014 32.3734 21.7857C32.7657 19.07 32.2535 16.3007 30.9158 13.9049L34.5533 11.8737C36.3369 15.0681 37.0198 18.7605 36.4967 22.3815C35.9737 26.0025 34.2737 29.3508 31.659 31.9098C29.0444 34.4688 25.6604 36.0964 22.029 36.5415C18.3976 36.9866 14.7206 36.2245 11.5653 34.3727C8.41006 32.5209 5.95175 29.6823 4.56965 26.2949C3.18755 22.9074 2.95846 19.1593 3.91772 15.6287C4.87698 12.0982 6.97129 8.98135 9.87757 6.75906C12.7839 4.53676 16.3406 3.3325 19.9992 3.33203Z" fill="#E2E2E2"/>
+</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>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 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>

+ 25 - 0
src/denet/chrome/content.js

@@ -0,0 +1,25 @@
+import chromeMessageCenter from '@/uilts/messageCenter/chrome';
+import MESSAGE_ENUM from '@/uilts/messageCenter/chrome/messageEnum'
+
+export default {
+    // ---- 获取推文文案 ---- 
+    test({ tweetId }, overTime) {
+        return new Promise((res, rej) => {
+            chromeMessageCenter.sendToSW({
+                info: {
+                    actionType: MESSAGE_ENUM.CONTENT_TO_BACK_TEST,
+                },
+                data: {
+                    tweetId
+                },
+                overTime,
+                callback: (data) => {
+                    res(data);
+                },
+                failback: (e) => {
+                    rej(e)
+                }
+            })
+        })
+    }
+}

+ 7 - 0
src/denet/chrome/index.js

@@ -0,0 +1,7 @@
+import content from '@/denet/chrome/content'
+import sw from '@/denet/chrome/sw'
+
+export default {
+    content,
+    sw
+}

+ 25 - 0
src/denet/chrome/sw.js

@@ -0,0 +1,25 @@
+import chromeMessageCenter from '@/uilts/messageCenter/chrome';
+import MESSAGE_ENUM from '@/uilts/messageCenter/chrome/messageEnum'
+
+export default {
+    // ---- 获取推文文案 ---- 
+    test({ tweetId }, overTime) {
+        return new Promise((res, rej) => {
+            chromeMessageCenter.sendToContent({
+                info: {
+                    actionType: MESSAGE_ENUM.BACK_TO_CONTENT_TEST,
+                },
+                data: {
+                    tweetId
+                },
+                overTime,
+                callback: (data) => {
+                    res(data);
+                },
+                failback: (e) => {
+                    rej(e)
+                }
+            })
+        })
+    }
+}

+ 94 - 0
src/denet/content/doTask.js

@@ -0,0 +1,94 @@
+import MESSAGE_ENUM from '@/uilts/messageCenter/iframe/messageEnum'
+import messageCenter from '@/uilts/messageCenter/iframe'
+import { getQueryString } from '@/uilts/help'
+const iframeId = getQueryString('iframeId')
+
+// 做任务
+const doTask = {
+    createTweet({ tweetId }, overTime) {
+        return new Promise((res, rej) => {
+            messageCenter.send({
+                info: {
+                    actionType: MESSAGE_ENUM.IFRAME_DO_TASK_CREATE_TWEET,
+                    iframeId //用于告诉父窗口会传消息给哪个iframe
+                },
+                data: {
+                    tweetId
+                },
+                overTime,
+                callback: (data) => {
+                    res(data);
+                },
+                failback: (e) => {
+                    rej(e)
+                }
+            })
+        })
+    },
+    like({ tweetId }, overTime) {
+        return new Promise((res, rej) => {
+            messageCenter.send({
+                info: {
+                    actionType: MESSAGE_ENUM.IFRAME_DO_TASK_LIKE,
+                    iframeId //用于告诉父窗口会传消息给哪个iframe
+                },
+                data: {
+                    tweetId,
+                },
+                overTime,
+                callback: (data) => {
+                    res(data);
+                },
+                failback: (e) => {
+                    rej(e)
+                }
+            })
+        })
+    },
+    follows({ follow_name, twitterUserId }, overTime) {
+        return new Promise((res, rej) => {
+            messageCenter.send({
+                info: {
+                    actionType: MESSAGE_ENUM.IFRAME_DO_TASK_FOLLOWS,
+                    iframeId //用于告诉父窗口会传消息给哪个iframe
+                },
+                data: {
+                  follow_name,
+                  twitterUserId
+                },
+                overTime,
+                callback: (data) => {
+                    res(data);
+                },
+                failback: (e) => {
+                    rej(e)
+                }
+            })
+        })
+    },
+    reTweet({ tweetId }, overTime) {
+        return new Promise((res, rej) => {
+            messageCenter.send({
+                info: {
+                    actionType: MESSAGE_ENUM.IFRAME_DO_TASK_RETWEET,
+                    iframeId //用于告诉父窗口会传消息给哪个iframe
+                },
+                data: {
+                    tweetId
+                },
+                overTime,
+                callback: (data) => {
+                    res(data);
+                },
+                failback: (e) => {
+                    rej(e)
+                }
+            })
+        })
+    }
+}
+
+export default doTask
+
+// iframe > dom id 
+// iframe > createTweet  dom id 

+ 30 - 0
src/denet/content/dom.js

@@ -0,0 +1,30 @@
+import MESSAGE_ENUM from '@/uilts/messageCenter/iframe/messageEnum'
+import messageCenter from '@/uilts/messageCenter/iframe'
+import { getQueryString } from '@/uilts/help'
+const iframeId = getQueryString('iframeId')
+
+const dom = {
+    // ---- 获取推文文案 ---- 
+    getTweetText({ tweetId }, overTime) {
+        return new Promise((res, rej) => {
+            messageCenter.send({
+                info: {
+                    actionType: MESSAGE_ENUM.IFRAME_DOM_GET_TWEET_TEXT,
+                    iframeId //用于告诉父窗口会传消息给哪个iframe
+                },
+                data: {
+                    tweetId
+                },
+                overTime,
+                callback: (data) => {
+                    res(data);
+                },
+                failback: (e) => {
+                    rej(e)
+                }
+            })
+        })
+    }
+}
+
+export default dom

+ 29 - 0
src/denet/content/getData.js

@@ -0,0 +1,29 @@
+import MESSAGE_ENUM from '@/uilts/messageCenter/iframe/messageEnum'
+import messageCenter from '@/uilts/messageCenter/iframe'
+import { getQueryString } from '@/uilts/help'
+const iframeId = getQueryString('iframeId')
+
+const getData = {
+  getUserInfoByName({screen_name}, overTime) {
+    return new Promise((res, rej) => {
+      messageCenter.send({
+          info: {
+              actionType: MESSAGE_ENUM.IFRAME_GET_TWITTER_USER_INFO,
+              iframeId
+          },
+          data: {
+            screen_name
+          },
+          overTime,
+          callback: (data) => {
+              res(data);
+          },
+          failback: (e) => {
+              rej(e)
+          }
+      })
+    })
+  }
+}
+
+export default getData

+ 9 - 0
src/denet/content/index.js

@@ -0,0 +1,9 @@
+import doTask from '@/denet/content/doTask'
+import dom from '@/denet/content/dom'
+import getData from '@/denet/content/getData'
+
+export default {
+    doTask,
+    dom,
+    getData
+}

+ 9 - 0
src/denet/index.js

@@ -0,0 +1,9 @@
+import content from '@/denet/content'
+import chrome from '@/denet/chrome'
+
+const denet = {
+    content,
+    chrome
+}
+
+export default denet

+ 107 - 85
src/entry/background.js

@@ -35,6 +35,7 @@ import {
 import {
     closeAchPayNoticeHandler
 } from "@/logic/background/denet";
+import chromeMessageCenter from '@/uilts/messageCenter/chrome';
 
 try {
     chrome.runtime.onMessage.addListener(onMessageMethod);
@@ -144,23 +145,22 @@ chrome.tabs.onActivated.addListener(function (activeInfo) {
     setPopupConfig(activeInfo);
 })
 
-function thenInstalledMethod() {
+function thenInstalledMethod({ reason }) {
     try {
 
-        onInstalledCreateTab()
-        onInstalledMid()
+        onInstalledCreateTab({ reason })
         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) {
@@ -186,7 +186,7 @@ function onInstalledMethod({ id, previousVersion, reason }) {
             if (!info || !info.appVersionCode) {
                 setChromeStorage({ onInstalledMethod: JSON.stringify({ onInstalledMethod: '1' }) })
                 setChromeStorage({ baseInfo: JSON.stringify({ appVersionCode }) })
-                thenInstalledMethod()
+                thenInstalledMethod({ reason })
 
                 // 版本更新了
             } else if (appVersionCode != info.appVersionCode) {
@@ -198,7 +198,7 @@ function onInstalledMethod({ id, previousVersion, reason }) {
                 })
             } else {
                 setChromeStorage({ onInstalledMethod: JSON.stringify({ onInstalledMethod: '3' }) })
-                thenInstalledMethod()
+                thenInstalledMethod({ reason })
             }
             console.log('1-appVersionCode', appVersionCode)
             console.log('1-info', info)
@@ -224,82 +224,15 @@ function onInstalledMethod({ id, previousVersion, reason }) {
 
 function onMessageMethod(req, sender, sendResponse) {
     try {
-        if (req) {
-            switch (req.actionType) {
-                case "POPUP_LOGIN":
-                    twitterPinLoginToken();
-                    sendResponse('ok');
-                    break;
-                case "POPUP_PUBLISH_TWITTER_RED_PACK":
-                    popupRePublish(req);
-                    sendResponse('ok');
-                    break;
-                case "POPUP_SHOW_DENET_PUBLISH_DIALOG":
-                    checkShowPublishDialog();
-                    break;
-                case 'CONTENT_GET_PINED':
-                    checkPined();
-                    break;
-                case 'CONTENT_SET_BADGE':
-                    setBadgeInfo(req);
-                    break;
-                case 'CONTENT_HIDE_BADGE':
-                    hideBadge();
-                    break
-                case 'CONTENT_SEND_CODE':
-                    twitterPinLoginCode(sender, req.code);
-                    break;
-                case 'CONTENT_TWITTER_LOGIN':
-                    if (req.data) {
-                        twitterPinLoginToken();
-                        sendResponse('ok');
-                    }
-                    break
-                case "CONTENT_SEND_DISCORD_AUTH_CODE":
-                    discordLoginCode(req, sender);
-                    break
-                case 'RED_PACKET_SAVE_DISCORD_AUTH_WINDOW_ID':
-                    saveDiscordAuthWindowId(req);
-                    sendResponse('ok');
-                    break;
-                case 'CONTENT_FACEBOOK_SHARE_SUCCESS':
-                    facebookShareSuccess(req, sender);
-                    break;
-                case 'CONTENT_PONG':
-                    sendResponse('CONTENT_PONG');
-                    break
-                case 'CONTENT_WINDOW_LOADED_SET_POPUP_PAGE':
-                    // windwoLoadSetPopupPage(req, sender);
-                    break;
-                case 'CONTENT_SET_POPUP_CONFIG':
-                    setActionPopup(req, sender);
-                    break;
-                case 'CONTENT_GET_TWITTER_NFT_POST_PRE':
-                    getTwitterNftPostPre(req.data, sender)
-                    break
-                case 'CONTENT_NFT_TXT_PUBLISH':
-                    nftTxtPublish(req.data, sender)
-                    break
-                case 'CONTENT_HTTP_NET_WORK':
-                    httpNetWork(req.funcName, req.data, sender)
-                    break
-                case 'HTTP_CONTENT_TO_BACK':
-                    httpContentToBack(req, sender)
-                    sendResponse('ok')
-                    break
-                case 'CONTENT_TWITTER_SHORT_LINK':
-                    sendResponse('ok')
-                    req.arr_url.forEach(item => {
-                        if (item) {
-                            twitterShortUrl(sender, item)
-                        }
-                    });
-                    break
-                case 'CONTENT_CLOSE_ACH_PAY_NOTICE':
-                    closeAchPayNoticeHandler();
-                    break;
-            }
+        if (!req) {
+            return
+        }
+        if (req.info) {
+            newRuntimeOnMessageMethod(req, sender, sendResponse)
+        } else if (req.actionType) {
+            oldRuntimeOnMessageMethod(req, sender, sendResponse)
         }
+        chromeMessageCenter.init(req)
     } catch (error) {
         Report.reportLog({
             objectType: Report.objectType.background_function_catch,
@@ -309,4 +242,93 @@ function onMessageMethod(req, sender, sendResponse) {
     }
 }
 //加载bg.js 执行
-setMessageCount();
+setMessageCount();
+
+const newRuntimeOnMessageMethod = (req, sender, sendResponse) => {
+    let { info = {}, data = {} } = req
+    switch (info.actionType) {
+        case 'CONTENT_TO_BACK_TEST':
+            chromeMessageCenter.sendToContent(sender, { info, data: '123' })
+            break;
+
+        default:
+            break;
+    }
+}
+
+const oldRuntimeOnMessageMethod = (req, sender, sendResponse) => {
+    switch (req.actionType) {
+        case "POPUP_LOGIN":
+            twitterPinLoginToken();
+            sendResponse('ok');
+            break;
+        case "POPUP_PUBLISH_TWITTER_RED_PACK":
+            popupRePublish(req);
+            sendResponse('ok');
+            break;
+        case "POPUP_SHOW_DENET_PUBLISH_DIALOG":
+            checkShowPublishDialog();
+            break;
+        case 'CONTENT_GET_PINED':
+            checkPined();
+            break;
+        case 'CONTENT_SET_BADGE':
+            setBadgeInfo(req);
+            break;
+        case 'CONTENT_HIDE_BADGE':
+            hideBadge();
+            break
+        case 'CONTENT_SEND_CODE':
+            twitterPinLoginCode(sender, req.code);
+            break;
+        case 'CONTENT_TWITTER_LOGIN':
+            if (req.data) {
+                twitterPinLoginToken();
+                sendResponse('ok');
+            }
+            break
+        case "CONTENT_SEND_DISCORD_AUTH_CODE":
+            discordLoginCode(req, sender);
+            break
+        case 'RED_PACKET_SAVE_DISCORD_AUTH_WINDOW_ID':
+            saveDiscordAuthWindowId(req);
+            sendResponse('ok');
+            break;
+        case 'CONTENT_FACEBOOK_SHARE_SUCCESS':
+            facebookShareSuccess(req, sender);
+            break;
+        case 'CONTENT_PONG':
+            sendResponse('CONTENT_PONG');
+            break
+        case 'CONTENT_WINDOW_LOADED_SET_POPUP_PAGE':
+            // windwoLoadSetPopupPage(req, sender);
+            break;
+        case 'CONTENT_SET_POPUP_CONFIG':
+            setActionPopup(req, sender);
+            break;
+        case 'CONTENT_GET_TWITTER_NFT_POST_PRE':
+            getTwitterNftPostPre(req.data, sender)
+            break
+        case 'CONTENT_NFT_TXT_PUBLISH':
+            nftTxtPublish(req.data, sender)
+            break
+        case 'CONTENT_HTTP_NET_WORK':
+            httpNetWork(req.funcName, req.data, sender)
+            break
+        case 'HTTP_CONTENT_TO_BACK':
+            httpContentToBack(req, sender)
+            sendResponse('ok')
+            break
+        case 'CONTENT_TWITTER_SHORT_LINK':
+            sendResponse('ok')
+            req.arr_url.forEach(item => {
+                if (item) {
+                    twitterShortUrl(sender, item)
+                }
+            });
+            break
+        case 'CONTENT_CLOSE_ACH_PAY_NOTICE':
+            closeAchPayNoticeHandler();
+            break;
+    }
+}

+ 143 - 51
src/entry/content.js

@@ -37,9 +37,13 @@ import {
     refreshTabGroup,
     groupTipsSelectGroupTab,
     TwitterApiUserByScreenName,
-    showPublishDialog
+    showPublishDialog,
+    getTweetUserFollowStatus,
+    sendContentByTwitterID,
+    getExtensionStorgeDataForIframe,
+    doTaskIframeTwitterAPI
 } from "@/logic/content/twitter.js";
-
+import denet from '@/denet'
 import { httpBackToContentCallBack } from '@/uilts/chromeExtension.js'
 import {
     hideNFTGroupList,
@@ -56,6 +60,10 @@ import {
     injectDenet
 } from "@/logic/content/denet.js";
 
+import doTask from '@/logic/content/help/doTask'
+import getData from '@/logic/content/help/getData'
+import chromeMessageCenter from '@/uilts/messageCenter/chrome';
+
 chrome.storage.onChanged.addListener(changes => {
     initExecuteScript(changes)
 })
@@ -69,57 +77,110 @@ window.onload = () => {
         data: {}
     });
 };
-window.onmessage = (res) => {
-    if (res.data && res.data.actionType) {
-        switch (res.data.actionType) {
-            case "IFRAME_SHOW_IFREME":
-                showIframeHandler();
-                break;
-            case "IFRAME_HIDE_IFREME":
-                hideIframeHandler();
-                break;
-            case "IFRAME_SHOW_TWITTER_PUBLISH_DIALOG":
-                showTwitterPublishDialogHandler(res.data.publishRes);
-                break;
-            case "IFRAME_RED_PACKET_REPLY_CLICK":
-                replyHandle(res.data.data || {});
-                break;
-            case "IFRAME_RED_PACKET_SHOW_BIND_TWEET_NOTICE":
-                noticeBindTweet(res.data.data || {});
-                break;
-            case "IFRAME_CLOSE_BIND_TWEET":
-                hideNoticeBindTweet();
-                break;
-            case "IFRAME_RED_PACKET_GET_TWEET_AUTHOR":
-                getTweetAuthorByDom(res.data.data || {});
-                break;
-            case "IFRAME_RED_PACKET_CHECK_FACEBOOK_REPLY":
-                facebookReplyTweet(res.data.data || {});
-                break;
-            case "IFRAME_RED_PACKET_ON_TWEET_REPLY_CLICK":
-                onTweetReplyClick(res.data.data || {});
-                break;
-            // case 'IFRAME_TWITTER_API_DO_TASK':
-            //     doTaskTwitterAPI(res.data)
-            //     break
-            // case "IFRAME_DO_TASK":
-            //     findTweetByIdDoTask(res.data.task_data, res.data.task_type)
-            //     break
-            case 'IFREME_TAB_GROUP_SET_IFRAME_HEIGHT':
-                setTabGroupIframeStyle(res.data.data);
-                break
-            case 'IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP':
-                getTweetProfileNavTop(res.data.data);
-                break;
-            case 'IFRAME_PAGE_JUMP':
-                pageJumpHandler(res.data.data);
-                break;
-        }
+
+const oldOnMessageMethod = (res) => {
+    switch (res.data.actionType) {
+        case "IFRAME_SHOW_IFREME":
+            showIframeHandler();
+            break;
+        case "IFRAME_HIDE_IFREME":
+            hideIframeHandler();
+            break;
+        case "IFRAME_SHOW_TWITTER_PUBLISH_DIALOG":
+            showTwitterPublishDialogHandler(res.data.publishRes);
+            break;
+        case "IFRAME_RED_PACKET_REPLY_CLICK":
+            replyHandle(res.data.data || {});
+            break;
+        case "IFRAME_RED_PACKET_SHOW_BIND_TWEET_NOTICE":
+            noticeBindTweet(res.data.data || {});
+            break;
+        case "IFRAME_CLOSE_BIND_TWEET":
+            hideNoticeBindTweet();
+            break;
+        case "IFRAME_RED_PACKET_GET_TWEET_AUTHOR":
+            getTweetAuthorByDom(res.data.data || {});
+            break;
+        case "IFRAME_RED_PACKET_CHECK_FACEBOOK_REPLY":
+            facebookReplyTweet(res.data.data || {});
+            break;
+        case "IFRAME_RED_PACKET_ON_TWEET_REPLY_CLICK":
+            onTweetReplyClick(res.data.data || {});
+            break;
+        // case 'IFRAME_TWITTER_API_DO_TASK':
+        //     doTaskTwitterAPI(res.data)
+        //     break
+        // case "IFRAME_DO_TASK":
+        //     findTweetByIdDoTask(res.data.task_data, res.data.task_type)
+        //     break
+        case 'IFREME_TAB_GROUP_SET_IFRAME_HEIGHT':
+            setTabGroupIframeStyle(res.data.data);
+            break
+        case 'IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP':
+            getTweetProfileNavTop(res.data.data);
+            break;
+        case 'IFRAME_PAGE_JUMP':
+            pageJumpHandler(res.data.data);
+            break;
+        case 'IFRAME_GET_EXTENSION_STORGE_DATA':
+            getExtensionStorgeDataForIframe(res.data.data);
+            break;
+
+        case 'IFRAME_API_GET_TWEET_USER_FOLLOW_STATUS':
+            getTweetUserFollowStatus(res.data);
+            break;
+        case 'IFRAME_TWITTER_API_DO_TASK':
+            doTaskIframeTwitterAPI(res.data);
+            break;
+        case 'IFRAME_API_GET_TWEET_USER_INFO_START':
+            let data = JSON.parse(res.data.data);
+
+            TwitterApiUserByScreenName({
+                iframeId: res.data.iframeId,
+                ...data
+            })
+            break;
+
+        case 'GET_CONTENT_BY_TWITTER_ID':
+            sendContentByTwitterID(res.data)
+            break
     }
-};
+}
 
+const newOnMessageMethod = (res) => {
+    let { info = {}, data = {} } = res.data
+    switch (info.actionType) {
+        case 'IFRAME_DO_TASK_CREATE_TWEET':
+            doTask.TwitterApiCreateTweet({ info, data })
+            break
+        case 'IFRAME_DO_TASK_LIKE':
+            doTask.TwitterLikeAPI({ info, data })
+            break
+        case 'IFRAME_DO_TASK_RETWEET':
+            doTask.TwitterRetweetAPI({ info, data })
+            break
+        case 'IFRAME_DO_TASK_FOLLOWS':
+            doTask.TwitterFollowAPI({ info, data })
+            break
+        case 'IFRAME_GET_TWITTER_USER_INFO':
+            getData.TwitterApiGetUserInfoByName({ info, data })
+            break
+    }
+}
 
-chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
+
+window.onmessage = (res) => {
+    if (!res.data) {
+        return
+    }
+    if (res.data.actionType) {
+        oldOnMessageMethod(res)
+    } else if (res.data.info) {
+        newOnMessageMethod(res)
+    }
+}
+
+const oldRuntimeOnMessageMethod = (req, sender, sendResponse) => {
     switch (req.actionType) {
         case 'BG_SHOW_PIN_TIPS':
             showPinTips()
@@ -222,6 +283,37 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
         case 'Hide_ToolBox_By_Nft':
             toolBox.hideBuyNft(req)
             break;
+        case 'IFRAME_API_GET_TWEET_USER_FOLLOW_STATUS':
+            getTweetUserFollowStatus(req);
+            break;
+        case 'GET_CONTENT_BY_TWITTER_ID':
+            sendContentByTwitterID(req.data.tweet_Id)
+            break
+        case 'TEST':
+            console.log('TEST')
+            break
+    }
+}
+
+const newRuntimeOnMessageMethod = (req, sender, sendResponse) => {
+
+}
+chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
+    if (req.actionType) {
+        oldRuntimeOnMessageMethod(req, sender, sendResponse)
+    } else if (req.info) {
+        newRuntimeOnMessageMethod(req, sender, sendResponse)
+        chromeMessageCenter.init(req)
     }
     sendResponse && sendResponse('ok');
-})
+
+})
+
+// --- test ---
+// async function funcTest() {
+//     let res = await denet.chrome.content.test({ tweetId: 22 })
+//     console.log('test sendmessage', res)
+// }
+// setTimeout(() => {
+//     funcTest()
+// }, 3000);

+ 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)
     }
-}
+}

+ 16 - 1
src/http/help.js

@@ -1,6 +1,6 @@
 import { getChromeStorage } from '@/uilts/chromeExtension.js'
 import { srcPublishSuccess } from '@/http/publishApi'
-import { bindRepost } from '@/http/treasure'
+import { bindRepost, bindPostContent } from '@/http/treasure'
 
 // 重新绑定推文id
 export const reSetBindTwtterId = ({
@@ -39,3 +39,18 @@ export const reSetBindRepost = (params, callback) => {
     })
 }
 
+
+
+export const reSetBindPostContent = (params, callback) => {
+    getChromeStorage('userInfo', (_userInfo) => {
+        if (_userInfo && _userInfo.uid) {
+            bindPostContent({
+                params
+            }).then((res) => {
+                if (res.code == 0 || res.code == 3003) {
+                    callback && callback()
+                }
+            })
+        }
+    })
+}

+ 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') || ''
   }

+ 17 - 1
src/http/toolBoxApi.js

@@ -18,7 +18,7 @@ export function getAllPostEditorAppData(params) {
 
 export function screenshotWebsite(params) {
     return service({
-        url: `/post/editor/screenshotWebsite`,
+        url: `/post/editor/screenshotWebsiteV2`,
         method: 'post',
         data: params
     })
@@ -47,3 +47,19 @@ export function unlockNftCert(params) {
         data: params
     })
 }
+
+export function getContentTypeConfig(params) {
+  return service({
+      url: `/post/editor/getContentTypeConfig`,
+      method: 'post',
+      data: params
+  })
+}
+
+export function getPostEditorConfig(params) {
+  return service({
+      url: `/post/editor/getConfig`,
+      method: 'post',
+      data: params
+  })
+}

+ 29 - 2
src/http/treasure.js

@@ -27,12 +27,21 @@ export function inviteDetail(params) {
 
 export function inviteList(params) {
     return service({
-        url: `/post/treasure/invite/list`,
+        url: `/post/treasure/invite/list/v2`,
         method: "post",
         data: params,
     });
 }
 
+export function inviteListRefresh(params) {
+    return service({
+        url: `/post/treasure/invite/list/refresh`,
+        method: "post",
+        data: params,
+    });
+
+}
+
 export function treasureOpen(params) {
     return service({
         url: `/post/treasure/open`,
@@ -74,4 +83,22 @@ export function bindRepost(params) {
         method: "post",
         data: params,
     });
-}
+}
+
+export function bindPostContent(params) {
+    return service({
+        url: `/post/bindPostSrcContent`,
+        method: "post",
+        data: params,
+    });
+}
+
+export function receiveListV2(params) {
+    return service({
+        url: `/post/treasure/receive/list/v2`,
+        method: "post",
+        data: params,
+    });
+}
+
+

+ 3 - 2
src/iframe/ach-cashier.js

@@ -2,5 +2,6 @@ import { createApp } from 'vue'
 import App from '@/view/iframe/ach-pay/cashier.vue'
 
 const app = createApp(App);
-
-app.mount('#app');
+import CoutomSentry from "@/uilts/sentry.js"
+CoutomSentry.initVue(app)
+app.mount('#app');

+ 2 - 1
src/iframe/tool-box-buy-nft.js

@@ -3,6 +3,7 @@ import App from '@/view/iframe/tool-box/buy-nft.vue'
 import AutoLog from '@/log-center/autoLog';
 
 const app = createApp(App);
-
+import CoutomSentry from "@/uilts/sentry.js"
+CoutomSentry.initVue(app)
 app.use(AutoLog);
 app.mount('#app');

+ 3 - 2
src/iframe/tool-box-guide.js

@@ -6,10 +6,11 @@ import "ant-design-vue/dist/antd.css"; // or 'ant-design-vue/dist/antd.less'
 import {message} from "ant-design-vue";
 
 const app = createApp(App);
-
+import CoutomSentry from "@/uilts/sentry.js"
+CoutomSentry.initVue(app)
 app.use(message);
 app.mount('#app');
 
 window.onload= () => {
     document.title = 'DeNet'
-}
+}

+ 3 - 1
src/iframe/tool-box.js

@@ -1,4 +1,6 @@
 import { createApp } from 'vue'
 import App from '@/view/iframe/tool-box/index.vue'
 const app = createApp(App);
-app.mount('#app');
+import CoutomSentry from "@/uilts/sentry.js"
+CoutomSentry.initVue(app)
+app.mount('#app');

+ 3 - 0
src/iframe/treasure-hunt.js

@@ -1,6 +1,9 @@
 import { createApp } from 'vue'
 import App from '@/view/iframe/test/index.vue'
 import AutoLog from '@/log-center/autoLog';
+import CoutomSentry from "@/uilts/sentry.js"
+
 const app = createApp(App);
+CoutomSentry.initVue(app)
 app.use(AutoLog)
 app.mount('#app');

+ 14 - 7
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 = {
@@ -26,6 +28,8 @@ export const objectType = {
     loginButton: "login-button",
     withdrawButton: "withdraw-button",
     topupButton: "topup-button",
+    previewNextButton: 'preview-next-button',
+    setPublishContent: 'set-publish-content',
 
 
     getMoreGiveaway: "get-more-giveaway",
@@ -68,7 +72,7 @@ export const objectType = {
     // background文件安装catch异常
     background_function_catch: 'background-function-catch',
     // background 文件chrome 函数 try
-    background_function_try:'background-function-try',
+    background_function_try: 'background-function-try',
     // create Nft
     create_nfts_button: 'create-nfts-button',
     confirm_transfer_button: 'confirm-transfer-button',
@@ -82,6 +86,7 @@ export const objectType = {
     top_right_button: 'top-right-button',
     fullscreen_button: 'fullscreen-button',
     encrypte_nft_button: 'encrypte-nft-button',
+    preRepost: 'preRepost',
 }
 
 export const pageSource = {
@@ -135,6 +140,8 @@ export const pageSource = {
     post_editor_guide_page_right: 'post-editor-guide-page-right',
     buy_posteditor_nft_dialog: 'buy-posteditor-nft-dialog',
 
+    // 夺宝模式 - 领取列表页
+    who_get_money_page: 'who-get-money-page'
 }
 
 export const extParams = {
@@ -150,11 +157,11 @@ export const bizType = {
 }
 
 export const getCurrentBizType = (type) => {
-  let obj = {};
-  obj[PlayType.common] = bizType.RedPacket;
-  obj[PlayType.lottery] = bizType.Lottery;
-  obj[PlayType.treasure] = bizType.Treasure;
-  obj[PlayType.postEditor] = bizType.ToolBox;
+    let obj = {};
+    obj[PlayType.common] = bizType.RedPacket;
+    obj[PlayType.lottery] = bizType.Lottery;
+    obj[PlayType.treasure] = bizType.Treasure;
+    obj[PlayType.postEditor] = bizType.ToolBox;
 
-  return obj[type];
+    return obj[type];
 }

+ 16 - 14
src/logic/background/facebook.js

@@ -10,21 +10,23 @@ export function facebookShareSuccess(params, sender) {
         let { id } = sender.tab || {};
         chrome.tabs.remove(id);
 
-        fetchAddFinishEvent({
+        if(!data.bizType) {
+          fetchAddFinishEvent({
             eventType: data.type,
             luckdropId: data.taskLuckdropId
-        }).then(res => {
-            if (res.code == 0) {
-                setTimeout(() => {
-                    sendActivetabMessage({
-                        actionType: 'BG_FACEBOOK_SHARE_SUCCESS',
-                        data: data
-                    });
-                })
-            }
-        }).catch((error) => {
-            console.log('catch', error)
-        })
+          }).then(res => {
+              if (res.code == 0) {
+                  setTimeout(() => {
+                      sendActivetabMessage({
+                          actionType: 'BG_FACEBOOK_SHARE_SUCCESS',
+                          data: data
+                      });
+                  })
+              }
+          }).catch((error) => {
+              console.log('catch', error)
+          })
+        }
     } catch (error) {
         Report.reportLog({
             objectType: Report.objectType.background_function_catch,
@@ -52,4 +54,4 @@ function sendActivetabMessage(message = {}) {
             errMsg: error.message
         })
     }
-}
+}

+ 31 - 20
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',
@@ -328,20 +333,26 @@ function sendActivetabMessage(message = {}) {
  * 安装后打开新标签页
  */
 
-export function onInstalledCreateTab() {
+export function onInstalledCreateTab({ reason }) {
     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,
+                        reason
+                    })
+                }, 5000)
+            });
+
             let url = 'https://twitter.com/search?q=%23denet'
             // jump_info
             if (!res || !res.jump_type) {
@@ -442,7 +453,7 @@ export function onInstalledCreateTab() {
 
 /**
  * 在popop重新发送
- * @param {*} req 
+ * @param {*} req
  */
 export function popupRePublish(req) {
     try {
@@ -507,11 +518,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 +741,4 @@ const createTabShowGiveaway = (params) => {
     chrome.tabs.create({
         url: params.url,
     });
-}
+}

+ 117 - 41
src/logic/content/ParseCard.js

@@ -1,7 +1,7 @@
-import { getChromeStorage, setChromeStorage } from '@/uilts/chromeExtension.js'
 import ToolBox from '@/view/content/tool-box/index.vue'
 import { createApp } from 'vue'
-
+import { getStorage, setStorage, guid } from '@/uilts/help'
+import { chromeExtensionUrl } from '@/uilts/chromeExtension'
 // 解析卡片类
 // 1.dom匹配
 // 2.找出网页匹配 获取twitterid
@@ -61,19 +61,29 @@ class ParseCard {
         // 是否有#DeNet
         return has_denet
     }
-    parseAllDeNetCard() {
+    parseAllDeNetCard(has_iframe = false) {
         let de_net_card = []
         try {
             let arr_article = document.querySelectorAll('article') || []
             let _txt
             for (let i in arr_article) {
                 _txt = arr_article[i].innerText || ''
-                if ((_txt.includes('#DeNet') || _txt.includes('#DNFT') || this.compatibleMask(arr_article[i])) && !this.isHasIframeByArticle(arr_article[i])) {
-                    de_net_card.push({
-                        time: new Date().getTime(),
-                        dom: arr_article[i]
-                    })
+                if (has_iframe) {
+                    if ((_txt.includes('#DeNet') || _txt.includes('#DNFT') || this.compatibleMask(arr_article[i]))) {
+                        de_net_card.push({
+                            time: new Date().getTime(),
+                            dom: arr_article[i]
+                        })
+                    }
+                } else {
+                    if ((_txt.includes('#DeNet') || _txt.includes('#DNFT') || this.compatibleMask(arr_article[i])) && !this.isHasIframeByArticle(arr_article[i])) {
+                        de_net_card.push({
+                            time: new Date().getTime(),
+                            dom: arr_article[i]
+                        })
+                    }
                 }
+
             }
         } catch (error) {
         }
@@ -154,9 +164,9 @@ class ParseCard {
             return
         }
     }
-    parseAllDeNetCardParmas() {
+    parseAllDeNetCardParmas(has_iframe = false) {
         let json_data = []
-        this.parseAllDeNetCard().forEach((item) => {
+        this.parseAllDeNetCard(has_iframe).forEach((item) => {
             let _obj = this.parseCardParmas(item.dom)
             if (_obj.tweet_Id && _obj.short_url && _obj.dom_card) {
                 _obj.time = item.time
@@ -178,23 +188,24 @@ class ParseCard {
     }
     // 获取短链接和渲染卡片数据
     async getCardParmas(card_json_data) {
-        let sort_link_data = await getChromeStorage('cardData') || []
+        let sort_link_data = getStorage('denetCardData') || []
+        // let sort_link_data = await getChromeStorage('cardData') || []
         let has_post_Id_card_data = this.getLocalHasPostIdData(sort_link_data, card_json_data)
-        let need_net_short_url = this.filterShortUrl(sort_link_data, card_json_data)
+        let need_net_short_urls = this.filterShortUrl(sort_link_data, card_json_data)
 
         // 校验存储大小
         let new_item = this.checkShortUrlArraySize(sort_link_data)
         if (sort_link_data.length != new_item.length) {
-            setChromeStorage({ cardData: JSON.stringify(new_item) })
+            setStorage('denetCardData', new_item)
         }
         return {
             has_post_Id_card_data,
-            need_net_short_url
+            need_net_short_urls
         }
     }
     filterShortUrl(sort_link_data, card_json_data) {
         let has = false
-        let need_net_short_url = []
+        let need_net_short_urls = []
 
         card_json_data.forEach((card_item) => {
             has = false
@@ -204,11 +215,11 @@ class ParseCard {
                 }
             })
             if (!has) {
-                need_net_short_url.push(card_item.short_url)
+                need_net_short_urls.push(card_item.short_url)
             }
         })
         // 返回的是没有postid的
-        return need_net_short_url
+        return need_net_short_urls
     }
     getLocalHasPostIdData(sort_link_data = [], card_json_data = []) {
         // 
@@ -224,8 +235,53 @@ class ParseCard {
         })
         return has_post_Id_card_data
     }
+    netShortUrl(need_net_short_urls = [], callback) {
+        // 1. 获取短链接
+        let denetCardData = getStorage('denetCardData') || []
+
+        need_net_short_urls.forEach((short_url) => {
+            // // 本地没有 存储 
+            if (denetCardData.filter((item) => { return item.short_url == short_url }).length == 0) {
+                denetCardData.push({
+                    short_url
+                })
+            }
+        })
+
+        setStorage('denetCardData', denetCardData)
+
+        // 发起网络请求
+        if (!navigator.onLine) {
+            return
+        }
+        let now_time
+        for (let i in denetCardData) {
+            now_time = new Date().getTime()
+            // 没请求过 || 现在时间 - 网络请求时间 >= 3s && 没有post_Id
+            if ((!denetCardData[i].fetch_time || (now_time - denetCardData[i].fetch_time) >= 3000) && !denetCardData[i].post_Id) {
+                // 发起网络请求请求
+                denetCardData[i].fetch_time = now_time
+                fetch(denetCardData[i].short_url) // 返回一个Promise对象 
+                    .then((res) => {
+                        return res.text() // res.text()是一个Promise对象
+                    }).then((res) => {
+                        res = res.toString()
+                        let str_arr = res.match(/denetme.net\/([\s\S]*?)"/) || []
+                        let post_Id = str_arr[1] || ''
+                        if (!post_Id) {
+                            return
+                        }
+                        denetCardData[i].post_Id = post_Id
+                        setStorage('denetCardData', denetCardData)
+                        callback && callback()
+                    }).catch((error) => {
+                        console.log('catch', error)
+                    })
+            }
+        }
+    }
     checkShortUrlArraySize(_array) {
-        if (new Blob(_array).size >= 1024 * 1024) {
+        if (new Blob(_array).size >= 1024 * 1024 * 4) {
             _array.splice(0, parseInt(_array.length / 2))
         }
         return _array
@@ -238,7 +294,7 @@ class ParseCard {
             tweet_str = `&tweetId=${tweet_Id}`
         }
         _iframe.id = post_Id
-        _iframe_url = chrome.runtime.getURL('/iframe/tool-box.html') + `?page_type=${'card'}&postId=${post_Id}&tweetId=${tweet_Id}`;
+        _iframe_url = chromeExtensionUrl + ('iframe/tool-box.html') + `?page_type=${'card'}&postId=${post_Id}&tweetId=${tweet_Id}`;
         _iframe.allow = "camera *;microphone *"
         // debugger mode
         if (window.location.href.includes('denet_debugger')) {
@@ -250,14 +306,16 @@ class ParseCard {
         return _iframe
     }
     createIframe({ post_Id = '', tweet_Id = '', tweet_author = '', page_type = '' }, if_center = false) {
+        let _iframeId = `denet-${guid()}`
         let _iframe = document.createElement('iframe')
         let _iframe_url = ''
         let tweet_str = ''
         if (tweet_Id) {
             tweet_str = `&tweetId=${tweet_Id}`
         }
-        _iframe.id = post_Id
-        _iframe_url = chrome.runtime.getURL('/iframe/red-packet.html') + `?postId=${post_Id}${tweet_str}&tweet_author=${tweet_author}&window_origin=${window.location.origin}&page_type=${page_type}`;
+        _iframe.id = _iframeId
+        _iframe.dataset.card = 'denet'
+        _iframe_url = chromeExtensionUrl + ('iframe/red-packet.html') + `?postId=${post_Id}${tweet_str}&tweet_author=${tweet_author}&window_origin=${window.location.origin}&page_type=${page_type}&iframeId=${_iframeId}`;
         // debugger mode
         if (window.location.href.includes('denet_debugger')) {
             _iframe_url = _iframe_url + '&denet_debugger=1'
@@ -274,22 +332,24 @@ class ParseCard {
         let projectId = project_arr[0]
         let _iframe = document.createElement('iframe')
         _iframe.id = project_Id
-        _iframe.src = chrome.runtime.getURL('/iframe/nft-card.html') + `?projectId=${projectId}&tweetId=${tweet_Id}&twitterAccount=${project_arr[1]}`;
+        _iframe.src = chromeExtensionUrl + ('iframe/nft-card.html') + `?projectId=${projectId}&tweetId=${tweet_Id}&twitterAccount=${project_arr[1]}`;
         _iframe.style.cssText = 'border:medium none; width:375px; min-height:300px;'
         return _iframe
     }
     createNftGroupIframe({ project_Id, tweet_Id }) {
         let _iframe = document.createElement('iframe')
         _iframe.id = project_Id
-        _iframe.src = chrome.runtime.getURL('/iframe/nft-group-card.html') + `?projectId=${project_Id}&tweet_Id=${tweet_Id}`;
+        _iframe.src = chromeExtensionUrl + ('iframe/nft-group-card.html') + `?projectId=${project_Id}&tweet_Id=${tweet_Id}`;
         _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 _iframeId = `denet-${guid()}`
         let _iframe = document.createElement('iframe')
-        _iframe.id = params.post_Id
-        _iframe.src = chrome.runtime.getURL('/iframe/treasure-hunt.html') + `?params=${JSON.stringify(params)}`;
-        _iframe.style.cssText = 'border:medium none; width:375px; min-height:500px; border: 1px solid #DCDCDC; border-radius: 20px;'
+        _iframe.id = _iframeId
+        _iframe.dataset.card = 'denet'
+        _iframe.src = chromeExtensionUrl + ('iframe/treasure-hunt.html') + `?params=${JSON.stringify(params)}&iframeId=${_iframeId}`;
+        _iframe.style.cssText = 'border:medium none; width:375px; min-height:580px; border: 1px solid #DCDCDC; border-radius: 20px;'
         return _iframe
     }
     isHasIframeByArticle(dom_card) {
@@ -480,7 +540,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
         }
@@ -500,7 +560,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 }) {
@@ -528,28 +588,34 @@ class ParseCard {
         if (!dom_card || !dom_card.parentElement) {
             return
         }
-        let dom = dom_card.querySelector('div[id^=jsc_c_]').parentElement
-        dom.style = 'min-height:500px'
+        let card = dom_card.querySelector('div[id^=jsc_c_]');
+        let dom = card && card.parentElement;
         if (dom) {
-            for (let i = 0; i < dom.childNodes.length; i++) {
-                if (dom.childNodes[i].dataset && dom.childNodes[i].dataset.testid && dom.childNodes[i].dataset.testid == 'card.wrapper') {
-                    dom.children[i].style.display = 'none'
-                }
-            }
-
-            if (dom.nextElementSibling && dom.nextElementSibling.id && dom.nextElementSibling.id.indexOf('jsc_c_') >= 0) {
-                dom.nextElementSibling.style.display = 'none'
-            }
             let originUrl = new URL(short_url);
             let post_Id = originUrl.pathname.slice(1);
 
             if (post_Id.indexOf('luckdraw/') >= 0) {
+                hideImage(dom);
+                dom.style = 'min-height:500px'
                 post_Id = post_Id.replace('luckdraw/', '');
                 dom.appendChild(this.createIframe({ post_Id, tweet_author, page_type: '抽奖' }, true))
-            } else if (!post_Id.includes('/')) {
+            } else if (post_Id.indexOf('/') === -1) {
+                hideImage(dom);
+                dom.style = 'min-height:500px'
                 dom.appendChild(this.createIframe({ post_Id, tweet_author }, true))
             }
         }
+
+        function hideImage(dom) {
+            for (let i = 0; i < dom.childNodes.length; i++) {
+                if (dom.childNodes[i].dataset && dom.childNodes[i].dataset.testid && dom.childNodes[i].dataset.testid == 'card.wrapper') {
+                    dom.children[i].style.display = 'none'
+                }
+            }
+            if (dom.nextElementSibling && dom.nextElementSibling.id && dom.nextElementSibling.id.indexOf('jsc_c_') >= 0) {
+                dom.nextElementSibling.style.display = 'none'
+            }
+        }
     }
     replaceNftGroupDomRedPacket({ dom_card, tweet_Id, post_Id, time, short_url }) {
         if (!dom_card || !dom_card.parentElement) {
@@ -572,5 +638,15 @@ class ParseCard {
             dom.appendChild(this.createNftGroupIframe({ project_Id, tweet_Id }))
         }
     }
+    // 根据推特id获取文章推文
+    getContentByTwitterId(tweet_Id) {
+        let txt = ''
+        let card_json_data = this.parseAllDeNetCardParmas(true)
+        let result = card_json_data.filter((item) => { return item.tweet_Id == tweet_Id }) || []
+        if (result.length > 0 && result[0].dom_card) {
+            txt = result[0].dom_card.querySelector('[data-testid="tweetText"]').innerText.replace('…', ' ')
+        }
+        return txt
+    }
 }
 export default new ParseCard()

+ 6 - 4
src/logic/content/ToolBox.js

@@ -1,4 +1,6 @@
 import { $ } from "@/uilts/help";
+import { chromeExtensionUrl } from '@/uilts/chromeExtension'
+
 export let toolbox_fixed_tweetId = ''
 
 export const toolBox = new class ToolBox {
@@ -18,7 +20,7 @@ export const toolBox = new class ToolBox {
             display:none;
             border:medium none;  filter: drop-shadow(rgba(0, 0, 0, 0.2) 0px 4px 20px);
             `
-        iframe.src = chrome.runtime.getURL('/iframe/tool-box.html') + `?page_type=${'full'}`;
+        iframe.src = chromeExtensionUrl + ('iframe/tool-box.html') + `?page_type=${'full'}`;
         iframe.allow = "camera *;microphone *"
         document.body.append(iframe)
     }
@@ -59,12 +61,12 @@ export const toolBox = new class ToolBox {
     // 购买NFT
     buyNft(req) {
         let iframe = document.createElement('iframe')
-            iframe.src = chrome.runtime.getURL('/iframe/tool-box-buy-nft.html') + `?postId=${req.data.postId}`;
+        iframe.src = chromeExtensionUrl + ('iframe/tool-box-buy-nft.html') + `?postId=${req.data.postId}`;
         let ifAppend = document.querySelector('#denet-tool-box-buy-nft')
         if (ifAppend) return;
         let div = document.createElement(`div`);
-            div.id = 'denet-tool-box-buy-nft';
-            div.innerHTML = `
+        div.id = 'denet-tool-box-buy-nft';
+        div.innerHTML = `
                 ${iframe.outerHTML}
                 <div class="mask_bg"></div>
                 <style>

+ 2 - 2
src/logic/content/facebook.js

@@ -17,7 +17,7 @@ export function initFacebookContent() {
 
 /**
  * 注入分享页面逻辑
- * @returns 
+ * @returns
  */
 function injectShareCode() {
     const {href, pathname} = window.location;
@@ -66,4 +66,4 @@ function shareCallback() {
             chrome.runtime.sendMessage({ actionType: "CONTENT_FACEBOOK_SHARE_SUCCESS", data: params })
         }
     }
-}
+}

+ 155 - 0
src/logic/content/help/doTask.js

@@ -0,0 +1,155 @@
+import messageCenter from '@/uilts/messageCenter/content';
+import { getCookie, isMobileTwitter } from '@/uilts/help'
+import axios from 'axios';
+
+const TwitterApiCreateTweet = ({ info, data }) => {
+    let params = {
+        queryId: "hC1nuE-2d1NX5LYBuuAvtQ",
+        features: {
+            "dont_mention_me_view_api_enabled": true,
+            "interactive_text_enabled": true,
+            "responsive_web_uc_gql_enabled": false,
+            "vibe_api_enabled": true,
+            "responsive_web_edit_tweet_api_enabled": false,
+            "standardized_nudges_misinfo": true,
+            "responsive_web_enhance_cards_enabled": false
+        },
+        variables: {
+            "tweet_text": data.txt,
+            "media": {
+                "media_entities": [],
+                "possibly_sensitive": false
+            },
+            "withDownvotePerspective": true,
+            "withReactionsMetadata": false,
+            "withReactionsPerspective": false,
+            "withSuperFollowsTweetFields": true,
+            "withSuperFollowsUserFields": true,
+            "semantic_annotation_ids": [],
+            "dark_request": false
+        }
+    };
+    let url = isMobileTwitter() ? "https://mobile.twitter.com/i/api/graphql/K9It0MijE2UOlX-8wLyPYA/CreateTweet" : "https://twitter.com/i/api/graphql/hC1nuE-2d1NX5LYBuuAvtQ/CreateTweet"
+    axios.post(url,
+        params, {
+        headers: {
+            "accept": "*/*",
+            "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
+            "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
+            "content-type": "application/json",
+            "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"101\", \"Google Chrome\";v=\"101\"",
+            "sec-ch-ua-mobile": "?0",
+            "sec-ch-ua-platform": "\"Windows\"",
+            "sec-fetch-dest": "empty",
+            "sec-fetch-mode": "cors",
+            "sec-fetch-site": "same-origin",
+            "x-csrf-token": getCookie('ct0'),
+            "x-twitter-active-user": "yes",
+            "x-twitter-auth-type": "OAuth2Session",
+            "x-twitter-client-language": "en"
+        },
+    }).then(function (response) {
+        messageCenter.send({ info, data: response })
+    }).catch(function (err) {
+        messageCenter.send({ info, data: err })
+    });
+}
+
+const TwitterLikeAPI = ({ info, data }) => {
+    let url = isMobileTwitter() ? "https://mobile.twitter.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet" : "https://twitter.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet"
+    fetch(url, {
+        "headers": {
+            "accept": "*/*",
+            "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
+            "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
+            "content-type": "application/json",
+            "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"101\", \"Google Chrome\";v=\"101\"",
+            "sec-ch-ua-mobile": "?0",
+            "sec-ch-ua-platform": "\"Windows\"",
+            "sec-fetch-dest": "empty",
+            "sec-fetch-mode": "cors",
+            "sec-fetch-site": "same-origin",
+            "x-csrf-token": getCookie('ct0'),
+            "x-twitter-active-user": "yes",
+            "x-twitter-auth-type": "OAuth2Session",
+            "x-twitter-client-language": "en"
+        },
+        "referrer": "https://twitter.com/home",
+        "referrerPolicy": "strict-origin-when-cross-origin",
+        "body": "{\"variables\":{\"tweet_id\":\"" + data.tweetId + "\"},\"queryId\":\"lI07N6Otwv1PhnEgXILM7A\"}",
+        "method": "POST",
+        "mode": "cors",
+        "credentials": "include"
+    }).then(() => {
+        // 返回信息
+        messageCenter.send({ info, data: { task_done: true } })
+    }).catch(() => {
+        messageCenter.send({ info, data: { task_done: false } })
+    })
+}
+
+const TwitterFollowAPI = ({ info, data }) => {
+    let url = isMobileTwitter() ? "https://mobile.twitter.com/i/api/1.1/friendships/create.json" : "https://twitter.com/i/api/1.1/friendships/create.json"
+    fetch(url, {
+        "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": "zh-cn"
+        },
+        "referrer": "https://twitter.com/home",
+        "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&user_id=" + data.twitterUserId + "",
+        "method": "POST",
+        "mode": "cors",
+        "credentials": "include"
+    }).then(() => {
+        messageCenter.send({ info, data: { task_done: true, follow_name: data.follow_name } })
+    }).catch(() => {
+        messageCenter.send({ info, data: { task_done: false, follow_name: data.follow_name } })
+    })
+}
+
+const TwitterRetweetAPI = ({ info, data }) => {
+    let url = isMobileTwitter() ? "https://mobile.twitter.com/i/api/graphql/ojPdsZsimiJrUGLR1sjUtA/CreateRetweet" : "https://twitter.com/i/api/graphql/ojPdsZsimiJrUGLR1sjUtA/CreateRetweet"
+    fetch(url, {
+        "headers": {
+            "accept": "*/*",
+            "accept-language": "zh,en;q=0.9,zh-CN;q=0.8",
+            "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
+            "content-type": "application/json",
+            "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\"",
+            "sec-fetch-dest": "empty",
+            "sec-fetch-mode": "cors",
+            "sec-fetch-site": "same-origin",
+            "x-csrf-token": getCookie('ct0'),
+            "x-twitter-active-user": "yes",
+            "x-twitter-auth-type": "OAuth2Session",
+            "x-twitter-client-language": "zh-cn"
+        },
+        "referrer": "https://twitter.com/home",
+        "referrerPolicy": "strict-origin-when-cross-origin",
+        "body": "{\"variables\":{\"tweet_id\":\"" + data.tweetId + "\",\"dark_request\":false},\"queryId\":\"ojPdsZsimiJrUGLR1sjUtA\"}",
+        "method": "POST",
+        "mode": "cors",
+        "credentials": "include"
+    }).then(() => {
+        messageCenter.send({ info, data: { task_done: true } })
+    }).catch(() => {
+        messageCenter.send({ info, data: { task_done: false } })
+    })
+}
+
+export default {
+    TwitterApiCreateTweet,
+    TwitterLikeAPI,
+    TwitterRetweetAPI,
+    TwitterFollowAPI
+}

+ 33 - 0
src/logic/content/help/getData.js

@@ -0,0 +1,33 @@
+import messageCenter from '@/uilts/messageCenter/content';
+import { getCookie, isMobileTwitter } from '@/uilts/help'
+import axios from 'axios';
+
+const TwitterApiGetUserInfoByName = ({info, data}) => {
+  let url = isMobileTwitter() ? `https://mobile.twitter.com/i/api/graphql/gr8Lk09afdgWo7NvzP89iQ/UserByScreenName?variables=%7B%22screen_name%22%3A%22${data.screen_name}%22%2C%22withSafetyModeUserFields%22%3Atrue%2C%22withSuperFollowsUserFields%22%3Atrue%7D` : `https://twitter.com/i/api/graphql/mCbpQvZAw6zu_4PvuAUVVQ/UserByScreenName?variables=%7B%22screen_name%22%3A%22${data.screen_name}%22%2C%22withSafetyModeUserFields%22%3Atrue%2C%22withSuperFollowsUserFields%22%3Atrue%7D`
+  axios.get(url, {
+      headers: {
+          "accept": "*/*",
+          "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
+          "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
+          "content-type": "application/json",
+          "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"101\", \"Google Chrome\";v=\"101\"",
+          "sec-ch-ua-mobile": "?0",
+          "sec-ch-ua-platform": "\"Windows\"",
+          "sec-fetch-dest": "empty",
+          "sec-fetch-mode": "cors",
+          "sec-fetch-site": "same-origin",
+          "x-csrf-token": getCookie('ct0'),
+          "x-twitter-active-user": "yes",
+          "x-twitter-auth-type": "OAuth2Session",
+          "x-twitter-client-language": "en"
+      }
+  }).then(res => {
+    messageCenter.send({ info, data: res.data.data, })
+  }).catch(err => {
+    messageCenter.send({ info, data: {err} })
+  })
+}
+
+export default {
+  TwitterApiGetUserInfoByName
+}

+ 74 - 35
src/logic/content/help/twitter.js

@@ -1,43 +1,82 @@
+import { getStorage, setStorage, getVisitorId, setCookie, getCookie, guid } from '@/uilts/help'
+import { getChromeStorage, setChromeStorage } from '@/uilts/chromeExtension.js'
 
 // 根据提示dom 跳转到推文详情页面
 export const jumpTwitterDetailByAlert = () => {
-    let num = 10
-    let timer = setInterval(() => {
-        if (num <= 0) {
-            clearInterval(timer)
-            return
-        }
-        let alert = document.querySelector('div[role=alert]')
-        if (alert) {
-            let a = alert.querySelector('a')
-            if (a) {
-                clearInterval(timer)
-                a.click()
-            }
-        }
-        num--
-    }, 500)
+  let num = 10
+  let timer = setInterval(() => {
+    if (num <= 0) {
+      clearInterval(timer)
+      return
+    }
+    let alert = document.querySelector('div[role=alert]')
+    if (alert) {
+      let a = alert.querySelector('a')
+      if (a) {
+        clearInterval(timer)
+        a.click()
+      }
+    }
+    num--
+  }, 500)
 }
 
 export const showEditTweet = (callback) => {
-    let bigBtn = document.querySelector('a[data-testid="SideNav_NewTweet_Button"]');
-    if (bigBtn) {
-        bigBtn.click();
-    } else {
-        let smallBtn = document.querySelector('a[href="/compose/tweet"]')
-        smallBtn && smallBtn.click();
+  let bigBtn = document.querySelector('a[data-testid="SideNav_NewTweet_Button"]');
+  if (bigBtn) {
+    bigBtn.click();
+  } else {
+    let smallBtn = document.querySelector('a[href="/compose/tweet"]')
+    smallBtn && smallBtn.click();
+  }
+  let num = 10
+  let timer = setInterval(() => {
+    if (num <= 0) {
+      clearInterval(timer)
+      return
+    }
+    let inputEle = document.querySelector('div[contenteditable="true"]');
+    if (inputEle) {
+      clearInterval(timer)
+      callback && callback()
     }
-    let num = 10
-    let timer = setInterval(() => {
-        if(num <= 0){
-            clearInterval(timer)
-            return
-        }
-        let inputEle = document.querySelector('div[contenteditable="true"]');
-        if(inputEle){
-            clearInterval(timer)
-            callback && callback()
-        }
-        num-- 
-    }, 500);
+    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) });
 }

+ 38 - 38
src/logic/content/nft.js

@@ -1,6 +1,6 @@
 import { getOffsetRect, nextTick } from '@/uilts/help'
 import { listJoinNftGroup } from '@/http/nft';
-import { getChromeStorage } from '@/uilts/chromeExtension.js'
+import { getChromeStorage, chromeExtensionUrl } from '@/uilts/chromeExtension.js'
 import { _setPublishContent, publishNFTTweetPost, bindTwitterArt, bindTwitterArtMethod } from './twitter';
 import { jumpTwitterDetailByAlert } from '@/logic/content/help/twitter.js'
 import Report from "@/log-center/log"
@@ -18,29 +18,29 @@ export const showNFTGroupIcon = () => {
     let where = isTwitter && toolElem && !isAppend && ifShowNftGroup;
     if (where) {
         let oDiv = document.createElement(`div`);
-            oDiv.id = 'de-nft-group-enter';
+        oDiv.id = 'de-nft-group-enter';
         let oImg = document.createElement('img');
-            oImg.src = groupImgNoSelect;
-            oImg.className = 'addGroup';
-            oDiv.innerHTML = `
+        oImg.src = groupImgNoSelect;
+        oImg.className = 'addGroup';
+        oDiv.innerHTML = `
                 ${oImg.outerHTML}
                 <style>
                     #de-nft-group-enter {position:relative; display:flex; padding:0 8px;}
                     #de-nft-group-enter .addGroup {cursor:pointer; height:32px;}
                 </style>
             `;
-            oDiv.addEventListener('click', (e) => {
-                showNFTGroupList(e);
-                e.stopPropagation();
-                // report
-                Report.reportLog({
-                    pageSource: Report.pageSource.mainPage,
-                    businessType: Report.businessType.buttonClick,
-                    objectType: Report.objectType.buttonSecond
-                }, {
-                    type: 2
-                });
-            })
+        oDiv.addEventListener('click', (e) => {
+            showNFTGroupList(e);
+            e.stopPropagation();
+            // report
+            Report.reportLog({
+                pageSource: Report.pageSource.mainPage,
+                businessType: Report.businessType.buttonClick,
+                objectType: Report.objectType.buttonSecond
+            }, {
+                type: 2
+            });
+        })
         toolElem.firstChild.appendChild(oDiv)
         // report
         Report.reportLog({
@@ -61,11 +61,11 @@ export const showNFTGroupList = (e) => {
     let wHeight = document.body.offsetHeight || document.body.clientHeight;
     if ((top + height + 290) > wHeight) oTop = top - 290;
     let iframe = document.createElement('iframe');
-        iframe.src = chrome.runtime.getURL(`/iframe/nft-group.html`)
-        iframe.style.cssText = 'border:medium none; width:315px; height:260px;';
+    iframe.src = chromeExtensionUrl + (`iframe/nft-group.html`)
+    iframe.style.cssText = 'border:medium none; width:315px; height:260px;';
     let html = document.createElement('div');
-        html.id = 'de-nft-group-list';
-        html.innerHTML = `
+    html.id = 'de-nft-group-list';
+    html.innerHTML = `
             <div class="de-nft-group-div">
                 ${iframe.outerHTML}
             </div>
@@ -141,11 +141,11 @@ export const endPostContent = () => {
     return new Promise((resolve) => {
         let inputEle = document.querySelector('div[contenteditable="true"]');
         let range = document.createRange();
-            range.selectNodeContents(inputEle);
-            range.collapse(false);
+        range.selectNodeContents(inputEle);
+        range.collapse(false);
         let sel = window.getSelection();
-            sel.removeAllRanges();
-            sel.addRange(range);
+        sel.removeAllRanges();
+        sel.addRange(range);
         resolve()
     })
 }
@@ -171,7 +171,7 @@ export const setNFTGroupContent = (res) => {
         nextTick(() => {
             _addTweetButtonListen()
         }, 100)
-        
+
     } else {
         endPostContent().then(() => {
             let inputEle = document.querySelector('div[contenteditable="true"]');
@@ -195,38 +195,38 @@ export const elemAddEventListener = (elem, action, fn) => {
 
 
 export const addJoinedGroupList = () => {
-    if(ifShowNftGroup) {
-        let {pathname} = window.location;
+    if (ifShowNftGroup) {
+        let { pathname } = window.location;
 
         let iframe = document.createElement('iframe');
-            iframe.id = 'de-joined-group-list';
-            iframe.src = chrome.runtime.getURL('/iframe/joined-group-list.html');
-            iframe.style.cssText = `border: medium none;height: 120px;border-radius: 16px;margin-bottom: 16px`
+        iframe.id = 'de-joined-group-list';
+        iframe.src = chromeExtensionUrl + ('iframe/joined-group-list.html');
+        iframe.style.cssText = `border: medium none;height: 120px;border-radius: 16px;margin-bottom: 16px`
 
         let iframeContent = document.getElementById('de-joined-group-list');
 
         if (!iframeContent && pathname == '/home') {
             let sidebarColumn = document.querySelector('div[data-testid="sidebarColumn"]');
-            if(sidebarColumn) {
+            if (sidebarColumn) {
                 let searchDom = sidebarColumn.querySelector('form[role="search"]');
-                if(searchDom) {
+                if (searchDom) {
                     let listWrapperDom = searchDom.parentElement.parentElement.parentElement.parentElement;
-                    if(listWrapperDom) {
+                    if (listWrapperDom) {
                         let listParent = listWrapperDom.parentElement;
-                        if(listParent) {
+                        if (listParent) {
                             listParent.insertBefore(iframe, listWrapperDom.nextElementSibling.nextElementSibling);
                         }
                     }
                 }
-            } 
+            }
         }
     }
 };
 
 export const setJoinedGroupIframeStyle = (params) => {
-    let {height = '321px'} = params;
+    let { height = '321px' } = params;
     let iframeContent = document.getElementById('de-joined-group-list');
-    if(iframeContent) {
+    if (iframeContent) {
         iframeContent.style.height = height;
     }
 }

+ 452 - 141
src/logic/content/twitter.js

@@ -1,7 +1,8 @@
-import { getChromeStorage, setChromeStorage } from '@/uilts/chromeExtension.js'
-import { throttle, getQueryString, getCookie, nextTick, getQueryStringByUrl } from '@/uilts/help'
+import { getChromeStorage, setChromeStorage, chromeExtensionUrl } from '@/uilts/chromeExtension.js'
+import { throttle, getQueryString, getCookie, nextTick, getQueryStringByUrl, getStorage, setStorage, getInnerIframeURL, isMobileTwitter } from '@/uilts/help'
 import { discordAuthRedirectUri, iframeHost } from '@/http/configAPI'
 import { reportSrcPublishEvent } from '@/http/publishApi'
+
 import Report from "@/log-center/log"
 import { fetchAddFinishEvent } from '@/logic/background/fetch/facebook';
 import { showNFTGroupIcon, hideNFTGroupList, checkUserJoinGroup, elemAddEventListener, addJoinedGroupList } from '@/logic/content/nft';
@@ -9,7 +10,10 @@ import { jumpTwitterDetailByAlert, showEditTweet } from '@/logic/content/help/tw
 import { clearPostContent, setGroupIconStatus } from '@/logic/content/nft.js'
 import { toolBox } from '@/logic/content/ToolBox'
 import axios from 'axios';
-import messageCenter from '@/uilts/messageCenter';
+import messageCenter from '@/uilts/messageCenter/content';
+import { PlayType } from '@/types';
+import { reSetBindPostContent } from '@/http/help.js';
+import { setDeviceInfo } from '@/logic/content/help/twitter';
 
 let dom = {};
 
@@ -23,6 +27,7 @@ let systemInfo = {
     theme: 'light'
 }
 
+
 let fixProfileTabAutoTimer = null;
 
 
@@ -59,7 +64,7 @@ function getDiscordAuthCode() {
  * @param port
  */
 function renderDom() {
-    if (window.location.href.indexOf('https://twitter.com') > -1) {
+    if (window.location.href.indexOf('https://twitter.com') > -1 || window.location.href.indexOf('https://mobile.twitter.com') > -1 ) {
         _createBtnDom();
         onWindowResize();
         checkHasDeBtn();
@@ -116,6 +121,13 @@ export function showTwitterPublishDialogHandler(publishRes) {
     // _setPublishContent(publishRes.srcContent);
     setDialogPublishContent(publishRes.srcContent);
     _publishTweetEvent(publishRes, bindTwitterArtMethod);
+
+    Report.reportLog({
+        businessType: Report.businessType.pageView,
+        objectType: Report.objectType.setPublishContent,
+        postId: publishRes.postId
+    }, {
+    });
 }
 
 export function twitterPublishHandler(res) {
@@ -225,12 +237,30 @@ function _publishTweetEvent(params, cb) {
             bindTwitterArt.needBind = true;
             bindTwitterArt.postId = params.postId;
             tweetPublishStore.showPublishDialog = false;
+
+            bindContentStr(params);
             // checkIsShowReSend(dialog, params);
             cb && cb()
         });
     }, 800)
 }
 
+function bindContentStr(params) {
+    if (params && params.postBizData) {
+        if (typeof params.postBizData == 'string') {
+            let objBizData = JSON.parse(params.postBizData);
+            let inputEle = document.querySelector('div[contenteditable="true"]');
+            if (objBizData.luckdropType == PlayType.treasure && inputEle) {
+                let textContent = inputEle.innerText;
+                reSetBindPostContent({
+                    postId: params.postId,
+                    postSrcContent: textContent,
+                })
+            }
+        }
+    }
+}
+
 function onClosePublishDialogHandle(dom, params) {
     // 如果是 Tool box
     if (params.postType == 3) {
@@ -398,7 +428,7 @@ function _addIframe() {
     // let span = document.createElement('span');
     // const shadowRoot = span.attachShadow({mode: 'closed'})
     let iframe = document.createElement('iframe');
-    iframe.src = chrome.runtime.getURL('/iframe/publish.html')
+    iframe.src = chromeExtensionUrl + ('iframe/publish.html')
     iframe.id = 'iframe-content'
     iframe.style.cssText = 'position:fixed;top:0px;right:0;display:block; width:100%;height:100%;z-index:10000; border: medium none;display:none;background: rgba(255,255,255,0);';
     // shadowRoot.appendChild(iframe);
@@ -421,9 +451,9 @@ function addPublishTipsIframe(params = {}) {
             let iframe = document.createElement('iframe');
             iframe.id = 'de-publish-tips'
             if (params.type == 'nft') {
-                iframe.src = chrome.runtime.getURL('/iframe/publish-tips.html?type="nft"');
+                iframe.src = chromeExtensionUrl + ('iframe/publish-tips.html?type="nft"');
             } else {
-                iframe.src = chrome.runtime.getURL('/iframe/publish-tips.html');
+                iframe.src = chromeExtensionUrl + ('iframe/publish-tips.html');
             }
 
             iframe.style.cssText = `border: medium none; width:270px;height:500px;position: fixed; right: ${right}px; top: 5%;z-index: -1`
@@ -440,7 +470,7 @@ export function noticeBindTweet(params) {
     hidePopupPage();
     let iframe = document.createElement('iframe');
     iframe.id = 'de-notice-bind-tweet';
-    iframe.src = chrome.runtime.getURL('/iframe/bind-tweet.html') + `?params=${JSON.stringify(params)}`;
+    iframe.src = chromeExtensionUrl + ('iframe/bind-tweet.html') + `?params=${JSON.stringify(params)}`;
     iframe.style.cssText = `border: medium none; width:400px;min-height:313px;position: fixed; right: 16px; top: 16px;border-radius: 20px;`
     let iframeContent = document.getElementById('de-notice-bind-tweet');
     if (!iframeContent) {
@@ -529,7 +559,7 @@ const setDialogPublishContent = throttle(function (content) {
         if (inputEle) {
             inputEle.dispatchEvent(event);
         }
-    }, 300)
+    }, 800)
 }, 600);
 
 /**
@@ -649,11 +679,22 @@ function createTweetToolbarToolBox() {
 function addSliderNavDeBtn() {
     try {
         let isSmall = false;
+        let isFloating = false;
+        let floatingTweetBtn;
         let tweetBtn = document.querySelector('a[data-testid="SideNav_NewTweet_Button"]');
-        if (tweetBtn && tweetBtn.querySelector('svg')) {
-            isSmall = true;
+        if (tweetBtn) {
+            if (tweetBtn.querySelector('svg')) {
+                isSmall = true;
+            }
+        } else {
+            // 手机打开twitter 发推按钮
+            floatingTweetBtn = document.querySelector('div[data-testid="FloatingActionButtonBase"]');
+            if (floatingTweetBtn) {
+                isFloating = true;
+            }
         }
-        if (!isSmall) {
+
+        if (!isSmall && !isFloating) {
             let bigDom = document.querySelector('a[href="/compose/tweet"]').parentNode.parentNode;
             let deBtn = document.getElementById('de-btn');
             if (bigDom && !deBtn) {
@@ -665,15 +706,19 @@ function addSliderNavDeBtn() {
                 });
             }
         } else {
-            let smallDom = document.querySelector('a[href="/compose/tweet"]').parentNode.parentNode;
             let deBtn3 = document.getElementById('de-btn3');
-            if (smallDom && !deBtn3) {
-                dom && dom.deBtn3 && smallDom.appendChild(dom.deBtn3);
-                Report.reportLog({
-                    pageSource: Report.pageSource.mainPage,
-                    businessType: Report.businessType.buttonView,
-                    objectType: Report.objectType.buttonMain
-                });
+            if (isFloating && !deBtn3) {
+                floatingTweetBtn.appendChild(dom.deBtn3);
+            } else {
+                let smallDom = document.querySelector('a[href="/compose/tweet"]').parentNode.parentNode;
+                if (smallDom && !deBtn3) {
+                    dom && dom.deBtn3 && smallDom.appendChild(dom.deBtn3);
+                    Report.reportLog({
+                        pageSource: Report.pageSource.mainPage,
+                        businessType: Report.businessType.buttonView,
+                        objectType: Report.objectType.buttonMain
+                    });
+                }
             }
         }
     } catch (e) {
@@ -766,14 +811,14 @@ export function bindTwitterArtMethod() {
 
 import parseCard from './ParseCard'
 
-// 检测dom改变 
-// 获取短链接 
-// 查看本地是否有postid 
-// 如果有 修改dom 返回 
-// 如果没有 网络请求 
-// 获取postid 
-// 获取twitterid 
-// 检测当前所有dom 如果没有 
+// 检测dom改变
+// 获取短链接
+// 查看本地是否有postid
+// 如果有 修改dom 返回
+// 如果没有 网络请求
+// 获取postid
+// 获取twitterid
+// 检测当前所有dom 如果没有
 
 
 
@@ -808,73 +853,80 @@ function onChangePageMain(targetNode) {
 // 2.监听卡片是否可见
 // 3.如果可见了 去找
 
-function setIframeRedPacket(type = 'twitter') {
+function setIframeCard(type = 'twitter') {
     // 获取所有卡片参数
     let card_json_data
-    switch (type) {
-        case 'facebook':
-            card_json_data = parseCard.parseFacebookCardParmas()
-            for (let i in card_json_data) {
-                parseCard.replaceFacebookPacket(card_json_data[i])
-            }
-            break;
-        default:
-            card_json_data = parseCard.parseAllDeNetCardParmas()
-            // 过滤出可以请求的短链接
-            parseCard.getCardParmas(card_json_data).then((res) => {
-                for (let i in res.has_post_Id_card_data) {
-                    let item = res.has_post_Id_card_data[i];
-                    if (item && item.post_Id && item.post_Id.indexOf('nft/') >= 0) {
-                        parseCard.replaceNftDomRedPacket(item)
-                    } else if (item && item.post_Id && item.post_Id.indexOf('nft_group/') >= 0) {
-                        parseCard.replaceNftGroupDomRedPacket(item)
-                    } else if (item && item.post_Id && item.post_Id.indexOf('luckdraw/') >= 0) {
-                        item.post_Id = item.post_Id.split('luckdraw/')[1] || ''
-                        item.page_type = '抽奖'
-                        parseCard.replaceDOMRedPacket(item)
-                    } else if (item && item.post_Id && item.post_Id.indexOf('toolbox/') >= 0) {
-                        item.page_type = 'toolbox'
-                        item.post_Id = item.post_Id.split('toolbox/')[1] || ''
-                        if (item.post_Id) {
-                            parseCard.replaceIframeToolBox(item)
-                        }
-                    } else if (item && item.post_Id && !item.post_Id.includes('/')) {
-                        item.page_type = '红包'
-                        parseCard.replaceDOMRedPacket(item)
-                        // 夺宝链接
-                    } else if (item && item.post_Id && item.post_Id.includes('treasure/')) {
-                        // https://testh5.denetme.net/treasure/{postid}
-                        // https://testh5.denetme.net/treasure/invite/{inviteCode}
-                        // 邀请链接
-                        if (item.post_Id.includes('invite/')) {
-                            item.invite_code = item.post_Id.split('invite/')[1] || ''
-                            item.page_type = '邀请链接'
-                            if (item.invite_code) {
-                                item.post_Id = ''
-                                parseCard.replaceDOMTreasureCard(item)
-                            }
-                        } else {
-                            // 原始链接
-                            item.page_type = '原始链接'
-                            item.post_Id = item.post_Id.split('treasure/')[1] || ''
-                            if (item.post_Id) {
-                                parseCard.replaceDOMTreasureCard(item)
+    if (type == 'facebook') {
+        card_json_data = parseCard.parseFacebookCardParmas()
+        for (let i in card_json_data) {
+            parseCard.replaceFacebookPacket(card_json_data[i])
+        }
+    }
+    else if (type == 'twitter') {
+        card_json_data = parseCard.parseAllDeNetCardParmas()
+        // 过滤出可以请求的短链接
+        parseCard.getCardParmas(card_json_data).then((res) => {
+            for (let i in res.has_post_Id_card_data) {
+                let item = res.has_post_Id_card_data[i];
+                if (item && item.post_Id && item.post_Id.indexOf('nft/') >= 0) {
+                    parseCard.replaceNftDomRedPacket(item)
+                } else if (item && item.post_Id && item.post_Id.indexOf('nft_group/') >= 0) {
+                    parseCard.replaceNftGroupDomRedPacket(item)
+                } else if (item && item.post_Id && item.post_Id.indexOf('luckdraw/') >= 0) {
+                    item.post_Id = item.post_Id.split('luckdraw/')[1] || ''
+                    item.page_type = '抽奖'
+                    parseCard.replaceDOMRedPacket(item)
+                } else if (item && item.post_Id && item.post_Id.indexOf('toolbox/') >= 0) {
+                    item.page_type = 'toolbox'
+                    item.post_Id = item.post_Id.split('toolbox/')[1] || ''
+                    if (item.post_Id) {
+                        parseCard.replaceIframeToolBox(item)
+                    }
+                } else if (item && item.post_Id && !item.post_Id.includes('/')) {
+                    item.page_type = '红包'
+                    parseCard.replaceDOMRedPacket(item)
+                    // 夺宝链接
+                } else if (item && item.post_Id && item.post_Id.includes('treasure/')) {
+                    // https://testh5.denetme.net/treasure/{postid}
+                    // https://testh5.denetme.net/treasure/invite/{inviteCode}
+                    // 邀请链接
+                    if (item.post_Id.includes('invite/')) {
+                        let arr = item.post_Id.split('/')
+                        let index
+                        for (let i in arr) {
+                            index = Number(i) + 1
+                            if (arr[i] == 'invite' && arr.length >= index) {
+                                item.invite_code = arr[index];
+                                if (arr.length > index + 1) {
+                                    item.invite_channel = arr[index + 1];
+                                } else {
+                                    item.invite_channel = '';
+                                }
+                                break
                             }
                         }
-                    }
-                }
-                if (res.need_net_short_url.length > 0) {
-                    // 请求短链接
-                    chrome.runtime.sendMessage({ actionType: "CONTENT_TWITTER_SHORT_LINK", data: "", arr_url: res.need_net_short_url }, (res) => {
-                        if (!res) {
-                            Report.reportLog({
-                                objectType: Report.objectType.parse_card_error
-                            });
+
+                        item.page_type = '邀请链接'
+                        if (item.invite_code) {
+                            item.post_Id = ''
+                            parseCard.replaceDOMTreasureCard(item)
                         }
-                    })
+                    } else {
+                        // 原始链接
+                        item.page_type = '原始链接'
+                        item.post_Id = item.post_Id.split('treasure/')[1] || ''
+                        if (item.post_Id) {
+                            parseCard.replaceDOMTreasureCard(item)
+                        }
+                    }
                 }
-            })
-            break;
+            }
+            if (res.need_net_short_urls.length > 0) {
+                parseCard.netShortUrl(res.need_net_short_urls, () => {
+                    changeQueueNum(5)
+                })
+            }
+        })
     }
 }
 
@@ -901,7 +953,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(() => {
@@ -940,7 +992,7 @@ function initParseCard() {
                     return
                 }
                 initGroupTip()
-                setIframeRedPacket()
+                setIframeCard()
                 checkHasSliderDeBtn();
                 changeQueueNum(-1)
                 showNFTCard()
@@ -954,7 +1006,7 @@ function initParseCard() {
                 if (queue_num <= 0) {
                     return
                 }
-                setIframeRedPacket('facebook')
+                setIframeCard('facebook')
                 changeQueueNum(-1)
             }, 1000)
         }
@@ -999,6 +1051,7 @@ export function init() {
         addJoinedGroupList();
         getSysTheme();
         addGroupTab();
+        setDeviceInfo();
         // 预加载全屏 toobbox
         toolBox.initFull()
     }
@@ -1031,6 +1084,49 @@ export function init() {
     });
 }
 
+export const getTweetUserFollowStatus = (params) => {
+    let { tweetId, userList, iframeGUId, type } = JSON.parse(params.data);
+    let promiseList = [];
+    for (let i = 0; i < userList.length; i++) {
+        promiseList[i] = TwitterApiUserByScreenNameReq({ screen_name: userList[i]['name'] });
+    }
+
+    Promise.allSettled(promiseList).then((res) => {
+        let list = [];
+        if (res && res.length) {
+            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)
+                }
+            }
+        }
+        messageCenter.send({
+            info: {
+                iframeId: params.iframeId,
+                actionType: 'CONTENT_GET_TWEET_USER_FOLLOW_STATUS_RES'
+            },
+            data: {
+                list, tweetId, type, iframeId: params.iframeId, iframeGUId
+            }
+        })
+
+        // chrome.runtime.sendMessage({ actionType: 'CONTENT_GET_TWEET_USER_FOLLOW_STATUS_RES', data: list, tweetId, type: params.type, iframeId: params.iframeId }, () => { })
+    }).catch(err => {
+        messageCenter.send({
+            info: {
+                iframeId: params.iframeId,
+                actionType: 'CONTENT_GET_TWEET_USER_FOLLOW_STATUS_RES'
+            },
+            data: {
+                list: [], tweetId, type, iframeId: params.iframeId, iframeGUId
+            }
+        })
+        // chrome.runtime.sendMessage({ actionType: 'CONTENT_GET_TWEET_USER_FOLLOW_STATUS_RES', data: [], tweetId, type: params.type, iframeId: params.iframeId }, () => { })
+    })
+}
+
 function onPageVisbile() {
     document.addEventListener('visibilitychange', function () {
         let isHidden = document.hidden;
@@ -1073,7 +1169,7 @@ export function facebookReplyTweet(params) {
 }
 
 export function replyHandle(params) {
-    let iframe = window.parent.document.getElementById(params.postId);
+    let iframe = window.parent.document.getElementById(params.iframeId);
     let replyBtn = iframe.parentNode.parentNode.querySelector('div[data-testid="reply"]') ||
         iframe.parentNode.parentNode.parentNode.querySelector('div[data-testid="reply"]');
     if (replyBtn) {
@@ -1096,8 +1192,8 @@ export function replyHandle(params) {
 
                 let eleList = tweetReply.parentNode.parentNode.parentNode.parentNode.parentNode.querySelectorAll('span[data-text="true"]');
                 reportReplyResult(eleList, params, () => {
-                    // iframe.contentWindow.postMessage({ actionType: 'CONTENT_RED_PACKET_REPLY_RASK_FINSH', data: {} }, '*');
-                    chrome.runtime.sendMessage({ actionType: "CONTENT_RED_PACKET_REPLY_RASK_FINSH", data: { postId: params.postId } }, () => { })
+                    iframe.contentWindow.postMessage({ actionType: 'CONTENT_RED_PACKET_REPLY_RASK_FINSH', data: { postId: params.postId } }, '*');
+                    // chrome.runtime.sendMessage({ actionType: "CONTENT_RED_PACKET_REPLY_RASK_FINSH", data: { postId: params.postId } }, () => { })
                 });
             })
         }
@@ -1105,7 +1201,7 @@ export function replyHandle(params) {
 }
 
 export function onTweetReplyClick(params) {
-    let iframe = window.parent.document.getElementById(params.postId);
+    let iframe = window.parent.document.getElementById(params.iframeId);
     let replyBtn = iframe.parentNode.parentNode.querySelector('div[data-testid="reply"]') ||
         iframe.parentNode.parentNode.parentNode.querySelector('div[data-testid="reply"]');
     if (replyBtn) {
@@ -1149,13 +1245,35 @@ function onReplyDialogOpen(params, iframe) {
                     businessType: Report.businessType.buttonClick,
                     objectType: Report.objectType.replyClickByTwitterList
                 });
+                let editDom = dialog.querySelector('div[contenteditable="true"]');
+                let eleList = []
+                if(editDom) {
+                  eleList = editDom.querySelectorAll('span[data-text="true"]');
+                } else {
+                  // mobile.twitter.com
+                  editDom = dialog.querySelector('textarea');
+                  if(editDom) {
+                    let value = editDom.value;
+                    if(value) {
+                      let strArr = value.split(' ');
+                      if(strArr && strArr.length) {
+                        for(let i = 0; i < strArr.length; i++) {
+                          eleList.push({
+                            innerText: strArr[i]
+                          })
+                        }
+                      }
+                    }
+                  }
+                }
 
-                let eleList = dialog.querySelector('div[contenteditable="true"]').querySelectorAll('span[data-text="true"]');
-                reportReplyResult(eleList, params, () => {
+                if(eleList.length) {
+                  reportReplyResult(eleList, params, () => {
                     // 上報完成
-                    // iframe.contentWindow.postMessage({ actionType: 'CONTENT_RED_PACKET_REPLY_RASK_FINSH', data: {} }, '*');
-                    chrome.runtime.sendMessage({ actionType: "CONTENT_RED_PACKET_REPLY_RASK_FINSH", data: { postId: params.postId } }, () => { })
-                })
+                    iframe.contentWindow.postMessage({ actionType: 'CONTENT_RED_PACKET_REPLY_RASK_FINSH', data: { postId: params.postId } }, '*');
+                    // chrome.runtime.sendMessage({ actionType: "CONTENT_RED_PACKET_REPLY_RASK_FINSH", data: { postId: params.postId } }, () => { })
+                  })
+                }
             });
         }
     }, 1000);
@@ -1288,10 +1406,12 @@ export function checkTwitterTaskState() {
         })
         // 点击取消
         clickByDataTestId(e, 'confirmationSheetCancel', () => {
+            console.log('DO_TASK1')
             chrome.runtime.sendMessage({ actionType: "DO_TASK", tweet_Id, task_type, task_data, task_done: false }, () => { })
         })
         // 点击 蒙层
         if (e.target && e.target.nextSibling && e.target.nextSibling.dataset && e.target.nextSibling.dataset.testid == 'confirmationSheetDialog') {
+            console.log('DO_TASK2')
             chrome.runtime.sendMessage({ actionType: "DO_TASK", tweet_Id, task_type, task_data, task_done: false }, () => { })
         }
     }, true)
@@ -1346,7 +1466,7 @@ export function getTweetAuthorByDom(params) {
         }
     }
 }
-export function doTaskTwitterAPI({ task_data, task_type, tasks }) {
+export function doTaskTwitterAPI({ task_data, task_type, tasks, iframeId }) {
     switch (task_type) {
         case 'like':
             TwitterLikeAPI(task_data.tweet_Id)
@@ -1369,7 +1489,7 @@ export function doTaskTwitterAPI({ task_data, task_type, tasks }) {
                     case '1':
                         item.relatedUsers.forEach((item) => {
                             if (item.name && item.twitterUserId) {
-                                TwitterFollowAPI(item, task_data.tweet_Id)
+                                TwitterFollowAPI(item, task_data.tweet_Id);
                             }
                         })
                         break
@@ -1381,7 +1501,7 @@ export function doTaskTwitterAPI({ task_data, task_type, tasks }) {
                     // 推文发推
                     case '10':
                         // 发推
-                        TwitterApiCreateTweet({ text: task_data.tweet_text, tweet_Id: task_data.tweet_Id })
+                        TwitterApiCreateTweet({ text: task_data.tweet_text, tweet_Id: task_data.tweet_Id, iframeId })
                         break
                 }
 
@@ -1390,15 +1510,88 @@ export function doTaskTwitterAPI({ task_data, task_type, tasks }) {
     }
 }
 
+export function doTaskIframeTwitterAPI(params) {
+    let { tweet_Id, tweet_text, task_type, tasks, iframeGUId } = JSON.parse(params.data);
+    if (task_type == 'tasks') {
+        tasks.forEach((item) => {
+            switch (String(item.type)) {
+                // 关注指定用户
+                case '1':
+                    item.relatedUsers.forEach((item) => {
+                        if (item.name && item.twitterUserId) {
+                            TwitterFollowAPI(item, tweet_Id);
+                        }
+                    })
+                    break
+                // 点赞
+                case '2':
+                    TwitterLikeAPI(tweet_Id)
+                    break
+                // 推文发推
+                case '10':
+                    // 发推
+                    TwitterApiCreateTweet({ text: tweet_text, tweet_Id, iframeId: params.iframeId, iframeGUId, iframeMsg: true })
+                    break
+            }
+        })
+    } else if (task_type == 'like') {
+        TwitterLikeAPI(tweet_Id)
+    }
+}
+
 export function showJoinDialog(data) {
     let iframe = document.querySelector('#nftProjectId')
     iframe.style.display = 'block'
     iframe.contentWindow.postMessage({ actionType: 'SHOW_JOIN_DATA', data }, '*');
-    iframe.src = chrome.runtime.getURL(`/iframe/buy-nft.html#/group?params=${JSON.stringify(data)}&time=${new Date().getTime()}`)
+    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;
+    }
+    let url = isMobileTwitter() ? 'https://mobile.twitter.com/i/api/1.1/friendships/update.json' : "https://twitter.com/i/api/1.1/friendships/update.json";
+    return fetch(url, {
+        "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", {
+    let url = isMobileTwitter() ? "https://mobile.twitter.com/i/api/1.1/friendships/create.json" : "https://twitter.com/i/api/1.1/friendships/create.json"
+    fetch(url, {
         "headers": {
             "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
             "content-type": "application/x-www-form-urlencoded",
@@ -1420,15 +1613,19 @@ 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')
         chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'follow', task_data, task_done: false }, () => { })
     })
 }
 
 
 const TwitterRetweetAPI = (tweet_Id) => {
-    fetch("https://twitter.com/i/api/graphql/ojPdsZsimiJrUGLR1sjUtA/CreateRetweet", {
+    let url = isMobileTwitter() ? "https://mobile.twitter.com/i/api/graphql/ojPdsZsimiJrUGLR1sjUtA/CreateRetweet" : "https://twitter.com/i/api/graphql/ojPdsZsimiJrUGLR1sjUtA/CreateRetweet"
+    fetch(url, {
         "headers": {
             "accept": "*/*",
             "accept-language": "zh,en;q=0.9,zh-CN;q=0.8",
@@ -1454,12 +1651,14 @@ const TwitterRetweetAPI = (tweet_Id) => {
     }).then(() => {
         chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'retweet', task_data: '', task_done: true }, () => { })
     }).catch(() => {
+        console.log('DO0_TASK4')
         chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'retweet', task_data: '', task_done: false }, () => { })
     })
 }
 
 const TwitterLikeAPI = (tweet_Id) => {
-    fetch("https://twitter.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet", {
+    let url = isMobileTwitter() ? "https://mobile.twitter.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet" : "https://twitter.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet"
+    fetch(url, {
         "headers": {
             "accept": "*/*",
             "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
@@ -1485,12 +1684,13 @@ const TwitterLikeAPI = (tweet_Id) => {
     }).then(() => {
         chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'like', task_data: '', task_done: true }, () => { })
     }).catch(() => {
+        console.log('DO_TASK5')
         chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'like', task_data: '', task_done: false }, () => { })
     })
 }
 
-
-const TwitterApiCreateTweet = ({ text, tweet_Id }) => {
+const TwitterApiCreateTweet = ({ text, tweet_Id, iframeId,
+    iframeGUId, iframeMsg }) => {
     let data = {
         queryId: "hC1nuE-2d1NX5LYBuuAvtQ",
         features: {
@@ -1500,7 +1700,9 @@ const TwitterApiCreateTweet = ({ text, tweet_Id }) => {
             "vibe_api_enabled": true,
             "responsive_web_edit_tweet_api_enabled": false,
             "standardized_nudges_misinfo": true,
-            "responsive_web_enhance_cards_enabled": false
+            "responsive_web_enhance_cards_enabled": false,
+            "tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": false,
+            "responsive_web_text_conversations_enabled": false
         },
         variables: {
             "tweet_text": text,
@@ -1517,7 +1719,8 @@ const TwitterApiCreateTweet = ({ text, tweet_Id }) => {
             "dark_request": false
         }
     };
-    axios.post(`https://twitter.com/i/api/graphql/hC1nuE-2d1NX5LYBuuAvtQ/CreateTweet`,
+    let url = isMobileTwitter() ? "https://mobile.twitter.com/i/api/graphql/K9It0MijE2UOlX-8wLyPYA/CreateTweet" : "https://twitter.com/i/api/graphql/hC1nuE-2d1NX5LYBuuAvtQ/CreateTweet"
+    axios.post(url,
         data, {
         headers: {
             "accept": "*/*",
@@ -1536,16 +1739,43 @@ const TwitterApiCreateTweet = ({ text, tweet_Id }) => {
             "x-twitter-client-language": "en"
         },
     }).then(function (response) {
-        chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'createTweet', task_data: '', task_done: true, response })
+        console.log(response)
+        let data = response.data;
+        if (iframeMsg) {
+            messageCenter.send({
+                info: {
+                    iframeId,
+                    actionType: 'CONTENT_CREATE_TWEET_FINISH'
+                },
+                data: {
+                    tweet_Id, iframeId, iframeGUId, response: data, done: true
+                }
+            })
+        } else {
+            chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'createTweet1', task_data: '', task_done: '是', response, iframeId })
+        }
     }).catch(function (err) {
-        chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'createTweet', task_data: '', task_done: false })
+        console.log('err --1', err)
+        if (iframeMsg) {
+            messageCenter.send({
+                info: {
+                    iframeId,
+                    actionType: 'CONTENT_CREATE_TWEET_FINISH'
+                },
+                data: {
+                    tweet_Id, iframeId, iframeGUId, done: false
+                }
+            })
+        } else {
+            chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'createTweet1', task_data: '', task_done: '否', iframeId })
+        }
     });
 }
 
-
-export const TwitterApiUserByScreenName = (params) => {
-    let { screen_name, tweetId = '', objectType = '' } = params;
-    axios.get(`https://twitter.com/i/api/graphql/mCbpQvZAw6zu_4PvuAUVVQ/UserByScreenName?variables=%7B%22screen_name%22%3A%22${screen_name}%22%2C%22withSafetyModeUserFields%22%3Atrue%2C%22withSuperFollowsUserFields%22%3Atrue%7D`, {
+const TwitterApiUserByScreenNameReq = (params) => {
+    let { screen_name } = params || {};
+    let url = isMobileTwitter() ? `https://mobile.twitter.com/i/api/graphql/gr8Lk09afdgWo7NvzP89iQ/UserByScreenName?variables=%7B%22screen_name%22%3A%22${screen_name}%22%2C%22withSafetyModeUserFields%22%3Atrue%2C%22withSuperFollowsUserFields%22%3Atrue%7D` : `https://twitter.com/i/api/graphql/mCbpQvZAw6zu_4PvuAUVVQ/UserByScreenName?variables=%7B%22screen_name%22%3A%22${screen_name}%22%2C%22withSafetyModeUserFields%22%3Atrue%2C%22withSuperFollowsUserFields%22%3Atrue%7D`
+    return axios.get(url, {
         headers: {
             "accept": "*/*",
             "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
@@ -1562,10 +1792,43 @@ export const TwitterApiUserByScreenName = (params) => {
             "x-twitter-auth-type": "OAuth2Session",
             "x-twitter-client-language": "en"
         },
-    }).then(function (response) {
-        chrome.runtime.sendMessage({ actionType: "CONTENT_API_GET_TWEET_USER_INFO_RES", data: response.data.data || {}, tweetId, objectType }, () => { })
+    })
+}
+
+
+export const TwitterApiUserByScreenName = (params, cb) => {
+    let { screen_name, tweetId = '', objectType = '', iframeId = '', iframeMsg = false, iframeGUId } = params;
+
+    TwitterApiUserByScreenNameReq({ screen_name }).then(function (response) {
+        if (iframeMsg) {
+            messageCenter.send({
+                info: {
+                    iframeId,
+                    actionType: 'CONTENT_API_GET_TWEET_USER_INFO_END'
+                },
+                data: {
+                    iframeGUId, response: response.data.data || {}, objectType
+                }
+            })
+        } else {
+            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 }, () => { })
+        if (iframeMsg) {
+            messageCenter.send({
+                info: {
+                    iframeId,
+                    actionType: 'CONTENT_API_GET_TWEET_USER_INFO_END'
+                },
+                data: {
+                    iframeGUId, response: {}, objectType
+
+                }
+            })
+        } else {
+            chrome.runtime.sendMessage({ actionType: "CONTENT_API_GET_TWEET_USER_INFO_RES", data: {}, tweetId, objectType, iframeId }, () => { })
+        }
     });
 }
 
@@ -1722,7 +1985,7 @@ const initGroupTip = () => {
         if (iframe_banner) {
             if (twitterAccount != getQueryStringByUrl(iframe_banner.src, 'twitterAccount')) {
                 iframe_banner.style.display = 'none'
-                // iframe_banner.src = chrome.runtime.getURL(`/iframe/group-card.html?twitterAccount=${twitterAccount}`)
+                // iframe_banner.src = chromeExtensionUrl + (`iframe/group-card.html?twitterAccount=${twitterAccount}`)
                 iframe_banner.contentWindow.postMessage({ actionType: 'SHOW_BANNER', twitterAccount }, '*');
             }
             return
@@ -1732,7 +1995,7 @@ const initGroupTip = () => {
             let iframe = document.createElement('iframe')
             iframe.id = 'denet_group_banner'
             iframe.style.cssText = 'border: medium none; display:none; width:100%; height:100px;'
-            iframe.src = chrome.runtime.getURL(`/iframe/group-card.html?twitterAccount=${twitterAccount}`)
+            iframe.src = chromeExtensionUrl + (`iframe/group-card.html?twitterAccount=${twitterAccount}`)
             // iframe.contentWindow.postMessage({ actionType: 'SHOW_BANNER', twitterAccount }, '*');
             if (dom && !dom.parentNode.children[0].querySelector('iframe')) {
                 // dom.parentNode.insertBefore(iframe, dom)
@@ -1763,7 +2026,7 @@ export const showBuyNFT = ({ nft_project_Id, post_Id = '' }) => {
     }
     let iframe = document.querySelector('#nftProjectId')
     iframe.style.display = 'block'
-    iframe.src = chrome.runtime.getURL(`/iframe/buy-nft.html#/?nftProjectId=${nft_project_Id}&postId=${post_Id}`)
+    iframe.src = chromeExtensionUrl + (`iframe/buy-nft.html#/?nftProjectId=${nft_project_Id}&postId=${post_Id}`)
 }
 
 const initBuyNFT = () => {
@@ -1782,7 +2045,7 @@ export const showNFTCard = () => {
     let where = isTwitter && userElem && tabIndex;
     if (where) {
         let iframe = document.createElement('iframe');
-        iframe.src = chrome.runtime.getURL(`/iframe/nft-card.html`)
+        iframe.src = chromeExtensionUrl + (`iframe/nft-card.html`)
         iframe.style.cssText = 'border:medium none; width:100%; height:290px;';
         let nftElement = document.createElement('div');
         nftElement.id = 'de-nft-node';
@@ -1823,7 +2086,7 @@ export const appendPopupPage = (params = {}) => {
 
     let iframe = document.createElement('iframe');
     iframe.id = 'de-popup-page';
-    iframe.src = chrome.runtime.getURL('/iframe/popup-page.html') + `#${path}`;
+    iframe.src = chromeExtensionUrl + ('iframe/popup-page.html') + `#${path}`;
     iframe.style.cssText = `border: medium none; width: 375px !important;
         height: 650px;position: fixed; right: 16px; top: 16px;background: #FFFFFF;border: 0.5px solid #919191;box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.2);box-sizing: border-box;z-index: 90000;
         animation-duration: 0.5s !important;
@@ -1870,7 +2133,7 @@ export const showPopupPage = (params = {}) => {
     }
     if (iframe) {
         if (path) {
-            iframe.src = chrome.runtime.getURL('/iframe/popup-page.html') + `#${path}`;
+            iframe.src = chromeExtensionUrl + ('iframe/popup-page.html') + `#${path}`;
         }
         iframe.style.transform = 'translateX(-' + 395 + 'px)';
 
@@ -1985,14 +2248,14 @@ export const setPopupConfByPopupPage = () => {
 }
 
 
-/** 
- * 
- * Group Tab List Start 
+/**
+ *
+ * Group Tab List Start
  */
 
 /**
- * 
- * 创建 Group Tab 
+ *
+ * 创建 Group Tab
  */
 const createGroupTabNode = () => {
     let groupIcon = document.createElement('img');
@@ -2221,7 +2484,12 @@ const addPageScrollEvent = () => {
         contentHeight: contentDom.offsetHeight
     }
 
-    messageCenter.send('de-tab-group-content', 'CONTENT_GROUP_LIST_SCROLL', data)
+    messageCenter.send({
+        info: {
+            iframeId: 'de-tab-group-content', actionType: 'CONTENT_GROUP_LIST_SCROLL'
+        },
+        data
+    })
 
     // chrome.runtime.sendMessage({
     //     actionType: "CONTENT_GROUP_LIST_SCROLL",
@@ -2307,7 +2575,11 @@ const setGroupTabSelfStyle = (params = {}) => {
  * 切换到 Group tab时 刷新列表
  */
 export const refreshTabGroup = () => {
-    messageCenter.send('de-tab-group-content', 'CONTENT_REFRESH_TAB_GROUP_LIST', {})
+    messageCenter.send({
+        info: {
+            iframeId: 'de-tab-group-content', actionType: 'CONTENT_REFRESH_TAB_GROUP_LIST'
+        }
+    })
     //     chrome.runtime.sendMessage({
     //         actionType: "CONTENT_REFRESH_TAB_GROUP_LIST",
     //         data: {}
@@ -2388,7 +2660,7 @@ const addTabGroupContent = (cb) => {
     }
     let iframe = document.createElement('iframe');
     iframe.id = 'de-tab-group-content';
-    iframe.src = `${iframeHost}/tab-group` + `?params=${JSON.stringify(params)}`;
+    iframe.src = getInnerIframeURL(`${iframeHost}/tab-group` + `?params=${JSON.stringify(params)}&iframeId=${iframe.id}`);
     iframe.style.cssText = `border: medium none; height: 500px;display: none`
 
     let iframeContent = getGroupTabContentNode();
@@ -2490,7 +2762,9 @@ export const getTweetProfileNavTop = (params) => {
     let top = document.querySelector('div[role="tablist"]').closest('nav').getBoundingClientRect().top;
 
     messageCenter.send({
-        actionType: "CONTENT_SEND_GROUP_NAV_TOP",
+        info: {
+            actionType: "CONTENT_SEND_GROUP_NAV_TOP"
+        },
         data: {
             top,
             scrollTop: params.scrollTop
@@ -2534,6 +2808,18 @@ export const setGroupInfo = (params = {}) => {
     }
 }
 
+export const getExtensionStorgeDataForIframe = (data) => {
+    getChromeStorage(data.key).then((res) => {
+        messageCenter.send({
+            info: {
+                iframeId: data.iframeId,
+                actionType: `IFRAME_GET_EXTENSION_STORGE_DATA-${data.messageId}`
+            },
+            data: res
+        })
+    });
+}
+
 const getSysTheme = () => {
     const themeMedia = window.matchMedia("(prefers-color-scheme: light)");
     if (themeMedia.matches) {
@@ -2557,7 +2843,9 @@ const sysThemeChange = () => {
     setTimeout(() => {
         let bgColor = document.querySelector('body').style.backgroundColor;
         messageCenter.send({
-            actionType: "CONTENT_SYS_THEME_CHANGE",
+            info: {
+                actionType: "CONTENT_SYS_THEME_CHANGE"
+            },
             data: {
                 theme: systemInfo.theme,
                 twitterTheme: bgColor == 'rgb(0, 0, 0)' ? 'dark' : 'light'
@@ -2572,10 +2860,10 @@ const sysThemeChange = () => {
     }, 800)
 }
 
-/** 
- * 
- * Group Tab List End 
- * 
+/**
+ *
+ * Group Tab List End
+ *
  */
 
 
@@ -2594,3 +2882,26 @@ export const showPublishDialog = () => {
         smallBtn.click();
     }
 }
+
+// 获取推文发送回去
+export const sendContentByTwitterID = (params) => {
+    let { tweet_Id, iframeGUId } = JSON.parse(params.data);
+    // 获取内容
+    let txt = parseCard.getContentByTwitterId(tweet_Id);
+    messageCenter.send({
+      info: {
+          iframeId: params.iframeId,
+          actionType: 'CONTENT_GET_TWEET_TXT'
+      },
+      data: {
+          tweet_Id, txt, iframeGUId
+      }
+    })
+    // 发送
+    // chrome.runtime.sendMessage({
+    //     actionType: "CONTENT_GET_TWEET_TXT", data: {
+    //         tweet_Id,
+    //         txt
+    //     }
+    // })
+}

+ 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",
-    "denet_app_version_code": "20",
+    "version": "1.1.7.4",
+    "denet_app_version_code": "24",
     "background": {
         "service_worker": "/js/background.js"
     },

+ 2 - 1
src/uilts/chromeExtension.js

@@ -68,6 +68,7 @@ export function getChromeStorage(key = '', callback) {
 //     } catch {
 //     }
 // }
+export let chromeExtensionUrl = chrome.runtime.getURL('/')
 
 export function setChromeCookie({
     name,
@@ -118,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);

+ 64 - 1
src/uilts/help.js

@@ -1,3 +1,7 @@
+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");
   let r = window.location.search.substr(1).match(reg);
@@ -110,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("; "); //分割
@@ -265,4 +276,56 @@ export function $(key, cache = true) {
     }
   }
   return _dom
-}
+}
+
+export const getInnerIframeURL = (url) => {
+  let iframeUrl = url;
+  if (url.includes('?')) {
+    iframeUrl += `&appVersionCode=${appVersionCode}`;
+  } else {
+    iframeUrl += `?appVersionCode=${appVersionCode}`;
+  }
+  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')
+}
+
+export function isMobileTwitter() {
+  let isMobile = false;
+  if(window.location.href.startsWith('https://mobile.twitter.com')) {
+    isMobile = true;
+  }
+  return isMobile;
+}

+ 129 - 0
src/uilts/messageCenter/chrome/index.js

@@ -0,0 +1,129 @@
+import { guid } from '@/uilts/help'
+//  iframe 通信中心
+class ChromeMessageCenter {
+    constructor() {
+        //  缓存事件队列
+        this.messageCallbackMap = new Map();
+        this.messageFailbackMap = new Map();
+        this.timer = null
+    }
+
+    sendToContent(sender, { info = {}, data = {}, callback, overTime, failback }) {
+        if (!info.messageId) {
+            info.messageId = `${info.actionType}-${guid()}` // 唯一的ID,用于标记回调函数
+        }
+        try {
+            chrome.tabs.sendMessage(sender.tab.id, {
+                info,
+                data
+            })
+
+            if (info.messageId && callback) {
+                // 带回调callback 的message, 要求携带messageId,callback,failback等
+                this.listen(info.messageId, callback)
+            }
+            if (failback) {
+                this.addFailback(info.messageId, overTime, failback)
+            }
+
+        } catch (error) {
+            failback({
+                error: 2,
+                msg: String(error)
+            })
+        }
+    }
+
+    sendToSW({ info = {}, data = {}, callback, overTime, failback }) {
+        if (!info.messageId) {
+            info.messageId = `${info.actionType}-${guid()}` // 唯一的ID,用于标记回调函数
+        }
+        try {
+            chrome.runtime.sendMessage({
+                info,
+                data
+            })
+
+            if (info.messageId && callback) {
+                // 带回调callback 的message, 要求携带messageId,callback,failback等
+                this.listen(info.messageId, callback)
+            }
+            if (failback) {
+                this.addFailback(info.messageId, overTime, failback)
+            }
+
+        } catch (error) {
+            failback({
+                error: 2,
+                msg: String(error)
+            })
+        }
+    }
+
+    listen(messageId, callback) {
+        // 序列添加失败回调
+        this.messageCallbackMap.set(messageId, { callback })
+    }
+
+    addFailback(messageId, overTime = 2000, failback) {
+        // 序列添加失败回调
+        this.messageFailbackMap.set(messageId, {
+            time: new Date().getTime(),
+            overTime,
+            failback
+        })
+        this.checkTimer()
+    }
+
+    init(req = {}) {
+        const { info, data } = req;
+        if (!info || !data) {
+            return
+        }
+        // 序列删除 失败回调
+        this.messageFailbackMap.delete(info.messageId);
+
+        // 执行成功回调
+        const _item = this.messageCallbackMap.get(info.messageId);
+        if (_item) {
+            const callback = _item.callback
+            callback(data)
+            // 序列删除 成功回调
+            this.messageCallbackMap.delete(info.messageId)
+        }
+        this.checkTimer()
+    }
+    checkTimer() {
+        if (this.timer) {
+            return
+        }
+        let key, value, now_time
+        this.timer = setInterval(() => {
+            if (this.messageFailbackMap.size == 0) {
+                clearInterval(this.timer)
+                this.timer = null
+            }
+
+            // 轮询查看有无超期的message信息
+            now_time = new Date().getTime();
+            for (let item of this.messageFailbackMap.entries()) {
+                key = item[0] || ''
+                value = item[1] || {}
+
+                if (now_time - value.time > value.overTime) {
+                    const callback = value.failback
+                    callback && callback({
+                        error: 1,
+                        msg: "message 超时错误"
+                    })
+                    this.messageFailbackMap.delete(key)
+                }
+            }
+        }, 1000)
+    }
+}
+
+// messageCenter在页面内实例化一次
+const chromeMessageCenter = new ChromeMessageCenter();
+
+export default chromeMessageCenter;

+ 13 - 0
src/uilts/messageCenter/chrome/messageEnum.js

@@ -0,0 +1,13 @@
+/** 向ServiceWorker发送的事件定义 */
+const CONTENT_TO_BACK_ENUM = {
+    CONTENT_TO_BACK_TEST: 'CONTENT_TO_BACK_TEST'
+}
+
+
+/** 接收ServiceWorker的事件定义 */
+const BACK_TO_CONTENT_ENUM = {
+    /** 切换到group tab */
+    BACK_TO_CONTENT_TEST: 'BACK_TO_CONTENT_TEST'
+}
+
+export default { ...CONTENT_TO_BACK_ENUM, ...BACK_TO_CONTENT_ENUM }

+ 60 - 0
src/uilts/messageCenter/content/index.js

@@ -0,0 +1,60 @@
+class ContentMessageCenter {
+    constructor() {
+        this.iframeMap = new Map();
+        this.messageCallbackMap = new Map();
+        // this.listen()
+    }
+
+    findIframeById(id) {
+        let target = this.iframeMap.get(id);
+        if (!target) {
+            target = document.getElementById(id)
+            this.iframeMap.set('id', target)
+        }
+        return target
+    }
+
+    send({ info, data }) {
+        const target = this.findIframeById(info.iframeId);
+        target && target.contentWindow.postMessage({
+            info,
+            data
+        }, '*')
+    }
+
+    sendAll({ info, data }) {
+        const targets = document.querySelectorAll('iframe[data-card=denet]') || []
+        targets.forEach((item) => {
+            item.contentWindow.postMessage({
+                info,
+                data
+            }, '*')
+        })
+    }
+
+    // ---- don't use ---- 
+    // add(actionType, callback) {
+    //     let activeQuene = this.messageCallbackMap.get(actionType);
+    //     if (activeQuene?.length > 0) {
+    //         activeQuene.push(callback)
+    //     } else {
+    //         this.messageCallbackMap.set(actionType, [callback])
+    //     }
+    // }
+    // ---- don't use ---- 
+    // listen() {
+    //     window.addEventListener('message', (e) => {
+    //         const { actionType, data } = e.data;
+    //         console.log('get message in content ...', actionType, data)
+    //         const quene = this.messageCallbackMap.get(actionType) || [];
+    //         while (quene.length > 0) {
+    //             let callback = quene.pop();
+    //             callback(data)
+    //         }
+    //     })
+    // }
+}
+
+const contentMessageCenter = new ContentMessageCenter();
+
+export default contentMessageCenter;

+ 22 - 0
src/uilts/messageCenter/content/messageEnum.js

@@ -0,0 +1,22 @@
+/** 向父窗口发送的事件定义 */
+const SEND_MESSAGE_ENUM = {
+    IFREME_TAB_GROUP_SET_IFRAME_HEIGHT: 'IFREME_TAB_GROUP_SET_IFRAME_HEIGHT',
+    /** group tab 内的列表项点击 */
+    IFRAME_PAGE_JUMP: 'IFRAME_PAGE_JUMP',
+    IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP: 'IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP',
+    /** 获取content的localstorge数据 */
+    IFRAME_GET_EXTENSION_STORGE_DATA: 'IFRAME_GET_EXTENSION_STORGE_DATA',
+
+}
+
+/** 接收父窗口的事件定义 */
+const RECEIVE_MESSAGE_ENUM = {
+    /** 切换到group tab */
+    CONTENT_REFRESH_TAB_GROUP_LIST: 'CONTENT_REFRESH_TAB_GROUP_LIST',
+    /** group打开时,页面发生滚动 */
+    CONTENT_GROUP_LIST_SCROLL: 'CONTENT_GROUP_LIST_SCROLL',
+    CONTENT_SEND_GROUP_NAV_TOP: 'CONTENT_SEND_GROUP_NAV_TOP',
+    CONTENT_SYS_THEME_CHANGE: 'CONTENT_SYS_THEME_CHANGE'
+}
+
+export default { ...SEND_MESSAGE_ENUM, ...RECEIVE_MESSAGE_ENUM }

+ 106 - 0
src/uilts/messageCenter/iframe/index.js

@@ -0,0 +1,106 @@
+import { guid } from '@/uilts/help'
+//  iframe 通信中心
+class IframeMessageCenter {
+    constructor() {
+        //  缓存事件队列
+        this.messageCallbackMap = new Map();
+        this.messageFailbackMap = new Map();
+        this.timer = null
+        this.init()
+    }
+
+    send({ info = {}, data = {}, callback, overTime, failback }) {
+        if (callback) {
+            info.messageId = `${info.actionType}-${guid()}` // 唯一的ID,用于标记回调函数
+        }
+        window.parent.postMessage({
+            info,
+            data
+        }, '*');
+        if (info.messageId && callback) {
+            // 带回调callback 的message, 要求携带messageId,callback,failback等
+            this.listen(info.messageId, callback)
+            if (failback) {
+                this.addFailback(info.messageId, overTime, failback)
+            }
+        }
+    }
+
+    listen(key, callback) {
+        // 序列添加失败回调
+        this.messageCallbackMap.set(key, { callback })
+    }
+
+    addFailback(key, overTime = 2000, failback) {
+        // 序列添加失败回调
+        this.messageFailbackMap.set(key, {
+            time: new Date().getTime(),
+            overTime,
+            failback
+        })
+        this.checkTimer()
+    }
+
+    init() {
+        window.addEventListener('message', (e) => {
+            let { info = {}, data = {} } = e.data;
+            let key, item
+
+            // 如果有messageId && 是自己发送的
+            if (info.messageId) {
+                key = info.messageId
+                item = this.messageCallbackMap.get(key)
+            }
+
+            if (info.actionType && !item) {
+                key = info.actionType
+                item = this.messageCallbackMap.get(key)
+            }
+
+            // 执行成功回调
+            if (item) {
+                // 序列删除 失败回调      
+                this.messageFailbackMap.delete(key)
+                const callback = item.callback
+                callback(data)
+                // 序列删除 成功回调
+                this.messageCallbackMap.delete(key)
+            }
+        })
+
+        this.checkTimer()
+    }
+    checkTimer() {
+        if (this.timer) {
+            return
+        }
+        let key, value, now_time
+        this.timer = setInterval(() => {
+            if (this.messageFailbackMap.size == 0) {
+                clearInterval(this.timer)
+                this.timer = null
+            }
+
+            // 轮询查看有无超期的message信息
+            now_time = new Date().getTime();
+            for (let item of this.messageFailbackMap.entries()) {
+                key = item[0] || ''
+                value = item[1] || {}
+
+                if (now_time - value.time > value.overTime) {
+                    const callback = value.failback
+                    callback && callback({
+                        error: 1,
+                        msg: "message 超时错误"
+                    })
+                    this.messageFailbackMap.delete(key)
+                }
+            }
+        }, 1000)
+    }
+}
+
+// messageCenter在每个iframe内实例化一次
+const iframeMessageCenter = new IframeMessageCenter();
+
+export default iframeMessageCenter;

+ 34 - 0
src/uilts/messageCenter/iframe/messageEnum.js

@@ -0,0 +1,34 @@
+/** 向父窗口发送的事件定义 */
+const SEND_MESSAGE_ENUM = {
+    IFREME_TAB_GROUP_SET_IFRAME_HEIGHT: 'IFREME_TAB_GROUP_SET_IFRAME_HEIGHT',
+    /** group tab 内的列表项点击 */
+    IFRAME_PAGE_JUMP: 'IFRAME_PAGE_JUMP',
+    IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP: 'IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP',
+    /** 获取content的localstorge数据 */
+    IFRAME_GET_EXTENSION_STORGE_DATA: 'IFRAME_GET_EXTENSION_STORGE_DATA',
+    // ---- 做任务 ----
+    IFRAME_DO_TASK_CREATE_TWEET: 'IFRAME_DO_TASK_CREATE_TWEET',
+    IFRAME_DO_TASK_LIKE: 'IFRAME_DO_TASK_LIKE',
+    IFRAME_DO_TASK_FOLLOWS: 'IFRAME_DO_TASK_FOLLOWS',
+    IFRAME_DO_TASK_RETWEET: 'IFRAME_DO_TASK_RETWEET',
+
+    // ---- 获取推文内容 ----
+    IFRAME_DOM_GET_TWEET_TEXT: 'IFRAME_DOM_GET_TWEET_TEXT',
+
+    // ---- 获取twitter用户信息 ----
+    IFRAME_GET_TWITTER_USER_INFO: 'IFRAME_GET_TWITTER_USER_INFO',
+
+
+}
+
+/** 接收父窗口的事件定义 */
+const RECEIVE_MESSAGE_ENUM = {
+    /** 切换到group tab */
+    CONTENT_REFRESH_TAB_GROUP_LIST: 'CONTENT_REFRESH_TAB_GROUP_LIST',
+    /** group打开时,页面发生滚动 */
+    CONTENT_GROUP_LIST_SCROLL: 'CONTENT_GROUP_LIST_SCROLL',
+    CONTENT_SEND_GROUP_NAV_TOP: 'CONTENT_SEND_GROUP_NAV_TOP',
+    CONTENT_SYS_THEME_CHANGE: 'CONTENT_SYS_THEME_CHANGE'
+}
+
+export default { ...SEND_MESSAGE_ENUM, ...RECEIVE_MESSAGE_ENUM }

+ 0 - 50
src/uilts/messageCenter/index.js

@@ -1,50 +0,0 @@
-class MessageCenter { 
-    constructor() { 
-        this.iframeMap = new Map();
-        this.messageCallbackMap = new Map();
-        // this.listen()
-    }
-
-    findIframeById(id) { 
-        let target = this.iframeMap.get(id);
-        if (!target) { 
-            target = document.getElementById(id)
-            this.iframeMap.set('id', target)
-        }
-        return target
-    }
-
-    send(id, actionType, data) {
-        const target = this.findIframeById(id);
-        target && target.contentWindow.postMessage({
-            actionType,
-            data
-        }, '*')
-    }
-
-    // don't use
-    add(actionType, callback) {
-        let activeQuene = this.messageCallbackMap.get(actionType);
-        if (activeQuene?.length > 0) {
-            activeQuene.push(callback)
-        } else { 
-            this.messageCallbackMap.set(actionType, [callback])
-        }
-    }
-    // don't use
-    listen() { 
-        window.addEventListener('message', (e) => { 
-            const { actionType, data } = e.data;
-            console.log('get message in content ...', actionType, data)
-            const quene = this.messageCallbackMap.get(actionType) ||  [];
-            while (quene.length > 0) { 
-                let callback = quene.pop();
-                callback(data)
-            }
-        })
-    }
-}
-
-const messageCenter = new MessageCenter();
-
-export default messageCenter;

+ 12 - 1
src/view/components/currency-list.vue

@@ -186,7 +186,18 @@ const searchCurrency = debounce(function (searchWords) {
     }).then(res => {
         if (res.code == 0) {
             if (res.data.currencyCategories && res.data.currencyCategories.length) {
-                let list = res.data.currencyCategories[0];
+                let currencyCategories = res.data.currencyCategories;
+
+                let arr = [];
+                for(let i = 0; i < currencyCategories.length; i++) {
+                  let item = currencyCategories[i];
+                  arr = arr.concat(item.data);
+                }
+
+                currencyCategories[0]['data'] = arr;
+
+                let list = currencyCategories[0];
+
                 if (list && list.data && list.data.length) {
                     searchList.value = list.data;
                 } else {

+ 6 - 5
src/view/components/custom-card-cover.vue

@@ -89,10 +89,10 @@
                 <img class="img" :src="data.currencyIconUrl" /> <span class="txt"> {{data.tokenSymbol}}  <template v-if="data.currencyCode != 'USD'">equivalent (Crypto)</template></span>
             </div>
 
-            <img class="img-treasure-big" :src="require('@/assets/img/icon-card-cover-treasure-big.png')">
+            <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">
@@ -181,9 +181,9 @@ const props = defineProps({
 watch(() => props.show, (newVal) => {
       if(newVal) {
         zoomCom.value && zoomCom.value.setFontZoom(0);
-        zoomCom1.value && zoomCom.value.setFontZoom(0);
-        zoomCom2.value && zoomCom.value.setFontZoom(0);
-        zoomCom3.value && zoomCom.value.setFontZoom(0);
+        zoomCom1.value && zoomCom1.value.setFontZoom(0);
+        zoomCom2.value && zoomCom2.value.setFontZoom(0);
+        zoomCom3.value && zoomCom3.value.setFontZoom(0);
       }
     },
     {
@@ -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;

+ 39 - 0
src/view/components/loading.vue

@@ -0,0 +1,39 @@
+<template>
+    <img :src="icon" alt="" class="loading"
+        :style="{ 'width': `${width}px`, 'height': `${height}px`, 'margin-left': `-${width / 2}px`, 'margin-top': `-${height / 2}px` }" />
+</template>
+<script setup>
+import { defineProps } from "vue";
+const props = defineProps({
+    width: {
+        type: Number,
+        default: 40
+    },
+    height: {
+        type: Number,
+        default: 40
+    },
+    icon: {
+        type: String,
+        default: require('@/assets/svg/icon-loading-gray2.svg')
+    }
+})
+</script>
+<style lang="scss" scoped>
+.loading {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    animation: rotation 1s linear infinite;
+}
+
+@keyframes rotation {
+    from {
+        -webkit-transform: rotate(0deg);
+    }
+
+    to {
+        -webkit-transform: rotate(360deg);
+    }
+}
+</style>

+ 12 - 9
src/view/content/message/index.vue

@@ -3,14 +3,16 @@
         <template v-for="item in state.list" :key="item.createTimestamp">
             <div class="denet-message-area" @click="clickItem(item)" v-if="item.bizType == 2">
                 <img :src="require('@/assets/img/icon-message-fail.png')" alt />
-                <span>You were not selected from {{item.bizData.twitterAccount}}'s giveaway events... Click to see more giveaways!</span>
+                <span>You were not selected from {{ item.bizData.twitterAccount }}'s giveaway events... Click to see more
+                    giveaways!</span>
                 <div class="denet-message-close" @click.stop="clickClose(item)">
                     <img :src="require('@/assets/img/icon-message-close.png')" alt />
                 </div>
             </div>
             <div class="denet-message-area" @click="clickItem(item)" v-if="item.bizType == 1">
                 <img :src="require('@/assets/img/icon-message-win.png')" alt />
-                <span>Congratulations! You won <b class="denet-message-money"> {{getPrize(item.bizData)}}</b> from {{item.bizData.twitterAccount}}'s giveaway!🎉</span>
+                <span>Congratulations! You won <b class="denet-message-money"> {{ getPrize(item.bizData) }}</b> from
+                    {{ item.bizData.twitterAccount }}'s giveaway!🎉</span>
                 <div class="denet-message-close" @click.stop="clickClose(item)">
                     <img :src="require('@/assets/img/icon-message-close.png')" alt />
                 </div>
@@ -35,16 +37,16 @@ let state = reactive({
 let timer, now_time
 
 // 获取奖励
-const getPrize = (item) => { 
+const getPrize = (item) => {
     const { lotteryMoney, lotteryTokenSymbol, twitterAccount, rewardType, customizedReward } = item;
     if (rewardType === RewardType.custom) {
         return customizedReward;
     } else {
-        return `${item.bizData.lotteryMoney} ${item.bizData.lotteryTokenSymbol}` 
+        return `${item.bizData.lotteryMoney} ${item.bizData.lotteryTokenSymbol}`
     }
 }
 
-// 过5秒消失逻辑
+// 过20秒消失逻辑
 const overTimeClose = () => {
     if (timer) {
         return
@@ -56,7 +58,7 @@ const overTimeClose = () => {
         }
         now_time = new Date().getTime()
         for (let i in state.list) {
-            if ((now_time - state.list[i].read_time) >= 5000) {
+            if ((now_time - state.list[i].read_time) >= 20000) {
                 state.list.splice(i, 1)
             }
         }
@@ -121,9 +123,10 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
 </script>
 
 <style lang="scss" >
-#denet_message{
+#denet_message {
     text-align: left;
 }
+
 .denet-message {
     position: fixed;
     max-height: 100%;
@@ -131,7 +134,7 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
     top: 0;
     right: 0;
     width: 500px;
-    z-index: 9999;    
+    z-index: 9999;
     text-align: left;
 
     &-area {
@@ -147,7 +150,7 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
         margin-left: 129px;
         animation: right_to_left 1s;
         text-align: left;
-        
+
         img:first-child {
             width: 40px;
             height: 40px;

+ 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;

+ 28 - 29
src/view/iframe/buy-nft/buy/pay.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-back.svg')" @click="clickBack" />
@@ -7,8 +7,7 @@
         </div>
         <!-- 内容 -->
         <div class="area-content">
-            <div
-                class="left"
+            <div class="left"
                 :class="{ auto: tempCurrentCurrencyInfo.currencyCode === 'USD' && Number(finalAmountData.rechargeAmountValue) <= 0 }">
                 <img :src="require('@/assets/img/img-box5.png')" v-show="pay_info.home.sale_plan.itemCount == 5"
                     alt="" />
@@ -22,8 +21,7 @@
                     </div>
                 </div>
             </div>
-            <div
-                class="right"
+            <div class="right"
                 :class="{ none: tempCurrentCurrencyInfo.currencyCode === 'USD' && Number(finalAmountData.rechargeAmountValue) <= 0 }">
                 <div class="card-content" v-if="tempCurrentCurrencyInfo.currencyCode">
                     <template v-if="tempCurrentCurrencyInfo.currencyCode !== 'USD'">
@@ -49,8 +47,7 @@
                             <img class="img" :src="require('@/assets/subject/top-01.svg')" />
                             <div class="font">Deposit to Send Giveaway</div>
                         </div>
-                        <payment-info-usd
-                            :finalAmountData="finalAmountData">
+                        <payment-info-usd :finalAmountData="finalAmountData">
                         </payment-info-usd>
                     </template>
                 </div>
@@ -104,19 +101,19 @@
                         <div class="desc">Balance</div>
                         <div class="price">
                             $
-                            {{tempCurrentCurrencyInfo.balance}}
+                            {{ tempCurrentCurrencyInfo.balance }}
                         </div>
                     </div>
-                    <img class="refresh"
-                        :class="{ 'icon-refresh-rotate': refreshRotate }"
-                        :src=" require('@/assets/svg/icon-form-refresh.svg')"
-                        @click="updateCurrencyBanlce"/>
+                    <img class="refresh" :class="{ 'icon-refresh-rotate': refreshRotate }"
+                        :src="require('@/assets/svg/icon-form-refresh.svg')" @click="updateCurrencyBanlce" />
                 </div>
                 <!-- Play -->
                 <div class="buy1 usd" @click="clickPayUSD">
                     <div class="left">Pay</div>
                     <div class="right">
-                        {{ finalAmountData.rechargeAmountValue > 0 ? finalAmountData.rechargeAmountValue : finalAmountData.orderAmountValue }}
+                        {{ finalAmountData.rechargeAmountValue > 0 ? finalAmountData.rechargeAmountValue :
+                                finalAmountData.orderAmountValue
+                        }}
                         {{ pay_info.home.sale_plan.currencyInfo.tokenSymbol }}
                     </div>
                 </div>
@@ -125,10 +122,7 @@
     </div>
 
     <!-- 预览页充值 -->
-    <message-box
-        :dialogVisible="showDepositMessageBox"
-        title="Is the Deposit Completed?"
-        @cancel="depositAchCancel"
+    <message-box :dialogVisible="showDepositMessageBox" title="Is the Deposit Completed?" @cancel="depositAchCancel"
         @confirm="depositAchConfirm">
     </message-box>
 </template>
@@ -145,10 +139,10 @@ import messageBox from "@/view/components/message-box.vue";
 import BtnLoading from '../components/btn-loading.vue'
 import { payNftMysteryBoxWithBalance } from "@/http/pay";
 import { calcRechargePayAmount } from "@/http/account";
-import { getChromeStorage, setChromeStorage } from "@/uilts/chromeExtension"
+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');
@@ -181,7 +175,7 @@ let dialogStyle = reactive({
 
 const calcRechPayAmount = async (params) => {
     let res = await calcRechargePayAmount({
-        params : params
+        params: params
     })
 
     if (res.code == 0) {
@@ -220,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,
@@ -285,17 +279,17 @@ const clickPlay = () => {
 }
 
 const clickPayUSD = () => {
-    if(Number(finalAmountData.value.rechargeAmountValue) > 0) {
+    if (Number(finalAmountData.value.rechargeAmountValue) > 0) {
         setTimeout(() => {
             showDepositMessageBox.value = true;
         }, 1000)
-        chrome.tabs.getCurrent(tab =>{
+        chrome.tabs.getCurrent(tab => {
             let achPayInfo = {
                 amountValue: finalAmountData.value.rechargeAmountValue,
                 tab: tab
             };
-            let guideUrl = chrome.runtime.getURL('/iframe/ach-cashier.html');
-            setChromeStorage({ achPayInfo : JSON.stringify(achPayInfo)});
+            let guideUrl = chromeExtensionUrl + ('iframe/ach-cashier.html');
+            setChromeStorage({ achPayInfo: JSON.stringify(achPayInfo) });
 
             chrome.tabs.create({
                 url: guideUrl
@@ -315,7 +309,7 @@ let tempCurrentCurrencyInfo = ref({});
 
 const refreshRotate = ref(false);
 const updateCurrencyBanlce = () => {
-    if(!refreshRotate.value) {
+    if (!refreshRotate.value) {
         refreshRotate.value = true;
         getCurrencyInfo()
         setTimeout(() => {
@@ -362,7 +356,7 @@ const amountInterval = () => {
 
 const setDialogStyle = () => {
     let clientHeight = window.innerHeight;
-    if(clientHeight >= 840) {
+    if (clientHeight >= 840) {
         dialogStyle.height = 800;
     } else {
         dialogStyle.height = clientHeight - 40;
@@ -460,7 +454,7 @@ onUnmounted(() => {
 
             .tip {
                 margin-top: 15px;
-                font-size: 16px;    
+                font-size: 16px;
                 display: flex;
                 justify-content: space-between;
 
@@ -480,7 +474,7 @@ onUnmounted(() => {
         .right {
             width: 400px;
             margin: 30px 56px 0px 30px;
-            
+
             &.none {
                 display: none;
             }
@@ -649,23 +643,28 @@ onUnmounted(() => {
 .balance {
     display: flex;
     margin-right: 20px;
+
     .icon {
         width: 40px;
         height: 40px;
     }
+
     .con {
         padding: 0 5px;
+
         .desc {
             color: rgba($color: #000000, $alpha: 0.5);
             font-size: 12px;
             margin-bottom: 4px;
         }
+
         .price {
             font-size: 14px;
             font-weight: bold;
             word-break: break-all;
         }
     }
+
     .refresh {
         width: 40px;
         cursor: pointer;

+ 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" })
     })
 
 })

+ 18 - 0
src/view/iframe/nft/card.vue

@@ -56,6 +56,7 @@ const isShare = ref(false);
 const isLoading = ref(true);
 const isShowGuide = ref(false);
 const nftProjectId = ref('');
+const nftAccount = ref('');
 let tweetId = ref('');
 
 const getSaleInfo = () => {
@@ -89,6 +90,7 @@ const getSaleData = (projectId) => {
 }
 
 const getSaleProjectInfo = (account) => {
+    nftAccount.value = account;
     getTwitterSaleNftProjectInfo({
         params: {
             twitterAccount: account
@@ -193,6 +195,22 @@ const msgListener = (req, sender, sendResponse) => {
 
 onMounted(() => {
     onRuntimeMsg();
+    // 切换用户
+    chrome.tabs.onUpdated.addListener((id, info) => {
+        if (info.status === "loading" && (info && info.url) && !isShare.value) {
+            let url = new URL(info.url);
+            let pathname = url.pathname;
+            let pathArr;
+            if (pathname) {
+                pathname = pathname.slice(1);
+                pathArr = pathname.split('/');
+                if (nftAccount.value !== pathArr[0]) {
+                    console.log(3333)
+                    getSaleInfo()
+                }
+            }
+        }
+    })
 })
 
 

+ 24 - 13
src/view/iframe/publish/components/get-more.vue

@@ -1,23 +1,26 @@
 <template>
-    <div class="get-more-btns"  v-if="props.style_type == 3">
+    <div class="get-more-btns" v-if="props.style_type == 3">
         <div class="get-more-btn" @click="jumpMore">
             <img width="22" :src="require('@/assets/svg/icon-wallet-success.svg')" />
-            <font>View wallet</font>
+            <span>View wallet</span>
         </div>
         <div class="get-more-btn" @click="jumpMore">
             <img width="22" :src="require('@/assets/svg/icon-big-give.svg')" />
-            <font>Get More Giveaway</font>
+            <span>Get More Giveaway</span>
         </div>
     </div>
     <div class="getMore" @click="jumpMore" v-if="props.style_type == 1">
         <img width="20" :src="require('@/assets/svg/icon-big-give.svg')" />
-        <font>Get More Giveaway</font>
+        <span>Get More Giveaway</span>
         <img height="20" :src="require('@/assets/svg/icon-cell-arrow-right.svg')" />
     </div>
     <div class="get_more" v-if="props.style_type == 2" @click="jumpMore">
         <img width="18" :src="require('@/assets/svg/icon-big-give.svg')" />
         <span>Get More Giveaway</span>
     </div>
+    <div v-if="style_type == 4" @click="jumpMore">
+        <slot></slot>
+    </div>
 </template>
 
 <script setup>
@@ -48,12 +51,16 @@ onBeforeMount(() => {
 })
 
 const jumpMore = () => {
-    Report.reportLog({
-      pageSource: props.reportData.pageSource,
-      businessType: Report.businessType.buttonClick,
-      objectType: Report.objectType.getMoreGiveaway,
-      postId: props.reportData.postId
-    });
+    if (props.reportData) {
+        Report.reportLog({
+            pageSource: props.reportData.pageSource,
+            businessType: Report.businessType.buttonClick,
+            objectType: Report.objectType.getMoreGiveaway,
+            postId: props.reportData.postId,
+            redPacketType: props.reportData.redPacketType
+        });
+    }
+
     if (moreUrl.value) {
         window.open(moreUrl.value)
     }
@@ -75,7 +82,7 @@ const jumpMore = () => {
         margin: 0 5px;
     }
 
-    font {
+    span {
         color: #000;
         font-size: 15px;
         font-weight: 500;
@@ -99,7 +106,8 @@ const jumpMore = () => {
         margin-right: 8px;
     }
 }
-.get-more-btns  {
+
+.get-more-btns {
     display: flex;
     cursor: pointer;
     user-select: none;
@@ -108,6 +116,7 @@ const jumpMore = () => {
     padding: 13px 0;
     box-shadow: 0px -2px 10px rgba(0, 0, 0, 0.06);
     position: relative;
+
     .get-more-btn {
         flex: 1;
         display: flex;
@@ -117,6 +126,7 @@ const jumpMore = () => {
         align-items: center;
         justify-content: center;
         height: 44px;
+
         font {
             font-weight: 600;
             font-size: 14px;
@@ -126,6 +136,7 @@ const jumpMore = () => {
             color: #000000;
         }
     }
+
     &::after {
         content: "";
         width: 1px;
@@ -133,7 +144,7 @@ const jumpMore = () => {
         position: absolute;
         left: 50%;
         top: 13px;
-        background-color: rgba(0,0,0,.2);
+        background-color: rgba(0, 0, 0, .2);
         transform: scale(0.5);
         transform-origin: 0 0;
     }

+ 13 - 21
src/view/iframe/publish/components/give-dialog-head.vue

@@ -4,35 +4,25 @@
             <!-- 关闭按钮 -->
             <div class="close-btn" @click="close">
                 <template v-if="publishType == 'TOOL_BOX'">
-                    <img  class="icon-close"
-                    :src="require('@/assets/svg/icon-close.svg')"
-                    v-if="toolBoxPageData.activePage == 'EDITOR'"/>
-                    <img class="icon-close"
-                        :src="require('@/assets/svg/icon-back.svg')"
-                        v-else/>
+                    <img class="icon-close" :src="require('@/assets/svg/icon-close.svg')"
+                        v-if="toolBoxPageData.activePage == 'EDITOR'" />
+                    <img class="icon-close" :src="require('@/assets/svg/icon-back.svg')" v-else />
                 </template>
                 <template v-else>
-                    <img  class="icon-close"
-                    :src="require('@/assets/svg/icon-close.svg')"
-                    v-if="showComType == 'default'"/>
-                    <img class="icon-close"
-                        :src="require('@/assets/svg/icon-back.svg')"
-                        v-else/>
+                    <img class="icon-close" :src="require('@/assets/svg/icon-close.svg')"
+                        v-if="showComType == 'default'" />
+                    <img class="icon-close" :src="require('@/assets/svg/icon-back.svg')" v-else />
                 </template>
             </div>
             <!-- 标题 -->
             <div class="title">
-                {{title}}
+                {{ title }}
             </div>
         </div>
         <div class="right">
             <!-- 更多按钮 -->
-            <img :src="require('@/assets/svg/icon-more-l.svg')"
-                class="more"
-                @click="showMoreOption = true">
-            <div class="area-option" 
-                v-if="showMoreOption" 
-                @click="showMoreOption = false">
+            <img :src="require('@/assets/svg/icon-more-l.svg')" class="more" @click="showMoreOption = true">
+            <div class="area-option" v-if="showMoreOption" @click="showMoreOption = false">
                 <div class="option">
                     <div class="item" @click="goTransactionsList()">
                         <img :src="require('@/assets/svg/icon-menu.svg')">
@@ -46,6 +36,7 @@
 
 <script setup>
 import { ref, defineEmits, defineProps } from "vue";
+import { chromeExtensionUrl } from "@/uilts/chromeExtension"
 
 const props = defineProps({
     publishType: {
@@ -76,7 +67,7 @@ const emits = defineEmits(["close"]);
 let showMoreOption = ref(false);
 
 const goTransactionsList = () => {
-    window.open(`${chrome.runtime.getURL('/iframe/home.html#/transactions')}`)
+    window.open(`${chromeExtensionUrl + ('iframe/home.html#/transactions')}`)
 }
 
 const close = () => {
@@ -98,6 +89,7 @@ const close = () => {
     .left {
         display: flex;
         align-items: center;
+
         .title {
             font-size: 16px;
             font-weight: 500;
@@ -161,7 +153,7 @@ const close = () => {
                 }
 
                 .item:hover {
-                        background: #F5F5F5;
+                    background: #F5F5F5;
                 }
             }
         }

+ 4 - 4
src/view/iframe/publish/components/giveaway-poster.vue

@@ -14,7 +14,7 @@
                             validityDuration: baseFormData.validityDuration,
                             customPosterUrl: customPosterInfo && customPosterInfo.before && customPosterInfo.before.imagePath || '',
                             userInfo: {
-                                nickName: userInfo.name,
+                                nickName: userInfo.nickName,
                                 avatarUrl: userInfo.avatarUrl
                             },
                             rewardType: baseFormData.rewardType,
@@ -65,7 +65,7 @@
                             validityDuration: baseFormData.validityDuration,
                             customPosterUrl: customPosterInfo && customPosterInfo.after && customPosterInfo.after.imagePath || '',
                             userInfo: {
-                                nickName: userInfo.name,
+                                nickName: userInfo.nickName,
                                 avatarUrl: userInfo.avatarUrl
                             },
                             rewardType: baseFormData.rewardType,
@@ -220,7 +220,7 @@ onMounted(() => {
     calcPreviewCanvasParams();
     getUserInfo((res) => {
         if(res) {
-            getUserName(res.nickName);
+            // getUserName(res.nickName);
         }
     });
     window.addEventListener('resize',function () {
@@ -354,4 +354,4 @@ onMounted(() => {
     top: unset;
     left: unset;
 }
-</style>
+</style>

+ 1 - 1
src/view/iframe/publish/components/nft-setting.vue

@@ -5,7 +5,7 @@
                 <div class="sel"><a-radio value="public"></a-radio></div>
                 <div class="inp">
                     <img :src=" require('@/assets/svg/icon-post-edit-open.svg') " />
-                    <span>Publick</span>
+                    <span>Public</span>
                 </div>
             </label>
             <label class="item">

+ 22 - 22
src/view/iframe/publish/components/pay-button.vue

@@ -1,13 +1,13 @@
 <template>
-<!-- pay 支付按钮 -->
+    <!-- pay 支付按钮 -->
     <div class="pay-wrapper">
         <slot name="balance"></slot>
         <div class="pay-btn">
-            <div class="iframe-pay"
-                v-show="currentCurrencyInfo.currencyCode == 'USD'">
-                <div class="token-pay"
-                    @click="clickPayUSD">
-                    Pay ${{finalAmountData.rechargeAmountValue > 0 && USDepositStatus != 'SUCCESS' ? finalAmountData.rechargeAmountValue : finalAmountData.orderAmountValue}}
+            <div class="iframe-pay" v-show="currentCurrencyInfo.currencyCode == 'USD'">
+                <div class="token-pay" @click="clickPayUSD">
+                    Pay ${{ finalAmountData.rechargeAmountValue > 0 && USDepositStatus != 'SUCCESS' ?
+                            finalAmountData.rechargeAmountValue : finalAmountData.orderAmountValue
+                    }}
                 </div>
 
                 <!-- <iframe
@@ -15,11 +15,9 @@
                     ref="iframe"
                     :src="`${payConfig.paypalHtml}?paypalClientId=${payConfig.paypalClientId}&amount=${props.finalAmountData.finalAmountValue}`"></iframe> -->
             </div>
-            <div class="token-pay"
-                :class="{ disabled: Number(currentCurrencyInfo.balance) < Number(payConfig.amount) }"
-                v-if="currentCurrencyInfo.currencyCode != 'USD'"
-                @click="balancePay">
-                Pay {{payConfig.amount || 0}} {{currentCurrencyInfo.tokenSymbol}}
+            <div class="token-pay" :class="{ disabled: Number(currentCurrencyInfo.balance) < Number(payConfig.amount) }"
+                v-if="currentCurrencyInfo.currencyCode != 'USD'" @click="balancePay">
+                Pay {{ payConfig.amount || 0 }} {{ currentCurrencyInfo.tokenSymbol }}
             </div>
         </div>
     </div>
@@ -30,9 +28,9 @@ import { onMounted, ref, defineProps, defineEmits, watch, defineExpose } from "v
 
 import { PlayType } from '@/types';
 
-import {payTaskLuckdropWithBalance} from "@/http/publishApi"
+import { payTaskLuckdropWithBalance } from "@/http/publishApi"
 import Report from "@/log-center/log"
-import {setChromeStorage, getChromeStorage} from "@/uilts/chromeExtension"
+import { setChromeStorage, getChromeStorage, chromeExtensionUrl } from "@/uilts/chromeExtension"
 
 const props = defineProps({
     finalAmountData: {
@@ -99,7 +97,7 @@ const balancePay = () => {
     }, {
         type: Report.getCurrentBizType(props.bizType)
     });
-    if(payIng) {
+    if (payIng) {
         return;
     }
     payIng = true;
@@ -109,8 +107,8 @@ const balancePay = () => {
             postId: props.payConfig.postId
         }
     }).then(res => {
-        if(res.code == 0) {
-            emits("payFinish", {...res.data});
+        if (res.code == 0) {
+            emits("payFinish", { ...res.data });
         }
         payIng = false;
     }).catch(() => {
@@ -119,17 +117,17 @@ const balancePay = () => {
 }
 
 const clickPayUSD = () => {
-    if(props.finalAmountData.rechargeAmountValue > 0 && props.USDepositStatus != 'SUCCESS') {
+    if (props.finalAmountData.rechargeAmountValue > 0 && props.USDepositStatus != 'SUCCESS') {
         setTimeout(() => {
             emits("showDepositMask", {});
         }, 1000)
-        chrome.tabs.getCurrent(tab =>{
+        chrome.tabs.getCurrent(tab => {
             let achPayInfo = {
                 amountValue: props.finalAmountData.rechargeAmountValue,
                 tab: tab
             };
-            let guideUrl = chrome.runtime.getURL('/iframe/ach-cashier.html');
-            setChromeStorage({ achPayInfo : JSON.stringify(achPayInfo)});
+            let guideUrl = chromeExtensionUrl + ('iframe/ach-cashier.html');
+            setChromeStorage({ achPayInfo: JSON.stringify(achPayInfo) });
 
             chrome.tabs.create({
                 url: guideUrl
@@ -203,13 +201,14 @@ defineExpose({
 
             .icon {
                 width: 14px;
-                margin-left:6px;
+                margin-left: 6px;
             }
 
             .desc {
-                margin-right:6px
+                margin-right: 6px
             }
         }
+
         .msg {
             font-size: 13px;
             color: #898989;
@@ -232,6 +231,7 @@ defineExpose({
             padding: 0 30px;
             word-break: break-all;
             cursor: pointer;
+
             &.disabled {
                 background: #DEDEDE;
             }

+ 3 - 2
src/view/iframe/publish/components/preview-card.vue

@@ -29,7 +29,7 @@
                             validityDuration: baseFormData.validityDuration,
                             customPosterUrl: customPosterInfo && customPosterInfo.after && customPosterInfo.after.imagePath || '',
                             userInfo: {
-                                nickName: userInfo.name,
+                                nickName: userInfo.nickName,
                                 avatarUrl: userInfo.avatarUrl
                             },
                             rewardType: baseFormData.rewardType,
@@ -74,11 +74,12 @@
                             customPosterUrl: customPosterInfo && customPosterInfo.before && customPosterInfo.before.imagePath || '',
                             addFans: baseFormData.addFans,
                             userInfo: {
-                                nickName: userInfo.name,
+                                nickName: userInfo.nickName,
                                 avatarUrl: userInfo.avatarUrl
                             },
                             rewardType: baseFormData.rewardType,
                             customizedReward: baseFormData.customizedReward,
+                            upGainAmountUsdValue: upGainAmountUsdValue
                         }">
                     </custom-card-horizontal-cover>
                 </div>

+ 80 - 16
src/view/iframe/publish/give-dialog.vue

@@ -309,9 +309,9 @@
                                         usdEstimateOrderAmount: treasureFormData.usdEstimateOrderAmount,
                                         upGainAmountUsdValue: treasureFormData.upGainAmountUsdValue,
                                         currencyIconUrl: currentCurrencyInfo.iconPath,
-                                        customPosterUrl: customPosterInfo && customPosterInfo.after && customPosterInfo.after.imagePath || '',
+                                        customPosterUrl: previewCustomPosterUrl,
                                         userInfo: {
-                                            nickName: userInfo.name,
+                                            nickName: userInfo.nickName,
                                             avatarUrl: userInfo.avatarUrl
                                         },
                                     }"></custom-card-cover>
@@ -455,6 +455,7 @@
 import { ref, watch, reactive, defineProps, defineEmits, onMounted, nextTick, provide, computed } from "vue";
 import { postPublish, syncChainTokenRechargeRecord, getCurrencyInfoByCode, getUser } from "@/http/publishApi";
 import { getInviteGuildInfo, getInviteGuildInfoByOpenApi, saveInviteGuildInfo } from "@/http/discordApi";
+import { getPostEditorConfig } from "@/http/toolBoxApi";
 import { payCalcFee, getPayConfig } from "@/http/pay";
 import { upGainCalculate } from "@/http/treasureApi";
 import { getFrontConfig, calcRechargePayAmount } from "@/http/account";
@@ -490,6 +491,8 @@ import ComponentZoom from '@/view/components/component-zoom.vue'
 
 const config = {
     number: 'BigNumber',
+    precision: 64,            // Number of significant digits for BigNumbers
+    epsilon: 1e-60
 }
 const math = create(all, config);
 
@@ -538,7 +541,9 @@ let cropperType = ref('before')
 let customPosterInfo = ref({})
 let customPosterData = ref({})
 let customShowNewImage = ref(false)
-let refCropper = ref('')
+let refCropper = ref('');
+
+let previewCustomPosterUrl = ref('');
 
 // 当前展示组件内容 default(表单)  preview(预览)  topUp(充值)
 let showComType = ref("default");
@@ -829,6 +834,7 @@ watch(
             timer.value = setInterval(() => {
                 getCurrencyInfo({loop: true});
             }, 10000)
+            savePostEditorConfig();
         } else {
             clearInterval(timer.value);
         }
@@ -1166,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 = '';
@@ -1240,8 +1250,11 @@ const submitRequest = async () => {
             showComType.value = "preview";
             previewFontSize.value = calcFontSize(baseFormData.amountValue, 238, 56);
             isBack.value = false;
-        } else {
-            console.log(res);
+        } else if(res.code == 2101){
+            const { usdPrice, minAmount, luckdropPostConfig = [] } = currentCurrencyInfo.value;
+            let currentLuckDropConfig = luckdropPostConfig.find(item => item.luckdropType === selectModeInfo.type);
+
+            message.warning(`The prize pool must be above $${currentLuckDropConfig.minTotalUsdAmount} and the average prize must be above $${currentLuckDropConfig.minAvgUsdAmount} per person.`);
         }
     })
     .catch((err) => {
@@ -1359,6 +1372,14 @@ const payStatusHandle = (payStatus) => {
     switch (payStatus) {
         case 1:
             emits("postPublishFinish", { publishRes });
+            Report.reportLog({
+              pageSource: Report.pageSource.previewPage,
+              businessType: Report.businessType.buttonClick,
+              objectType: Report.objectType.previewNextButton,
+              postId: publishRes.postId
+            }, {
+              type: Report.getCurrentBizType(selectModeInfo.type)
+            });
             showComType.value = "default";
             initParams();
             break;
@@ -1480,7 +1501,7 @@ const calcFansUnitAmount = () => {
         unitAmount = calcToken2UsdEstimate({amount: unitAmount, usdPrice: currentCurrencyInfo.value.usdPrice });
     }
 
-    return unitAmount;
+    return Math.floor(unitAmount * 1000) / 1000;
 };
 
 const setUpGainAmountUsdValue = (params) => {
@@ -1525,7 +1546,16 @@ const onUsdEstimateOrderAmountInput = () => {
 const onAmountInput = () => {
     let val = baseFormData.amountValue;
     // val = val.replace(/[^\d^\.]+/g, "");
-    val = String(val).replace(/^\D*(\d*(?:\.\d{0,18})?).*$/g, '$1');
+
+    let num = 2;
+    let minAmount = currentCurrencyInfo.value.minAmount;
+    let minArr = minAmount.split('.');
+    if(minArr && minArr.length > 1) {
+      num = minArr[1].length || 2;
+    }
+    let reg = new RegExp('^\\D*(\\d*(?:\\.\\d{0,'+num+'})?).*$', 'g');
+
+    val = String(val).replace(reg, '$1');
 
     const maxCount = baseFormData.rewardType === RewardType.money ? Number.MAX_SAFE_INTEGER : 100000000;
 
@@ -1638,12 +1668,15 @@ const calcIptValue = (cb) => {
         };
     }
 
-    if (math.format(math.evaluate(`${baseFormData.amountValue} / ${baseFormData.totalCount}`)) < +currentCurrencyInfo.value.minAmount) {
+    let val1 = +math.format(math.divide(math.bignumber(+baseFormData.amountValue), math.bignumber(+baseFormData.totalCount)));
+    let val2 = +math.format(math.divide(math.bignumber(+baseFormData.amountValue), math.bignumber(+currentCurrencyInfo.value.minAmount)));
+
+    if (val1 < +currentCurrencyInfo.value.minAmount) {
         flag = false;
     }
     return {
         flag,
-        count: Math.floor(math.format(math.evaluate(`${baseFormData.amountValue} / ${currentCurrencyInfo.value.minAmount}`)))
+        count: Math.floor(val2)
     }
 };
 
@@ -1662,11 +1695,19 @@ const checkUsdMinNumber = (isInTemplate) => {
             // 当前token允许的usd最小金额为0 或单个红包最小金额为0,则无限制
             return forbiddenText;
         } else {
-            const isAmountForbidden = currentLuckDropConfig?.minTotalUsdAmount ? math.format(math.evaluate(amountValue * usdPrice)) < currentLuckDropConfig.minTotalUsdAmount : false;
-            const isAvgForbidden = currentLuckDropConfig?.minAvgUsdAmount ? math.format(math.evaluate(amountValue / totalCount * usdPrice)) < currentLuckDropConfig.minAvgUsdAmount : false;
-            forbiddenText = isAmountForbidden && isAvgForbidden ?
+            let val1 = 0;
+            if(currentLuckDropConfig?.minAvgUsdAmount) {
+              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.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)}
-                            or the average prize must be above
+                            and the average prize must be above
                             ${isInTemplate ? ('<span class="font-color-1D9BF0">$' + currentLuckDropConfig.minAvgUsdAmount +' per person.</span>' ): ('$' + currentLuckDropConfig.minAvgUsdAmount + ' per person.') }`
                             : '';
         }
@@ -1689,8 +1730,7 @@ const checkTreasureAmountRange = (isInTemplate) => {
             let txt =  `The prize pool must be above ${isInTemplate ? ('<span class="font-color-1D9BF0">$' + currentLuckDropConfig.minTotalUsdAmount + '</span>') : ('$' + currentLuckDropConfig.minTotalUsdAmount)}
                             and the average prize must be above
                             ${isInTemplate ? ('<span class="font-color-1D9BF0">$' + currentLuckDropConfig.minAvgUsdAmount +' per person.</span>' ): ('$' + currentLuckDropConfig.minAvgUsdAmount + ' per person.') }`
-
-            const isAmountForbidden = currentLuckDropConfig?.minTotalUsdAmount ? +math.format(math.evaluate(baseFormData.amountValue * usdPrice)) < currentLuckDropConfig?.minTotalUsdAmount : false;
+            const isAmountForbidden = currentLuckDropConfig?.minTotalUsdAmount ? +math.format(math.multiply(math.bignumber(+baseFormData.amountValue), math.bignumber(usdPrice))) < currentLuckDropConfig?.minTotalUsdAmount : false;
 
             const isAvgForbidden = treasureFormData.fansUnitAmount !== '' && currentLuckDropConfig?.minAvgUsdAmount ? treasureFormData.fansUnitAmount < minAmount || treasureFormData.fansUnitAmount < currentLuckDropConfig?.minAvgUsdAmount : false;
 
@@ -2075,7 +2115,7 @@ const getUserName = (screenName) => {
 const getLocalCurrencyInfoByCode = async () => {
     let storageUserInfo = await getChromeStorage('userInfo') || {};
     userInfo.value = storageUserInfo;
-    getUserName(storageUserInfo.nickName);
+    // getUserName(storageUserInfo.nickName);
     if(!currentCurrencyInfo.value.currencyCode) {
         getCurrencyInfo();
     }
@@ -2135,8 +2175,11 @@ const selectPublishMode = (params, index) => {
         baseFormData.rewardType = RewardType.money;
         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 || ''
     }
 
     onIptSetErrorTxt();
@@ -2158,6 +2201,14 @@ const onToolBoxPageChange = (params) => {
 
 const toolBoxPublishFinish = (params) => {
     toolBoxPageData.activePage = 'EDITOR';
+    Report.reportLog({
+      pageSource: Report.pageSource.previewPage,
+      businessType: Report.businessType.buttonClick,
+      objectType: Report.objectType.previewNextButton,
+      postId: params.publishRes.postId
+    }, {
+      type: Report.getCurrentBizType(PlayType.postEditor)
+    });
     emits("postPublishFinish", { publishRes: params.publishRes });
 }
 
@@ -2234,6 +2285,7 @@ const successImage = (data) => {
 const confirmData = (data) => {
     close()
     customPosterData.value = customPosterInfo.value;
+    previewCustomPosterUrl.value =  customPosterInfo.value && customPosterInfo.value.after && customPosterInfo.value.after.imagePath || ''
 }
 /**
  * 显示通用奖品名称编辑框
@@ -2322,11 +2374,22 @@ const onPageVisbile = () => {
     });
 }
 
+const savePostEditorConfig = () => {
+  getPostEditorConfig({
+    params: {}
+  }).then(res => {
+    if(res.code == 0 && res.data) {
+      setChromeStorage({ postEditorConfig : JSON.stringify(res.data)})
+    }
+  })
+}
+
 onMounted(() => {
     setFrontConfig();
     setPayConfig();
     getLocalCurrencyInfoByCode();
     onPageVisbile();
+    savePostEditorConfig();
     window.addEventListener('resize', function () {
         setDialogStyle(true);
     })
@@ -2489,6 +2552,7 @@ onMounted(() => {
 
                     .form-left-sheet {
                         width: 500px;
+                        height: max-content;
                     }
 
                     .form-right-sheet {

+ 55 - 77
src/view/iframe/publish/tool-box/child/editor.vue

@@ -23,7 +23,7 @@
           <div class="app-list">
             <div class="app" v-for="(app, idx) in historyList" :key="idx" @click="clickHistoryAppHandler(app)">
               <div class="img-wrapper">
-                <img class="img" :class="{ 'small-img': !app.appId }" :src="app.iconPath" :onerror="imgOnError" />
+                <img class="img" :class="{ 'small-img': !app.appId && !app.contentType }" :src="app.iconPath" :onerror="imgOnError" />
               </div>
               <div class="name">
                 {{ app.name }}
@@ -51,10 +51,9 @@
 
 <script setup>
 import { ref, defineProps, defineEmits, onMounted } from "vue";
-import axios from 'axios';
 import Report from "@/log-center/log"
 import { message } from "ant-design-vue";
-import { convertUrl, getAllPostEditorAppData, checkInputUrlInBlacklist } from "@/http/toolBoxApi";
+import { getAllPostEditorAppData, checkInputUrlInBlacklist } from "@/http/toolBoxApi";
 import { setChromeStorage, getChromeStorage } from "@/uilts/chromeExtension"
 import { checkURL, debounce } from "@/uilts/help"
 
@@ -78,9 +77,6 @@ let appList = ref();
 const emits = defineEmits(["changeShowCom"]);
 
 const searchHandler = async (_params) => {
-  let siteTitle = '', favicon = '';
-  let timer = null;
-
   // report
   Report.reportLog({
     pageSource: Report.pageSource.publisherDialog,
@@ -96,35 +92,26 @@ const searchHandler = async (_params) => {
 
   siteUrl.value = siteUrl.value.trim();
 
+  let postEditorConfig  = await getChromeStorage('postEditorConfig') || {};
+
   if (!checkURL(siteUrl.value)) {
     message.info('Incorrect URL entered');
     //提示
     return;
   }
-  const loadingHide = message.loading('loading...', 0);
-  timer = setTimeout(() => {
-    loadingHide();
-    message.error('Page loading failed');
-  }, 1000 * 15);
-
-  if(!_params) {
-    let blackListRes = await checkInputUrlInBlacklist({
-      params: {
-        url: siteUrl.value
-      }
-    })
 
-    if(blackListRes.code == 0) {
-      if(blackListRes.data) {
-        loadingHide();
-        clearTimeout(timer);
-        message.info('This site is not supported');
-        return;
+  if (!_params) {
+    if(postEditorConfig.inputUrlBlackList && postEditorConfig.inputUrlBlackList.length) {
+      for(let i = 0; i < postEditorConfig.inputUrlBlackList.length; i++) {
+        let url =  postEditorConfig.inputUrlBlackList[i];
+        if(siteUrl.value.startsWith(url)) {
+          message.info('This site is not supported');
+          return;
+        }
       }
     }
   }
 
-  let siteRes = await axios.get(siteUrl.value);
 
   let currentApp = {
     appId: '',
@@ -137,61 +124,28 @@ const searchHandler = async (_params) => {
     linkImagePath: '',
     name: '',
   }
+  let urlObj = new URL(siteUrl.value);
 
-  if (siteRes) {
-    if (siteRes.headers['content-type'].indexOf('text/html') < 0 || siteRes.request.status > 403) {
-      loadingHide();
-      message.error('Page loading failed');
-      return;
-    }
-    let urlObj = new URL(siteUrl.value);
-    if (siteRes.data) {
-      siteTitle = getTitleByHtmlStr(siteRes.data);
-      if (!siteTitle) {
-        siteTitle = urlObj.hostname;
-        currentApp.defaultTit = siteTitle;
-      }
-      currentApp.name = siteTitle;
-    }
-    favicon = urlObj.origin + '/favicon.ico';
-  }
-  currentApp.iconPath = favicon;
+  currentApp.iconPath = urlObj.origin + '/favicon.ico';
 
-  if(_params) {
+  if (_params) {
     currentApp = _params;
   }
-  
-  let convertRes = await convertUrl({ params: { originUrl: siteUrl.value } });
-  let params = { convertUrl: siteUrl.value, 
-                  originUrl: siteUrl.value, 
-                  appId: currentApp.appId, 
-                  linkImagePath: currentApp.linkImagePath, 
-                  currentApp };
-
-  loadingHide();
-  clearTimeout(timer);
-
-  if (convertRes && convertRes.code == 0) {
-    let { convertUrl } = convertRes.data || {};
-    params.convertUrl = convertUrl;
-  }
-  emits('changeShowCom', params)
-}
 
-const getTitleByHtmlStr = (str = '') => {
-  let tag_start = '<title>'
-  let tag_end = '</title>'
-  let index1 = str.indexOf(tag_start) + tag_start.length;
-  let index2 = str.indexOf(tag_end);
+  let siteConvertUrl = getConvertUrl({postEditorConfig, siteUrl: siteUrl.value});
 
-  if (index1 < tag_start.length || index2 < 0 || index2 < index1) {
-    return '';
-  }
+  let params = {
+    convertUrl: siteConvertUrl || siteUrl.value,
+    originUrl: siteUrl.value,
+    appId: currentApp.appId,
+    linkImagePath: currentApp.linkImagePath,
+    currentApp
+  };
 
-  return str.substring(index1, index2) || '';
-};
+  emits('changeShowCom', params)
+}
 
-const clickHistoryAppHandler =  debounce(function(params) {
+const clickHistoryAppHandler = debounce(function (params) {
   if (params.appId) {
     clickAppHandler(params, false);
   } else {
@@ -209,7 +163,7 @@ const clickHistoryAppHandler =  debounce(function(params) {
   });
 }, 800);
 
-const clickAppHandler =  debounce(function(params, isReport = true) {
+const clickAppHandler = debounce(function (params, isReport = true) {
   let { createType, defaultUrl, appId, linkImagePath } = params;
   switch (createType) {
     case 1:
@@ -253,10 +207,11 @@ const createGuideWindow = (params, isUpdate = false) => {
   openWindowList = [];
   selectAppGuideData = {};
 
-  let windowWith = window.screen.width - 500;
+  let windowWith = window.screen.width > 800 ? window.screen.width - 500 : 500;
   let guideUrl = chrome.runtime.getURL('/iframe/tool-box-guide.html');
 
-  setChromeStorage({ selectGuideApp : JSON.stringify(params)}, async () => {
+  setChromeStorage({ selectGuideApp: JSON.stringify(params) }, async () => {
+    console.log(windowWith, 'window', window)
     let window1 = await chrome.windows.create({
       width: windowWith,
       type: 'normal',
@@ -269,12 +224,12 @@ const createGuideWindow = (params, isUpdate = false) => {
       width: 500,
       type: 'popup',
       url: guideUrl,
-      left: windowWith,
+      left: window.screen.availLeft > 0 ? windowWith : window.screen.availLeft + windowWith,
       state: 'normal'
     })
     openWindowList.push(window2);
 
-    setChromeStorage({ guideAppWindowList: JSON.stringify({list: openWindowList})});
+    setChromeStorage({ guideAppWindowList: JSON.stringify({ list: openWindowList }) });
 
     // report
     Report.reportLog({
@@ -297,6 +252,29 @@ const getAppList = () => {
   })
 }
 
+const getConvertUrl = (params) => {
+  let {postEditorConfig = {}, siteUrl} = params;
+  const urlConvertConfigList = postEditorConfig.urlConvertConfigList || [];
+  let convertUrl = siteUrl;
+  if(urlConvertConfigList && urlConvertConfigList.length) {
+    for(let i = 0; i < urlConvertConfigList.length; i++) {
+      let urlPattern = urlConvertConfigList[i]['urlPattern'];
+      let reg = new RegExp(urlPattern);
+      let regMatch = siteUrl.match(reg);
+      if(regMatch && regMatch.length) {
+        let count = regMatch.length;
+        let urlConvertFormat = urlConvertConfigList[i]['urlConvertFormat'];
+        for(let j = 1; j < count; j++) {
+          urlConvertFormat = urlConvertFormat.replace(`{group${j}}`, regMatch[j])
+        }
+        convertUrl = urlConvertFormat;
+        break;
+      }
+    }
+  }
+
+  return convertUrl;
+}
 
 const onRuntimeMsg = () => {
   chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {

+ 107 - 12
src/view/iframe/publish/tool-box/child/preview.vue

@@ -49,9 +49,7 @@
                                     {{ previewData.currentApp.linkTitle }}
                                 </template>
                                 <template v-else>
-                                    {{ previewData.currentApp.defaultTit ? defaultLinkTitle :
-                                            previewData.currentApp.name
-                                    }}
+                                    {{ resourceInfo.title }}
                                 </template>
                             </div>
                         </div>
@@ -127,22 +125,60 @@ const props = defineProps({
     hasNft: {
         type: Boolean,
         default: false
+    },
+    resourceInfo: {
+        type: Object,
+        default: () => {
+          return {}
+        }
+    },
+    contentTypeConfig: {
+        type: Object,
+        default: () => {
+          return {
+
+          }
+        }
     }
 })
 
 watch(() => props.screenshotWebsiteData,
     (newVal) => {
         let { appId } = props.previewData;
-        if (loadingHide && (!appId || appId && !props.previewData.linkImagePath) && (newVal.url || newVal.status)) {
-            loadingHide();
-            loadingHide = null;
-            submitPublish();
+        if (loadingHide && (!appId || appId && !props.previewData.linkImagePath) && newVal.status) {
+                console.log(props.resourceInfo, 'resourceInfo')
+            if(appId) {
+              loadingHide();
+              loadingHide = null;
+              submitPublish();
+            } else {
+              if(props.resourceInfo.isSet) {
+                loadingHide();
+                loadingHide = null;
+                submitPublish();
+              }
+            }
         }
     },
     {
         deep: true
     })
 
+watch(() => props.resourceInfo,
+    (newVal) => {
+      console.log(newVal, 'resourceInfo')
+      let { appId } = props.previewData;
+      if (!appId && loadingHide && newVal.isSet && props.screenshotWebsiteData.status) {
+        loadingHide();
+        loadingHide = null;
+        submitPublish();
+      }
+    },
+    {
+        deep: true
+    })
+
+
 watch(() => props.showCom,
     (newVal) => {
         if (newVal == 'EDITOR' && loadingHide) {
@@ -210,11 +246,16 @@ const publishHandler = () => {
     if (loadingHide) {
         return;
     }
-    if ((!appId || appId && !props.previewData.linkImagePath) && (!props.screenshotWebsiteData.url && !props.screenshotWebsiteData.status)) {
+    if ((!appId || appId && !props.previewData.linkImagePath) && !props.screenshotWebsiteData.status) {
         loadingHide = message.loading('loading...', 0);
         return;
     }
 
+    if (!appId && !props.resourceInfo.isSet) {
+      loadingHide = message.loading('loading...', 0);
+      return;
+    }
+
     submitPublish();
 }
 
@@ -225,16 +266,50 @@ const submitPublish = () => {
         return;
     }
 
-    setHistoryData(currentApp);
+    if(!appId) {
+        let allowContentTypes = props.contentTypeConfig.allowContentTypes || [];
+        let isSupport = false;
+
+        if(props.resourceInfo.loadSuccess) {
+          for(let i = 0; i< allowContentTypes.length; i++){
+            let idx = props.resourceInfo.contentType.indexOf(allowContentTypes[i]);
+            if(idx > -1) {
+              isSupport = true;
+              break;
+            }
+          }
+        } else {
+          message.error('Page loading failed');
+          return;
+        }
+
+        if(!isSupport) {
+          message.warning(props.contentTypeConfig.unSupportToast);
+          return;
+        }
+    }
+
+    let linkTitle = props.resourceInfo.title;
 
-    let linkTitle = currentApp.name ? currentApp.name : currentApp.defaultTit;
+    let appData = {
+      ...currentApp
+    }
+    if(!props.resourceInfo.hasTitle) {
+      let contentType = props.resourceInfo.contentType || '';
+      appData.iconPath = props.screenshotWebsiteData.viewBgImageFullPath;
+      appData.contentType = contentType;
+      linkTitle = contentType ? getResourceTitle({contentType}) : '';
+    }
+
+    setHistoryData(appData, {linkTitle: !appId ? linkTitle : '' });
 
     let postBizData = {
         convertUrl,
         originUrl,
         appId,
         linkTitle: !appId ? linkTitle : '',
-        linkImagePath: props.screenshotWebsiteData.url
+        linkImagePath: props.screenshotWebsiteData.url,
+        viewBgImagePath: props.screenshotWebsiteData.viewBgImagePath
     };
     if (props.certNftProjectId !== '') {
         postBizData['certNftProjectId'] = props.certNftProjectId;
@@ -247,6 +322,7 @@ const submitPublish = () => {
         },
     };
 
+    let subLoadingHide = message.loading('loading...', 0);
     submitIng.value = true;
 
     Report.reportLog({
@@ -261,20 +337,39 @@ const submitPublish = () => {
 
     postPublish(data).then((res) => {
         submitIng.value = false;
+        subLoadingHide();
         if (res.code == 0) {
             let publishRes = res.data;
             emits("publishFinish", { publishRes });
         } else {
         }
     }).catch((err) => {
+      subLoadingHide();
       submitIng.value = false;
         console.log(err);
     });
 }
 
-const setHistoryData = async (params) => {
+const getResourceTitle = (params) => {
+  let {contentType} = params;
+  let contentTypeTitleMap = props.contentTypeConfig.contentTypeTitleMap || {};
+  let title = ''
+  for (let key in contentTypeTitleMap) {
+    if(contentType.indexOf(key) > -1) {
+      title = contentTypeTitleMap[key];
+      break;
+    }
+  }
+  return title;
+}
+
+const setHistoryData = async (params, {linkTitle = ''}) => {
     const maxLength = 9;
     let { list = [] } = await getChromeStorage('toolBoxAppHistoryData') || {};
+    if (linkTitle) {
+      params.name = linkTitle;
+    }
+
     if (list.length) {
         let hasSite = list.find(item => item.defaultUrl == params.defaultUrl);
         if (hasSite) {

+ 90 - 5
src/view/iframe/publish/tool-box/index.vue

@@ -8,6 +8,8 @@
             :defaultLinkTitle="pageData.defaultLinkTitle"
             :certNftProjectId="certNftProjectId"
             :hasNft="hasNft"
+            :resourceInfo="resourceInfo"
+            :contentTypeConfig="contentTypeConfig"
             @publishFinish="publishFinish">
             <nft-setting ref="nftSettingDom" @change="changeSetting"></nft-setting>
         </preview>
@@ -15,9 +17,9 @@
 </template>
 
 <script setup>
-import { ref, reactive, watch, defineProps, defineEmits } from "vue";
-
-import { screenshotWebsite } from "@/http/toolBoxApi";
+import { ref, reactive, watch, defineProps, defineEmits, onMounted } from "vue";
+import axios from 'axios';
+import { screenshotWebsite, getContentTypeConfig } from "@/http/toolBoxApi";
 import editor from '@/view/iframe/publish/tool-box/child/editor.vue'
 import preview from '@/view/iframe/publish/tool-box/child/preview.vue'
 import Report from "@/log-center/log"
@@ -71,12 +73,29 @@ let certNftProjectId = ref('')
 
 let screenshotWebsiteData = reactive({
     url: '',
+    viewBgImagePath: '',
+    viewBgImageFullPath: '',
     status: '',
 });
 
 let nftSettingDom = ref(null);
 let hasNft = ref(false);
 
+let contentTypeConfig = ref({
+  allowContentTypes: [],
+  unSupportToast: '',
+  contentTypeTitleMap: {}
+})
+
+let resourceInfo = ref({
+  isSet: false,
+  contentType: '',
+  statusCode: '',
+  title: '',
+  hasTitle: false,
+  loadSuccess: false
+});
+
 const changeShowCom = (params) => {
     showCom.value = 'PREVIEW';
     previewData.convertUrl = params.convertUrl;
@@ -86,7 +105,19 @@ const changeShowCom = (params) => {
     previewData.currentApp = params.currentApp || {};
 
     screenshotWebsiteData.url = '';
+    screenshotWebsiteData.viewBgImagePath = '';
+    screenshotWebsiteData.viewBgImageFullPath = '';
     screenshotWebsiteData.status = '';
+
+    resourceInfo.value = {
+      isSet: false,
+      contentType: '',
+      statusCode: '',
+      title: '',
+      hasTitle: false,
+      loadSuccess: false
+    };
+
     if(!params.appId || params.appId && !params.linkImagePath) {
         screenshotWebsite({
             params: {
@@ -96,8 +127,10 @@ const changeShowCom = (params) => {
             if(showCom.value != 'PREVIEW') {
                 return;
             }
-            if(res.code == 0) {
-                screenshotWebsiteData.url = res.data;
+            if(res.code == 0 && res.data) {
+                screenshotWebsiteData.url = res.data.linkImagePath;
+                screenshotWebsiteData.viewBgImagePath = res.data.viewBgImagePath;
+                screenshotWebsiteData.viewBgImageFullPath = res.data.viewBgImageFullPath;
                 screenshotWebsiteData.status = 1;
             } else {
                 screenshotWebsiteData.status = 1;
@@ -110,9 +143,52 @@ const changeShowCom = (params) => {
         })
     }
 
+    if(!params.appId) {
+      getResourceInfo({url:params.convertUrl});
+    }
+
     emits("onPageChange", {page: showCom.value});
 }
 
+const getResourceInfo = ({url}) => {
+  axios.get(url).then(res => {
+    if(res) {
+      resourceInfo.value.isSet = true;
+      resourceInfo.value.contentType = res.headers['content-type'];
+      resourceInfo.value.statusCode = res.request.status;
+      resourceInfo.value.hasTitle = resourceInfo.value.contentType.indexOf('text/html') > -1 ? true : false;
+      resourceInfo.value.loadSuccess = true;
+
+      let siteTitle = '';
+      if(resourceInfo.value.hasTitle) {
+        siteTitle = getTitleByHtmlStr(res.data);
+        if (!siteTitle) {
+          let urlObj = new URL(url);
+          siteTitle = urlObj.hostname;
+        }
+      }
+      resourceInfo.value.title = siteTitle;
+    }
+
+  }).catch(err => {
+    resourceInfo.value.isSet = true;
+  })
+}
+
+const getTitleByHtmlStr = (str = '') => {
+  let tag_start = '<title>'
+  let tag_end = '</title>'
+  let index1 = str.indexOf(tag_start) + tag_start.length;
+  let index2 = str.indexOf(tag_end);
+
+  if (index1 < tag_start.length || index2 < 0 || index2 < index1) {
+    return '';
+  }
+
+  return str.substring(index1, index2) || '';
+};
+
+
 const publishFinish = (params) => {
     emits("toolBoxPublishFinish", params);
 }
@@ -121,6 +197,15 @@ const changeSetting = (id = '') => {
     certNftProjectId.value = id;
 }
 
+onMounted(() => {
+  getContentTypeConfig({
+    params: {}
+  }).then(res => {
+    if(res.code == 0) {
+      contentTypeConfig.value = res.data;
+    }
+  })
+})
 </script>
 
 <style lang="scss" scoped>

+ 83 - 96
src/view/iframe/red-packet/luck-draw.vue

@@ -200,9 +200,11 @@
                     </div>
                 </div>
             </div>
-            <get-more :reportData="{pageSource: Report.pageSource.received_success_page,
-                                    postId: state.postId
-                                    }"></get-more>
+            <get-more :reportData="{
+                pageSource: Report.pageSource.received_success_page,
+                postId: state.postId,
+                redPacketType: Report.redPacketType.lottery
+            }"></get-more>
         </div>
 
 
@@ -237,7 +239,7 @@
                 validityDuration: state.count_down_time,
                 countDown: state.count_down_time,
                 userInfo: {
-                    nickName: state.detail.postUserInfo.name,
+                    nickName: state.detail.postUserInfo.nickName,
                     avatarUrl: state.detail.postUserInfo.avatarUrl
                 },
                 rewardType: state.detail.rewardType,
@@ -264,9 +266,7 @@
                         <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">
@@ -314,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>
 
             <!-- 没有抽中 -->
@@ -349,10 +349,11 @@
                     <img :src="require('@/assets/svg/icon-win-time.svg')" alt />
                     <span>{{ state.count_down_time || '' }}</span>
                 </div>
-                <get-more :style_type="2"
-                          :reportData="{pageSource: Report.pageSource.waitingLotteryPage,
-                                        postId: state.postId
-                                      }"></get-more>
+                <get-more :style_type="2" :reportData="{
+                    pageSource: Report.pageSource.waitingLotteryPage,
+                    postId: state.postId,
+                    redPacketType: Report.redPacketType.lottery
+                }"></get-more>
                 <div class="notification_switch" v-if="state.notification_show">
                     <span>Announcement Notification</span>
                     <a-switch v-model:checked="state.notification_switch" @change="changeNotification" />
@@ -410,8 +411,9 @@
                 </div>
             </div>
             <get-more :reportData="{
-              pageSource: Report.pageSource.missingLotteryPage,
-              postId: state.postId
+                pageSource: Report.pageSource.missingLotteryPage,
+                postId: state.postId,
+                redPacketType: Report.redPacketType.lottery
             }" v-if="state.close_status != '等待结果'"></get-more>
         </div>
 
@@ -434,7 +436,7 @@
         </div>
 
         <div v-show="state.loading_redbag" class="redbag">
-            <img :src="require('@/assets/img/icon-loading-redbag.gif')" alt />
+            <img :src="require('@/assets/img/icon-loading-redbag.png')" alt />
         </div>
 
     </div>
@@ -457,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 } 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'
@@ -468,6 +470,7 @@ import { getInviteGuildInfo } from "@/http/discordApi";
 import GlobalTip from '@/view/components/global-tip.vue';
 import customCardCover from '@/view/components/custom-card-cover.vue';
 import { RewardType, PlayType } from "@/types";
+import denet from '@/denet'
 
 var moment = require('moment');
 
@@ -577,13 +580,8 @@ async function clickLikeBtn() {
             break
         case '3':
             state.loading_show = true
-            chrome.tabs.getCurrent((tab) => {
-                chrome.tabs.sendMessage(tab.id, {
-                    actionType: "IFRAME_TWITTER_API_DO_TASK", task_data: {
-                        tweet_Id: state.tweetId
-                    }, task_type: 'like'
-                }, (res) => { console.log(res) });
-            })
+            let likeRes = await denet.content.doTask.like({ tweetId: state.tweetId });
+            likeRes && doTaskReport({...likeRes, task_type: 'like', do_type: 'api'}, {tab: {}});
             break
         default:
             window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
@@ -603,7 +601,7 @@ async function clickLikeBtn() {
     });
 }
 function clickDone() {
-    window.open(`${chrome.runtime.getURL('/iframe/home.html')}`)
+    window.open(`${chromeExtensionUrl + ('iframe/home.html')}`)
     // 埋点
     Report.reportLog({
         objectType: Report.objectType.wallet_button,
@@ -694,13 +692,8 @@ async function clickRetweetBtn() {
             break
         case '3':
             state.loading_show = true
-            chrome.tabs.getCurrent((tab) => {
-                chrome.tabs.sendMessage(tab.id, {
-                    actionType: "IFRAME_TWITTER_API_DO_TASK", task_data: {
-                        tweet_Id: state.tweetId
-                    }, task_type: 'retweet'
-                }, (res) => { console.log(res) });
-            })
+            let retweetRes = await denet.content.doTask.reTweet({ tweetId: state.tweetId });
+            retweetRes && doTaskReport({...retweetRes, task_type: 'retweet', do_type: 'api'}, {tab: {}});
             break
         default:
             window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
@@ -723,6 +716,7 @@ async function clickRetweetBtn() {
 function onTweetReplyClick(params) {
     let replyData = {
         postId: state.postId,
+        iframeId: state.iframeId,
         type: params.type,
         taskLuckdropId: state.detail.taskLuckdropId
     }
@@ -759,6 +753,7 @@ async function clickReply(params) {
 
     let replyData = {
         postId: state.postId,
+        iframeId: state.iframeId,
         type: params.type,
         taskLuckdropId: state.detail.taskLuckdropId
     }
@@ -848,7 +843,8 @@ function feacebookShareUrl(params = {}) {
     let { href = '', type = '', taskLuckdropId } = params;
     let cbParams = JSON.stringify({
         type,
-        taskLuckdropId
+        taskLuckdropId,
+        iframeId: state.iframeId
     })
     let shareUrl = `https://www.facebook.com/dialog/share?app_id=${facebookAppConfig.facebookAppId}&display=popup&href=${href}&redirect_uri=${facebookAppConfig.faceShareRedirectUrl}?params=${cbParams}`;
 
@@ -1010,16 +1006,20 @@ async function clickFollowAll(item, is_all) {
             arr_name.forEach((item) => {
                 follow_data.push(item)
             })
-            state.loading_show = true
-            chrome.tabs.getCurrent((tab) => {
-                chrome.tabs.sendMessage(tab.id, {
-                    actionType: "IFRAME_TWITTER_API_DO_TASK",
-                    task_data: {
-                        tweet_Id: state.tweetId,
-                        follow_data: follow_data,
-                    },
-                    task_type: 'follow'
-                }, (res) => { console.log(res) });
+            state.loading_show = true;
+            let promiseList = [];
+            for (let i = 0; i < follow_data.length; i++) {
+                promiseList[i] = denet.content.doTask.follows({ follow_name: follow_data[i]['name'], twitterUserId: follow_data[i]['twitterUserId'] });
+            }
+
+            Promise.allSettled(promiseList).then((res) => {
+                if (res && res.length) {
+                    let resList = res.filter(item => item.status == 'fulfilled');
+                    for (let i = 0; i < resList.length; i++) {
+                      let item = resList[i].value;
+                      item && doTaskReport({...item, task_type: 'follow', task_data: {follow_name: item.follow_name}, do_type: 'api'}, {tab: {}});
+                    }
+                }
             })
 
             break
@@ -1070,15 +1070,38 @@ const reSetBindTwtterId = (_params) => {
     })
 }
 
-const reportBindTweetSuccess = (params) => {
+const reportBindTweetSuccess = async (params) => {
     let { discordTask, srcUserId } = params || {};
     discordTaskDetail = discordTask;
-    sendChromeTabMessage({
-        actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
-        data: {
-            screen_name: srcUserId
-        }
-    })
+
+    let {user = {}} = await denet.content.getData.getUserInfoByName({ screen_name: srcUserId });
+    if (user && user.result && user.result.legacy) {
+      let legacy = user.result.legacy;
+      reportParams.twitterFans = legacy ? legacy.followers_count : 0;
+
+      if (!discordTaskDetail) {
+          if (reportParams.hasReport) return;
+          reportParams.hasReport = true;
+          Report.reportLog({
+              objectType: Report.objectType.tweetPostBinded,
+              twitterFans: reportParams.twitterFans,
+              redPacketType: 1,
+              postId: state.postId
+          });
+      } else {
+          if (reportParams.discordFans !== '') {
+              if (reportParams.hasReport) return;
+              reportParams.hasReport = true;
+              Report.reportLog({
+                  objectType: Report.objectType.tweetPostBinded,
+                  twitterFans: reportParams.twitterFans,
+                  discordFans: reportParams.discordFans,
+                  redPacketType: 1,
+                  postId: state.postId
+              });
+          }
+      }
+    }
 
     if (discordTask) {
         getDiscordInfo({ inviteUrl: JSON.parse(discordTask.bizData).inviteUrl }, (res) => {
@@ -1452,7 +1475,7 @@ function initTaskDetail(cb) {
 let tab_index = 0
 const doTaskReport = (req, sender) => {
     state.loading_show = false
-    let follow_name = req.task_data.follow_name || ''
+    let follow_name = req.task_data ? req.task_data.follow_name : '';
     // 1 Twitter follow Twitter ScreenName
     // 2 Tweet like
     // 3 Retweet
@@ -1561,6 +1584,8 @@ onMounted(() => {
     state.process_mode = process.env.NODE_ENV
     state.postId = getQueryString('postId')
     state.window_origin = getQueryString('window_origin') || '';
+    state.iframeId = getQueryString('iframeId') || ''
+
     if (state.window_origin.indexOf('twitter.com') > -1) {
         state.tweetId = getQueryString('tweetId')
         state.tweet_author = getQueryString('tweet_author');
@@ -1639,7 +1664,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()
@@ -1961,12 +1986,14 @@ function handleErrorCode(res) {
 //   });
 // }
 function onWindowMessage() {
-    window.addEventListener("message", function (event) {
+    window.onmessage = function (event) {
         if (event.data) {
             switch (event.data.actionType) {
                 case 'CONTENT_RED_PACKET_REPLY_RASK_FINSH':
-                    state.done.reply = true;
-                    state.done.reply_red = false;
+                    if (event.data.data.postId == state.postId) {
+                        state.done.reply = true;
+                        state.done.reply_red = false;
+                    }
                     break;
                 case 'CONTENT_RED_PACKET_GET_TWEET_AUTHOR':
                     fullName = event.data.data.fullName
@@ -1976,7 +2003,7 @@ function onWindowMessage() {
                     break;
             }
         }
-    });
+    }
 }
 
 function onPageVisbile() {
@@ -2005,42 +2032,6 @@ function onRuntimeMsg() {
                 state.loading_show = false
                 doTaskReport(req, sender);
                 break;
-            case 'CONTENT_RED_PACKET_REPLY_RASK_FINSH':
-                if (req.data && req.data.postId == state.postId) {
-                    state.done.reply = true;
-                    state.done.reply_red = false;
-                }
-                break;
-            case 'CONTENT_API_GET_TWEET_USER_INFO_RES':
-                let { user } = req.data || {};
-                if (user && user.result && user.result.legacy) {
-                    let legacy = user.result.legacy;
-                    reportParams.twitterFans = legacy ? legacy.followers_count : 0;
-
-                    if (!discordTaskDetail) {
-                        if (reportParams.hasReport) return;
-                        reportParams.hasReport = true;
-                        Report.reportLog({
-                            objectType: Report.objectType.tweetPostBinded,
-                            twitterFans: reportParams.twitterFans,
-                            redPacketType: 1,
-                            postId: state.postId
-                        });
-                    } else {
-                        if (reportParams.discordFans !== '') {
-                            if (reportParams.hasReport) return;
-                            reportParams.hasReport = true;
-                            Report.reportLog({
-                                objectType: Report.objectType.tweetPostBinded,
-                                twitterFans: reportParams.twitterFans,
-                                discordFans: reportParams.discordFans,
-                                redPacketType: 1,
-                                postId: state.postId
-                            });
-                        }
-                    }
-                }
-                break;
             case 'USER_SETTING':
                 setNotification(req.data)
                 break;
@@ -2168,10 +2159,6 @@ function discordAuth(actionState = 'default') {
                     type: 'normal',
                     url: authorizeUrl
                 }, function (window) {
-                    let windowId = window.id;
-                    callEventPageMethod("RED_PACKET_SAVE_DISCORD_AUTH_WINDOW_ID", {
-                        windowId: windowId
-                    });
                 })
             }
         }
@@ -3385,7 +3372,7 @@ body {
 
 .none {
     display: flex;
-    align-item: center;
+    align-items: center;
     justify-content: center;
     width: 100%;
     height: 100%;

+ 78 - 91
src/view/iframe/red-packet/red-packet.vue

@@ -210,10 +210,11 @@
           </div>
         </div>
       </div>
-      <get-more  :reportData="{
-                    pageSource: Report.pageSource.received_success_page,
-                    postId: state.postId
-                  }" ></get-more>
+      <get-more :reportData="{
+        pageSource: Report.pageSource.received_success_page,
+        postId: state.postId,
+        redPacketType: Report.redPacketType.giveaway
+      }"></get-more>
     </div>
 
 
@@ -245,7 +246,7 @@
         type: PlayType.common,
         validityDuration: state.detail.validityDuration,
         userInfo: {
-          nickName: state.detail.postUserInfo.name,
+          nickName: state.detail.postUserInfo.nickName,
           avatarUrl: state.detail.postUserInfo.avatarUrl
         },
         rewardType: state.detail.rewardType,
@@ -368,9 +369,10 @@
         </div>
       </div>
       <get-more :reportData="{
-                    pageSource: Report.pageSource.expiredPage,
-                    postId: state.postId
-                  }" ></get-more>
+        pageSource: Report.pageSource.expiredPage,
+        postId: state.postId,
+        redPacketType: Report.redPacketType.giveaway
+      }"></get-more>
     </div>
 
 
@@ -392,7 +394,7 @@
     </div>
 
     <div v-show="state.loading_redbag" class="redbag">
-      <img :src="require('@/assets/img/icon-loading-redbag.gif')" alt />
+      <img :src="require('@/assets/img/icon-loading-redbag.png')" alt />
     </div>
 
   </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 } 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'
@@ -423,6 +425,7 @@ import { getInviteGuildInfo } from "@/http/discordApi";
 import GlobalTip from '@/view/components/global-tip.vue'
 import customCardCover from '@/view/components/custom-card-cover.vue';
 import { RewardType, PlayType } from '@/types';
+import denet from '@/denet'
 
 var moment = require('moment');
 
@@ -527,13 +530,9 @@ async function clickLikeBtn() {
       break
     case '3':
       state.loading_show = true
-      chrome.tabs.getCurrent((tab) => {
-        chrome.tabs.sendMessage(tab.id, {
-          actionType: "IFRAME_TWITTER_API_DO_TASK", task_data: {
-            tweet_Id: state.tweetId
-          }, task_type: 'like'
-        }, (res) => { console.log(res) });
-      })
+      let likeRes = await denet.content.doTask.like({ tweetId: state.tweetId });
+      likeRes && doTaskReport({...likeRes, task_type: 'like', do_type: 'api'}, {tab: {}});
+
       break
     default:
       window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
@@ -552,7 +551,7 @@ async function clickLikeBtn() {
   });
 }
 function clickDone() {
-  window.open(`${chrome.runtime.getURL('/iframe/home.html')}`)
+  window.open(`${chromeExtensionUrl + ('iframe/home.html')}`)
   // 埋点
   Report.reportLog({
     objectType: Report.objectType.wallet_button,
@@ -642,13 +641,8 @@ async function clickRetweetBtn() {
       break
     case '3':
       state.loading_show = true
-      chrome.tabs.getCurrent((tab) => {
-        chrome.tabs.sendMessage(tab.id, {
-          actionType: "IFRAME_TWITTER_API_DO_TASK", task_data: {
-            tweet_Id: state.tweetId
-          }, task_type: 'retweet'
-        }, (res) => { console.log(res) });
-      })
+      let retweetRes = await denet.content.doTask.reTweet({ tweetId: state.tweetId });
+      retweetRes && doTaskReport({...retweetRes, task_type: 'retweet', do_type: 'api'}, {tab: {}});
       break
     default:
       window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
@@ -670,6 +664,7 @@ async function clickRetweetBtn() {
 function onTweetReplyClick(params) {
   let replyData = {
     postId: state.postId,
+    iframeId: state.iframeId,
     type: params.type,
     taskLuckdropId: state.detail.taskLuckdropId
   }
@@ -685,6 +680,7 @@ async function clickReply(params) {
 
   let replyData = {
     postId: state.postId,
+    iframeId: state.iframeId,
     type: params.type,
     taskLuckdropId: state.detail.taskLuckdropId
   }
@@ -893,17 +889,20 @@ async function clickFollowAll(item, is_all) {
         follow_data.push(item)
       })
       state.loading_show = true
-      chrome.tabs.getCurrent((tab) => {
-        chrome.tabs.sendMessage(tab.id, {
-          actionType: "IFRAME_TWITTER_API_DO_TASK",
-          task_data: {
-            tweet_Id: state.tweetId,
-            follow_data: follow_data,
-          },
-          task_type: 'follow'
-        }, (res) => { console.log(res) });
-      })
+      let promiseList = [];
+      for (let i = 0; i < follow_data.length; i++) {
+          promiseList[i] = denet.content.doTask.follows({ follow_name: follow_data[i]['name'], twitterUserId: follow_data[i]['twitterUserId'] });
+      }
 
+      Promise.allSettled(promiseList).then((res) => {
+        if (res && res.length) {
+            let resList = res.filter(item => item.status == 'fulfilled');
+            for (let i = 0; i < resList.length; i++) {
+              let item = resList[i].value;
+              item && doTaskReport({...item, task_type: 'follow', task_data: {follow_name: item.follow_name}, do_type: 'api'}, {tab: {}});
+            }
+        }
+      })
       break
     default:
       openFollowTabs(arr_name)
@@ -951,15 +950,37 @@ const reSetBindTwtterId = (_params) => {
   })
 }
 
-const reportBindTweetSuccess = (params) => {
+const reportBindTweetSuccess = async (params) => {
   let { discordTask, srcUserId } = params || {};
   discordTaskDetail = discordTask;
-  sendChromeTabMessage({
-    actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
-    data: {
-      screen_name: srcUserId
+  let {user = {}} = await denet.content.getData.getUserInfoByName({ screen_name: srcUserId });
+  if (user && user.result && user.result.legacy) {
+    let legacy = user.result.legacy;
+    reportParams.twitterFans = legacy ? legacy.followers_count : 0;
+
+    if (!discordTaskDetail) {
+        if (reportParams.hasReport) return;
+        reportParams.hasReport = true;
+        Report.reportLog({
+            objectType: Report.objectType.tweetPostBinded,
+            twitterFans: reportParams.twitterFans,
+            redPacketType: 1,
+            postId: state.postId
+        });
+    } else {
+        if (reportParams.discordFans !== '') {
+            if (reportParams.hasReport) return;
+            reportParams.hasReport = true;
+            Report.reportLog({
+                objectType: Report.objectType.tweetPostBinded,
+                twitterFans: reportParams.twitterFans,
+                discordFans: reportParams.discordFans,
+                redPacketType: 1,
+                postId: state.postId
+            });
+        }
     }
-  })
+  }
 
   if (discordTask) {
     getDiscordInfo({ inviteUrl: JSON.parse(discordTask.bizData).inviteUrl }, (res) => {
@@ -1194,6 +1215,7 @@ function setFrontConfig() {
 };
 
 function init(initParams) {
+  state.loading_show = true;
   let { type } = initParams || {};
   onPageVisbile();
   onWindowMessage();
@@ -1233,6 +1255,7 @@ function init(initParams) {
       handleErrorCode(res)
     }
   }).finally(() => {
+    state.loading_show = false
     state.loading_redbag = false
   })
 }
@@ -1286,7 +1309,8 @@ function initTaskDetail(cb) {
 let tab_index = 0
 const doTaskReport = (req, sender) => {
   state.loading_show = false
-  let follow_name = req.task_data.follow_name || ''
+  let follow_name = req.task_data ? req.task_data.follow_name : '';
+
   // 1 Twitter follow Twitter ScreenName
   // 2 Tweet like
   // 3 Retweet
@@ -1358,6 +1382,7 @@ const doTaskReport = (req, sender) => {
 onMounted(() => {
   state.process_mode = process.env.NODE_ENV
   state.postId = getQueryString('postId')
+  state.iframeId = getQueryString('iframeId') || ''
   state.window_origin = getQueryString('window_origin') || '';
   if (state.window_origin.indexOf('twitter.com') > -1) {
     state.tweetId = getQueryString('tweetId')
@@ -1431,7 +1456,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()
@@ -1480,11 +1505,11 @@ function handleFinishRedPacket() {
     if (res.code == 0) {
       if (res.data.finished) {
         state.receiveAmount = res.data.receiveAmount
-        if (state.receiveAmount == 0) {
-          showRabbitPage()
-        } else {
-          state.status = 'success'
-        }
+        // if (state.receiveAmount == 0) {
+        //   showRabbitPage()
+        // } else {
+        //   state.status = 'success'
+        // }
         init()
         // 埋点
         Report.reportLog({
@@ -1758,8 +1783,10 @@ function onWindowMessage() {
     if (event.data) {
       switch (event.data.actionType) {
         case 'CONTENT_RED_PACKET_REPLY_RASK_FINSH':
-          state.done.reply = true;
-          state.done.reply_red = false;
+          if (event.data.data.postId == state.postId) {
+            state.done.reply = true;
+            state.done.reply_red = false;
+          }
           break;
         case 'CONTENT_RED_PACKET_GET_TWEET_AUTHOR':
           fullName = event.data.data.fullName
@@ -1798,43 +1825,6 @@ function onRuntimeMsg() {
         state.loading_show = false
         doTaskReport(req, sender);
         break;
-      case 'CONTENT_RED_PACKET_REPLY_RASK_FINSH':
-        if (req.data && req.data.postId == state.postId) {
-          state.done.reply = true;
-          state.done.reply_red = false;
-        }
-        break;
-      case 'CONTENT_API_GET_TWEET_USER_INFO_RES':
-        let { user } = req.data || {};
-        if (user && user.result && user.result.legacy) {
-          let legacy = user.result.legacy;
-          reportParams.twitterFans = legacy ? legacy.followers_count : 0;
-
-          if (!discordTaskDetail) {
-            if (reportParams.hasReport) return;
-            reportParams.hasReport = true;
-            Report.reportLog({
-              objectType: Report.objectType.tweetPostBinded,
-              twitterFans: reportParams.twitterFans,
-              redPacketType: 0,
-              postId: state.postId
-            });
-          } else {
-            if (reportParams.discordFans !== '') {
-              if (reportParams.hasReport) return;
-              reportParams.hasReport = true;
-              Report.reportLog({
-                objectType: Report.objectType.tweetPostBinded,
-                twitterFans: reportParams.twitterFans,
-                discordFans: reportParams.discordFans,
-                redPacketType: 0,
-                postId: state.postId
-              });
-            }
-          }
-
-        }
-        break;
     }
     sendResponse && sendResponse();
   })
@@ -1959,10 +1949,6 @@ function discordAuth(actionState = 'default') {
           type: 'normal',
           url: authorizeUrl
         }, function (window) {
-          let windowId = window.id;
-          callEventPageMethod("RED_PACKET_SAVE_DISCORD_AUTH_WINDOW_ID", {
-            windowId: windowId
-          });
         })
       }
     }
@@ -2074,6 +2060,7 @@ body {
     position: fixed;
     top: 0;
     left: 0;
+    user-select: none;
 
     img {
       margin-top: 172px;

+ 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;

+ 24 - 17
src/view/iframe/tool-box/buy-nft.vue

@@ -1,26 +1,22 @@
 <template>
-    <div class="nft-layer">
+    <div class="nft-layer" v-if="nftAuthINfo">
         <div class="title">
-            <img @click="close" :src=" require('@/assets/svg/icon-close.svg') " />
-            <span class="text">Unlock by Ruomeng NFT</span>
+            <img @click="close" :src="require('@/assets/svg/icon-close.svg')" />
+            <span class="text">Unlock by {{ nftAuthINfo.nftProjectName }} NFT</span>
         </div>
         <div class="content">
             <div class="img">
                 <img v-if="nftAuthINfo && nftAuthINfo.icon" :src="nftAuthINfo.icon" />
             </div>
             <div class="tips">
-                <span>only Ruomeng NFT holder can view the content</span>
+                <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;

+ 24 - 18
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.linkImagePath" :src=" state.detail.linkImagePath " />
+                <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: '固定右上角',
@@ -659,11 +660,13 @@ const msgListener = (req, sender, sendResponse) => {
             flex-direction: column;
             width: 100%;
             height: 100%;
-            background-color: rgba($color: #000000, $alpha: .8);
+            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;

+ 14 - 10
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.linkImagePath" :src=" detail.linkImagePath " />
+                <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,
@@ -237,11 +237,13 @@ const hideMask = (data) => {
             flex-direction: column;
             width: 100%;
             height: 100%;
-            background-color: rgba($color: #000000, $alpha: .8);
+            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;

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

@@ -0,0 +1,265 @@
+<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="clickOption" :src="sortTypeIcon" alt="">
+            </div>
+        </div>
+        <receive-list :sortType="sortType"></receive-list>
+    </div>
+</template>
+<script setup>
+import { inject, ref, onMounted } from 'vue'
+import ReceiveList from '@/view/iframe/treasure-hunt/components/receive-list.vue'
+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')
+
+let optionList = ref([
+    {
+        icon: amountIcon,
+        label: 'Amount',
+        type: 2
+    },
+    {
+        icon: timeIcon,
+        label: 'Time',
+        type: 1
+    }
+])
+onMounted(() => {
+    // 埋点
+    Report.reportLog({
+        businessType: Report.businessType.pageView,
+        pageSource: Report.pageSource.who_get_money_page,
+        postId: state.postId,
+        shareLinkId: state.invite_code || '',
+    })
+})
+
+
+let sortType = ref(2);
+
+
+const clickBack = () => {
+    state.page_show = ''
+}
+
+
+
+const clickOption = () => {
+    if (sortType.value == 1) {
+        sortType.value = 2
+    } else if (sortType.value == 2) {
+        sortType.value = 1
+    }
+    // 切换图标
+    sortTypeIcon.value = optionList.value.filter((item) => { return item.type == sortType.value })[0].icon;
+}
+
+</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
+    if (state.boxs[i].openStatus == 0) {
+        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>

+ 20 - 10
src/view/iframe/treasure-hunt/components/btn.vue

@@ -1,6 +1,7 @@
 <template>
     <div :class="{ 'area-btn': disabled }">
-        <div class="btn-submit" @click="clickBtn" :class="{ 'no': loading, 'disabled': disabled }">
+        <div class="btn-submit" @click="clickBtn" :class="{ 'no': loading, 'disabled': disabled }"
+            @mouseenter="mouseItem" @mouseleave="mouseLeaveItem">
             <img :src="require('@/assets/svg/icon-iframe-loading.svg')" alt="" class="loading" v-if="loading && icon" />
             <img :src="require('@/assets/svg/icon-btn-box.svg')" alt="" v-if="!loading && icon" />
             <span :style="{ 'font-size': fontSize, 'color': txtCorlor, 'font-weight': fontWeight }">{{ txt }}</span>
@@ -44,25 +45,34 @@ let props = defineProps({
         type: String
     }
 })
-const emit = defineEmits(['on-click'])
+const emit = defineEmits(['on-click', 'on-mouseEnter', 'on-mouseLeave'])
+
+const mouseItem = () => {
+    if (props.disabled) {
+        emit('on-mouseEnter')
+    }
+}
+
+const mouseLeaveItem = () => {
+    if (props.disabled) {
+        emit('on-mouseLeave')
+    }
+}
 
 const clickBtn = () => {
-    if (!props.disabled) {
+    if (props.disabled == false && props.loading == false) {
         emit('on-click')
     }
 }
 
+
 const refresh = () => {
     if (!refreshRotate.value) {
         refreshRotate.value = true;
         setTimeout(() => {
             refreshRotate.value = false;
         }, 1000)
-
-        state.init(() => {
-            state.inviteInit()
-            state.inviteList()
-        })
+        state.refreshInit()
     }
 }
 </script>
@@ -124,8 +134,8 @@ const refresh = () => {
     }
 
     .disabled {
-        cursor: no-drop;
-        background: rgba(56, 154, 255, 0.2);
+        cursor: default;
+        background: rgba(56, 154, 255, 0.4);
         color: #FFFFFF;
         width: 305px;
         font-weight: 600;

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

@@ -0,0 +1,192 @@
+<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,
+            sortType: 2
+        }
+    }).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 {

+ 370 - 167
src/view/iframe/treasure-hunt/components/invite-friends.vue

@@ -1,227 +1,430 @@
 <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"
-                :data-clipboard-text="state.detail.inviteCopyUrl">
-                Copy
-            </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 class="invite-friends">
+    <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 <span>Real New follower</span> of {{ followUserStr }} to receive rewards
         </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>
+      <div class="invite-friends-content-body">
+        <template v-if="state.share_list_end">
+          <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 v-show="state.share_list_end" class="share-item copy-btn" @click="clickCopy"
+              v-click-log="state.log_invite_copy_btn_click" :data-clipboard-text="state.detail.inviteCopyUrl">
+              <img :src="require('@/assets/svg/icon-copy-url-teasure.svg')" alt="">
+              <div class="name">
+                Copy URL
+              </div>
+            </div>
+          </div>
+        </template>
+        <template v-else>
+          <v-loading></v-loading>
+        </template>
+      </div>
     </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" @onClick="clickBtn" font-weight="600"
+      @onMouseEnter="mouseItem" @onMouseLeave="mouseLeave"></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 VLoading from '@/view/components/loading.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'
+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 = {
-    businessType: Report.businessType.buttonView,
-    pageSource: Report.pageSource.inviteFriendsPage,
-    objectType: Report.objectType.openChestButton,
-    redPacketType: Report.redPacketType.treasure,
-    shareLinkId: state.invite_code,
-    myShareLinkId: state.detail.inviteCopyUrl,
-    currentInvitedNum: state.detail.inviteCount,
-    postId: state.postId
+  businessType: Report.businessType.buttonView,
+  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
 }
 
 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.detail.inviteCount,
-    postId: state.postId
+  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
 }
 state.log_invite_copy_btn_click = {
-    businessType: Report.businessType.buttonClick,
-    pageSource: Report.pageSource.inviteFriendsPage,
-    objectType: Report.objectType.copyButton,
-    redPacketType: Report.redPacketType.treasure,
-    shareLinkId: state.invite_code,
-    myShareLinkId: state.detail.inviteCopyUrl,
-    currentInvitedNum: state.detail.inviteCount,
-    postId: state.postId
+  businessType: Report.businessType.buttonClick,
+  pageSource: Report.pageSource.inviteFriendsPage,
+  objectType: Report.objectType.copyButton,
+  redPacketType: Report.redPacketType.treasure,
+  shareLinkId: state.invite_code,
+  myShareLinkId: state.detail.inviteCopyUrl,
+  currentInvitedNum: state.inviteCount,
+  postId: state.postId
 }
+
+let facebookAppConfig = {
+  facebookAppId: "",
+  faceShareRedirectUrl
+};
+
+let selectShareApp = ref({});
+let showShareTips = ref(false);
+let followUserStr = ref('');
+
 onMounted(() => {
-    state.btn_loading = false
-    try {
-        chrome.management.get('ophjlpahpchlmihnnnihgmmeilfjmjjc', (res) => {
-            let linePluginInstalled = 0
-            if (res) {
-                linePluginInstalled = 1
-            }
-            inviteChannel({
-                params: {
-                    linePluginInstalled,
-                    postId: state.postId
-                }
-            }).then((res) => {
-                if (res.code == 0) {
-                    state.share_list = res.data
-                }
-            })
-        })
-    } catch (error) {
-        console.error(error)
+  state.btn_loading = false
+  setFrontConfig();
+  initInviteChannel();
+  getFollowUserStr();
+})
+
+const mouseItem = () => {
+  if (state.boxs.filter((item) => { return item.openStatus == 0 }).length) {
+    state.active_share_channel = true
+  }
+}
+
+const mouseLeave = () => {
+  state.active_share_channel = false
+}
+
+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()
+})
+chrome.management.onEnabled.addListener(() => {
+  initInviteChannel()
 })
 
-async function clickBtn() {
-    let _userInfo = await state.checkIsLogin()
-    if (!_userInfo) {
+chrome.management.onInstalled.addListener(() => {
+  initInviteChannel()
+})
+chrome.management.onUninstalled.addListener(() => {
+  initInviteChannel()
+})
+
+let linePluginInstalled
+const initInviteChannel = () => {
+  try {
+    chrome.management.get('ophjlpahpchlmihnnnihgmmeilfjmjjc', (res) => {
+      if ((res && linePluginInstalled == 1) || (!res && linePluginInstalled == 0)) {
         return
-    }
-    state.btn_loading = true
-    state.treasureOpen()
+      }
+      if (res) {
+        linePluginInstalled = 1
+      } else {
+        linePluginInstalled = 0
+      }
+
+      inviteChannel({
+        params: {
+          linePluginInstalled,
+          postId: state.postId
+        }
+      }).then((res) => {
+        if (res.code == 0) {
+          state.share_list = res.data
+          state.share_list_end = true
+        }
+      })
+    })
+  } catch (error) {
+    console.error(error)
+  }
+}
+
+async function clickBtn() {
+  let _userInfo = await state.checkIsLogin()
+  if (!_userInfo) {
+    return
+  }
+  state.btn_loading = true
+  state.treasureOpen()
+  // 埋点
+  Report.reportLog(state.log_invite_btn_click)
 }
 
 const clickShare = (item) => {
-    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)
-        e.clearSelection();
+  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)
+    e.clearSelection();
+  })
+  showShareTips.value = true;
+  selectShareApp.value = item;
+
+  if (item.name == 'facebook') {
+    setChromeStorage({
+      shareFacebookData: JSON.stringify({
+        contentStr: item.inviteContent
+      })
     })
-    chrome.tabs.create({
+    let cbParams = {
+      bizType: 'TEASURE_INVITE'
+    }
+    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)}`;
+
+    setTimeout(() => {
+      showShareTips.value = false;
+      chrome.windows.create({
+        width: 800,
+        type: 'normal',
+        url
+      }, function (window) {
+      })
+    }, 1000)
+
+  } else {
+    setTimeout(() => {
+      showShareTips.value = false;
+      channelLoadingImg.value = '';
+      chrome.tabs.create({
         url: item.redirectPath
-    });
-    let strArr = item.treasureInviteUrl.split('/');
-    let channelName = window.atob(strArr[strArr.length-1]);
-    Report.reportLog({
-      businessType: Report.businessType.buttonClick,
-      pageSource: Report.pageSource.inviteFriendsPage,
-      objectType: Report.objectType.channelButton,
-      shareLinkId: state.invite_code,
-      myShareLinkId: state.detail.inviteCopyUrl,
-      currentInvitedNum: state.detail.inviteCount,
-    }, {
-      'channel-name': channelName
-    });
+      });
+    }, 1000)
+  }
+  Report.reportLog({
+    businessType: Report.businessType.buttonClick,
+    pageSource: Report.pageSource.inviteFriendsPage,
+    objectType: Report.objectType.channelButton,
+    shareLinkId: state.invite_code,
+    myShareLinkId: state.detail.inviteCopyUrl,
+    currentInvitedNum: state.inviteCount,
+    postId: state.postId,
+    redPacketType: Report.redPacketType.treasure
+  }, {
+    'channel-name': item.name
+  });
 }
 
+const setFrontConfig = () => {
+  getFrontConfig({
+    params: {},
+  }).then((res) => {
+    if (res.code == 0) {
+      facebookAppConfig.facebookAppId = res.data.fbClientId;
+    }
+  });
+};
+
+
 
 const clickCopy = () => {
-    var clipboard = new ClipboardJS('.copy-btn');
-    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)
-        e.clearSelection();
-    })
+  var clipboard = new ClipboardJS('.copy-btn');
+  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)
+    e.clearSelection();
+  })
 
-    clipboard.on('error', function (e) {
-        state.toast.txt = 'Copy Error'
-        state.toast.has_icon = false
-        state.toast.show = true
-        setTimeout(() => {
-            state.toast.show = false
-        }, 2000)
-    })
+  clipboard.on('error', function (e) {
+    state.toast.txt = 'Copy Error'
+    state.toast.has_icon = false
+    state.toast.show = true
+    setTimeout(() => {
+      state.toast.show = false
+    }, 2000)
+  })
 }
 </script>
 <style lang="scss" scoped>
 .invite-friends {
-    padding: 18px 16px 25px 16px;
-    background: #fff;
+  padding: 9px 14px 14px 14px;
+  background: #fff;
+  box-sizing: border-box;
+
+  .invite-friends-content {
+    height: 238px;
+    overflow-y: hidden;
+    margin-bottom: 10px;
+    box-sizing: border-box;
 
-    .txt {
-        font-style: normal;
-        font-weight: 500;
-        font-size: 13px;
-        line-height: 18px;
-        /* or 129% */
-        margin-bottom: 18.5px;
+    .invite-friends-content-head {
+      margin-bottom: 14px;
+      padding: 0 6px;
+      box-sizing: border-box;
 
-        letter-spacing: 0.3px;
+      .title {
+        font-weight: 900;
+        font-size: 18px;
+        margin-bottom: 7px;
+      }
+
+      .info {
+        font-weight: 400;
+        font-size: 12px;
+        color: #7A7A7A;
+        line-height: 15px;
+
+        span {
+          font-weight: 800;
+          font-size: 12px;
+          line-height: 15px;
+          color: #000000;
+        }
+      }
 
-        color: #000000;
     }
 
-    .area-url {
-        height: 70px;
-        background: rgba(29, 155, 240, 0.01);
-        border: 1px solid #1D9BF0;
-        border-radius: 5px;
+    .invite-friends-content-body {
+      position: relative;
+      height: 159px;
+      overflow: hidden;
+
+      .tips {
+        position: absolute;
+        top: -42px;
+        left: 0;
+        width: 146px;
+      }
+
+      .share-list-active {
+        background: rgba(29, 155, 240, 0.1);
+        border: 1.5px solid #1D9BF0 !important;
+        border-radius: 10px;
+      }
+
+      .share-list {
         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;
+        flex-wrap: wrap;
+        width: 100%;
+        box-sizing: border-box;
+        border: 1.5px solid #fff;
+        overflow: hidden;
 
-            color: #737373;
-            font-weight: 400;
-            font-size: 13px;
-            white-space: normal;
+        .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;
 
-            word-wrap: break-word;
 
-            word-break: break-all;
-        }
+          cursor: pointer;
+
+          img {
+            width: 40px;
+            height: 40px;
+            border-radius: 100px;
+            margin-bottom: 8px;
+          }
 
-        .btn {
-            user-select: none;
-            background: #1D9BF0;
-            border-radius: 35px;
-            width: 100px;
+          .name {
+            font-weight: 400;
+            font-size: 12px;
+            color: #898989;
+            width: 100%;
+            overflow: hidden;
+            text-overflow: ellipsis; //文本溢出显示省略号
+            white-space: nowrap;
             text-align: center;
-            line-height: 37px;
-            height: 37px;
-            font-weight: 700;
-            font-size: 15px;
-            color: #fff;
-            cursor: pointer;
+          }
         }
-    }
 
-    .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;
+        .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>

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels