浏览代码

add repack page

jihuaqiang 2 年之前
父节点
当前提交
7434a21acb
共有 92 个文件被更改,包括 8378 次插入273 次删除
  1. 7 1
      package.json
  2. 二进制
      src/assets/img/icon-box2.png
  3. 二进制
      src/assets/img/icon-card-cover-treasure-big.png
  4. 二进制
      src/assets/img/icon-flash-active.png
  5. 二进制
      src/assets/img/icon-gold-close-box.png
  6. 二进制
      src/assets/img/icon-gold-open-box-big.png
  7. 二进制
      src/assets/img/icon-gold-open-box.png
  8. 二进制
      src/assets/img/icon-loading-channel.png
  9. 二进制
      src/assets/img/icon-loading-redbag.png
  10. 二进制
      src/assets/img/icon-purple-close-box.png
  11. 二进制
      src/assets/img/icon-purple-open-big.png
  12. 二进制
      src/assets/img/icon-purple-open-box.png
  13. 二进制
      src/assets/img/icon-silver-close-box.png
  14. 二进制
      src/assets/img/icon-silver-open-box-big.png
  15. 二进制
      src/assets/img/icon-silver-open-box.png
  16. 二进制
      src/assets/img/icon-treasure-box.png
  17. 二进制
      src/assets/img/img-preview-treasure-link-bg.png
  18. 3 0
      src/assets/svg/icon-back-2.svg
  19. 2 0
      src/assets/svg/icon-big-treasure.svg
  20. 2 0
      src/assets/svg/icon-btn-box.svg
  21. 2 0
      src/assets/svg/icon-card-cover-treasure-small.svg
  22. 1 0
      src/assets/svg/icon-card-cover-treasure-tasks.svg
  23. 2 0
      src/assets/svg/icon-channel-tips.svg
  24. 16 0
      src/assets/svg/icon-copy-url-teasure.svg
  25. 1 0
      src/assets/svg/icon-create-nfts.svg
  26. 3 0
      src/assets/svg/icon-custom-cover-btn.svg
  27. 3 0
      src/assets/svg/icon-form-amount.svg
  28. 4 0
      src/assets/svg/icon-form-cost.svg
  29. 3 0
      src/assets/svg/icon-form-custom-cover.svg
  30. 1 0
      src/assets/svg/icon-form-follow.svg
  31. 3 0
      src/assets/svg/icon-form-task.svg
  32. 8 0
      src/assets/svg/icon-form-time.svg
  33. 1 0
      src/assets/svg/icon-form-winners.svg
  34. 4 0
      src/assets/svg/icon-green-yes.svg
  35. 3 0
      src/assets/svg/icon-invite-list.svg
  36. 1 0
      src/assets/svg/icon-invite.svg
  37. 13 0
      src/assets/svg/icon-invited-more.svg
  38. 4 0
      src/assets/svg/icon-loading-channel.svg
  39. 3 0
      src/assets/svg/icon-post-edit-luck.svg
  40. 3 0
      src/assets/svg/icon-post-edit-open.svg
  41. 4 0
      src/assets/svg/icon-post-lock.svg
  42. 3 0
      src/assets/svg/icon-refresh-treasure.svg
  43. 5 0
      src/assets/svg/icon-silver-open-box.svg
  44. 1 0
      src/assets/svg/icon-small-treasure.svg
  45. 4 0
      src/assets/svg/icon-sort-amount.svg
  46. 4 0
      src/assets/svg/icon-sort-time.svg
  47. 1 0
      src/assets/svg/icon-three-line.svg
  48. 3 0
      src/assets/svg/icon-tip-arrow.svg
  49. 5 0
      src/assets/svg/icon-transaction-s.svg
  50. 4 0
      src/assets/svg/icon-treasure-return.svg
  51. 5 0
      src/assets/svg/icon-user1.svg
  52. 3 0
      src/assets/svg/icon-while-user.svg
  53. 3 0
      src/assets/svg/icon-while-yes.svg
  54. 0 19
      src/assets/svg/img-A0.svg
  55. 0 19
      src/assets/svg/img-A1.svg
  56. 0 44
      src/assets/svg/img-B0.svg
  57. 0 44
      src/assets/svg/img-B1.svg
  58. 3 0
      src/assets/svg/img-LT0.svg
  59. 3 0
      src/assets/svg/img-LT1.svg
  60. 3 0
      src/assets/svg/img-P1.svg
  61. 3 0
      src/assets/svg/img-P2.svg
  62. 3 0
      src/assets/svg/img-P3.svg
  63. 2 0
      src/assets/svg/img-T0.svg
  64. 2 0
      src/assets/svg/img-T1.svg
  65. 11 0
      src/assets/svg/img-preview-treasure-01-bg.svg
  66. 0 58
      src/components/HelloWorld.vue
  67. 61 0
      src/components/component-zoom.vue
  68. 605 0
      src/components/custom-card-cover.vue
  69. 52 0
      src/components/font-amount.vue
  70. 46 0
      src/components/font-zoom.vue
  71. 142 0
      src/components/get-more.vue
  72. 58 0
      src/components/global-tip.vue
  73. 2 2
      src/http/configAPI.js
  74. 31 0
      src/log-center/autoLog/click.js
  75. 23 0
      src/log-center/autoLog/index.js
  76. 50 0
      src/log-center/autoLog/show.js
  77. 9 0
      src/log-center/log.js
  78. 165 0
      src/log-center/logEnum.js
  79. 120 0
      src/log-center/logger.js
  80. 19 0
      src/main.js
  81. 12 0
      src/pages/red-packet/index.vue
  82. 3489 0
      src/pages/red-packet/luck-draw.vue
  83. 2926 0
      src/pages/red-packet/red-packet.vue
  84. 10 3
      src/pages/tab-group.vue
  85. 5 0
      src/router/index.js
  86. 50 0
      src/types/global.js
  87. 1 0
      src/types/index.js
  88. 41 12
      src/uilts/chromeExtension.js
  89. 3 1
      src/uilts/help.js
  90. 78 65
      src/uilts/messageCenter/index.js
  91. 2 1
      src/uilts/messageCenter/messageEnum.js
  92. 210 4
      yarn.lock

+ 7 - 1
package.json

@@ -11,10 +11,14 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@sentry/tracing": "^7.12.0",
+    "@sentry/vue": "^7.12.0",
     "@vue/composition-api": "^1.7.0",
+    "ant-design-vue": "^2.2.8",
     "axios": "^0.27.2",
     "core-js": "^3.8.3",
     "element-plus": "2.1.10",
+    "moment": "^2.29.4",
     "vue": "^3.2.13",
     "vue-router": "^4.1.2"
   },
@@ -42,7 +46,9 @@
       "parser": "@babel/eslint-parser"
     },
     "rules": {
-      "no-undef": 0
+      "no-undef": 0,
+      "no-unused-vars": 0,
+      "vue/multi-word-component-names": "off"
     }
   },
   "browserslist": [

二进制
src/assets/img/icon-box2.png


二进制
src/assets/img/icon-card-cover-treasure-big.png


二进制
src/assets/img/icon-flash-active.png


二进制
src/assets/img/icon-gold-close-box.png


二进制
src/assets/img/icon-gold-open-box-big.png


二进制
src/assets/img/icon-gold-open-box.png


二进制
src/assets/img/icon-loading-channel.png


二进制
src/assets/img/icon-loading-redbag.png


二进制
src/assets/img/icon-purple-close-box.png


二进制
src/assets/img/icon-purple-open-big.png


二进制
src/assets/img/icon-purple-open-box.png


二进制
src/assets/img/icon-silver-close-box.png


二进制
src/assets/img/icon-silver-open-box-big.png


二进制
src/assets/img/icon-silver-open-box.png


二进制
src/assets/img/icon-treasure-box.png


二进制
src/assets/img/img-preview-treasure-link-bg.png


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

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

文件差异内容过多而无法显示
+ 2 - 0
src/assets/svg/icon-big-treasure.svg


文件差异内容过多而无法显示
+ 2 - 0
src/assets/svg/icon-btn-box.svg


文件差异内容过多而无法显示
+ 2 - 0
src/assets/svg/icon-card-cover-treasure-small.svg


文件差异内容过多而无法显示
+ 1 - 0
src/assets/svg/icon-card-cover-treasure-tasks.svg


文件差异内容过多而无法显示
+ 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>

文件差异内容过多而无法显示
+ 1 - 0
src/assets/svg/icon-create-nfts.svg


+ 3 - 0
src/assets/svg/icon-custom-cover-btn.svg

@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M17.8749 11.7838L17.1198 12.5169L15.6097 11.0508L16.3648 10.3177C16.4403 10.2444 16.5158 10.1711 16.6668 10.1711C16.7423 10.1711 16.8933 10.2444 16.9688 10.3177L17.9504 11.2707C18.0259 11.4173 18.0259 11.6372 17.8749 11.7838ZM10.5507 15.8891V17.4286H12.1364L16.7423 12.9568L15.2321 11.4906L10.5507 15.8891ZM16.5913 4.96617C16.5913 4.15977 15.9117 3.5 15.0811 3.5H4.51014C3.67956 3.5 3 4.15977 3 4.96617V15.2293C3 16.0357 3.67956 16.6955 4.51014 16.6955H9.04057V15.3026L9.87115 14.4962H4.51014L7.15289 11.1974L9.04057 13.3966L11.6833 10.0977L12.8914 11.6372L16.5913 7.9718V4.96617Z" fill="#2F2F2F"/>
+</svg>

+ 3 - 0
src/assets/svg/icon-form-amount.svg

@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 12.0058V13.5734C4 14.8694 6.6875 15.9231 10 15.9231C13.3125 15.9231 16 14.8694 16 13.5734V12.0058C14.7094 13.0741 12.35 13.5734 10 13.5734C7.65 13.5734 5.29062 13.0741 4 12.0058ZM4 8.15454V10.049C4 11.3449 6.6875 12.3986 10 12.3986C13.3125 12.3986 16 11.3449 16 10.049V8.15454C14.7094 9.4028 12.3469 10.049 10 10.049C7.65313 10.049 5.29062 9.4028 4 8.15454ZM10 3C6.6875 3 4 4.31434 4 5.93706C4 7.55979 6.6875 8.87413 10 8.87413C13.3125 8.87413 16 7.55979 16 5.93706C16 4.31434 13.3125 3 10 3Z" fill="#2F2F2F"/>
+</svg>

+ 4 - 0
src/assets/svg/icon-form-cost.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M11 13.575V14.5455C11 15.3477 12.5677 16 14.5 16C16.4323 16 18 15.3477 18 14.5455V13.575C17.2471 14.2364 15.8708 14.5455 14.5 14.5455C13.1292 14.5455 11.7529 14.2364 11 13.575ZM11 11.1909V12.3636C11 13.1659 12.5677 13.8182 14.5 13.8182C16.4323 13.8182 18 13.1659 18 12.3636V11.1909C17.2471 11.9636 15.869 12.3636 14.5 12.3636C13.131 12.3636 11.7529 11.9636 11 11.1909ZM14.5 8C12.5677 8 11 8.81364 11 9.81818C11 10.8227 12.5677 11.6364 14.5 11.6364C16.4323 11.6364 18 10.8227 18 9.81818C18 8.81364 16.4323 8 14.5 8Z" fill="#2F2F2F"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5.42061 15.1282H5.4046C5.36893 15.2284 5.31128 15.3204 5.23468 15.397C5.09904 15.5326 4.91508 15.6088 4.72326 15.6088C4.53144 15.6088 4.34747 15.5326 4.21184 15.397C4.0762 15.2614 4 15.0774 4 14.8856C4 14.8202 4.01049 14.7614 4.02325 14.7114C4.33797 12.5974 5.72065 10.833 7.60544 9.98625C6.73631 9.26192 6.18262 8.1708 6.18262 6.95024C6.18262 4.76854 7.95117 3 10.1329 3C11.9921 3 13.5513 4.28442 13.9716 6.01437C13.5574 6.03701 13.1526 6.08619 12.7643 6.16045C12.6313 5.7191 12.3901 5.32421 12.0716 5.00682C12.3898 5.32432 12.6308 5.71925 12.7636 6.16059C12.6833 6.17595 12.6037 6.19239 12.5248 6.20988C12.2083 5.18971 11.2556 4.44651 10.1329 4.44651C8.75252 4.44651 7.62914 5.5699 7.62914 6.95024C7.62914 7.92308 8.18723 8.76842 9 9.18266V11.0304C7.15844 11.4847 5.73735 13.02 5.45165 14.9216L5.42061 15.1282ZM4.24375 14.8867C4.24375 15.0139 4.29418 15.1359 4.38397 15.226L4.38341 15.2254C4.29328 15.1353 4.24264 15.013 4.24264 14.8856C4.24264 14.842 4.25033 14.8004 4.26132 14.7602C4.56633 12.6796 5.9484 10.9491 7.82382 10.1557C7.91323 10.1179 8.00376 10.0822 8.09535 10.0487L8.09682 10.0497C6.08391 10.7858 4.582 12.5814 4.26243 14.7613C4.25144 14.8016 4.24375 14.8432 4.24375 14.8867Z" fill="#2F2F2F"/>
+</svg>

+ 3 - 0
src/assets/svg/icon-form-custom-cover.svg

@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M17.8749 11.7838L17.1198 12.5169L15.6097 11.0508L16.3648 10.3177C16.4403 10.2444 16.5158 10.1711 16.6668 10.1711C16.7423 10.1711 16.8933 10.2444 16.9688 10.3177L17.9504 11.2707C18.0259 11.4173 18.0259 11.6372 17.8749 11.7838ZM10.5507 15.8891V17.4286H12.1364L16.7423 12.9568L15.2321 11.4906L10.5507 15.8891ZM16.5913 4.96617C16.5913 4.15977 15.9117 3.5 15.0811 3.5H4.51014C3.67956 3.5 3 4.15977 3 4.96617V15.2293C3 16.0357 3.67956 16.6955 4.51014 16.6955H9.04057V15.3026L9.87115 14.4962H4.51014L7.15289 11.1974L9.04057 13.3966L11.6833 10.0977L12.8914 11.6372L16.5913 7.9718V4.96617Z" fill="#2F2F2F"/>
+</svg>

文件差异内容过多而无法显示
+ 1 - 0
src/assets/svg/icon-form-follow.svg


+ 3 - 0
src/assets/svg/icon-form-task.svg

@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M4.267 4.82609L4.27273 15.7875L15.7324 15.7826L15.7273 4.82122L13.8182 4.82609V5.4287C13.819 5.75195 13.6858 6.06233 13.4476 6.29171C13.2095 6.52109 12.886 6.65072 12.548 6.65217H7.452C6.75136 6.65217 6.18182 6.10313 6.18182 5.4287V4.82609H4.267ZM12.548 5.43478L12.5455 4.22348L7.452 4.21739L7.45455 4.22348V5.4287L12.548 5.43478ZM13.64 3.6087H15.7241C16.0613 3.60789 16.3851 3.73512 16.6243 3.96246C16.8635 4.1898 16.9987 4.49866 17 4.82122V15.7875C16.9995 16.1089 16.8658 16.417 16.6282 16.6443C16.3905 16.8716 16.0684 16.9995 15.7324 17H4.26764C3.56891 17 3 16.4558 3 15.7875V4.82122C3.00017 4.49979 3.13369 4.19157 3.37124 3.96423C3.6088 3.73689 3.93096 3.60902 4.267 3.6087H6.36C6.58082 3.24591 6.98491 3 7.452 3H12.548C13.0151 3 13.4198 3.24652 13.64 3.6087ZM9.17585 11.4432L11.9743 8.20321C12.0799 8.08088 12.2271 8.00801 12.3835 8.00062C12.5399 7.99324 12.6926 8.05195 12.8081 8.16383C12.9236 8.27572 12.9924 8.43162 12.9994 8.59723C13.0064 8.76285 12.951 8.92461 12.8453 9.04694L9.60606 12.7969C9.49393 12.9263 9.33577 13 9.17054 13H9.167C9.08447 12.9995 9.00296 12.9806 8.92774 12.9447C8.85252 12.9087 8.78526 12.8565 8.7303 12.7913L7.14992 10.9163C7.04568 10.7926 6.99209 10.6302 7.00095 10.4647C7.0098 10.2992 7.08037 10.1442 7.19713 10.0338C7.31389 9.92341 7.46727 9.86665 7.62354 9.87603C7.77981 9.88541 7.92616 9.96014 8.0304 10.0838L9.17585 11.4432Z" fill="#2F2F2F"/>
+</svg>

+ 8 - 0
src/assets/svg/icon-form-time.svg

@@ -0,0 +1,8 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<mask id="path-1-outside-1_24371_182246" maskUnits="userSpaceOnUse" x="2" y="2" width="16" height="16" fill="black">
+<rect fill="white" x="2" y="2" width="16" height="16"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M3 10C3 6.14 6.14 3 10 3C13.86 3 17 6.14 17 10C17 13.86 13.86 17 10 17C6.14 17 3 13.86 3 10ZM4.0045 10C4.0045 13.3055 6.694 15.9955 10 15.9955C13.3055 15.9955 15.9955 13.3055 15.9955 10C15.9955 6.694 13.3055 4.0045 10 4.0045C6.694 4.0045 4.0045 6.694 4.0045 10ZM10.001 9.99788H12.5005C12.778 9.99788 13.0025 10.2204 13.0025 10.4979C13.0025 10.7754 12.778 10.9979 12.5005 10.9979H9.50104C9.22404 10.9979 9.00104 10.7754 9.00104 10.4979V6.49887C9.00104 6.22187 9.22354 5.99688 9.50104 5.99688C9.77854 5.99688 10.001 6.22137 10.001 6.49887V9.99788Z"/>
+</mask>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M3 10C3 6.14 6.14 3 10 3C13.86 3 17 6.14 17 10C17 13.86 13.86 17 10 17C6.14 17 3 13.86 3 10ZM4.0045 10C4.0045 13.3055 6.694 15.9955 10 15.9955C13.3055 15.9955 15.9955 13.3055 15.9955 10C15.9955 6.694 13.3055 4.0045 10 4.0045C6.694 4.0045 4.0045 6.694 4.0045 10ZM10.001 9.99788H12.5005C12.778 9.99788 13.0025 10.2204 13.0025 10.4979C13.0025 10.7754 12.778 10.9979 12.5005 10.9979H9.50104C9.22404 10.9979 9.00104 10.7754 9.00104 10.4979V6.49887C9.00104 6.22187 9.22354 5.99688 9.50104 5.99688C9.77854 5.99688 10.001 6.22137 10.001 6.49887V9.99788Z" fill="#2F2F2F"/>
+<path d="M10.001 9.99788H9.80104V10.1979H10.001V9.99788ZM10 2.8C6.02954 2.8 2.8 6.02954 2.8 10H3.2C3.2 6.25046 6.25046 3.2 10 3.2V2.8ZM17.2 10C17.2 6.02954 13.9705 2.8 10 2.8V3.2C13.7495 3.2 16.8 6.25046 16.8 10H17.2ZM10 17.2C13.9705 17.2 17.2 13.9705 17.2 10H16.8C16.8 13.7495 13.7495 16.8 10 16.8V17.2ZM2.8 10C2.8 13.9705 6.02954 17.2 10 17.2V16.8C6.25046 16.8 3.2 13.7495 3.2 10H2.8ZM10 15.7955C6.80447 15.7955 4.2045 13.1951 4.2045 10H3.8045C3.8045 13.4159 6.58353 16.1955 10 16.1955V15.7955ZM15.7955 10C15.7955 13.195 13.195 15.7955 10 15.7955V16.1955C13.416 16.1955 16.1955 13.416 16.1955 10H15.7955ZM10 4.2045C13.1951 4.2045 15.7955 6.80447 15.7955 10H16.1955C16.1955 6.58353 13.4159 3.8045 10 3.8045V4.2045ZM4.2045 10C4.2045 6.80446 6.80446 4.2045 10 4.2045V3.8045C6.58354 3.8045 3.8045 6.58354 3.8045 10H4.2045ZM12.5005 9.79788H10.001V10.1979H12.5005V9.79788ZM13.2025 10.4979C13.2025 10.1089 12.8875 9.79788 12.5005 9.79788V10.1979C12.6686 10.1979 12.8025 10.3319 12.8025 10.4979H13.2025ZM12.5005 11.1979C12.8875 11.1979 13.2025 10.8869 13.2025 10.4979H12.8025C12.8025 10.6639 12.6686 10.7979 12.5005 10.7979V11.1979ZM9.50104 11.1979H12.5005V10.7979H9.50104V11.1979ZM8.80104 10.4979C8.80104 10.886 9.11372 11.1979 9.50104 11.1979V10.7979C9.33437 10.7979 9.20104 10.6648 9.20104 10.4979H8.80104ZM8.80104 6.49887V10.4979H9.20104V6.49887H8.80104ZM9.50104 5.79688C9.11192 5.79688 8.80104 6.11259 8.80104 6.49887H9.20104C9.20104 6.33116 9.33517 6.19688 9.50104 6.19688V5.79688ZM10.201 6.49887C10.201 6.11196 9.89004 5.79688 9.50104 5.79688V6.19688C9.66705 6.19688 9.80104 6.33079 9.80104 6.49887H10.201ZM10.201 9.99788V6.49887H9.80104V9.99788H10.201Z" fill="#2F2F2F" mask="url(#path-1-outside-1_24371_182246)"/>
+</svg>

文件差异内容过多而无法显示
+ 1 - 0
src/assets/svg/icon-form-winners.svg


+ 4 - 0
src/assets/svg/icon-green-yes.svg

@@ -0,0 +1,4 @@
+<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="6" cy="6" r="6" fill="#08B706"/>
+<path d="M3.6875 6L5.4783 7.79096L8.71773 3.34812" stroke="white" stroke-width="1.2"/>
+</svg>

文件差异内容过多而无法显示
+ 3 - 0
src/assets/svg/icon-invite-list.svg


文件差异内容过多而无法显示
+ 1 - 0
src/assets/svg/icon-invite.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-post-edit-luck.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 fill-rule="evenodd" clip-rule="evenodd" d="M5.05497 9.83636V7.82727C5.05497 6.12727 6.29133 4.89091 7.99133 4.89091H9.2277C10.7732 4.89091 12.1641 6.12727 12.1641 7.82727V9.83636H13.555V7.82727C13.555 5.35455 11.5459 3.5 9.2277 3.5H7.99133C5.51861 3.5 3.66406 5.50909 3.66406 7.82727V9.83636H5.05497ZM14.3273 20.5003H2.89091C2.11818 20.5003 1.5 19.8821 1.5 19.1094V12.0003C1.5 11.2276 2.27273 10.6094 2.89091 10.6094H14.1727C15.1 10.6094 15.5636 11.2276 15.5636 12.0003V19.1094C15.7182 19.8821 15.1 20.5003 14.3273 20.5003ZM20.1177 20.5458L21.8908 18.7097L21.7607 11.2568C22.0825 11.0797 22.381 10.8534 22.6513 10.5734C23.3567 9.84292 23.743 8.86219 23.7253 7.84692C23.7076 6.83165 23.2873 5.865 22.5569 5.15962C21.8264 4.45425 20.8457 4.06793 19.8304 4.08565C18.8151 4.10337 17.8485 4.52368 17.1431 5.25412C16.4377 5.98455 16.0514 6.96528 16.0691 7.98056C16.0869 8.99583 16.5072 9.96248 17.2376 10.6679C17.5176 10.9382 17.8237 11.154 18.1516 11.3198L18.1871 13.359L19.5642 14.6888L18.2344 16.0658L19.6115 17.3957L18.2816 18.7727L20.1177 20.5458ZM19.8592 5.73542C20.1976 5.72951 20.5245 5.85828 20.768 6.09341C21.0115 6.32853 21.1516 6.65075 21.1575 6.98917C21.1634 7.3276 21.0346 7.65451 20.7995 7.89799C20.5644 8.14147 20.2422 8.28157 19.9038 8.28748C19.5653 8.29339 19.2384 8.16461 18.9949 7.92949C18.7515 7.69436 18.6114 7.37215 18.6055 7.03372C18.5995 6.6953 18.7283 6.36839 18.9634 6.12491C19.1986 5.88143 19.5208 5.74132 19.8592 5.73542Z" fill="#424B51"/>
+</svg>

+ 3 - 0
src/assets/svg/icon-post-edit-open.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="M11.5957 5.58382C12.4466 5.58382 13.2627 5.92184 13.8643 6.52352C14.466 7.1252 14.804 7.94125 14.804 8.79215C14.804 9.64306 14.466 10.4591 13.8643 11.0608C13.2627 11.6625 12.4466 12.0005 11.5957 12.0005C10.7448 12.0005 9.92875 11.6625 9.32707 11.0608C8.72539 10.4591 8.38737 9.64306 8.38737 8.79215C8.38737 7.94125 8.72539 7.1252 9.32707 6.52352C9.92875 5.92184 10.7448 5.58382 11.5957 5.58382ZM5.17904 8.00049C5.69237 8.00049 6.16904 8.13799 6.58154 8.38549C6.44404 9.69632 6.82904 10.998 7.61737 12.0155C7.15904 12.8955 6.24237 13.5005 5.17904 13.5005C4.44969 13.5005 3.75022 13.2108 3.23449 12.695C2.71877 12.1793 2.42904 11.4798 2.42904 10.7505C2.42904 10.0211 2.71877 9.32167 3.23449 8.80594C3.75022 8.29022 4.44969 8.00049 5.17904 8.00049ZM18.0124 7.85352C18.7417 7.85352 19.4412 8.14325 19.9569 8.65897C20.4726 9.1747 20.7624 9.87417 20.7624 10.6035C20.7624 11.3329 20.4726 12.0323 19.9569 12.5481C19.4412 13.0638 18.7417 13.3535 18.0124 13.3535C16.949 13.3535 16.0324 12.7485 15.574 11.8685C16.3624 10.851 16.7474 9.54935 16.6099 8.23852C17.0224 7.99102 17.499 7.85352 18.0124 7.85352ZM5.63737 16.791C5.63737 14.8935 8.30487 13.3535 11.5957 13.3535C14.8865 13.3535 17.554 14.8935 17.554 16.791V18.3952H5.63737V16.791ZM0.595703 18.3952V17.0202C0.595703 15.746 2.3282 14.6735 4.67487 14.3619C4.13404 14.9852 3.80404 15.8468 3.80404 16.791V18.3952H0.595703ZM22.5957 18.3952H19.3874V16.791C19.3874 15.8468 19.0574 14.9852 18.5165 14.3619C20.8632 14.6735 22.5957 15.746 22.5957 17.0202V18.3952Z" fill="#424B51"/>
+</svg>

+ 4 - 0
src/assets/svg/icon-post-lock.svg

@@ -0,0 +1,4 @@
+<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M72.0799 86.2749H27.4304C24.4135 86.2749 22 83.6649 22 80.4025V50.388C22 47.1256 25.0169 44.5156 27.4304 44.5156H71.4766C75.0968 44.5156 76.9069 47.1256 76.9069 50.388V80.4025C77.5103 83.6649 75.0968 86.2749 72.0799 86.2749Z" fill="#F3B14D"/>
+<path d="M35.1867 40.4444V33.8186C35.1867 26.8184 40.1651 21.7274 47.0105 21.7274H51.989C58.212 21.7274 63.8128 26.8184 63.8128 33.8186V40.4444H69.4135V33.8186C69.4135 23.6366 61.3236 16 51.989 16H47.0105C37.0536 16 29.5859 24.2729 29.5859 33.8186V40.4444H35.1867Z" fill="#AEB9C2"/>
+</svg>

+ 3 - 0
src/assets/svg/icon-refresh-treasure.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="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>

文件差异内容过多而无法显示
+ 5 - 0
src/assets/svg/icon-silver-open-box.svg


文件差异内容过多而无法显示
+ 1 - 0
src/assets/svg/icon-small-treasure.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>

文件差异内容过多而无法显示
+ 1 - 0
src/assets/svg/icon-three-line.svg


+ 3 - 0
src/assets/svg/icon-tip-arrow.svg

@@ -0,0 +1,3 @@
+<svg width="10" height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M0.5 0H9.5L4.5 5L0.5 0Z" fill="black" fill-opacity="0.6"/>
+</svg>

+ 5 - 0
src/assets/svg/icon-transaction-s.svg

@@ -0,0 +1,5 @@
+<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="17" height="17" rx="8.5" transform="matrix(-1 0 0 1 17 0)" fill="#4CD6D6"/>
+<path d="M9.6611 5.16894L10.7911 4.5L12.6981 7.68105H4.5V6.37508H10.3846L9.6611 5.16688V5.16894Z" fill="white"/>
+<path d="M6.4148 12.4985L7.54684 11.8316L7.54581 11.8295L6.8213 10.6213H12.7079V9.31641H4.50781L6.4148 12.4985Z" fill="white"/>
+</svg>

+ 4 - 0
src/assets/svg/icon-treasure-return.svg

@@ -0,0 +1,4 @@
+<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M0 17C0 7.61116 7.61116 0 17 0C26.3888 0 34 7.61116 34 17C34 26.3888 26.3888 34 17 34C7.61116 34 0 26.3888 0 17Z" fill="#FFB443"/>
+<path d="M14.7368 11.8V7L7 15.4L14.7368 23.8V18.88C20.2632 18.88 24.1316 20.8 26.8947 25C25.7895 19 22.4737 13 14.7368 11.8Z" fill="white"/>
+</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>

+ 3 - 0
src/assets/svg/icon-while-user.svg

@@ -0,0 +1,3 @@
+<svg width="9" height="8" viewBox="0 0 9 8" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.5 4C5.60514 4 6.5 3.10514 6.5 2C6.5 0.894857 5.60514 8.16868e-08 4.5 8.16868e-08C4.23734 -7.49976e-05 3.97723 0.0516053 3.73454 0.152088C3.49186 0.252571 3.27135 0.399887 3.08562 0.585619C2.89989 0.771351 2.75257 0.991859 2.65209 1.23454C2.55161 1.47723 2.49992 1.73734 2.5 2C2.5 3.10514 3.39486 4 4.5 4ZM4.5 4.57143C3.16514 4.57143 0.5 5.33714 0.5 6.85714V8H8.5V6.85714C8.5 5.33714 5.83486 4.57143 4.5 4.57143Z" fill="white"/>
+</svg>

+ 3 - 0
src/assets/svg/icon-while-yes.svg

@@ -0,0 +1,3 @@
+<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3 7.5L7.15975 11.4647L12.8755 3.62562" stroke="white" stroke-width="2"/>
+</svg>

文件差异内容过多而无法显示
+ 0 - 19
src/assets/svg/img-A0.svg


文件差异内容过多而无法显示
+ 0 - 19
src/assets/svg/img-A1.svg


文件差异内容过多而无法显示
+ 0 - 44
src/assets/svg/img-B0.svg


文件差异内容过多而无法显示
+ 0 - 44
src/assets/svg/img-B1.svg


文件差异内容过多而无法显示
+ 3 - 0
src/assets/svg/img-LT0.svg


文件差异内容过多而无法显示
+ 3 - 0
src/assets/svg/img-LT1.svg


文件差异内容过多而无法显示
+ 3 - 0
src/assets/svg/img-P1.svg


文件差异内容过多而无法显示
+ 3 - 0
src/assets/svg/img-P2.svg


文件差异内容过多而无法显示
+ 3 - 0
src/assets/svg/img-P3.svg


文件差异内容过多而无法显示
+ 2 - 0
src/assets/svg/img-T0.svg


文件差异内容过多而无法显示
+ 2 - 0
src/assets/svg/img-T1.svg


+ 11 - 0
src/assets/svg/img-preview-treasure-01-bg.svg

@@ -0,0 +1,11 @@
+<svg width="375" height="500" viewBox="0 0 375 500" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="375" height="500" fill="url(#paint0_linear_24395_274606)"/>
+<defs>
+<linearGradient id="paint0_linear_24395_274606" x1="187" y1="-7.83211e-09" x2="187.5" y2="500" gradientUnits="userSpaceOnUse">
+<stop offset="0.388068" stop-color="#25180D"/>
+<stop offset="0.554041" stop-color="#5E4025"/>
+<stop offset="0.616047" stop-color="#876635"/>
+<stop offset="0.716041" stop-color="#24180C"/>
+</linearGradient>
+</defs>
+</svg>

+ 0 - 58
src/components/HelloWorld.vue

@@ -1,58 +0,0 @@
-<template>
-  <div class="hello">
-    <h1>{{ msg }}</h1>
-    <p>
-      For a guide and recipes on how to configure / customize this project,<br>
-      check out the
-      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
-    </p>
-    <h3>Installed CLI Plugins</h3>
-    <ul>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
-    </ul>
-    <h3>Essential Links</h3>
-    <ul>
-      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
-      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
-      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
-      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
-      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
-    </ul>
-    <h3>Ecosystem</h3>
-    <ul>
-      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
-      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
-      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
-      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
-      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
-    </ul>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'HelloWorld',
-  props: {
-    msg: String
-  }
-}
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped>
-h3 {
-  margin: 40px 0 0;
-}
-ul {
-  list-style-type: none;
-  padding: 0;
-}
-li {
-  display: inline-block;
-  margin: 0 10px;
-}
-a {
-  color: #42b983;
-}
-</style>

+ 61 - 0
src/components/component-zoom.vue

@@ -0,0 +1,61 @@
+<!-- 组件确定最大宽度时 可等比缩放组件 -->
+<template>
+    <span class="zoom-wrap" ref="zoomDom" :style="{ zoom: zoom, 'font-size': props.fontSize + 'px' }">
+        <slot></slot>
+    </span>
+</template>
+<script setup>
+import { ref, defineProps, onMounted, watch, defineExpose} from 'vue'
+
+let props = defineProps({
+    width: {
+        type: [String, Number],
+        default: '375'
+    },
+    fontSize: {
+        type: String,
+        default: '22'
+    },
+    txt: {
+        type: String,
+        default: ''
+    }
+})
+
+watch(() => props.txt, (newVal) => {
+      setFontZoom(300)
+    },
+    {
+        deep: true
+    })
+
+let zoom = ref(1);
+let zoomDom = ref({});
+
+const setFontZoom = (time = 600) => {
+    setTimeout(() => {
+        let offsetWidth = zoomDom.value && zoomDom.value.offsetWidth || props.width;
+        zoom.value = offsetWidth > props.width ? +props.width / offsetWidth : 1
+    }, time)
+}
+
+onMounted(() => {
+    setFontZoom(0)
+    setFontZoom()
+})
+
+defineExpose({
+  setFontZoom
+})
+</script>
+<style lang="scss" scoped>
+.zoom-wrap {
+    font-weight: 800;
+    color: #FFFFFF;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    white-space: nowrap;
+    width: fit-content;
+}
+</style>

+ 605 - 0
src/components/custom-card-cover.vue

@@ -0,0 +1,605 @@
+<!-- 自定义卡片红包封面 -->
+<template>
+    <div class="custom-card" v-if="data.customPosterUrl">
+        <img class="customImg" :src="data.customPosterUrl" />
+        <div class="common-bottom">
+            <div class="theme">
+                <img v-if="isLottaryCpd" class="icon" :src="require('@/assets/svg/icon-last-time.svg')"/>
+                <span v-if="isLottaryCpd" class="time" >{{data.countDown || formatSecondsAsDaysOrTime(data.validityDuration * 3600)}}</span>
+                <span class="info">{{isLottaryCpd ? 'Left' : 'Instant Giveaway'}}</span>
+            </div>
+            <div class="winner-info">
+                <component-zoom width="320" fontSize="12" ref="zoomCom1">
+                    <span class="count">{{data.totalCount}} Winners</span>
+                    <span>to Share </span>
+                    <span class="prize-name">{{isMoneyRewardCpd ? data.amountValue + ' ' + data.tokenSymbol : data.customizedReward}}</span>
+                </component-zoom>
+            </div>
+            <div class="open-btn" @click="open">
+                {{isLottaryCpd ? 'Participate Now' : 'Open Now'}}
+            </div>
+        </div>
+    </div>
+    <div class="not-open" v-else-if="isMoneyRewardCpd">
+        <img class="cover" v-if="data.type == PlayType.lottery" :src="require('@/assets/svg/img-preview-draw-bg.svg')"  />
+        <img class="cover" v-else-if="data.type == PlayType.common" src="@/assets/subject/001-card.png"  />
+        <img class="cover" v-else-if="data.type == PlayType.treasure" :src="require('@/assets/svg/img-preview-treasure-01-bg.svg')"  />
+
+        <img class="open-gif"
+            v-if="data.type == PlayType.lottery"
+            src="@/assets/img/img-preview-draw-box.png" />
+        <img class="open-gif"
+            v-else-if="data.type == PlayType.common"
+            :src="require('@/assets/gif/001.gif')" />
+
+        <img v-if="data.type == PlayType.lottery"
+            :src="require('@/assets/svg/img-preview-draw-open.svg')"
+            class="open"
+            @click="open" />
+        <img v-else-if="data.type == PlayType.common"
+            :src="require('@/assets/svg/icon-open.svg')"
+            class="open"
+            @click="open"/>
+
+        <div class="title" v-if="data.userInfo">
+            <img :src="data.userInfo.avatarUrl" />
+            <span v-if="data.type != PlayType.treasure">
+                {{data.userInfo.nickName || ""}}
+            </span>
+            <span class="treasure-info" v-else>
+                from @{{data.userInfo.nickName || ""}}
+            </span>
+        </div>
+
+        <div class="money-area" v-if="data.type != PlayType.treasure">
+            <div class="txt">
+                <span>{{data.currencyCode == 'USD' ? 'US Dollar' : data.tokenSymbol}} </span>
+                &nbsp;GIVEAWAY
+            </div>
+            <div class="coin">
+                <component-zoom width="300" fontSize="56" :txt="data.amountValue || 0" ref="zoomCom">
+                  <img v-if="data.currencyIconUrl" :src="data.currencyIconUrl || imgHeaderCover" />
+                  <span id="preview-after-amount">{{ getBit(data.amountValue) || 0 }}</span>
+                </component-zoom>
+            </div>
+            <div class="time-area" v-if="data.type == PlayType.lottery">
+                <img class="icon-clock" :src="require('@/assets/svg/icon-time.svg')" />
+                {{data.countDown || formatSecondsAsDaysOrTime(data.validityDuration * 3600)}}
+            </div>
+            <div class="people" v-else-if="data.type == PlayType.common">
+                {{ data.totalCount }} WINNERS TO SHARE
+            </div>
+        </div>
+        <div class="treasure-card-info" v-else>
+            <div class="treasure-row-1">
+                <div class="left">Treasure</div>
+                <component-zoom :width="160" :txt="data.amountValue || 0">
+                    <div class="right">${{ data.usdEstimateOrderAmount || 0 }}</div>
+                </component-zoom>
+            </div>
+
+            <div class="treasure-row-2">
+                Your Gain Up to $
+                <component-zoom :width="160" :txt="data.upGainAmountUsdValue || 0">
+                  <div class="amount">{{data.upGainAmountUsdValue || 0}}</div>
+                </component-zoom>
+            </div>
+
+            <div class="treasure-row-3" :style="{'visibility': data.currencyCode && data.currencyCode != 'USD'? 'visible' : 'hidden'}">
+                <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-treasure-box.png')">
+
+            <div class="treasure-row-4">
+               <img class="img" :src="require('@/assets/svg/icon-three-line.svg')"> to Hunt Treasure
+            </div>
+
+            <div class="open-btn" @click="open">
+                <img :src="require('@/assets/svg/icon-card-cover-treasure-small.svg')" alt="">
+                START
+            </div>
+        </div>
+    </div>
+
+    <!-- 改版之后的卡片 -->
+    <div class="custom-card" v-else>
+        <img class="cover" v-if="isLottaryCpd" :src="require('@/assets/subject/img-custom-lottary-bg.svg')"  />
+        <img class="cover" v-else :src="require('@/assets/subject/img-custom-common-bg.svg')"  />
+        <img class="gift" :src="require('@/assets/subject/icon-gift.gif')" />
+        <div class="prize">
+            <component-zoom width="300" fontSize="22" ref="zoomCom2">
+                <img class="icon" :src="require('@/assets/subject/icon-gift-inline.svg')"/>
+                <span class="name" id="custom-name" >
+                    {{data.customizedReward}}
+                    <span class="total" >X{{data.totalCount}}</span>
+                </span>
+            </component-zoom>
+
+        </div>
+        <!-- 底部公共模块 -->
+        <div class="common-bottom">
+            <div class="theme">
+                <img v-if="isLottaryCpd" class="icon" :src="require('@/assets/svg/icon-last-time.svg')"/>
+                <span v-if="isLottaryCpd" class="time" >{{data.countDown || formatSecondsAsDaysOrTime(data.validityDuration * 3600)}}</span>
+                <span class="info">{{isLottaryCpd ? 'Left' : 'Instant Giveaway'}}</span>
+            </div>
+            <div class="winner-info">
+                <component-zoom width="300" fontSize="12" ref="zoomCom3">
+                    <span class="count">{{data.totalCount}}Winners</span>
+                    <span>to Share </span>
+                    <span class="prize-name">{{isMoneyRewardCpd ? data.amountValue + ' ' + data.tokenSymbol : data.customizedReward}}</span>
+                </component-zoom>
+            </div>
+            <div class="open-btn" @click="open">
+                {{isLottaryCpd ? 'Participate Now' : 'Open Now'}}
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, ref, computed, onMounted, watch } from "vue";
+import { formatSecondsAsDaysOrTime } from "@/uilts/help";
+import ComponentZoom from "./component-zoom.vue";
+import { RewardType, PlayType } from "@/types";
+import { getBit } from "@/uilts/help";
+
+let zoomCom = ref('');
+let zoomCom1 = ref('');
+let zoomCom2 = ref('');
+let zoomCom3 = ref('');
+const props = defineProps({
+    show: {
+      type: Boolean,
+      default: true
+    },
+    data: {
+        type: Object,
+        default: () => {
+            return {
+                totalCount: 0,
+                amountValue: 0,
+                tokenSymbol: '',
+                currencyCode: '',
+                type: 1,
+                validityDuration: '',
+                countDown: '',
+                customPosterUrl: '',
+                userInfo: {
+                    avatarUrl: "",
+                    nickName: "",
+                },
+                rewardType: RewardType.money,
+                customizedReward: "",
+                upGainAmountUsdValue: ""
+            };
+        },
+    },
+});
+
+watch(() => props.show, (newVal) => {
+      if(newVal) {
+        zoomCom.value && zoomCom.value.setFontZoom(0);
+        zoomCom1.value && zoomCom1.value.setFontZoom(0);
+        zoomCom2.value && zoomCom2.value.setFontZoom(0);
+        zoomCom3.value && zoomCom3.value.setFontZoom(0);
+      }
+    },
+    {
+        deep: true
+    })
+
+
+
+let isMoneyRewardCpd =computed(() => {
+    return props.data.rewardType === RewardType.money
+});
+
+let isLottaryCpd = computed(() => props.data.type === PlayType.lottery);
+
+const defaultBaseWidth = isMoneyRewardCpd.value ? 56 : 22;
+const defaultTotalWidth = isMoneyRewardCpd.value ? 360 : 450;
+
+let amount_font_size = ref(defaultBaseWidth);
+
+const setFontSize = () =>{
+    let id = isMoneyRewardCpd.value ? 'preview-after-amount' : 'custom-name';
+    let lendom = document.querySelector(`#${id}`);
+    if (lendom) {
+        let lenstr = lendom.innerText.length;
+        let num = parseInt(defaultTotalWidth / lenstr);
+        amount_font_size.value = num < defaultBaseWidth ? num : defaultBaseWidth;
+    }
+}
+
+const emits = defineEmits(["clickOpenRedPacket"]);
+
+const open = () => {
+    emits("clickOpenRedPacket", {});
+};
+
+onMounted(() => {
+    // setFontSize()
+})
+</script>
+
+<style scoped lang="scss">
+.not-open {
+    width: 100%;
+    height: 100%;
+    position: relative;
+    border-radius: 16px;
+    filter: drop-shadow(0px 2px 20px rgba(0, 0, 0, 0.1));
+
+    .money-area {
+        width: 100%;
+        position: absolute;
+        top: 65px;
+
+        .txt {
+            font-weight: 800;
+            font-size: 16px;
+            letter-spacing: 0.3px;
+            color: #ffffff;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+
+            span {
+                color: #F9C545;
+            }
+        }
+
+        .coin {
+            text-align: center;
+            width: 100%;
+            padding: 3px 0;
+            margin: 0 auto;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            height: 85px;
+            box-sizing: border-box;
+
+            img {
+                width: 46px;
+                height: 46px;
+                border-radius: 50%;
+                border: 3px solid #ffffff;
+            }
+
+            #preview-after-amount {
+                margin-left: 15px;
+                font-weight: 800;
+                font-size: 60px;
+                line-height: 76px;
+                color: #ffffff;
+            }
+        }
+
+        .people {
+            font-weight: 800;
+            font-size: 13px;
+            line-height: 16px;
+            letter-spacing: 0.05em;
+            color: #ffffff;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+        }
+
+        .time-area {
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            width: 100%;
+            height: 46px;
+            background: rgba(0,0,0,.15);
+            color: #FFCC4D;
+            font-weight: 900;
+            font-size: 26px;
+            margin-top: -10px;
+            .icon-clock {
+                width: 26px;
+                height: 26px;
+                margin-right: 10px;
+            }
+        }
+    }
+
+    .treasure-card-info {
+        color: #fff;
+        position: absolute;
+        top: 86px;
+        width: 100%;
+        text-align: center;
+
+        .treasure-row-1 {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            font-weight: 900;
+            font-size: 25px;
+
+            .left {
+                margin-right: 7px;
+                color: #FFC83A;
+            }
+
+            .right {
+                font-weight: 900;
+                font-size: 25px;
+            }
+        }
+
+        .treasure-row-2 {
+            margin: 6px 0;
+            background: rgba(255, 255, 255, .1);
+            width: 100%;
+            height: 27px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            font-weight: 500;
+            font-size: 12px;
+
+            .amount {
+                font-weight: 800;
+                font-size: 17px;
+                margin-top: -2px;
+            }
+        }
+
+        .treasure-row-3 {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+
+            .img {
+                width: 13px;
+                margin-right: 3px;
+            }
+
+            .txt {
+                zoom: .8;
+                opacity: 0.7;
+            }
+        }
+
+        .treasure-row-4 {
+            display: flex;
+            align-items:center;
+            justify-content: center;
+            color: #65C1FF;
+            margin-top: 18px;
+            font-size: 16px;
+
+            .img {
+                width: 76px;
+                margin-right: 10px;
+            }
+        }
+
+        .img-treasure-big {
+            width: 200px;
+        }
+
+        .open-btn {
+            width: 88%;
+            height: 40px;
+            background: #1D9BF0;
+            border-radius: 75px;
+            display: flex;
+            align-items:center;
+            justify-content: center;
+            cursor: pointer;
+            font-weight: 800;
+            font-size: 15px;
+            margin-top: 12px;
+            position: relative;
+            left: 50%;
+            transform: translateX(-50%);
+
+            img {
+                width: 18px;
+                margin-right: 5px;
+            }
+        }
+    }
+
+    .title {
+        position: absolute;
+        top: 15px;
+        left: 15px;
+        z-index: 3;
+        width: 100%;
+        display: flex;
+        align-items: center;
+
+        img {
+            width: 24px;
+            height: 24px;
+            border: 2px solid #fff;
+            border-radius: 50%;
+        }
+
+        span {
+            margin-left: 10px;
+            font-weight: 600;
+            font-size: 16px;
+            letter-spacing: 0.3px;
+            color: #fff;
+        }
+
+        .treasure-info {
+            color: #fff;
+            opacity: 0.7;
+            font-weight: 300;
+        }
+    }
+
+    // .txt {
+    //   width: 100%;
+    //   position: absolute;
+    //   font-style: normal;
+    //   font-weight: 700;
+    //   font-size: 42px;
+    //   line-height: 50px;
+    //   text-align: center;
+
+    //   color: #FFF2D3;
+    //   top: 90px;
+    //   z-index: 3;
+    // }
+
+    img {
+        width: 100%;
+    }
+
+    .cover {
+        border-radius: 16px;
+    }
+
+    .up {
+        position: absolute;
+        top: 0;
+        // box-shadow: 0px 4px 44px rgba(0, 0, 0, 0.1);
+        z-index: 1;
+    }
+
+    .down {
+        position: absolute;
+        top: 253px;
+    }
+
+    .open {
+        width: 335px;
+        height: 50px;
+        cursor: pointer;
+        position: absolute;
+        bottom: 28px;
+        left: 50%;
+        margin-left: -167.5px;
+        z-index: 2;
+    }
+
+    .open-gif {
+        width: 200px;
+        height: 200px;
+        text-align: center;
+        position: absolute;
+        bottom: 90px;
+        left: 50%;
+        margin-left: -100px;
+        z-index: 3;
+    }
+}
+
+.custom-card {
+    position: relative;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    background:#111214;
+    position: relative;
+    border-radius: 10px;
+    .customImg {
+        width: 100%;
+        min-height: calc(100% - 125px);
+    }
+    .cover {
+        width: 100%;
+        min-height: 350px;
+        border-radius: 10px 10px 0 0;
+    }
+    .gift {
+        width: 210px;
+        position: absolute;
+        left: 50%;
+        top: 83px;
+        transform: translateX(-50%);
+    }
+    .prize {
+        width: 100%;
+        position: absolute;
+        top: 57%;
+        left: 0;
+        height: 47px;
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        font-style: normal;
+        font-weight: 800;
+        font-size: 22px;
+        line-height: 47px;
+        letter-spacing: 0.3px;
+
+        .icon {
+            width: 24px;
+        }
+        .name {
+            padding: 0 7px;
+            color: #fff;
+        }
+        .total {
+            color: #F5C03F;
+        }
+    }
+    .common-bottom {
+        width: 100%;
+        height: 125px;
+        background:#111214;
+        border-radius: 0 0 10px 10px;
+        padding: 10px 16px;
+        font-weight: 500;
+        font-size: 12px;
+        line-height: 14px;
+        letter-spacing: 0.3px;
+        color: #838383;
+        line-height: 20px;
+        .theme {
+            display: flex;
+            height: 20px;
+            align-items: center;
+            justify-content: flex-start;
+            .icon {
+                width: 12px;
+            }
+            .time {
+                margin: 0 4px;
+                color: #1D9BF0;
+            }
+        }
+        .winner-info {
+            display: flex;
+            height: 20px;
+            align-items: center;
+            justify-content: flex-start;
+            margin-bottom: 13px;
+            font-size: 12px;
+            .count{
+                color: #1D9BF0;
+                margin-right: 4px;
+            }
+            .prize-name {
+                color: #1D9BF0;
+                margin-left: 4px;
+            }
+        }
+        .open-btn {
+            width: 100%;
+            height: 45px;
+            background: linear-gradient(180deg, #4AB6FF 0%, #1D9BF0 100%, #1D9BF0 100%);
+            border: 1.5px solid rgba(255, 255, 255, 0.15);
+            border-radius: 52px;
+            line-height: 45px;
+            text-align: center;
+            cursor: pointer;
+            font-weight: 800;
+            font-size: 16px;
+            color: #FFFFFF;
+        }
+    }
+}
+</style>

+ 52 - 0
src/components/font-amount.vue

@@ -0,0 +1,52 @@
+<template>
+    <div>
+        <a-tooltip :title="amount" >
+           <span class="content" :style="{ fontSize: amount_font_size + 'px' }">{{ getBit(amount) }}</span>
+        </a-tooltip>
+    </div>
+</template>
+<script setup>
+import { ref, defineProps, onMounted, watch } from 'vue'
+import { getBit } from "@/uilts/help";
+
+let props = defineProps({
+    amount: {
+        type: String,
+        default: ''
+    },
+    width: {
+        type: Number,
+        default: 360
+    },
+    fontSize: {
+        type: Number,
+        default: 56
+    },
+
+})
+
+let amount_font_size = ref(60);
+watch(props, () => {
+    setFontSize()
+})
+function setFontSize(){
+    let amount = getBit(props.amount);
+    let _num = parseInt(props.width / amount.length);
+    amount_font_size.value = _num < props.fontSize ? _num : props.fontSize;
+}
+
+onMounted(() => {
+    setFontSize()
+})
+
+</script>
+<style lang="scss" scoped>
+.content {
+    word-break: break-all;
+    margin-left: 12px;
+    font-weight: 800;
+    font-size: 60px;
+    line-height: 76px;
+    color: #FFFFFF;
+}
+</style>

+ 46 - 0
src/components/font-zoom.vue

@@ -0,0 +1,46 @@
+<template>
+    <span class="zoom-text" :style="{ fontSize: amount_font_size + 'px' }">{{ amount }}</span>
+</template>
+<script setup>
+import { ref, defineProps, onMounted, watch } from 'vue'
+import { getBit } from "@/uilts/help";
+
+let props = defineProps({
+    amount: {
+        type: String,
+        default: ''
+    },
+    width: {
+        type: Number,
+        default: 360
+    },
+    fontSize: {
+        type: Number,
+        default: 56
+    },
+
+})
+
+let amount_font_size = ref(props.fontSize);
+watch(props, () => {
+    setFontSize()
+})
+function setFontSize(){
+    let amount = getBit(props.amount);
+    let _num = parseInt(props.width / amount.length);
+    amount_font_size.value = _num < props.fontSize ? _num : props.fontSize;
+}
+
+onMounted(() => {
+    setFontSize()
+})
+
+</script>
+<style lang="scss" scoped>
+.zoom-text {
+    word-break: break-all;
+    font-weight: 800;
+    font-size: 22px;
+    color: #FFFFFF;
+}
+</style>

+ 142 - 0
src/components/get-more.vue

@@ -0,0 +1,142 @@
+<template>
+    <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>
+        </div>
+        <div class="get-more-btn" @click="jumpMore">
+            <img width="22" :src="require('@/assets/svg/icon-big-give.svg')" />
+            <font>Get More Giveaway</font>
+        </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>
+        <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>
+</template>
+
+<script setup>
+import { getFrontConfig } from "@/http/account";
+// import { number } from "mathjs";
+import { onBeforeMount, ref, defineProps } from "vue";
+import Report from "@/log-center/log"
+
+const props = defineProps({
+    style_type: {
+        type: Number,
+        default: 1,
+    },
+    reportData: {
+        type: Object,
+    }
+})
+
+// const
+const moreUrl = ref('');
+
+onBeforeMount(() => {
+    getFrontConfig({
+        params: {},
+    }).then(res => {
+        moreUrl.value = res.data.moreLuckdropsUrl;
+    })
+})
+
+const jumpMore = () => {
+    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)
+    }
+}
+
+</script>
+
+<style lang="scss" scoped>
+.getMore {
+    display: flex;
+    height: 50px;
+    cursor: pointer;
+    user-select: none;
+    align-items: center;
+    justify-content: center;
+    box-shadow: 0px -2px 10px rgba(0, 0, 0, 0.06);
+
+    img {
+        margin: 0 5px;
+    }
+
+    font {
+        color: #000;
+        font-size: 15px;
+        font-weight: 500;
+        line-height: 18px;
+    }
+}
+
+.get_more {
+    margin-top: 58px;
+    width: 240px;
+    height: 54px;
+    background: #FFFFFF;
+    border: 1px solid #E8E8E8;
+    border-radius: 100px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    cursor: pointer;
+
+    img {
+        margin-right: 8px;
+    }
+}
+.get-more-btns  {
+    display: flex;
+    cursor: pointer;
+    user-select: none;
+    align-items: center;
+    justify-content: center;
+    padding: 13px 0;
+    box-shadow: 0px -2px 10px rgba(0, 0, 0, 0.06);
+    position: relative;
+    .get-more-btn {
+        flex: 1;
+        display: flex;
+        cursor: pointer;
+        user-select: none;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        height: 44px;
+        font {
+            font-weight: 600;
+            font-size: 14px;
+            line-height: 17px;
+            text-align: center;
+            letter-spacing: 0.3px;
+            color: #000000;
+        }
+    }
+    &::after {
+        content: "";
+        width: 1px;
+        height: 88px;
+        position: absolute;
+        left: 50%;
+        top: 13px;
+        background-color: rgba(0,0,0,.2);
+        transform: scale(0.5);
+        transform-origin: 0 0;
+    }
+}
+</style>

+ 58 - 0
src/components/global-tip.vue

@@ -0,0 +1,58 @@
+<template>
+    <div class="global-tip" v-if="state.is_show == 1">
+        <img :src="require('@/assets/svg/icon-global-tip.svg')" alt="">
+        <p>{{ state.msg }}</p>
+    </div>
+</template>
+<script setup>
+import { onMounted, reactive, defineProps } from "vue";
+import { getAppNotification } from '@/http/messageApi.js'
+let props = defineProps({
+    type: String,
+})
+// 显示位置:1-红包主体,2-发布器,3-插件主体
+
+let state = reactive({
+
+})
+
+onMounted(() => {
+    getAppNotification().then((res) => {
+        if (res.code == 0) {
+            res.data.forEach((item) => {
+                if (props.type == item.type) {
+                    state.is_show = item.isShow
+                    state.msg = item.message
+                }
+            })
+        }
+    })
+})
+
+</script>
+<style lang="scss" scoped>
+.global-tip {
+    position: absolute;
+    z-index: 3000;
+    display: flex;
+    height: 40px;
+    background: #000000;
+    opacity: 0.7;
+    align-items: center;
+    width: 100%;
+
+    img {
+        width: 15px;
+        height: 15px;
+        margin-left: 17px;
+        margin-right: 10px;
+    }
+
+    p {
+        color: #DCA550;
+        flex: 1;
+        margin: 0;
+        padding: 0;
+    }
+}
+</style>

+ 2 - 2
src/http/configAPI.js

@@ -1,6 +1,6 @@
-let manifest = require('./../../package.json')
+import { appVersionCode } from '@/uilts/help';
 
-export const appVersionCode = Number(manifest.denet_app_version_code)
+export { appVersionCode }
 
 const api = {
 	production: 'https://api.denetme.net',

+ 31 - 0
src/log-center/autoLog/click.js

@@ -0,0 +1,31 @@
+// 点击埋点自定义属性
+
+import { reportLog } from '../logger';
+import { getTargetElementWhenClick } from '@/uilts/help';
+import Report from "@/log-center/log";
+
+let clickDataMap = new Map();
+
+const clickHandle = (e) => { 
+    const target = getTargetElementWhenClick(e);
+    const { extParams, ...eventData } = clickDataMap.get(target?.denetClickLogkey);
+    return eventData && reportLog({
+        businessType: Report.businessType.buttonClick,
+        ...eventData
+    }, extParams)
+}
+
+const clickLog =  {
+    mounted: (el, binding) => { 
+        const { value } = binding;
+        el.denetClickLogkey = el.denetClickLogkey || Math.random().toString(36).slice(-6);
+        clickDataMap.set(el.denetClickLogkey, value);
+        el.addEventListener('click', clickHandle,true)
+    },
+    unmounted(el) { 
+        // remove EventListener
+        el.removeEventListener('click', clickHandle, true)
+    }
+}
+
+export default clickLog;

+ 23 - 0
src/log-center/autoLog/index.js

@@ -0,0 +1,23 @@
+// 埋点插件
+
+import { showReportDialog } from '@sentry/vue';
+import clickLog from './click';
+import ShowLogObserver from './show';
+
+const AutoLog = {};
+
+AutoLog.install = (app) => { 
+    app.directive('click-log', clickLog);
+    app.directive('show-log', {
+        mounted(el, binding) {
+            // 加载阶段设置随机key标记当前元素
+            el.denetShowLogkey = el.denetShowLogkey || Math.random().toString(36).slice(-6);
+            ShowLogObserver.add(el, binding);
+        },
+        unmounted(el) {
+            ShowLogObserver.remove(el);
+        },
+    });
+}
+
+export default AutoLog;

+ 50 - 0
src/log-center/autoLog/show.js

@@ -0,0 +1,50 @@
+import { reportLog } from '../logger';
+import { getActiveKeyAfterClick } from '@/uilts/help';
+import Report from "@/log-center/log"
+
+// 每个窗口共享一个Observer实例
+class ShowLogObserver { 
+    constructor() { 
+        this._observe = null;
+        this.showLogMap = new Map();
+        this.init();
+    }
+
+    init() {
+        this._observe = new IntersectionObserver((entries, observer) => {
+            entries.forEach((entry) => {
+                if (entry.intersectionRatio > 0.5) {
+                    this.report(entry);
+                    // show-log-once  ===  '1' &&  曝光之后取消观察
+                    if (entry?.target?.getAttribute('show-log-once') === '1') {
+                        this.remove(entry.target);
+                    }
+                }
+            })
+        }, {
+            root: null,
+            rootMargin: '0px',
+            threshold: 1
+        })
+    }
+
+    remove(el) { 
+        this._observe.unobserve(el);
+        this.showLogMap.delete(el.denetShowLogkey);
+    }
+
+    add(el, binding) { 
+        this._observe.observe(el);
+        this.showLogMap.set(el.denetShowLogkey, binding.value)
+    }
+
+    report(el) { 
+        const { extParams, ...eventData } = this.showLogMap.get(el?.target?.denetShowLogkey);
+        return eventData && reportLog({
+            businessType: Report.businessType.pageView,
+            ...eventData
+        }, extParams)
+    }
+}
+
+export default new ShowLogObserver();

+ 9 - 0
src/log-center/log.js

@@ -0,0 +1,9 @@
+import * as logger from './logger'
+import * as logEnum from './logEnum'
+
+
+
+export default {
+  ...logger,
+  ...logEnum
+}

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

@@ -0,0 +1,165 @@
+import { PlayType } from '@/types';
+
+export const logType = {
+    'denet': '150',//denet-event-log
+}
+
+export const redPacketType = {
+    nftSale: 2,
+    nftGroupSale: 3,
+    treasure: 4,
+    postEditor: 5,
+    giveaway: 0,
+    lottery: 1
+}
+
+export const businessType = {
+    buttonView: "buttonView",
+    buttonClick: "buttonClick",
+    // 页面曝光
+    pageView: "pageView",
+}
+
+export const objectType = {
+    buttonMain: "button-main",
+    buttonSecond: "button-second",
+    confirmButton: "confirm-button",
+    tweetPostBinded: "TweetPostBinded",
+    loginButton: "login-button",
+    withdrawButton: "withdraw-button",
+    topupButton: "topup-button",
+    previewNextButton: 'preview-next-button',
+    setPublishContent: 'set-publish-content',
+
+
+    getMoreGiveaway: "get-more-giveaway",
+    nextButton: "next-button",
+    openChestButton: "open-chest-button",
+    copyButton: "copy-button",
+    repostSuccess: "repostSuccess",
+    channelButton: 'channel-button',
+
+    //discord
+    getDiscordGuildNoData: 'get-discord-guild-no-data',
+    getDiscordGuildCatch: 'get-discord-guild-catch',
+    getDiscordGuildOpenApiNoData: 'get-discord-guild-openapi-no-data',
+    getDiscordGuildOpenApiCatch: 'get-discord-guild-openapi-catch',
+    saveDiscordGuildData: 'save-discord-guild-data',
+
+    // 按钮点击
+    open_button: 'open-button',
+    // 关注全部
+    follow_button: 'follow-button',
+    follow: 'follow',
+    retweet: 'retweet',
+    like: 'like',
+    comment_and_tag: 'comment-and-tag',
+    join_discord: 'discord',
+    share_facebook: 'share-facebook',
+
+    // 查看已领取红包列表
+    received_list: 'received-list',
+    // 点击检测任务
+    get_giveaway: 'get-giveaway',
+    // 成功领取到钱包
+    wallet_button: 'wallet-button',
+    // 卡片解析
+    parse_card_error: 'parse-card-error',
+    // 安装成功
+    chrome_extension_installed: 'chrome-extension-installed',
+    // 发送事件异常
+    chrome_extension_sendmessage_error: 'chrome-extension-sendmessage-error',
+    // background文件安装catch异常
+    background_function_catch: 'background-function-catch',
+    // background 文件chrome 函数 try
+    background_function_try: 'background-function-try',
+    // create Nft
+    create_nfts_button: 'create-nfts-button',
+    confirm_transfer_button: 'confirm-transfer-button',
+    redeem_button: 'redeem-button',
+    buy_button: 'buy-button',
+    buy_nft_button: 'buy-nft-button',
+    custom_link_button: 'custom-link-button',
+    history_button: 'history-button',
+    app_button: 'app-button',
+    enter_url_button: 'enter-url-button',
+    top_right_button: 'top-right-button',
+    fullscreen_button: 'fullscreen-button',
+    encrypte_nft_button: 'encrypte-nft-button',
+    preRepost: 'preRepost',
+}
+
+export const pageSource = {
+    mainPage: "main-page",
+    publisherDialog: "publisher-dialog",
+    currencySelectorPage: "currency-selector-page",
+    rechargePage: "recharge-page",
+    previewPage: "preview-page",
+    denetLogin: "denet-login",
+    denetHomePage: "denet-home-page",
+    denetWithdrawSelector: "denet-withdraw-selector",
+    denetWithdrawForm: "denet-withdraw-form",
+    denetWithdrawConfirm: "denet-withdraw-confirm",
+    denetTopupSelector: "denet-topup-selector",
+    denetMorePage: "denet-more-page",
+    denetSelector: "denet-selector",
+    nftShopPage: "nft-shop-page",
+    nftPreviewPage: "nft-preview-page",
+    denetNftTransferPage: "denet-nft-transfer-page",
+
+
+    newFansRewardPage: "new-fans-reward-page",
+    inviteFriendsPage: "invite-friends-page",
+    openTreasurePage: "open-treasure-page",
+    beenInvitedPage: "been-invited-page",
+    waitingLotteryPage: "waiting-lottery-page",
+    missingLotteryPage: "missing-lottery-page",
+    expiredPage: "expired-page",
+
+    // 待开红包页
+    pending_page: 'pending-page',
+    // 已领取任务页
+    task_page: 'task-page',
+    // 领取列表页
+    received_list_page: 'received-list-page',
+    // 红包过期
+    expired_page: 'expired-page',
+    // 红包被领完
+    been_claimed_page: 'been-claimed-page',
+    // 机器人检测未通过
+    robot_detection_failed_page: 'robot-detection-failed-page',
+    // 成功领取到钱包
+    received_success_page: 'received-success-page',
+    received_empty_rewards_page: 'received-empty-rewards-page',
+    pe_loading_page: 'pe-loading-page',
+    pe_display_page: 'pe-display-page',
+    nft_sales_window: 'nft-sales-window',
+    nft_post_page: 'nft-post-page',
+    main_page_dashboard: 'main-page-dashboard',
+    post_editor_guide_page_left: 'post-editor-guide-page-left',
+    post_editor_guide_page_right: 'post-editor-guide-page-right',
+    buy_posteditor_nft_dialog: 'buy-posteditor-nft-dialog',
+
+}
+
+export const extParams = {
+    success: 'success',
+    failure: 'failure'
+}
+
+export const bizType = {
+    Treasure: 0,
+    Lottery: 1,
+    RedPacket: 2,
+    ToolBox: 3,
+}
+
+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;
+
+    return obj[type];
+}

+ 120 - 0
src/log-center/logger.js

@@ -0,0 +1,120 @@
+import { logApi, reportFrontLogApi } from '@/http/logApi'
+import { getBrowser } from '@/uilts/help.js';
+import { logType } from './logEnum.js';
+import { getChromeStorage } from '@/uilts/chromeExtension'
+let userInfo = null;
+let mid = '';
+/**
+ * @eventData 以键值对存储,会在最终上报里解开的参数
+ * @extParams 最终上报到阿里云以json字符串存储的参数,如果extparams传入的不是obj会转换成obj
+ */
+export async function reportLog(eventData = {}, extParams = {}) {
+    // 过滤空值
+    let dataKey = Object.keys(eventData);
+    dataKey.forEach(key => {
+        if (eventData[key] === '') {
+            delete eventData[key]
+        }
+    })
+    // 2.reportLog 异常 存储到本地,再上报
+    try {
+        if (!userInfo) {
+            userInfo = await getChromeStorage('userInfo').catch((error) => {console.log(error) }) || null;
+        }
+        if (!mid) {
+            mid = await getChromeStorage('mid').catch((error) => {console.log(error) }) || '';
+        }
+        let isMobile = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
+        let platform = isMobile ? `mobile` : `pc`;
+        let browser = getBrowser();
+        if (chrome && chrome.tabs) {
+            chrome.tabs.getCurrent((tab) => {
+                if (tab && tab.url) {
+                    let { url = '' } = tab;
+                    let extData = {
+                        url,
+                        platform,
+                        browser,
+                        twitterId: userInfo && userInfo.nickName || '',
+                        ...eventData,
+                    }
+                    paramsPretreatmentAndRequest(logType.denet, extData, extParams)
+                } else {
+                    let extData = {
+                        platform,
+                        browser,
+                        twitterId: userInfo && userInfo.nickName || '',
+                        ...eventData,
+                    }
+                    paramsPretreatmentAndRequest(logType.denet, extData, extParams)
+                }
+            })
+        } else {
+            paramsPretreatmentAndRequest(logType.denet, eventData, extParams)
+        }
+    } catch (error) {
+        reportFrontLogApi({
+            logData: JSON.stringify({
+                funcName: 'reportLog',
+                errmsg: error.message
+            })
+        })
+    }
+}
+
+function paramsPretreatmentAndRequest(logType, eventData, extParams) {
+    extParams = wrapObject(extParams)
+    let obj = {};
+    let pageSource = eventData.pageSource;
+    if (eventData.hasOwnProperty('pageSource')) {
+        delete eventData.pageSource;
+    }
+    obj.logType = logType;
+    obj.eventData = JSON.stringify(eventData)
+    obj.extParams = JSON.stringify(extParams)
+    logApi({
+        params: {
+            pageSource,
+            ...obj
+        }
+    }).then(res => {
+    }).catch(err => {
+        reportFrontLogApi({
+            logData: JSON.stringify(err)
+        })
+    })
+}
+
+function wrapObject(extParams) {
+    if (typeDecide(extParams, 'Object')) {
+        return extParams
+    }
+    return { 'defaultExt': extParams }
+}
+
+/**
+ * 检测对象类型
+ */
+function typeDecide(o, type) {
+    return Object.prototype.toString.call(o) === `[object ${type}]`;
+}
+
+export async function getReportCommonParams () {
+  let commonParams = {};
+  if (!userInfo) {
+      userInfo = await getChromeStorage('userInfo') || null;
+  }
+  let isMobile = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
+  let platform = isMobile ? `mobile` : `pc`;
+
+  if (chrome && chrome.tabs) {
+      let tab = await chrome.tabs.getCurrent();
+      commonParams = {
+          url: tab && tab.url ? tab.url : '',
+          platform,
+          browser: getBrowser(),
+          twitterId: userInfo && userInfo.nickName || '',
+      }
+  }
+  return commonParams;
+}

+ 19 - 0
src/main.js

@@ -3,5 +3,24 @@ import App from './App.vue';
 import router from './router';
 
 const app = createApp(App);
+// 引入路由对象实例
+import "ant-design-vue/dist/antd.css"; // or 'ant-design-vue/dist/antd.less'
+import "@/assets/css/reset.css";
+import { message, Tooltip, Switch } from "ant-design-vue";
+
+import CoutomSentry from "@/uilts/sentry.js"
+
+CoutomSentry.initVue(app)
+
+message.config({
+  top: `10px`,
+  duration: 3,
+  maxCount: 1,
+})
+
+app.use(Tooltip)
+app.use(Switch)
+
+app.use(message)
 app.use(router);
 app.mount('#app')

+ 12 - 0
src/pages/red-packet/index.vue

@@ -0,0 +1,12 @@
+<template>
+	<red-packet v-if="state.page_type == '红包'"></red-packet>
+	<luck-draw v-else-if="state.page_type == '抽奖'"></luck-draw>
+</template>
+<script setup>
+import { reactive } from "vue";
+import RedPacket from "./red-packet.vue";
+import LuckDraw from "./luck-draw.vue";
+import { getQueryString } from "@/uilts/help.js";
+let state = reactive({});
+state.page_type = getQueryString("page_type") || "红包";
+</script>

+ 3489 - 0
src/pages/red-packet/luck-draw.vue

@@ -0,0 +1,3489 @@
+<!-- 红包任务页面 -->
+<template>
+    <div class="content">
+        <!-- global-tip -->
+        <global-tip :type="'1'"></global-tip>
+        <!-- open -->
+        <div v-show="state.status == 'opened'" class="opened">
+
+            <div class="header"
+                :style="{ 'backgroundImage': `url(${require('@/assets/subject/002-back-head-top-1.svg')})` }">
+                <!--  -->
+                <img :src="require('@/assets/subject/001-icon-red-packet.svg')" alt="">
+                <div class="txt">
+                    <p>Complete tasks</p>
+                    <p>to Draw Prizes</p>
+                </div>
+            </div>
+
+            <div class="list">
+                <template v-for="item, i in state.detail.taskCondition" v-bind:key="i">
+                    <div class="item" v-if="item.type == 1 && item.relatedUsers && item.relatedUsers.length > 0">
+                        <div class="item-content">
+                            <div class="item-follow-title">
+                                <img :src="require('@/assets/svg/icon-task-twitter.svg')" alt />
+                                <!-- <img :src="require('@/assets/svg/icon-follow.svg')" alt /> -->
+                                <div class="item-title">Follow</div>
+                                <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+                                    v-show="!state.done.follow && state.done.follow_red" />
+                                <img v-if="state.done.follow" :src="require('@/assets/svg/icon-true.svg')" alt />
+                                <div v-else class="btn" @click="clickFollowAll(item.relatedUsers, 'all')">Follow All
+                                </div>
+                            </div>
+                            <div class="item-follow-area">
+                                <template v-for="item2, i in item.relatedUsers" v-bind:key="i">
+                                    <div class="item-follow" v-if="item2.finished">
+                                        <span :class="{ finished: item2.finished }">@{{ item2.name }}</span>
+                                        <img :src="require('@/assets/svg/icon-true-ed.svg')" alt />
+                                    </div>
+                                    <div class="item-follow" v-else @click="clickFollowAll([item2])">
+                                        <span :class="{ finished: item2.finished }">@{{ item2.name }}</span>
+                                        <img :src="require('@/assets/svg/icon-add.svg')" alt />
+                                    </div>
+                                </template>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="item" v-if="item.type == 2">
+                        <img :src="require('@/assets/svg/icon-task-twitter.svg')" alt />
+                        <!-- <img :src="require('@/assets/svg/icon-like.svg')" alt /> -->
+                        <div class="item-content">
+                            <div class="item-title">Like</div>
+                        </div>
+                        <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+                            v-show="!state.done.like && state.done.like_red" />
+                        <img v-if="state.done.like" :src="require('@/assets/svg/icon-true.svg')" alt />
+                        <div v-else class="btn" @click="clickLikeBtn">Like</div>
+                    </div>
+                    <div class="item" v-if="item.type == 3">
+                        <img :src="require('@/assets/svg/icon-task-twitter.svg')" alt />
+                        <!-- <img :src="require('@/assets/svg/icon-retweet.svg')" alt /> -->
+                        <div class="item-content">
+                            <div class="item-title">Retweet</div>
+                        </div>
+                        <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+                            v-show="!state.done.retweet && state.done.retweet_red" />
+                        <img v-if="state.done.retweet" :src="require('@/assets/svg/icon-true.svg')" alt />
+                        <div v-else class="btn" @click="clickRetweetBtn">Retweet</div>
+                    </div>
+                    <!-- Comment、艾特 friends -->
+                    <div class="item" v-if="item.type == 9">
+                        <img :src="require('@/assets/svg/icon-task-twitter.svg')" alt />
+                        <div class="item-content">
+                            <div class="item-title">Comment and Tag 3 friends</div>
+                        </div>
+                        <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+                            v-show="!state.done.reply && state.done.reply_red" />
+                        <img v-if="state.done.reply" :src="require('@/assets/svg/icon-true.svg')" alt />
+                        <div v-else class="btn" @click="clickReply(item)">Comment</div>
+                    </div>
+                    <!-- repost feacebook -->
+                    <div class="item" v-if="item.type == 8">
+                        <img :src="require('@/assets/svg/icon-task-facebook.svg')" alt />
+                        <div class="item-content">
+                            <div class="item-title">Repost to Facebook</div>
+                        </div>
+                        <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+                            v-show="!state.done.repost_facebook && state.done.repost_facebook_red" />
+                        <img v-if="state.done.repost_facebook" :src="require('@/assets/svg/icon-true.svg')" alt />
+                        <div v-else class="btn" @click="clickRepostFacebook(item)">Repost</div>
+                    </div>
+                    <!-- join discord  -->
+                    <div class="item" v-if="item.type == 7">
+                        <img :src="require('@/assets/svg/icon-discord-mini.svg')" alt />
+                        <div class="item-content">
+                            <div class="item-title">Join Discord</div>
+                        </div>
+                        <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+                            v-show="!state.done.join_discord && state.done.join_discord_red" />
+                        <img v-if="state.done.join_discord" :src="require('@/assets/svg/icon-true.svg')" alt />
+                        <template v-else>
+                            <div v-if="joinDiscordIng" class="loading-wrapper">
+                                <img class="icon-loading" :src="require('@/assets/svg/icon-loading-gray.svg')" />
+                            </div>
+                            <div v-else class="btn" @click="joinDiscord">
+                                Join
+                            </div>
+                        </template>
+                    </div>
+                </template>
+            </div>
+            <!-- <div class="people" @click="clickRoad">
+        <div class="txt">
+          {{ state.detail.receiveCount || 0 }}/{{ state.detail.totalCount || 0 }} Winners,{{
+              state.detail.receiveAmountValue
+          }}/{{ state.detail.amountValue }} {{ state.detail.currencySymbol }}</div>
+        <div class="right" v-if="state.detail.allReceived">
+
+          <img :src="require('@/assets/svg/icon-right.svg')" alt class="road" />
+        </div>
+      </div> -->
+            <div class="footer">
+
+                <div class="btn" @click="clickGetGiveaways">Complete</div>
+            </div>
+        </div>
+
+
+        <!-- success -->
+        <div v-if="state.status == 'success'" class="success">
+            <div class="header" v-if="state.detail.rewardType === RewardType.money"
+                :style="{ 'backgroundImage': `url(${require('@/assets/subject/002-back-head-top-180.svg')})` }">
+                <div class="success-title">
+                    🎉 Awesome! You are Winner!
+                </div>
+                <div class="money">
+                    <img :src="state.detail.currencyIconPath" alt />
+                    <font-amount :amount="state.receiveAmount" class="big" :fontSize="46"></font-amount>
+                    <!-- <span class="small">{{ state.detail.currencySymbol }}</span> -->
+                </div>
+                <div class="done" @click="clickDone">
+                    <img :src="require('@/assets/subject/001-icon-done.svg')" alt class="icon-done" />
+                    <span>View Rewards In Wallet</span>
+                    <img :src="require('@/assets/svg/icon-right.svg')" alt class="icon-right" />
+                </div>
+            </div>
+            <div class="header header-custom-prize" v-else
+                :style="{ 'backgroundImage': `url(${successTopBgCpd})`, 'minHeight': '150px' }">
+                <div class="success-title">
+                    🎉 Awesome! You are the Winner!
+                </div>
+                <div class="custom-prize-show">
+                    <component-zoom width="340" fontSize="22" class="custom-prise-name">
+                        <img :src="require('@/assets/subject/icon-gift-inline.svg')" alt />
+                        <span>{{ state.detail.customizedReward }}</span>
+                    </component-zoom>
+                    <!-- <font-zoom :amount="state.detail.customizedReward" width="500" class="custom-prise-name" fontSize="22"></font-zoom> -->
+                </div>
+            </div>
+            <div class="luck-list-title">
+                <div>{{ state.detail.receiveCount || 0 }}/{{ state.detail.totalCount || 0 }} Winners</div>
+                <div class="right">
+                    <span class="text" v-if="state.detail.rewardType === RewardType.money">
+                        <a-tooltip :title="state.detail.receiveAmountValue">
+                            {{ getBit(state.detail.receiveAmountValue) }}
+                        </a-tooltip>
+                        /
+                        <a-tooltip :title="state.detail.amountValue">
+                            {{ getBit(state.detail.amountValue) || '' }}
+                        </a-tooltip>
+                    </span>
+                    {{ state.detail.currencySymbol || '' }}
+                </div>
+            </div>
+            <div class="luck-list max" @scroll="handleScroll($event)">
+                <div class="luck-item" v-for="item, i in state.detail.allReceived" v-bind:key="i">
+                    <img v-if="item.simpleUserInfoVO.avatarUrl" :src="item.simpleUserInfoVO.avatarUrl"
+                        @click="openTwitterDetail(item)" alt />
+                    <img v-else :src="require('@/assets/svg/icon-twitter.svg')" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-1.svg')" v-if="i == 0" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-2.svg')" v-if="i == 1" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-3.svg')" v-if="i == 2" alt />
+                    <div class="luck-content">
+                        <div class="luck-title" v-if="item.simpleUserInfoVO.nickName">{{ item.simpleUserInfoVO.nickName
+                        }}</div>
+                        <div class="luck-title" v-else>Twitter User</div>
+                        <div class="luck-time">{{ moment(item.receiveTimestamp).format('MM-DD HH:mm') }}</div>
+                    </div>
+                    <div class="luck-money" v-if="state.detail.rewardType === RewardType.money">
+                        <img :src="state.detail.currencyIconPath" alt />
+                        <div class="luck-money-txt">
+                            <a-tooltip :title="item.amountValue">
+                                {{ getBit(item.amountValue) }}
+                            </a-tooltip>
+                        </div>
+                    </div>
+                    <div class="luck-custom-prize" v-else>winner</div>
+                    <div class="luck-king" v-if="state.detail.rewardType === RewardType.money && item.maxAmount">
+                        <img :src="require('@/assets/svg/icon-king-hat.svg')" alt />
+                        <span>Luckiest Draw</span>
+                    </div>
+                </div>
+            </div>
+            <get-more :reportData="{
+                pageSource: Report.pageSource.received_success_page,
+                postId: state.postId,
+                redPacketType: Report.redPacketType.lottery
+            }"></get-more>
+        </div>
+
+
+        <!-- no-open -->
+        <div v-else-if="state.status == 'not-open'" class="not-open">
+            <!-- <template v-if="state.detail.posterType === 2 && state.detail.customPosterInstalled">
+                <img class="customImg" :src="state.detail.customPosterInstalled" />
+                <div class="customBottom">
+                    <div class="theme">
+                        <img class="icon" :src="require('@/assets/svg/icon-last-time.svg')"/>
+                        <span class="time">{{ state.count_down_time }}</span>
+                        <span class="info">Left</span>
+                    </div>
+                    <div class="winner-info">
+                        <span class="count">{{state.detail.totalCount}} Winners</span>
+                        <span>to Share </span>
+                        <span class="prize-name">{{state.detail.rewardType === RewardType.money ? state.detail.amountValue + ' ' + state.detail.currencySymbol : state.detail.customizedReward}}</span>
+                    </div>
+                    <div class="open-red" @click="clickOpenRedPacket">
+                        Participate Now
+                    </div>
+                </div>
+            </template> -->
+            <!-- <template v-else> -->
+            <custom-card-cover :data="{
+                totalCount: state.detail.totalCount,
+                amountValue: state.detail.amountValue,
+                tokenSymbol: state.detail.currencySymbol,
+                currencyCode: state.detail.amountCurrencyCode,
+                currencyIconUrl: state.detail.currencyIconPath,
+                type: PlayType.lottery,
+                validityDuration: state.count_down_time,
+                countDown: state.count_down_time,
+                userInfo: {
+                    nickName: state.detail.postUserInfo.nickName,
+                    avatarUrl: state.detail.postUserInfo.avatarUrl
+                },
+                rewardType: state.detail.rewardType,
+                customizedReward: state.detail.customizedReward,
+                customPosterUrl: state.detail.customPosterInstalled
+            }" @clickOpenRedPacket="clickOpenRedPacket"></custom-card-cover>
+            <!-- </template> -->
+        </div>
+
+
+        <!-- 领取列表 -->
+        <div v-else-if="state.status == 'luck-peopel-list'" class="luck-peopel-list">
+            <div class="head">
+                <img :src="require('@/assets/svg/icon-back.svg')" alt />
+            </div>
+            <div class="luck-list-title">
+                <div>{{ state.detail.receiveCount || 0 }}/{{ state.detail.totalCount || 0 }} Winners</div>
+                <div class="right" v-if="state.detail.rewardType === RewardType.money">
+                    <span class="text">
+                        <a-tooltip :title="state.detail.receiveAmountValue">
+                            {{ getBit(state.detail.receiveAmountValue) }}
+                        </a-tooltip>
+                        /
+                        <a-tooltip :title="state.detail.amountValue">
+                            {{ getBit(state.detail.amountValue) || '' }}
+                        </a-tooltip>
+                    </span> {{ state.detail.currencySymbol || '' }}
+                </div>
+            </div>
+            <div class="luck-list" @scroll="handleScroll">
+                <div class="luck-item" v-for="item, i in state.detail.allReceived" v-bind:key="i">
+                    <img v-if="item.simpleUserInfoVO.avatarUrl" :src="item.simpleUserInfoVO.avatarUrl" alt
+                        @click="openTwitterDetail(item)" />
+                    <img v-else :src="require('@/assets/svg/icon-twitter.svg')" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-1.svg')" v-if="i == 0" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-2.svg')" v-if="i == 1" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-3.svg')" v-if="i == 2" alt />
+                    <div class="luck-content">
+                        <div class="luck-title" v-if="item.simpleUserInfoVO.nickName">{{ item.simpleUserInfoVO.nickName
+                        }}</div>
+                        <div class="luck-title" v-else>Twitter User</div>
+                        <div class="luck-time">{{ moment(item.receiveTimestamp).format('MM-DD HH:mm:ss') }}</div>
+                    </div>
+                    <div class="luck-money" v-if="state.detail.rewardType === RewardType.money">
+                        <img :src="state.detail.currencyIconPath" alt />
+                        <div class="luck-money-txt">
+                            <a-tooltip :title="item.amountValue">
+                                {{ getBit(item.amountValue) }}
+                            </a-tooltip>
+                        </div>
+                    </div>
+                    <div class="luck-custom-prize" v-else>winner</div>
+                    <div class="luck-king" v-if="state.detail.rewardType === RewardType.money && item.maxAmount">
+                        <img :src="require('@/assets/svg/icon-king-hat.svg')" alt />
+                        <span>Luckiest Draw</span>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <!-- 关闭状态 -->
+        <div v-else-if="state.status == 'close'" class="close">
+            <!-- 红包被领完了 -->
+            <!-- <div class="header"
+                :style="{ 'backgroundImage': `url(${require('@/assets/subject/002-back-head-top.svg')})` }"
+                v-if="state.close_status == '已经过期了'">
+                <div class="rabbit">
+                    <img class="flower" :src="require('@/assets/svg/icon-flower.svg')" alt />
+                    <p>This Draw is Complete</p>
+                </div>
+            </div> -->
+            <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>
+
+            <!-- 没有抽中 -->
+            <div class="header"
+                :style="{ 'backgroundImage': `url(${require('@/assets/subject/002-back-head-top.svg')})` }"
+                v-if="state.close_status == '没有抽中'">
+                <div class="rabbit">
+                    <img :src="require('@/assets/subject/001-icon-rabbit.svg')" alt />
+                    <p>Good Luck Next Time!</p>
+                </div>
+            </div>
+
+
+            <!-- 等待结果 -->
+            <div class="header"
+                :style="{ 'backgroundImage': `url(${require('@/assets/subject/002-back-head-top.svg')})` }"
+                v-if="state.close_status == '等待结果'">
+            </div>
+            <div class="load-result" v-if="state.close_status == '等待结果'">
+                <div class="title">
+                    <img :src="require('@/assets/svg/icon-enter-ed.svg')" alt />
+                    <span>Participate Successful</span>
+                </div>
+                <!-- 票 -->
+                <div class="ticket">
+                    <div class="div-ticket">
+                        <img :src="require('@/assets/svg/icon-ticket.svg')" alt />
+                    </div>
+                </div>
+                <p>Announcement Winner</p>
+                <div class="time">
+                    <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,
+                    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" />
+                </div>
+            </div>
+
+            <div class="luck-list-title" v-show="state.close_status != '等待结果'">
+                <div>{{ state.detail.receiveCount || 0 }}/{{ state.detail.totalCount || 0 }} Winners</div>
+                <div class="right" v-if="state.detail.rewardType === RewardType.money">
+                    <span class="text">
+                        <a-tooltip :title="state.detail.receiveAmountValue">
+                            {{ getBit(state.detail.receiveAmountValue) }}
+                        </a-tooltip>
+                        /
+                        <a-tooltip :title="state.detail.amountValue">
+                            {{ getBit(state.detail.amountValue || '') }}
+                        </a-tooltip>
+                    </span> {{
+                            state.detail.currencySymbol || ''
+                    }}
+                </div>
+            </div>
+
+            <div class="luck-list max" @scroll="handleScroll" v-show="state.close_status != '等待结果'">
+                <div class="luck-item" v-for="item, i in state.detail.allReceived" v-bind:key="i">
+                    <img v-if="item.simpleUserInfoVO.avatarUrl" :src="item.simpleUserInfoVO.avatarUrl" alt
+                        @click="openTwitterDetail(item)" />
+                    <img v-else :src="require('@/assets/svg/icon-twitter.svg')" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-1.svg')" v-if="i == 0" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-2.svg')" v-if="i == 1" alt />
+                    <img class="win" :src="require('@/assets/svg/icon-win-3.svg')" v-if="i == 2" alt />
+                    <div class="luck-content">
+                        <div class="luck-title" v-if="item.simpleUserInfoVO.nickName">{{ item.simpleUserInfoVO.nickName
+                        }}</div>
+                        <div class="luck-title" v-else>Twitter User</div>
+                        <div class="luck-time">{{ moment(item.receiveTimestamp).format('MM-DD HH:mm:ss') }}</div>
+                    </div>
+                    <div class="luck-money" v-if="state.detail.rewardType === RewardType.money">
+                        <img :src="state.detail.currencyIconPath" alt />
+                        <div class="luck-money-txt">
+                            <a-tooltip :title="item.amountValue">
+                                {{ getBit(item.amountValue) }}
+                            </a-tooltip>
+                        </div>
+                    </div>
+                    <div class="luck-custom-prize" v-else>winner</div>
+                    <div class="luck-king" v-if="state.detail.rewardType === RewardType.money && item.maxAmount">
+                        <img :src="require('@/assets/svg/icon-king-hat.svg')" alt />
+                        <span>Luckiest Draw</span>
+                    </div>
+                </div>
+
+                <div class="empty" v-show="state.detail.allReceived && state.detail.allReceived.length == 0">
+                    <img :src="require('@/assets/svg/icon-error.svg')" alt />
+                </div>
+            </div>
+            <get-more :reportData="{
+                pageSource: Report.pageSource.missingLotteryPage,
+                postId: state.postId,
+                redPacketType: Report.redPacketType.lottery
+            }" v-if="state.close_status != '等待结果'"></get-more>
+        </div>
+
+
+        <!-- error -->
+        <div v-else-if="state.status == 'error'" class="error">
+            <img :src="require('@/assets/svg/icon-error.svg')" alt />
+            <div class="txt">
+                {{ state.error_txt }}
+            </div>
+            <div class="retry" v-show="state.retry" @click="clickRetry">
+                Retry
+            </div>
+        </div>
+
+
+        <!-- loading -->
+        <div v-show="state.loading_show" class="loading">
+            <img :src="require('@/assets/svg/icon-loading.svg')" alt />
+        </div>
+
+        <div v-show="state.loading_redbag" class="redbag">
+            <img :src="require('@/assets/img/icon-loading-redbag.png')" alt />
+        </div>
+
+    </div>
+    <div style="width: 100%; height: 30px; position: fixed; color: red; top:0;"
+        v-if="state.process_mode != 'production'">
+        {{ state.detail.validity }}</div>
+</template>
+
+<script>
+export default {
+    name: 'redPacket',
+}
+</script>
+<script setup>
+import { onMounted, reactive, ref, computed } from "vue";
+import { getPostDetail, getRedPacket, finishRedPacket, oneKeyLike, oneKeyReTweet, oneKeyFollow, getTaskDetail, getReceivedList, addFinishEvent } from '@/http/redPacket.js'
+import { getQueryString, guid, getBit, formatSecondsAsDaysOrTime, iframeId } from '@/uilts/help.js'
+import { message } from 'ant-design-vue';
+import FontAmount from '@/components/font-amount.vue'
+// import FontZoom from '@/src/components/font-zoom.vue'
+import ComponentZoom from '@/components/component-zoom.vue'
+import GetMore from '@/components/get-more.vue'
+import { setChromeStorage, getChromeStorage, sendCurrentTabMessage, chromeExtensionUrl, getChromeStorageFromExtension, setChromeStoragetoExtension, openUrlInNewWindow } from '@/uilts/chromeExtension.js'
+import Report from "@/log-center/log"
+import { srcPublishSuccess } from '@/http/publishApi'
+import { discordAuthUrl, checkGuildJoined } from '@/http/discordApi'
+import { discordAuthRedirectUri, faceShareRedirectUrl } from '@/http/configAPI'
+import { getSetting, putSetting } from '@/http/user'
+import { getFrontConfig } from "@/http/account";
+import { getInviteGuildInfo } from "@/http/discordApi";
+import GlobalTip from '@/components/global-tip.vue';
+import customCardCover from '@/components/custom-card-cover.vue';
+import { RewardType, PlayType } from "@/types";
+import messageCenter from "@/uilts/messageCenter";
+
+var moment = require('moment');
+
+let discordAuthorizeRequired = false;
+let joinDiscordActionState = 'default'; //authAndJoinIng  joinIng  reAuth
+let joinDiscordIng = ref(false);
+
+let facebookAppConfig = {
+    facebookAppId: "",
+    faceShareRedirectUrl
+};
+
+let reportParams = {
+    discordFans: '',
+    twitterFans: '',
+    done: {
+    },
+    hasReport: false,
+}
+
+let discordTaskDetail = null;
+
+let state = reactive({
+    status: '',
+    userId: '',
+    loading_show: false,
+    loading_redbag: true,
+    detail: {},
+    luck_list_end: false,
+    page_index: 1,
+    page_size: 20,
+    srcContentId: '',
+    customCover: '',
+    customGiveaway: '',
+    error_txt: `oops, new accounts cannot participate in this event,`,
+    receiveAmount: 0,
+    money: 0,
+    // 状态
+    done: {
+        follow: false,
+        like: false,
+        retweet: false,
+        join_discord: false,
+        repost_facebook: false,
+        reply: false
+    },
+    notification_show: false,
+    notification_switch: false,
+    open_timer_status: false,
+    count_down_time: ''
+})
+
+let fullName = '';
+
+let successTopBgCpd = computed(() => {
+    const { rewardType } = state.detail
+    switch (rewardType) {
+        case RewardType.custom:
+            return require('@/assets/subject/success-top-bg-2.svg');
+        default:
+            return require('@/assets/subject/002-back-head-top-180.svg');
+            break;
+    }
+});
+
+function clickRetry() {
+    init()
+}
+
+let follow_open_tabs = []
+
+async function clickLikeBtn() {
+    let _userInfo = await checkIsLogin()
+    if (!_userInfo) {
+        return
+    }
+    state.detail.finishTaskTypeV2 = state.detail.finishTaskTypeV2.toString() || ''
+    if (state.window_origin.indexOf('facebook.com') >= 0) {
+        state.detail.finishTaskTypeV2 = '2'
+    }
+    switch (state.detail.finishTaskTypeV2) {
+        case '1':
+            state.loading_show = true
+            oneKeyLike({
+                params: {
+                    tweetId: state.srcContentId
+                }
+            }).then((res) => {
+                state.loading_show = false
+                if (res.code == 0) {
+                    if (res.data.result) {
+                        state.done.like = true
+                    } else {
+                        state.done.like = false
+                        window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+                    }
+                } else {
+                    window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+                    state.done.like = false
+                }
+            }).catch(() => {
+                state.loading_show = false
+            })
+            break
+        case '2':
+            window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+            break
+        case '3':
+            state.loading_show = true
+            messageCenter.send({
+                info: {
+                    actionType: "IFRAME_TWITTER_API_DO_TASK",
+                    iframeId
+                },
+                data: {
+                    task_data: {
+                        tweet_Id: state.tweetId
+                    },
+                    task_type: 'like'
+                },
+                overTime: 5000,
+                callback: (data) => {
+                    console.log('like success..', data)
+                    if (!data.task_type || state.tweetId != data.tweet_Id) {
+                        return
+                    }
+                    state.loading_show = false
+                    doTaskReport(data);
+                },
+                failback: e => { 
+                    state.loading_show = false
+                    console.log('like fail..', e)
+                }
+            })
+            break
+        default:
+            window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+            break
+    }
+
+    // 埋点
+    Report.reportLog({
+        objectType: Report.objectType.like,
+        pageSource: Report.pageSource.task_page,
+        businessType: Report.businessType.buttonClick,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+}
+function clickDone() {
+    window.open(`${chromeExtensionUrl + ('iframe/home.html')}`)
+    // 埋点
+    Report.reportLog({
+        objectType: Report.objectType.wallet_button,
+        pageSource: Report.pageSource.received_success_page,
+        businessType: Report.businessType.buttonClick,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        redPacketType: 1,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+}
+function handleScroll(e) {
+    if (state.luck_list_end) {
+        return
+    }
+    e = e.target
+    if ((e.clientHeight + e.scrollTop) / e.scrollHeight > .8) {
+        state.luck_list_end = true
+        state.page_index++
+        handleReceivedList()
+    }
+}
+function handleReceivedList() {
+    getReceivedList({
+        params: {
+            pageNum: state.page_index,
+            pageSize: state.page_size,
+            postId: state.postId
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            if (res.data.length > 0) {
+                state.detail.allReceived = state.detail.allReceived.concat(res.data)
+                state.luck_list_end = false
+            } else {
+                state.luck_list_end = true
+            }
+        } else {
+            console.log('getReceivedList', res)
+        }
+    })
+}
+
+const openTwitterDetail = (item) => {
+    if (item.simpleUserInfoVO.nickName) {
+        window.open(`https://twitter.com/${item.simpleUserInfoVO.nickName}`)
+    }
+}
+
+async function clickRetweetBtn() {
+    let _userInfo = await checkIsLogin()
+    if (!_userInfo) {
+        return
+    }
+
+    state.detail.finishTaskTypeV2 = state.detail.finishTaskTypeV2.toString() || ''
+    if (state.window_origin.indexOf('facebook.com') >= 0) {
+        state.detail.finishTaskTypeV2 = '2'
+    }
+    switch (state.detail.finishTaskTypeV2) {
+        case '1':
+            state.loading_show = true
+            oneKeyReTweet({
+                params: {
+                    tweetId: state.srcContentId
+                }
+            }).then((res) => {
+                state.loading_show = false
+                if (res.code == 0) {
+                    if (res.data.result) {
+                        state.done.retweet = true
+                    } else {
+                        window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
+                        state.done.retweet = false
+                    }
+                } else {
+                    window.open(`https://twitter.com/retweet/like?tweet_id=${state.tweetId}`)
+                    state.done.retweet = false
+                }
+            }).catch(() => {
+                state.loading_show = false
+            })
+            break;
+        case '2':
+            window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
+            break
+        case '3':
+            state.loading_show = true
+            messageCenter.send({
+                info: {
+                    actionType: "IFRAME_TWITTER_API_DO_TASK",
+                    iframeId
+                },
+                data: {
+                    task_data: {
+                        tweet_Id: state.tweetId
+                    },
+                    task_type: 'retweet'
+                },
+                overTime: 5000,
+                callback: (data) => {
+                    console.log('retweet success..', data)
+                    if (!data.task_type || state.tweetId != data.tweet_Id) {
+                        return
+                    }
+                    state.loading_show = false
+                    doTaskReport(data);
+                },
+                failback: e => { 
+                    state.loading_show = false
+                    console.log('retweet fail..', e)
+                }
+            })
+            break
+        default:
+            window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
+            break;
+    }
+
+    // 埋点
+    Report.reportLog({
+        objectType: Report.objectType.retweet,
+        pageSource: Report.pageSource.task_page,
+        businessType: Report.businessType.buttonClick,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+}
+
+function onTweetReplyClick(params) {
+    let replyData = {
+        postId: state.postId,
+        type: params.type,
+        taskLuckdropId: state.detail.taskLuckdropId
+    }
+
+    window.parent.postMessage({ actionType: "IFRAME_RED_PACKET_ON_TWEET_REPLY_CLICK", data: replyData }, "*");
+}
+
+function changeNotification(checked) {
+    let noticeSwitch = checked ? 1 : 0;
+    // set
+    putSetting({
+        params: { noticeSwitch }
+    }).then(res => {
+        let { code } = res;
+        if (code === 0) {
+            state.notification_switch = checked
+        } else {
+            state.notification_switch = !checked
+        }
+    }).catch(() => {
+        state.notification_switch = !checked
+    })
+}
+
+function setNotification(req) {
+    state.notification_switch = req.status;
+}
+
+async function clickReply(params) {
+    let _userInfo = await checkIsLogin()
+    if (!_userInfo) {
+        return
+    }
+
+    let replyData = {
+        postId: state.postId,
+        type: params.type,
+        taskLuckdropId: state.detail.taskLuckdropId
+    }
+    if (state.window_origin.indexOf('facebook.com') > -1) {
+        let url = `https://twitter.com/${state.tweet_author}/status/${state.tweetId}?actionType=denetFacebookToTwitterReply&deReplyParams=${JSON.stringify(replyData)}`
+        window.open(url)
+    } else {
+        messageCenter.send({
+            info: {
+                actionType: "IFRAME_RED_PACKET_REPLY_CLICK",
+                iframeId
+            },
+            data: replyData
+        })
+        // window.parent.postMessage({ actionType: "IFRAME_RED_PACKET_REPLY_CLICK", data: replyData }, "*");
+    }
+
+    // 埋点
+    Report.reportLog({
+        objectType: Report.objectType.comment_and_tag,
+        pageSource: Report.pageSource.task_page,
+        businessType: Report.businessType.buttonClick,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        redPacketType: 1,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+}
+
+/**
+ * 点击repost facebook
+ */
+async function clickRepostFacebook(params) {
+    let _userInfo = await checkIsLogin()
+    if (!_userInfo) {
+        return
+    }
+
+    let deUrlParams = {
+        fullName,
+        tweetId: state.tweetId
+    }
+    let href = `${state.postRedirectUrl}?deUrlParams=${JSON.stringify(deUrlParams)}`;
+    console.log(href);
+    let shareUrlparams = {
+        href,
+        type: params.type,
+        taskLuckdropId: state.detail.taskLuckdropId
+    }
+
+    setChromeStoragetoExtension({
+        shareFacebookData: JSON.stringify({
+            contentStr: state.srcContent
+        })
+    })
+
+    // setChromeStorage({
+    //     shareFacebookData: JSON.stringify({
+    //         contentStr: state.srcContent
+    //     })
+    // })
+
+    let shareUrl = feacebookShareUrl(shareUrlparams);
+    openShareFacebookWindow({ url: shareUrl });
+
+    // 埋点
+    Report.reportLog({
+        objectType: Report.objectType.share_facebook,
+        pageSource: Report.pageSource.task_page,
+        businessType: Report.businessType.buttonClick,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        redPacketType: 1,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+}
+
+/**
+ * 分享到facebook
+ */
+function openShareFacebookWindow({ url }) {
+    const width = 800;
+
+    openUrlInNewWindow({
+        width,
+        type: 'normal',
+        url
+    })
+}
+
+/**
+ * 分享fecebook 地址
+ */
+function feacebookShareUrl(params = {}) {
+    let { href = '', type = '', taskLuckdropId } = params;
+    let cbParams = JSON.stringify({
+        type,
+        taskLuckdropId
+    })
+    let shareUrl = `https://www.facebook.com/dialog/share?app_id=${facebookAppConfig.facebookAppId}&display=popup&href=${href}&redirect_uri=${facebookAppConfig.faceShareRedirectUrl}?params=${cbParams}`;
+
+    return shareUrl;
+}
+
+/**
+ * 分享成功
+ */
+function facebookShareSuccess(params) {
+    let { taskLuckdropId } = params;
+
+    if (taskLuckdropId == state.detail.taskLuckdropId) {
+        state.done.repost_facebook = true;
+        state.done.repost_facebook_red = false;
+    }
+}
+
+
+function getValidity() {
+    let _d1, _d2, _d3, _h, _m, _s
+    if (!state.detail.myReceived.taskEndTimestamp) {
+        return
+    }
+    let timer = setInterval(() => {
+        let _time = new Date().getTime()
+        _d3 = state.detail.myReceived.taskEndTimestamp - _time
+        if (_d3 > 0) {
+            _d1 = moment(state.detail.myReceived.taskEndTimestamp)
+            _d2 = moment(_time)
+            _h = moment.duration(_d1.diff(_d2)).hours()
+            if (_h < 10) {
+                _h = '0' + _h
+            }
+            _m = moment.duration(_d1.diff(_d2)).minutes()
+            if (_m < 10) {
+                _m = '0' + _m
+            }
+            _s = moment.duration(_d1.diff(_d2)).seconds()
+            if (_s < 10) {
+                _s = '0' + _s
+            }
+            state.detail.validity = `${_h}:${_m}:${_s}`
+        } else {
+            state.detail.validity = `00:00:00`
+            clearInterval(timer)
+        }
+    }, 1000)
+}
+
+// 倒计时
+const getTimeStr = (end_time_ms) => {
+    let now_time_ms, now_time, end_time
+    let _time, _h, _m, _s, _time_str
+    now_time_ms = new Date().getTime()
+    _time = end_time_ms - now_time_ms
+    if (_time > 0) {
+        now_time = moment(now_time_ms)
+        end_time = moment(end_time_ms)
+        _h = moment.duration(end_time.diff(now_time)).hours()
+        _m = moment.duration(end_time.diff(now_time)).minutes()
+        _s = moment.duration(end_time.diff(now_time)).seconds()
+        if (_h < 10) {
+            _h = '0' + _h
+        }
+        if (_m < 10) {
+            _m = '0' + _m
+        }
+        if (_s < 10) {
+            _s = '0' + _s
+        }
+        _time_str = `${_h}:${_m}:${_s}`
+    } else {
+        _time_str = `00:00:00`
+    }
+    return _time_str
+}
+
+function openConutDownTime(end_time_ms, callback) {
+    end_time_ms = Number(end_time_ms) + 5000
+    let end_time_s = Number((end_time_ms - new Date().getTime()) / 1000)
+    let timer = setInterval(() => {
+        end_time_s = Number((end_time_ms - new Date().getTime()) / 1000)
+        if (state.open_timer_status == true) {
+            clearInterval(timer)
+        }
+        callback(formatSecondsAsDaysOrTime(end_time_s))
+    }, 1000);
+    callback(formatSecondsAsDaysOrTime(end_time_s))
+}
+
+const openFollowTabs = (arr_name) => {
+    let array_finish = arr_name.filter((item) => { return !item.finished })
+    // let array_finish = state.detail.taskCondition[0].relatedUsers.filter((item) => { return item.finished == false })
+    let url
+    if (array_finish.length > 0) {
+        state.done.follow = false
+        // 打开标签页的方法
+        array_finish.forEach((item) => {
+            url = `https://twitter.com/intent/follow?screen_name=${item.name}&tweet_id=${state.tweetId}`
+            chrome.tabs.create({ url }, (tab) => {
+                if (follow_open_tabs.filter((item) => { return item.url == tab.url }).length == 0) {
+                    follow_open_tabs.push(tab)
+                }
+            })
+        })
+    }
+}
+
+async function clickFollowAll(item, is_all) {
+    let _userInfo = await checkIsLogin()
+    console.log(_userInfo)
+    if (!_userInfo) {
+        return
+    }
+    let arr_name = []
+    for (let i in item) {
+        if (!item[i].finished) {
+            arr_name.push(item[i])
+        }
+    }
+    // ----
+    state.detail.finishTaskTypeV2 = state.detail.finishTaskTypeV2.toString() || ''
+    if (state.window_origin.indexOf('facebook.com') >= 0) {
+        state.detail.finishTaskTypeV2 = '2'
+    }
+    switch (state.detail.finishTaskTypeV2) {
+        case '1':
+            // openapi
+            state.loading_show = true
+            oneKeyFollow({
+                params: {
+                    names: arr_name
+                }
+            }).then((res) => {
+                state.loading_show = false
+                if (res.code == 0) {
+                    res.data.forEach((item1) => {
+                        state.detail.taskCondition[0].relatedUsers.forEach(item2 => {
+                            if (item1.name == item2.name && item1.finished) {
+                                item2.finished = true
+                            }
+                        });
+                    })
+                    openFollowTabs(arr_name)
+                }
+            }).catch(() => {
+                state.loading_show = false
+            })
+            break
+        case '2':
+            openFollowTabs(arr_name)
+            break
+        case '3':
+            if (arr_name.filter((item) => { return !item.twitterUserId }).length > 0) {
+                openFollowTabs(arr_name)
+                return
+            }
+            let follow_data = []
+            arr_name.forEach((item) => {
+                follow_data.push(item)
+            })
+            state.loading_show = true
+            messageCenter.send({
+                info: {
+                    actionType: "IFRAME_TWITTER_API_DO_TASK",
+                    iframeId
+                },
+                data: {
+                    task_data: {
+                        tweet_Id: state.tweetId,
+                        follow_data: follow_data,
+                    },
+                    task_type: 'follow'
+                },
+                overTime: 5000,
+                callback: (data) => { 
+                    console.log('follow success..', data)
+                    if (!data.task_type || state.tweetId != data.tweet_Id) {
+                        return
+                    }
+                    state.loading_show = false
+                    doTaskReport(data);
+                },
+                failback: e => { 
+                    state.loading_show = false
+                    console.log('follow fail..', e)
+                }
+            })
+            break
+        default:
+            openFollowTabs(arr_name)
+            break
+    }
+    // -------- 埋点 --------
+    let _log_obj = {
+        pageSource: Report.pageSource.task_page,
+        businessType: Report.businessType.buttonClick,
+        objectType: Report.objectType.follow,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    }
+    if (is_all) {
+        _log_obj.objectType = Report.objectType.follow_button
+    }
+    Report.reportLog(_log_obj, {
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+    });
+}
+
+
+// 重新绑定
+const reSetBindTwtterId = async (_params) => {
+    let postBizData = JSON.parse(_params.postBizData);
+    let { taskCondition } = postBizData;
+    let discordTask = JSON.parse(taskCondition).find(item => item.type == 7);
+
+    const _userInfo = await getChromeStorageFromExtension('userInfo')
+    if (_userInfo && _userInfo.uid) {
+            srcPublishSuccess({
+                params: {
+                    postId: state.postId,
+                    srcContentId: state.tweetId
+                }
+            }).then((res) => {
+                if (res.code == 0 || res.code == 3003) {
+                    init({ from: 'reSetBindTwtterId' })
+                    reportBindTweetSuccess({ discordTask, ..._params });
+                }
+            })
+        }
+}
+
+const reportBindTweetSuccess = (params) => {
+    let { discordTask, srcUserId } = params || {};
+    discordTaskDetail = discordTask;
+    messageCenter.send({
+        info: {
+            actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
+            iframeId
+        },
+        data: {
+            screen_name: srcUserId,
+            tweetId: state.tweetId
+        },
+        callback: (req) => {
+            let { user } = req.data || {};
+                if (req.tweetId == state.tweetId && 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
+                            });
+                        }
+                    }
+                }
+        },
+        failback: (e) => {
+            console.log('reportBindTweetSuccess fail', e)
+        }
+    })
+    sendCurrentTabMessage({
+        actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
+        data: {
+            screen_name: srcUserId,
+            tweetId: state.tweetId
+        }
+    })
+
+    if (discordTask) {
+        getDiscordInfo({ inviteUrl: JSON.parse(discordTask.bizData).inviteUrl }, (res) => {
+            if (res.inviteCode == res.code) {
+                reportParams.discordFans = res.approximate_member_count;
+
+                if (reportParams.twitterFans !== '' && !reportParams.hasReport) {
+                    reportParams.hasReport = true;
+                    Report.reportLog({
+                        objectType: Report.objectType.tweetPostBinded,
+                        twitterFans: reportParams.twitterFans,
+                        discordFans: reportParams.discordFans,
+                        redPacketType: 1,
+                        postId: state.postId
+                    });
+                }
+            }
+        })
+    }
+}
+
+const getDiscordInfo = (params, cb) => {
+    let { inviteUrl } = params;
+    if (!inviteUrl) return;
+
+    let inviteCode = '';
+    let arr = inviteUrl.split('/');
+    if (arr.length > 0) {
+        inviteCode = arr[arr.length - 1];
+    }
+    if (!inviteCode) {
+        return;
+    }
+
+    getInviteGuildInfo({
+        inviteCode
+    }).then(res => {
+        cb && cb({
+            ...res,
+            inviteCode
+        })
+    }).catch((err) => {
+    });
+}
+
+const showCloseEndTimePage = () => {
+    state.status = 'close'
+    state.open_timer_status = true
+    state.close_status = '已经过期了'
+    state.close_text = [`This Giveaways`, `expired on ${moment(state.detail.endTimestamp).format('MM-DD')}`]
+}
+
+const showCloseEndTimePageReport = () => {
+    // 埋点
+    Report.reportLog({
+        pageSource: Report.pageSource.expired_page,
+        businessType: Report.businessType.pageView,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+    });
+}
+
+const showSuccessPage = () => {
+    state.status = 'success'
+    state.open_timer_status = true;
+
+    if (!reportParams.reportReceivedPageViewSuccess) {
+        reportParams.reportReceivedPageViewSuccess = true;
+
+        // 埋点
+        Report.reportLog({
+            pageSource: Report.pageSource.received_success_page,
+            businessType: Report.businessType.pageView,
+            postId: state.postId,
+            srcContentId: state.tweetId,
+            senderId: state.userId,
+            isOldTwitterFans: reportParams.done.follow,
+            isOldDiscordFans: reportParams.done.join_discord,
+            redPacketType: 1,
+            customCover: state.customCover,
+            customGiveaway: state.customGiveaway,
+        });
+    }
+}
+
+const showNotOpenPage = () => {
+    state.status = 'not-open'
+    openConutDownTime(state.detail.endTimestamp, (time_str) => {
+        state.count_down_time = time_str
+        if (time_str == '00:00:00') {
+            init()
+        }
+    })
+    Report.reportLog({
+        pageSource: Report.pageSource.pending_page,
+        businessType: Report.businessType.pageView,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        redPacketType: 1,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+}
+const showOpenedPage = () => {
+    state.status = 'opened'
+    state.open_timer_status == true
+    initTaskDetail(() => {
+        showOpenedPageReport()
+    })
+}
+const showOpenedPageReport = () => {
+    reportParams.done.follow = state.done.follow;
+    reportParams.done.join_discord = state.done.join_discord;
+
+    // 埋点
+    Report.reportLog({
+        pageSource: Report.pageSource.task_page,
+        businessType: Report.businessType.pageView,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        isOldTwitterFans: state.done.follow,
+        isOldDiscordFans: state.done.join_discord,
+        redPacketType: 1,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+}
+
+const showRabbitPage = () => {
+    state.status = 'close'
+    state.close_status = '没有抽中'
+    state.open_timer_status = true
+}
+const showRabbitPageReport = () => {
+    Report.reportLog({
+        pageSource: Report.pageSource.received_empty_rewards_page,
+        businessType: Report.businessType.pageView,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+    });
+}
+const handleStatusPage = () => {
+    // status 红包状态(0:未开始,1:进行中,2:已结束,3:已终止,4:终止退款进行中)
+    // myReceived 我是否领取过
+    // taskFinishStatus 任务完成状态(0:未完成,1:已完成,2:已过期)
+    // receiveTimeExpired 是否已经过了红包的领取截止时间
+    // endTimestamp 开奖时间
+
+    // ---- 判断结构 ----
+    // 如果 红包状态 = 未开始
+    //    显示未打开页面 return
+
+    // 如果 红包状态 =  已终止 | 终止退款进行中
+    //      显示过期页面
+    // 如果 我领取过了
+    //    如果 任务完成状态 = 未完成 & 红包状态 = 进行中
+    //         显示任务未完成页面
+    //    如果 任务完成状态 = 未完成 & 红包状态 = 已结束
+    //         显示过期页面
+    //    如果 任务完成状态 = 已经完成
+    //        如果 (货币奖品类型 领取到红包金额 = 0 || 通用奖品类型 winner = 0) & 红包状态 = 已结束
+    //            显示兔子页面
+    //        否则如果 红包状态 = 已结束
+    //            显示成功页面
+    //        如果 红包状态 = 进行中
+    //            显示等待结果页面
+
+    //    如果 任务完成状态 = 已经过期
+    //        如果 红包状态 = 进行中
+    //            显示未打开页面
+    //        否则
+    //            显示已经过期页面
+
+    // 如果 我没有领取过 & 红包状态 = 进行中
+    //    如果 过了红包的领取截止时间 = true
+    //        显示已经过期页面
+    //    如果 过了红包的领取截止时间 = false
+    //        显示未打开页面
+
+    // 如果 我没有领取过 & 红包状态 = 已结束 | 已终止 | 终止退款进行中
+    //    显示过期页面
+
+    // -------- 华丽的分割线 --------
+    // 如果 红包状态 = 未开始
+
+    if (state.detail.status == 0) {
+        showNotOpenPage()
+        return
+    }
+    // 如果 红包状态 =  已终止 | 终止退款进行中
+    if (state.detail.status == 3 || state.detail.status == 4) {
+        //      显示过期页面
+        showCloseEndTimePage()
+        showCloseEndTimePageReport()
+    }
+    // 如果 我领取过了
+    else if (state.detail.myReceived) {
+        state.receiveAmount = state.detail.myReceived.amountValue || 0
+        state.detail.taskCondition = JSON.parse(state.detail.taskCondition)
+        // 如果 任务完成状态 = 未完成 & 红包状态 = 进行中
+        if (state.detail.myReceived.taskFinishStatus == 0 && state.detail.status == 1) {
+            // 显示任务未完成页面
+            showOpenedPage()
+            if (state.process_mode != 'production') {
+                getValidity()
+            }
+            //    如果 任务完成状态 = 未完成 & 红包状态 = 已结束
+            else if (state.detail.myReceived.taskFinishStatus == 0 && state.detail.status == 2) {
+                // 显示已经过期页面
+                showCloseEndTimePage()
+                showCloseEndTimePageReport()
+            }
+            //如果 任务完成状态 = 已经完成
+        } else if (state.detail.myReceived.taskFinishStatus == 1) {
+            // 领取到空红包 & 红包状态 = 已结束
+            if (((state.detail.rewardType === RewardType.money && state.receiveAmount == 0) || (state.detail.rewardType === RewardType.custom && state.detail.myReceived.winner === 0)) && state.detail.status == 2) {
+                showRabbitPage()
+                showRabbitPageReport()
+            } else if (state.detail.status == 2) {
+                // 显示成功页面
+                showSuccessPage()
+            }
+            // 如果  红包状态 = 进行中
+            else if (state.detail.status == 1) {
+                // 显示等待结果页面
+                showLoadResult()
+                openTimer()
+            }
+            // 如果 任务完成状态 = 已经过期
+        } else {
+            // 如果 红包状态 = 进行中
+            if (state.detail.status == 1) {
+                // 显示未打开页面
+                showNotOpenPage()
+                // 否则
+            } else {
+                // 显示已经过期页面
+                showCloseEndTimePage()
+                showCloseEndTimePageReport()
+            }
+        }
+        // 如果 我没有领取过
+    } else {
+        // 如果 红包状态 = 进行中
+        if (state.detail.status == 1) {
+            // 如果 过了红包的领取截止时间 = true
+            if (state.detail.receiveTimeExpired) {
+                // 显示过期页面
+                showCloseEndTimePage()
+                showCloseEndTimePageReport()
+                // 如果 过了红包的领取截止时间 = false
+            } else {
+                // 显示未打开页面
+                showNotOpenPage()
+            }
+            // 红包状态 = 已经结束了 | 已经终止 | 终止退款中
+        } else {
+            // 显示过期页面
+            showCloseEndTimePage()
+            showCloseEndTimePageReport()
+        }
+    }
+
+}
+
+function setFrontConfig() {
+    getFrontConfig({
+        params: {},
+    }).then((res) => {
+        if (res.code == 0) {
+            facebookAppConfig.facebookAppId = res.data.fbClientId;
+        }
+    });
+};
+
+function init(initParams) {
+    let { type } = initParams || {};
+    onPageVisbile();
+    onWindowMessage();
+    setFrontConfig();
+    getPostDetail({
+        params: {
+            postId: state.postId
+        }
+    }).then((res) => {
+        state.loading_show = false
+        // 领取0元为空红包继续流程
+        // ---- 完成任务接口 ----
+        // 如果金额是0
+        //    显示没有抽中
+        if (res.code == 0) {
+            state.srcContent = res.data.srcContent;
+            state.postRedirectUrl = res.data.postRedirectUrl;
+
+            // 判断推特id,绑定逻辑
+            state.srcContentId = res.data.srcContentId
+
+            if (!state.srcContentId) {
+                reSetBindTwtterId(res.data)
+                return
+            }
+            state.detail = JSON.parse(res.data.postBizData)
+            state.detail.taskCondition = state.detail.taskCondition || []
+            state.tweetId = state.srcContentId;
+            state.userId = res.data.srcUserId;
+            state.tweet_author = state.detail.postUserInfo && state.detail.postUserInfo.nickName || '';
+            state.customCover = state.detail.posterType == 2 ? 1 : 0;
+            state.customGiveaway = state.detail.rewardType == 2 ? 1 : 0;
+            // 不要删除这个console
+            console.log('postBizData', state.detail)
+            checkFacebookReply();
+            handleStatusPage()
+        } else {
+            handleErrorCode(res)
+        }
+    }).finally(() => {
+        state.loading_redbag = false
+    })
+}
+
+async function initTaskDetail(cb) {
+    const _userInfo = await getChromeStorageFromExtension('userInfo')
+    console.log('_userInfo', _userInfo)
+
+    if (_userInfo && _userInfo.uid) {
+            // 任务详情
+            getTaskDetail({
+                params: {
+                    postId: state.postId
+                }
+            }).then((res) => {
+                if (res.code.toString()) {
+                    for (let i in res.data) {
+                        switch (res.data[i].type) {
+                            case 1:
+                                state.done.follow = res.data[i].finished
+                                state.detail.taskCondition[0].relatedUsers = res.data[i].detail
+                                break
+                            case 2:
+                                state.done.like = res.data[i].finished
+                                break
+                            case 3:
+                                state.done.retweet = res.data[i].finished
+                                break
+                            case 7:
+                                state.done.join_discord = res.data[i].finished
+                                discordAuthorizeRequired = res.data[i].discordAuthorizeRequired
+                                break
+                            case 8:
+                                state.done.repost_facebook = res.data[i].finished;
+                                break;
+                            case 9:
+                                state.done.reply = res.data[i].finished;
+                                if (!state.done.reply) {
+                                    onTweetReplyClick({ type: 9 });
+                                }
+                                break;
+                        }
+                    }
+                } else {
+                    handleErrorCode(res)
+                }
+                cb && cb()
+            })
+        }
+}
+
+let tab_index = 0
+const doTaskReport = (req, sender) => {
+    state.loading_show = false
+    let follow_name = req.task_data.follow_name || ''
+    // 1 Twitter follow Twitter ScreenName
+    // 2 Tweet like
+    // 3 Retweet
+    let event_type = 0
+    switch (req.task_type) {
+        case 'retweet':
+            event_type = 3
+            state.done.retweet = req.task_done
+            if (!req.task_done && req.do_type == 'api') {
+                window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
+            }
+            break;
+        case 'like':
+            event_type = 2
+            state.done.like = req.task_done
+            //
+            if (!req.task_done && req.do_type == 'api') {
+                window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+            }
+            break
+        case 'follow':
+            event_type = 1
+            // for (let i = 0; i < follow_open_tabs.length; i++) {
+            //   if (follow_open_tabs[i].id == sender.tab.id) {
+            //     follow_open_tabs.splice(i, 1)
+            //     break
+            //   }
+            // }
+            // chrome.tabs.getCurrent((tab) => {
+            //   if (follow_open_tabs.length > 0) {
+            //     tab_index = follow_open_tabs[follow_open_tabs.length - 1].index
+            //   } else {
+            //     tab_index = tab.index
+            //   }
+            //   chrome.tabs.highlight({ windowId: tab.windowId, tabs: tab_index })
+            // })
+            let has_no_finished = false
+            state.detail.taskCondition[0].relatedUsers.forEach((item) => {
+                if (follow_name == item.name) {
+                    item.finished = req.task_done
+                }
+            })
+            state.detail.taskCondition[0].relatedUsers.forEach((item) => {
+                if (!item.finished) {
+                    has_no_finished = true
+                }
+            })
+            if (!has_no_finished) {
+                state.done.follow = true
+                state.done.follow_red = false
+                openFollowTabs(state.detail.taskCondition[0].relatedUsers)
+            }
+            break
+    }
+    if (req.do_type != 'api') {
+        chrome.tabs.remove(sender.tab.id)
+    }
+    if (req.task_done) {
+        addFinishEvent({
+            params: {
+                eventData: follow_name,
+                eventType: event_type,
+                luckdropId: state.detail.taskLuckdropId
+            }
+        })
+    }
+}
+
+let open_timer_flag = false
+// 倒计时开奖
+const openTimer = () => {
+    if (open_timer_flag) {
+        return
+    }
+    open_timer_flag = true
+
+    openConutDownTime(state.detail.endTimestamp, (time_str) => {
+        state.count_down_time = time_str
+        if (time_str == '00:00:00') {
+            init()
+        }
+    })
+}
+
+async function showLoadResult() {
+    state.status = 'close'
+    state.close_status = '等待结果'
+    const _userInfo = await getChromeStorageFromExtension('userInfo')
+    if (_userInfo) {
+        getUserSetting()
+    }
+}
+
+const getUserSetting = () => {
+    getSetting({}).then((res) => {
+        let { code, data } = res;
+        if (code === 0) {
+            state.notification_show = true
+            state.notification_switch = data.noticeSwitch === 1 ? true : false;
+        }
+    });
+}
+
+onMounted(() => {
+    state.process_mode = process.env.NODE_ENV
+    state.postId = getQueryString('postId')
+    state.window_origin = getQueryString('window_origin') || '';
+    if (state.window_origin.indexOf('twitter.com') > -1) {
+        state.tweetId = getQueryString('tweetId')
+        state.tweet_author = getQueryString('tweet_author');
+    }
+
+    getTweetAuthor()
+    init()
+    onRuntimeMsg();
+    // state.loading_show = true
+    // state.status = 'not-open'
+    // state.status = 'success'
+    // state.status = 'close'
+    // state.close_status = '已经过期了'
+    // state.close_text = [`This Giveaways`, `expired on ${moment(state.detail.endTimestamp).format('MM-DD')}`]
+    // state.close_status = '没有抽中'
+    // state.close_status = '已过期'
+
+})
+
+function getTweetAuthor() {
+    if (state.window_origin.indexOf('twitter.com') > -1) {
+        messageCenter.send({
+            info: {
+                actionType: "IFRAME_RED_PACKET_GET_TWEET_AUTHOR",
+                iframeId
+            },
+            data: {
+                postId: state.postId,
+                taskLuckdropId: state.detail.taskLuckdropId
+            },
+            callback: (data) => { 
+                console.log('getTweetAuthor', data)
+                fullName = data.fullName
+            },
+            failback: (e) => {
+                console.log('getTweetAuthor fail..', e)
+            }
+        })
+    }
+}
+
+function checkFacebookReply() {
+    if (state.window_origin.indexOf('twitter.com') > -1) {
+        messageCenter.send({
+            info: {
+                actionType: "IFRAME_RED_PACKET_CHECK_FACEBOOK_REPLY",
+                iframeId
+            },
+            data: { postId: state.postId },
+            callback: (data) => { 
+                clickReply(data)
+            },
+            failback: (e) => {
+                console.log('checkFacebookReply fail', e)
+            }
+        })
+        // window.parent.postMessage({
+        //     actionType: "IFRAME_RED_PACKET_CHECK_FACEBOOK_REPLY", data: {
+        //         postId: state.postId
+        //     }
+        // }, "*");
+    }
+}
+
+// 点击领取
+function clickOpenRedPacket() {
+    messageCenter.send({
+        info: {
+            actionType: 'CONTENT_GET_PINED',
+        },
+        data: {}
+    })
+    // callEventPageMethod('CONTENT_GET_PINED', {})
+    handleRedPacket()
+}
+
+function handleRedPacket() {
+    state.loading_show = true
+    getRedPacket({
+        params: {
+            postId: state.postId
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            init()
+        } else {
+            state.loading_show = false
+            handleErrorCode(res)
+        }
+    }).catch(() => {
+        state.loading_show = false
+    })
+    // 埋点
+    Report.reportLog({
+        pageSource: Report.pageSource.pending_page,
+        businessType: Report.businessType.buttonClick,
+        objectType: Report.objectType.open_button,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        redPacketType: 1,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+}
+
+// chrome.storage.onChanged.addListener(changes => {
+//     if (changes.userInfo && changes.userInfo.newValue) {
+//         // let item = JSON.parse(changes.userInfo.newValue)
+//         state.loading_show = false
+//         init()
+//     }
+// })
+
+// 校验是否封路
+async function checkIsLogin() {
+    const userInfo = await getChromeStorageFromExtension('userInfo').catch((e) => { console.log(e)})
+    if (userInfo) {
+        return userInfo
+    } else {
+        state.loading_show = true
+        setTimeout(() => {
+            state.loading_show = false
+        }, 3000)
+        messageCenter.send({
+            info: {
+                actionType: 'POPUP_LOGIN',
+            },
+            data: {}
+        })
+        return null
+    }
+}
+
+async function clickGetGiveaways() {
+    let _userInfo = await checkIsLogin()
+    if (_userInfo) {
+        handleFinishRedPacket()
+    }
+}
+
+function handleFinishRedPacket() {
+    state.loading_show = true
+    finishRedPacket({
+        params: {
+            postId: state.postId
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            if (res.data.finished) {
+                state.receiveAmount = res.data.receiveAmount
+                init()
+                // 埋点
+                Report.reportLog({
+                    pageSource: Report.pageSource.task_page,
+                    businessType: Report.businessType.buttonClick,
+                    objectType: Report.objectType.get_giveaway,
+                    postId: state.postId,
+                    srcContentId: state.tweetId,
+                    senderId: state.userId,
+                    customCover: state.customCover,
+                    customGiveaway: state.customGiveaway,
+                }, {
+                    get_giveaway_result: Report.extParams.success
+                });
+            } else {
+                state.loading_show = false
+                let _data = res.data.conditionResult
+                for (let i in _data) {
+                    switch (_data[i].type.toString()) {
+                        case '1':
+                            state.detail.taskCondition[0].relatedUsers = _data[i].detail
+                            if (_data[i].finished) {
+                                state.done.follow = true
+                                state.done.follow_red = false
+                            } else {
+                                // alert('Please complete the task: follow')
+                                state.done.follow = false
+                                state.done.follow_red = true
+                            }
+                            break
+                        case '2':
+                            if (_data[i].finished) {
+                                state.done.like = true
+                                state.done.like_red = false
+                            } else {
+                                // alert('Please complete the task: like tweet')
+                                state.done.like = false
+                                state.done.like_red = true
+                            }
+                            break
+                        case '3':
+                            if (_data[i].finished) {
+                                state.done.retweet = true
+                                state.done.retweet_red = false
+                            } else {
+                                // alert('Please complete the task: Retweet')
+                                state.done.retweet_red = true
+                                state.done.retweet = false
+                            }
+                            break
+                        case '7':
+                            //join discord
+                            discordAuthorizeRequired = _data[i].discordAuthorizeRequired;
+                            if (_data[i].finished) {
+                                state.done.join_discord = true
+                                state.done.join_discord_red = false
+                            } else {
+                                state.done.join_discord = false;
+                                state.done.join_discord_red = true
+                            }
+                            break
+                        case '8':
+                            //repost feacebook
+                            if (_data[i].finished) {
+                                state.done.repost_facebook = true
+                                state.done.repost_facebook_red = false
+                            } else {
+                                state.done.repost_facebook = false;
+                                state.done.repost_facebook_red = true
+                            }
+                            break
+                        case '9':
+                            //reply
+                            if (_data[i].finished) {
+                                state.done.reply = true
+                                state.done.reply_red = false
+                            } else {
+                                state.done.reply = false;
+                                state.done.reply_red = true
+                            }
+                            break
+                    }
+                }
+                // 埋点
+                Report.reportLog({
+                    pageSource: Report.pageSource.task_page,
+                    businessType: Report.businessType.buttonClick,
+                    objectType: Report.objectType.get_giveaway,
+                    postId: state.postId,
+                    srcContentId: state.tweetId,
+                    senderId: state.userId,
+                    customCover: state.customCover,
+                    customGiveaway: state.customGiveaway,
+                }, {
+                    get_giveaway_result: Report.extParams.failure,
+                });
+                if (discordAuthorizeRequired) {
+                    discordAuth('reAuth');
+                }
+            }
+        } else {
+            state.loading_show = false
+            // 埋点
+            Report.reportLog({
+                pageSource: Report.pageSource.task_page,
+                businessType: Report.businessType.buttonClick,
+                objectType: Report.objectType.get_giveaway,
+                postId: state.postId,
+                srcContentId: state.tweetId,
+                senderId: state.userId,
+                customCover: state.customCover,
+                customGiveaway: state.customGiveaway,
+            }, {
+                get_giveaway_result: Report.extParams.failure,
+            });
+            handleErrorCode(res)
+        }
+    }).catch(() => {
+        state.loading_show = false
+    })
+}
+
+
+function handleErrorCode(res) {
+    switch (res.code.toString()) {
+        // 数据异常,请联系管理员
+        case '-102':
+
+            break
+        //系统错误
+        case '-101':
+
+            break
+
+        // 参数不对
+        case '-103':
+            break
+        // 接口被限流
+        case '-105':
+            break
+
+        // 访问凭证不存在
+        case '-107':
+            break
+        // 重复操作过于频繁
+        case '-106':
+            message.error('Clicking too often, wait a moment and click again')
+            state.loading_show = false
+            break
+        // 红包不存在
+        case '2001':
+            // message.error(res.msg)
+            break
+        // 还未到红包领取时间
+        case '2002':
+            // message.error(res.msg)
+            break
+        // 已超过红包领取时间
+        case '2003':
+            init()
+            break
+        // 红包支付状态异常 没有可提交的任务红包
+        case '2004':
+            init()
+            break
+        // 红包活动已结束
+        case '2006':
+            init()
+            break
+        // 红包金额已经被领取完了
+        case '2007':
+            state.status = 'close'
+            state.close_status = '已经过期了'
+            state.close_text = [`This Giveaways`, `expired on ${moment(state.detail.endTimestamp).format('MM-DD')}`]
+            init()
+            break
+        // 红包个数已经被领取完了
+        case '2008':
+            state.status = 'close'
+            state.close_status = '已经过期了'
+            state.close_text = [`This Giveaways`, `expired on ${moment(state.detail.endTimestamp).format('MM-DD')}`]
+            init()
+            break
+        // 该用户不满足领取条件
+        case '2009':
+            state.error_txt = [`oops, new accounts cannot participate in this event,`]
+            state.status = 'error'
+            state.retry = true
+            // 埋点
+            Report.reportLog({
+                pageSource: Report.pageSource.robot_detection_failed_page,
+                businessType: Report.businessType.pageView,
+                postId: state.postId,
+                srcContentId: state.tweetId,
+                senderId: state.userId,
+            });
+            break
+        // 无法校验用户Twitter信息
+        case '2010':
+            // message.error(res.msg)
+            break
+        // 用户已经领过该红包
+        case '2011':
+            // message.error(res.msg)
+            break
+        // 推文不存在
+        case '2022':
+            // message.error(res.msg)
+            break
+        // 推文未发布 and 不是红包任务的推文
+        case '2023':
+            // message.error(res.msg)
+            break
+        // 没有可提交的任务红包
+        case '2024':
+            state.status = 'not-open'
+            break
+        // 红包任务已完成
+        case '2025':
+            break
+        // 任务已经过期
+        case '2026':
+            break
+        // 任务未完成
+        case '2027':
+            break
+        // 红包金额每人不足1分钱
+        case '2028':
+            break
+        // 推文未发布
+        case '2029':
+            message.error('Tweet not posted')
+            break
+        // 不是红包任务的推文
+        case '2030':
+            break
+        case '2037':
+            showCloseEndTimePage()
+            init()
+            break
+        //用户没有领取过红包,无法重抽
+        case '2031':
+            break
+        // 需要重新授权 discord
+        case '1010':
+            discordAuth('reAuth');
+            break
+    }
+}
+
+// function clickBack() {
+//   state.status = 'opened'
+//   // 埋点
+//   Report.reportLog({
+//     pageSource: Report.pageSource.task_page,
+//     businessType: Report.businessType.pageView,
+//   });
+// }
+
+// function clickRoad() {
+//   state.status = 'luck-peopel-list'
+//   // 埋点
+//   Report.reportLog({
+//     pageSource: Report.pageSource.task_page,
+//     businessType: Report.businessType.buttonClick,
+//     objectType: Report.objectType.received_list
+//   });
+//   // 埋点
+//   Report.reportLog({
+//     pageSource: Report.pageSource.received_list_page,
+//     businessType: Report.businessType.pageView
+//   });
+// }
+function onWindowMessage() {
+    // window.addEventListener("message", 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;
+    //             //     break;
+    //             // case 'CONTENT_RED_PACKET_FACEBOOK_REPLY':
+    //             //     clickReply(event.data.data)
+    //             //     break;
+    //         }
+    //     }
+    // });
+}
+
+function onPageVisbile() {
+    document.addEventListener('visibilitychange', function () {
+        let isHidden = document.hidden;
+        if (!isHidden) {
+            checkJoinDiscord();
+        }
+    });
+}
+
+function onRuntimeMsg() {
+    messageCenter.listen('CONTENT_RED_PACKET_REPLY_RASK_FINSH', (req) => {
+        if (req.data && req.data.postId == state.postId) {
+            state.done.reply = true;
+            state.done.reply_red = false;
+        }
+    })
+
+    messageCenter.listen('BACK_DISCORD_LOGIN_SUCCESS', () => {
+        console.log('on success in frame');
+        discordLoginSuccess();
+    })
+
+    // chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
+    //     switch (req.actionType) {
+    //         case 'BG_FACEBOOK_SHARE_SUCCESS':
+    //             facebookShareSuccess(req.data);
+    //             break;
+    //         case 'USER_SETTING':
+    //             setNotification(req.data)
+    //             break;
+    //     }
+    //     sendResponse && sendResponse();
+    // })
+}
+
+/**
+ * 检查是否加入discord
+ */
+function checkJoinDiscord() {
+    // 如果上次的状态是 joinIng 检查是否真正join
+    if (joinDiscordActionState == 'joinIng') {
+        joinDiscordActionState = 'default';
+        let url = getInviteUrl();
+        if (url) {
+            joinDiscordIng.value = true;
+            checkGuildJoinedStatus({ url }, (res = {}) => {
+                joinDiscordIng.value = false;
+                if (res.code == 0) {
+                    let { joined } = res.data || {};
+                    if (joined) {
+                        state.done.join_discord = true;
+                    } else {
+                        state.done.join_discord = false;
+                    }
+                } else if (res.code == 1010) {
+                    discordAuth('reAuth');
+                }
+            })
+        }
+    }
+}
+
+
+const checkGuildJoinedStatus = ({ url }, cb) => {
+    checkGuildJoined({
+        params: {
+            inviteUrl: url
+        }
+    }).then(res => {
+        cb && cb(res);
+    }).catch(err => {
+        cb && cb({ catch: true })
+    })
+}
+
+/**
+ * 加入discord 事件
+ */
+async function joinDiscord() {
+    let _userInfo = await checkIsLogin();
+    if (!_userInfo) {
+        return
+    }
+    if (joinDiscordIng.value) {
+        return;
+    }
+    // 埋点
+    Report.reportLog({
+        objectType: Report.objectType.join_discord,
+        pageSource: Report.pageSource.task_page,
+        businessType: Report.businessType.buttonClick,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        redPacketType: 1,
+        customCover: state.customCover,
+        customGiveaway: state.customGiveaway,
+    });
+
+    let url = getInviteUrl();
+    if (url) {
+        joinDiscordIng.value = true;
+        checkGuildJoinedStatus({ url }, (res) => {
+            setTimeout(() => {
+                joinDiscordIng.value = false;
+            }, 1500);
+            if (res.code == 0) {
+                let { joined } = res.data || {};
+                if (joined) {
+                    state.done.join_discord = true;
+                } else {
+                    state.done.join_discord = false;
+                    if (discordAuthorizeRequired) {
+                        discordAuth('authAndJoinIng');
+                    } else {
+                        openInviteUrl();
+                    }
+                }
+            } else if (res.code == 1010) {
+                discordAuth('authAndJoinIng');
+            }
+            if (res.catch) {
+                //判断是否需要授权
+                if (discordAuthorizeRequired) {
+                    discordAuth('authAndJoinIng');
+                } else {
+                    openInviteUrl();
+                }
+            }
+        })
+    }
+}
+
+/**
+ * discord授权
+ */
+function discordAuth(actionState = 'default') {
+    let state = guid();
+    discordAuthUrl({
+        params: {
+            redirectUrl: discordAuthRedirectUri,
+            state
+        }
+    }).then(res => {
+        if (res.code == 0) {
+            let { authorizeUrl = '' } = res.data || {};
+            if (authorizeUrl) {
+                joinDiscordActionState = actionState;
+                const width = 500;
+                chrome.windows.create({
+                    width,
+                    type: 'normal',
+                    url: authorizeUrl
+                }, function (window) {
+                    let windowId = window.id;
+                    callEventPageMethod("RED_PACKET_SAVE_DISCORD_AUTH_WINDOW_ID", {
+                        windowId: windowId
+                    });
+                })
+            }
+        }
+    })
+}
+
+/**
+ * sendMessage
+ */
+const callEventPageMethod = (actionType, data, callback) => {
+    chrome.runtime.sendMessage(
+        {
+            actionType: actionType,
+            data: data
+        },
+        function (response) {
+            if (typeof callback === "function") callback(response);
+        }
+    );
+};
+
+/**
+ * discord 授权成功
+ */
+function discordLoginSuccess() {
+    console.log('discordloginSuccess');
+    // 如果是授权并join 默认打开 邀请链接
+    if (joinDiscordActionState == 'authAndJoinIng') {
+        openInviteUrl();
+    }
+    if (discordAuthorizeRequired) {
+        discordAuthorizeRequired = false;
+    }
+}
+
+/**
+ * 获取discord邀请链接
+ */
+function getInviteUrl() {
+    let inviteData = state.detail.taskCondition.find(item => {
+        return item.type == 7;
+    });
+    let url;
+    if (inviteData && inviteData.bizData) {
+        url = JSON.parse(inviteData.bizData).inviteUrl;
+    }
+    return url;
+}
+
+/**
+ * 打开邀请discord链接
+ */
+function openInviteUrl() {
+    joinDiscordActionState = 'joinIng';
+    let url = getInviteUrl();
+    if (url) {
+        if (!url.startsWith('http')) {
+            url = 'https://' + url;
+        }
+        window.open(url);
+    }
+}
+
+</script>
+
+<style lang="scss" scoped>
+html,
+body {
+    margin: 0;
+    padding: 0;
+    width: 375px;
+    height: 500px;
+    background-color: unset !important;
+}
+
+:deep() .ant-switch {
+    background-color: #E9ECEE;
+    height: 14px;
+    line-height: 16px;
+    min-width: 36px;
+}
+
+:deep() .ant-switch-checked {
+    background-color: #AED8F5 !important;
+}
+
+:deep() .ant-switch::after {
+    width: 20px;
+    height: 20px;
+    top: -4px;
+    left: -1px;
+}
+
+:deep() .ant-switch-checked::after {
+    background-color: #1D9BF0 !important;
+    margin-left: 3px;
+    left: 100% !important;
+}
+
+.content {
+    position: relative;
+    width: 375px;
+    height: 500px;
+    background: #fafafa;
+    overflow: hidden;
+    box-sizing: border-box;
+    font-family: "SF Pro Display";
+    font-style: normal;
+
+    .loading {
+        background: #FFFFFF;
+        opacity: 0.8;
+        z-index: 222;
+        text-align: center;
+        width: 375px;
+        height: 500px;
+        position: fixed;
+        top: 0;
+        left: 0;
+
+        img {
+            margin-top: 216px;
+            width: 70px;
+            height: 70px;
+        }
+    }
+
+    .redbag {
+        z-index: 222;
+        text-align: center;
+        width: 375px;
+        height: 500px;
+        position: fixed;
+        top: 0;
+        left: 0;
+
+        img {
+            margin-top: 172px;
+            width: 130px;
+            height: 130px;
+        }
+    }
+
+    .error {
+        width: 100%;
+        height: 100%;
+        text-align: center;
+        position: relative;
+
+        img {
+            width: 100px;
+            height: 100px;
+            margin-top: 100px;
+        }
+
+        .txt {
+            font-weight: 500;
+            font-size: 22px;
+            line-height: 26px;
+            text-align: center;
+            letter-spacing: 0.3px;
+            color: #a8a8a8;
+            margin: 34px 44px 0 44px;
+        }
+
+        .retry {
+            position: absolute;
+            bottom: 30px;
+            left: 50%;
+            margin-left: -167.5px;
+            width: 335px;
+            height: 46px;
+            line-height: 46px;
+            text-align: center;
+            border-radius: 100px;
+            border: 1px solid #1D9BF0;
+            background: rgba(196, 196, 196, 0.01);
+            color: #1D9BF0;
+            font-size: 16px;
+            font-weight: 500;
+            cursor: pointer;
+        }
+    }
+
+    .success,
+    .close,
+    .luck-peopel-list {
+        filter: drop-shadow(0px 4px 94px rgba(0, 0, 0, 0.3));
+        width: 100%;
+        height: 100%;
+        border-radius: 11px;
+        background: #fff;
+        overflow: hidden;
+        display: flex;
+        flex-direction: column;
+
+        .close-title {
+            width: 100%;
+            font-weight: 600;
+            font-size: 27px;
+            line-height: 32px;
+            text-align: center;
+            letter-spacing: 0.3px;
+            font-weight: 800;
+            font-size: 22px;
+            color: #ffffff;
+        }
+
+        .head {
+            padding: 14px 16px;
+
+            img {
+                cursor: pointer;
+                width: 24px;
+                height: 24px;
+            }
+        }
+
+        .header {
+            text-align: center;
+            min-height: 160px;
+            width: 100%;
+            background: #fff;
+            // padding-top: 30px;
+            background-size: 100% 100%;
+            position: relative;
+            display: flex;
+            align-content: center;
+            flex-wrap: wrap;
+
+            .rabbit {
+                width: 100%;
+                height: 100%;
+                display: flex;
+                align-items: center;
+                align-content: center;
+                flex-wrap: wrap;
+                justify-content: center;
+
+                img {
+                    width: 150px;
+                    height: 80px;
+                    margin-bottom: 6px;
+                }
+
+                .flower {
+                    width: 62px;
+                    height: 62px;
+                }
+
+                p {
+                    width: 100%;
+                    margin: 0;
+                    padding: 0;
+                    font-size: 22px;
+                    font-weight: 800;
+
+                    color: #fff;
+                    text-align: center;
+                    letter-spacing: 0.3px;
+                }
+            }
+
+            .done {
+                cursor: pointer;
+                position: absolute;
+                top: 107px;
+                left: 50%;
+                margin-left: -150px;
+                width: 300px;
+                height: 60px;
+                display: flex;
+                align-items: center;
+                border-radius: 100px;
+                background: #ffffff;
+                box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);
+                justify-content: center;
+
+                span {
+                    color: #000000;
+                    font-size: 14px;
+                }
+
+                .icon-done {
+                    width: 24px;
+                    height: 24px;
+                    margin-right: 10px;
+                }
+
+                .icon-right {
+                    margin-left: 5px;
+                    width: 7px;
+                    height: 14px;
+                }
+            }
+
+            .title {
+                margin-top: 30px;
+                color: #fff7e4;
+                opacity: 0.6;
+
+                font-weight: 700;
+                font-size: 18px;
+                line-height: 21px;
+                letter-spacing: -0.3px;
+            }
+
+            .money {
+                margin-bottom: 30px;
+                width: 100%;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+
+                img {
+                    width: 40px;
+                    height: 40px;
+                    margin-right: 9px;
+                    border-radius: 50%;
+                    border: solid 2px #fff;
+                }
+
+                .big {
+                    font-weight: 700;
+                    font-size: 46px;
+                    line-height: 55px;
+                    /* identical to box height */
+
+                    letter-spacing: 0.3px;
+
+                    color: #fff;
+                }
+
+                .small {
+                    margin-left: 4px;
+
+                    font-weight: 700;
+                    font-size: 13px;
+                    line-height: 16px;
+                    /* identical to box height */
+
+                    letter-spacing: 0.5px;
+
+                    color: #fff;
+                }
+            }
+
+            .custom-prize-show {
+                width: 100%;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                height: 44px;
+                margin-top: 20px;
+
+                img {
+                    width: 24px;
+                    height: 24px;
+                    margin-right: 9px;
+                }
+            }
+        }
+
+
+
+        .luck-list-title {
+            /*      margin-top: 47px;*/
+            margin: 0 16px;
+            padding: 14px 0 11px 0;
+            background: #fff;
+            display: flex;
+            justify-content: space-between;
+            color: #B0B0B0;
+            font-weight: 500;
+            border-bottom: 1px solid #F2F2F2;
+
+            div:last-child {
+                text-align: right;
+            }
+
+            .text {
+                cursor: pointer;
+            }
+        }
+
+        .luck-list {
+            background: #fff;
+            overflow: auto;
+
+            &.max {
+                height: 250px;
+            }
+
+            .empty {
+                width: 100%;
+                height: 100%;
+                text-align: center;
+
+                img {
+                    margin-top: 70px;
+                    width: 100px;
+                    height: 100px;
+                }
+            }
+
+            .luck-item {
+                display: flex;
+                padding: 10px 0;
+                margin: 0 16px;
+                border-bottom: 1px solid #F2F2F2;
+                justify-content: space-between;
+                position: relative;
+
+                .win {
+                    position: absolute;
+                    left: 28px;
+                    bottom: 7px;
+                    width: 20px;
+                    height: 20px;
+                }
+
+                img:first-child {
+                    border-radius: 50%;
+                }
+
+                .luck-king {
+                    position: absolute;
+                    top: 36px;
+                    right: 0px;
+                    display: flex;
+                    align-items: center;
+
+                    img {
+                        width: 22px;
+                        height: 19px;
+                        margin: 0;
+                    }
+
+                    span {
+                        font-weight: 500;
+                        font-size: 12px;
+                        line-height: 14px;
+                        letter-spacing: 0.3px;
+                        color: #f5b945;
+                    }
+                }
+
+                img {
+                    cursor: pointer;
+                    width: 42px;
+                    height: 42px;
+                    margin-right: 12px;
+                }
+
+                .luck-content {
+                    flex: auto;
+
+                    .luck-title {
+                        color: #444444;
+                        font-weight: 500;
+                        font-size: 16px;
+                        letter-spacing: 0.3px;
+                        margin-bottom: 5px;
+                    }
+
+                    .luck-time {
+                        font-weight: 400;
+                        font-size: 12px;
+                        line-height: 14px;
+                        color: #B0B0B0;
+                    }
+                }
+
+                .luck-money {
+                    display: flex;
+                    height: 17px;
+                    align-items: center;
+                    height: 100%;
+
+                    img {
+                        width: 14px;
+                        height: 14px;
+                        margin-right: 6px;
+                    }
+
+                    .luck-money-txt {
+                        font-weight: 500;
+                        font-size: 14px;
+                        word-break: break-all;
+                        /* identical to box height */
+
+                        text-align: right;
+                        letter-spacing: 0.3px;
+
+                        color: #444444;
+                    }
+                }
+
+                .luck-custom-prize {
+                    font-weight: 500;
+                    font-size: 14px;
+                    letter-spacing: 0.3px;
+                    color: #F5B945;
+                }
+            }
+
+            .luck-item:last-child {
+                border: 0;
+            }
+        }
+    }
+
+    .close {
+        position: relative;
+
+        .load-result {
+            position: absolute;
+            width: 100%;
+            height: 100%;
+            top: 0;
+            left: 0;
+            text-align: center;
+            display: flex;
+            flex-wrap: wrap;
+            justify-content: center;
+            align-content: flex-start;
+
+            .title {
+                width: 100%;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                margin-top: 36px;
+
+                img {
+                    width: 26px;
+                    height: 26px;
+                    margin-right: 10px;
+                }
+
+                span {
+                    color: #FFFFFF;
+                    font-size: 18px;
+                    font-weight: 800;
+                    letter-spacing: 0.3px;
+
+                }
+            }
+
+            .ticket {
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                width: 100%;
+                height: 163px;
+
+                img {
+                    width: 250px;
+                    height: 103px;
+                    animation: myfirst 0.5s;
+                }
+
+            }
+
+            .div-ticket {
+                position: relative;
+                overflow: hidden;
+                transition-delay: 1s;
+            }
+
+            .div-ticket:after {
+                position: absolute;
+                right: -100%;
+                /*改变left的值,让其相对box影藏*/
+                top: 0;
+                width: 30%;
+                height: 100%;
+                content: "";
+                /* Safari 5.1 - 6.0 */
+                background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, .3) 50%, rgba(255, 255, 255, 0) 100%);
+                /* Opera 11.1 - 12.0 */
+                background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, .3) 50%, rgba(255, 255, 255, 0) 100%);
+                /* Firefox 3.6 - 15 */
+                background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, .3) 50%, rgba(255, 255, 255, 0) 100%);
+                /* 标准的语法 */
+                background: linear-gradient(to right, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, .3) 50%, rgba(255, 255, 255, 0) 100%);
+                transform: skewX(45deg);
+                animation: div_light 1s;
+                animation-delay: 0.5s;
+            }
+
+            // .div-ticket:hover:after {
+            //     right: 150%;
+            //     transition: 1s ease;
+            // }
+
+            p {
+                width: 100%;
+                margin: 0;
+                padding: 0;
+                color: #FCAB40;
+                text-align: center;
+                letter-spacing: 0.3px;
+                font-size: 18px;
+                font-weight: 700;
+
+            }
+
+            .time {
+                width: 100%;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                margin-top: 16px;
+
+                img {
+                    width: 22px;
+                    height: 22px;
+                    margin-right: 10px;
+                }
+
+                span {
+                    font-weight: 800;
+                    font-size: 28px;
+                    color: #3F3F3F;
+                }
+            }
+
+
+
+            .notification_switch {
+                border-top: 1px solid #EFEFEF;
+                justify-content: space-between;
+                position: absolute;
+                height: 48px;
+                width: 100%;
+                display: flex;
+                align-items: center;
+                bottom: 0;
+                padding: 0 22px 0 16px;
+
+            }
+        }
+    }
+
+
+
+    .success {
+        .header {
+
+            min-height: 180px;
+            align-content: flex-start;
+
+            .success-title {
+                color: #FFFFFF;
+                font-weight: 800;
+                font-size: 21px;
+                line-height: 27px;
+                margin-top: 28px;
+                text-align: center;
+                width: 100%;
+            }
+
+            .done {
+                top: 130px;
+            }
+        }
+
+        .luck-list-title {
+            margin-top: 10px;
+            border-bottom: 1px solid #ECECEC;
+        }
+
+        .header-custom-prize {
+            align-items: flex-start;
+
+            .success-title {
+                line-height: 21px;
+                margin-top: 23px;
+                font-size: 18px;
+            }
+        }
+    }
+
+    .opened {
+        filter: drop-shadow(0px 4px 94px rgba(0, 0, 0, 0.3));
+        width: 100%;
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        border-radius: 11px;
+        overflow: hidden;
+
+        .header {
+            text-align: center;
+            min-height: 110px;
+            width: 100%;
+            background: #fff;
+            // padding-top: 30px;
+            background-size: 100% 100%;
+            display: flex;
+            flex-wrap: wrap;
+            align-content: center;
+            justify-content: center;
+
+            img {
+                width: 52px;
+                height: 52px;
+                margin-right: 14px;
+            }
+
+            .txt {
+                color: #FFFFFF;
+                font-weight: 700;
+                font-size: 18px;
+                letter-spacing: 0.3px;
+
+                p {
+                    margin: 0;
+                    padding: 0;
+                    text-align: left;
+                }
+            }
+        }
+
+        .list {
+            overflow-y: auto;
+            padding: 0 16px 0 16px;
+            background: #ffffff;
+            flex: 1;
+
+            .item {
+                display: flex;
+                align-items: center;
+                // min-height: 50px;
+                border-bottom: 1px solid #f0f0f0;
+                padding: 12px 0;
+                box-sizing: border-box;
+
+                img {
+                    width: 24px;
+                    height: 24px;
+                }
+
+                .red-right {
+                    width: 35px;
+                    height: 24px;
+                }
+
+                .item-content {
+                    width: 100%;
+                    flex: 1;
+
+
+                    .item-follow-title {
+                        display: flex;
+                        align-items: center;
+                        margin-top: 20px;
+                        margin-bottom: 11px;
+                        position: relative;
+
+                        .btn {
+                            // position: absolute;
+                            // right: 0;
+                        }
+                    }
+
+                    .item-title {
+                        flex: 1;
+                        margin-left: 10px;
+                        font-weight: 500;
+                        font-size: 15px;
+                        letter-spacing: 0.3px;
+                        color: #000000;
+                    }
+
+                    .item-follow-area {
+                        display: flex;
+                        flex-wrap: wrap;
+
+                        .item-follow {
+                            cursor: pointer;
+                            border: 1px solid #ebebeb;
+                            border-radius: 1000px;
+                            height: 26px;
+                            margin-right: 5px;
+                            margin-bottom: 5px;
+                            display: flex;
+                            align-items: center;
+
+                            .finished {
+                                text-decoration: line-through;
+                                color: #949494;
+                            }
+
+                            span {
+                                margin-left: 8px;
+                                margin-right: 2px;
+                                color: #1D9BF0;
+                                opacity: 1;
+                            }
+
+                            img {
+                                width: 16px;
+                                height: 16px;
+                                margin-right: 7px;
+                            }
+                        }
+                    }
+
+                    span {
+                        font-weight: 400;
+                        font-size: 11px;
+                        line-height: 13px;
+                        letter-spacing: 0.3px;
+
+                        color: #000000;
+
+                        opacity: 0.4;
+                    }
+                }
+
+                .btn {
+                    width: 90px;
+                    height: 29px;
+                    line-height: 29px;
+                    background: rgba(56, 154, 255, 0.1);
+                    border-radius: 500px;
+                    text-align: center;
+                    letter-spacing: 0.3px;
+                    color: #1D9BF0;
+                    cursor: pointer;
+                }
+
+                .loading-wrapper {
+                    width: 90px;
+                    text-align: center;
+
+                    .icon-loading {
+                        animation: loading 1s infinite linear;
+                    }
+                }
+            }
+        }
+
+        .people {
+            cursor: pointer;
+            padding-left: 16px;
+            height: 38px;
+            line-height: 38px;
+            background: #fff;
+            box-shadow: 0px 1px 0px #f2f2f2;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+
+            .txt {
+                width: 90%;
+                font-weight: 400;
+                font-size: 12px;
+                line-height: 14px;
+                letter-spacing: 0.3px;
+                color: #000000;
+                opacity: 0.4;
+            }
+
+
+        }
+
+        .footer {
+            background: #ffffff;
+            display: flex;
+            padding: 15px 22px 15px 17px;
+
+            .btn {
+                background: #1D9BF0;
+                border-radius: 100px;
+                color: #fff;
+                width: 100%;
+                height: 48px;
+                font-weight: 600;
+                font-size: 18px;
+                line-height: 48px;
+                text-align: center;
+                cursor: pointer;
+            }
+
+            .grey {
+                background: #DDDDDD;
+                cursor: auto;
+            }
+        }
+    }
+
+    .not-open {
+        width: 100%;
+        height: 100%;
+        filter: drop-shadow(0px 2px 20px rgba(0, 0, 0, 0.1));
+        position: relative;
+        overflow: hidden;
+        border-radius: 11px;
+
+        .customImg {
+            width: 100%;
+            min-height: 373px;
+        }
+
+        .customBottom {
+            width: 100%;
+            height: 125px;
+            background: #111214;
+            padding: 10px 16px;
+            font-weight: 500;
+            font-size: 12px;
+            line-height: 14px;
+            letter-spacing: 0.3px;
+            color: #838383;
+            line-height: 20px;
+
+            .theme {
+                display: flex;
+                height: 20px;
+                align-items: center;
+                justify-content: flex-start;
+
+                .icon {
+                    width: 12px;
+                }
+
+                .time {
+                    margin: 0 4px;
+                    color: #1D9BF0;
+                }
+            }
+
+            .winner-info {
+                display: flex;
+                height: 20px;
+                align-items: center;
+                justify-content: flex-start;
+                margin-bottom: 13px;
+
+                .count {
+                    color: #1D9BF0;
+                    margin-right: 4px;
+                }
+
+                .prize-name {
+                    color: #1D9BF0;
+                    margin-left: 4px;
+                }
+            }
+
+            .open-red {
+                height: 45px;
+                background: linear-gradient(180deg, #4AB6FF 0%, #1D9BF0 100%, #1D9BF0 100%);
+                border: 1.5px solid rgba(255, 255, 255, 0.15);
+                border-radius: 52px;
+                line-height: 45px;
+                text-align: center;
+                cursor: pointer;
+                font-weight: 800;
+                font-size: 16px;
+                color: #FFFFFF;
+            }
+        }
+
+        .money-area {
+            width: 100%;
+            position: absolute;
+            top: 65px;
+            display: flex;
+            flex-wrap: wrap;
+            align-items: center;
+            justify-content: center;
+
+            .time-area {
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                position: relative;
+                width: 100%;
+                height: 46px;
+
+                div {
+                    width: 100%;
+                    height: 100%;
+                    position: absolute;
+                    background: #000000;
+                    z-index: 0;
+                    opacity: 0.15;
+                }
+
+                img {
+                    z-index: 1;
+                    width: 26px;
+                    height: 26px;
+                    margin-right: 10px;
+                }
+
+                span {
+                    z-index: 1;
+                    color: #FFCC4D;
+                    font-weight: 900;
+                    font-size: 26px;
+
+                }
+            }
+
+            .mark-area {
+                width: 100%;
+                display: flex;
+                justify-content: center;
+
+                img {
+                    width: 16px;
+                    height: 16px;
+                    margin-right: 4px;
+                }
+
+                .time {
+                    display: flex;
+                    align-items: center;
+
+                    span {
+                        color: #FFFFFF;
+                        font-weight: 800;
+                        font-size: 17px;
+                        letter-spacing: 0.05em;
+                        line-height: 22px;
+
+
+                    }
+
+                }
+
+                .win {
+                    display: flex;
+                    align-items: center;
+                    margin-left: 12px;
+                    color: #FFCC4D;
+                    letter-spacing: 0.05em;
+                    line-height: 22px;
+                    font-size: 17px;
+                    font-weight: 800;
+
+                }
+            }
+
+            .txt {
+                font-weight: 800;
+                font-size: 16px;
+                text-align: center;
+                letter-spacing: 0.3px;
+                color: #FFFFFF;
+            }
+
+            .coin {
+                text-align: center;
+                margin-top: 6px;
+                /*margin-bottom: 7px;*/
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                width: 90%;
+
+                img {
+                    width: 46px;
+                    height: 46px;
+                    border-radius: 50%;
+                    border: 3px solid #FFFFFF;
+                }
+
+                span {
+                    margin-left: 12px;
+                    font-weight: 800;
+                    font-size: 60px;
+                    line-height: 76px;
+                    color: #FFFFFF;
+                }
+            }
+
+            .people {
+                font-weight: 800;
+                font-size: 13px;
+                line-height: 16px;
+                letter-spacing: 0.05em;
+                text-align: center;
+                color: #FFFFFF;
+            }
+        }
+
+        .title {
+            position: absolute;
+            top: 15px;
+            left: 15px;
+            z-index: 3;
+            display: flex;
+            align-items: center;
+
+            img {
+                width: 24px;
+                height: 24px;
+                border: 2px solid #FFF;
+                border-radius: 50%;
+            }
+
+            span {
+                margin-left: 10px;
+                font-weight: 600;
+                font-size: 16px;
+                letter-spacing: 0.3px;
+                color: #fff;
+            }
+        }
+
+        // .txt {
+        //   width: 100%;
+        //   position: absolute;
+        //   font-style: normal;
+        //   font-weight: 700;
+        //   font-size: 42px;
+        //   line-height: 50px;
+        //   text-align: center;
+
+        //   color: #FFF2D3;
+        //   top: 90px;
+        //   z-index: 3;
+        // }
+
+        img {
+            width: 100%;
+        }
+
+        .up {
+            position: absolute;
+            top: 0;
+            // box-shadow: 0px 4px 44px rgba(0, 0, 0, 0.1);
+            z-index: 1;
+        }
+
+        .down {
+            position: absolute;
+            top: 253px;
+        }
+
+        .open {
+            width: 335px;
+            height: 50px;
+            cursor: pointer;
+            position: absolute;
+            bottom: 28px;
+            left: 50%;
+            margin-left: -167.5px;
+            z-index: 4;
+        }
+
+        .open-gif {
+            width: 200px;
+            height: 200px;
+            text-align: center;
+            position: absolute;
+            bottom: 80px;
+            left: 50%;
+            margin-left: -100px;
+            z-index: 3;
+        }
+    }
+
+    @keyframes loading {
+        from {
+            transform: rotate(0deg);
+        }
+
+        to {
+            transform: rotate(360deg);
+        }
+    }
+}
+
+
+@keyframes div_light {
+    0% {
+        right: -100%;
+    }
+
+
+
+    100% {
+        right: 150%;
+    }
+}
+
+@keyframes myfirst {
+    0% {
+        width: 250px;
+        height: 103px;
+    }
+
+    50% {
+        width: 300px;
+        height: 153px;
+    }
+
+    100% {
+        width: 250px;
+        height: 103px;
+    }
+}
+
+.none {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    height: 100%;
+}
+</style>

+ 2926 - 0
src/pages/red-packet/red-packet.vue

@@ -0,0 +1,2926 @@
+<!-- 红包任务页面 -->
+<template>
+  <div class="content">
+    <!-- global-tip -->
+    <global-tip :type="'1'"></global-tip>
+    <!-- open -->
+    <div v-show="state.status == 'opened'" class="opened">
+      <!-- <div class="header" :style="{ 'backgroundImage': `url(${require('@/assets/subject/001-back-head-top.svg')})` }">
+        <div class="title">AWESOME! YOU WILL GET</div>
+        <div class="money">
+          <img :src="state.detail.currencyIconPath" alt />
+          <font-amount :amount="state.money" class="big" :fontSize="46"></font-amount>
+        </div>
+      </div> -->
+
+      <div class="header" :style="{ 'backgroundImage': `url(${require('@/assets/subject/001-back-head-top-1.svg')})` }">
+        <!--  -->
+        <img :src="require('@/assets/subject/001-icon-red-packet.svg')" alt="">
+        <div class="txt">
+          <p>Complete tasks</p>
+          <p>to Draw Prizes</p>
+        </div>
+      </div>
+
+      <div class="list">
+        <template v-for="item, i in state.detail.taskCondition" v-bind:key="i">
+          <div class="item" v-if="item.type == 1 && item.relatedUsers && item.relatedUsers.length > 0">
+            <div class="item-content">
+              <div class="item-follow-title">
+                <img :src="require('@/assets/svg/icon-task-twitter.svg')" alt />
+                <!-- <img :src="require('@/assets/svg/icon-follow.svg')" alt /> -->
+                <div class="item-title">Follow</div>
+                <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+                  v-show="!state.done.follow && state.done.follow_red" />
+                <img v-if="state.done.follow" :src="require('@/assets/svg/icon-true.svg')" alt />
+                <div v-else class="btn" @click="clickFollowAll(item.relatedUsers, 'all')">Follow All</div>
+              </div>
+              <div class="item-follow-area">
+                <template v-for="item2, i in item.relatedUsers" v-bind:key="i">
+                  <div class="item-follow" v-if="item2.finished">
+                    <span :class="{ finished: item2.finished }">@{{ item2.name }}</span>
+                    <img :src="require('@/assets/svg/icon-true-ed.svg')" alt />
+                  </div>
+                  <div class="item-follow" v-else @click="clickFollowAll([item2])">
+                    <span :class="{ finished: item2.finished }">@{{ item2.name }}</span>
+                    <img :src="require('@/assets/svg/icon-add.svg')" alt />
+                  </div>
+                </template>
+              </div>
+            </div>
+          </div>
+          <div class="item" v-if="item.type == 2">
+            <img :src="require('@/assets/svg/icon-task-twitter.svg')" alt />
+            <!-- <img :src="require('@/assets/svg/icon-like.svg')" alt /> -->
+            <div class="item-content">
+              <div class="item-title">Like</div>
+            </div>
+            <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+              v-show="!state.done.like && state.done.like_red" />
+            <img v-if="state.done.like" :src="require('@/assets/svg/icon-true.svg')" alt />
+            <div v-else class="btn" @click="clickLikeBtn">Like</div>
+          </div>
+          <div class="item" v-if="item.type == 3">
+            <img :src="require('@/assets/svg/icon-task-twitter.svg')" alt />
+            <!-- <img :src="require('@/assets/svg/icon-retweet.svg')" alt /> -->
+            <div class="item-content">
+              <div class="item-title">Retweet</div>
+            </div>
+            <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+              v-show="!state.done.retweet && state.done.retweet_red" />
+            <img v-if="state.done.retweet" :src="require('@/assets/svg/icon-true.svg')" alt />
+            <div v-else class="btn" @click="clickRetweetBtn">Retweet</div>
+          </div>
+          <!-- Comment、艾特 friends -->
+          <div class="item" v-if="item.type == 9">
+            <img :src="require('@/assets/svg/icon-task-twitter.svg')" alt />
+            <div class="item-content">
+              <div class="item-title">Comment and Tag 3 friends</div>
+            </div>
+            <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+              v-show="!state.done.reply && state.done.reply_red" />
+            <img v-if="state.done.reply" :src="require('@/assets/svg/icon-true.svg')" alt />
+            <div v-else class="btn" @click="clickReply(item)">Comment</div>
+          </div>
+          <!-- repost feacebook -->
+          <div class="item" v-if="item.type == 8">
+            <img :src="require('@/assets/svg/icon-task-facebook.svg')" alt />
+            <div class="item-content">
+              <div class="item-title">Repost to Facebook</div>
+            </div>
+            <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+              v-show="!state.done.repost_facebook && state.done.repost_facebook_red" />
+            <img v-if="state.done.repost_facebook" :src="require('@/assets/svg/icon-true.svg')" alt />
+            <div v-else class="btn" @click="clickRepostFacebook(item)">Repost</div>
+          </div>
+          <!-- join discord  -->
+          <div class="item" v-if="item.type == 7">
+            <img :src="require('@/assets/svg/icon-discord-mini.svg')" alt />
+            <div class="item-content">
+              <div class="item-title">Join Discord</div>
+            </div>
+            <img :src="require('@/assets/gif/red-right.gif')" alt class="red-right"
+              v-show="!state.done.join_discord && state.done.join_discord_red" />
+            <img v-if="state.done.join_discord" :src="require('@/assets/svg/icon-true.svg')" alt />
+            <template v-else>
+              <div v-if="joinDiscordIng" class="loading-wrapper">
+                <img class="icon-loading" :src="require('@/assets/svg/icon-loading-gray.svg')" />
+              </div>
+              <div v-else class="btn" @click="joinDiscord">
+                Join
+              </div>
+            </template>
+          </div>
+        </template>
+      </div>
+      <!-- <div class="people" @click="clickRoad">
+        <div class="txt">
+          {{ state.detail.receiveCount || 0 }}/{{ state.detail.totalCount || 0 }} Winners,{{
+              state.detail.receiveAmountValue
+          }}/{{ state.detail.amountValue }} {{ state.detail.currencySymbol }}</div>
+        <div class="right" v-if="state.detail.allReceived">
+
+          <img :src="require('@/assets/svg/icon-right.svg')" alt class="road" />
+        </div>
+      </div> -->
+      <div class="footer">
+        <div class="winner">
+          <p>Winners</p>
+          <div class="right">
+            <template v-if="state.detail.allReceived" v-for="item, i in state.detail.allReceived.slice(0, 3)"
+              v-bind:key="i">
+              <img v-if="item.simpleUserInfoVO.avatarUrl" :src="item.simpleUserInfoVO.avatarUrl" alt
+                :style="{ left: `${(i) * 16}px`, zIndex: `${10 - i}` }" />
+              <img v-else :src="require('@/assets/svg/icon-twitter.svg')" alt
+                :style="{ left: `${(i) * 16}px`, zIndex: `${10 - i}` }" />
+            </template>
+            <img v-if="state.detail.allReceived && state.detail.allReceived.length > 3"
+              :src="require('@/assets/svg/icon-winner-more.svg')" alt
+              :style="{ left: `${3 * 16}px`, zIndex: `${10 - 3}` }" />
+          </div>
+        </div>
+        <div class="btn" @click="clickGetGiveaways">Complete</div>
+      </div>
+    </div>
+
+
+    <!-- success -->
+    <div v-if="state.status == 'success'" class="success">
+      <div class="header" v-if="state.detail.rewardType === RewardType.money"
+        :style="{ 'backgroundImage': `url(${require('@/assets/subject/001-back-head-top.svg')})` }">
+        <div class="money">
+          <img :src="state.detail.currencyIconPath" alt />
+          <font-amount :amount="state.receiveAmount" class="big" :fontSize="46"></font-amount>
+          <!-- <span class="small">{{ state.detail.currencySymbol }}</span> -->
+        </div>
+        <div class="done" @click="clickDone">
+          <img :src="require('@/assets/subject/001-icon-done.svg')" alt class="icon-done" />
+          <span>View Rewards In Wallet</span>
+          <img :src="require('@/assets/svg/icon-right.svg')" alt class="icon-right" />
+        </div>
+      </div>
+      <div class="header header-custom-prize" v-else
+        :style="{ 'backgroundImage': `url(${successTopBgCpd})`, 'minHeight': '150px' }">
+        <div class="success-title">
+          🎉 Awesome! You are the Winner!
+        </div>
+        <div class="custom-prize-show">
+          <img :src="require('@/assets/subject/icon-gift-inline.svg')" alt />
+          <font-zoom :amount="state.detail.customizedReward" width="500" class="custom-prise-name" fontSize="22">
+          </font-zoom>
+        </div>
+      </div>
+      <div class="luck-list-title">
+        <div>{{ state.detail.receiveCount || 0 }}/{{ state.detail.totalCount || 0 }} Winners</div>
+        <div class="right">
+          <span class="text" v-if="state.detail.rewardType === RewardType.money">
+            <a-tooltip :title="state.detail.receiveAmountValue">
+              {{ getBit(state.detail.receiveAmountValue) }}
+            </a-tooltip>
+            /
+            <a-tooltip :title="state.detail.amountValue">
+              {{ getBit(state.detail.amountValue) || '' }}
+            </a-tooltip>
+          </span>
+          {{ state.detail.currencySymbol || '' }}
+        </div>
+      </div>
+      <div class="luck-list max" @scroll="handleScroll($event)">
+        <div class="luck-item" v-for="item, i in state.detail.allReceived" v-bind:key="i">
+          <img v-if="item.simpleUserInfoVO.avatarUrl" :src="item.simpleUserInfoVO.avatarUrl"
+            @click="openTwitterDetail(item)" alt />
+          <img v-else :src="require('@/assets/svg/icon-twitter.svg')" alt />
+          <div class="luck-content">
+            <div class="luck-title" v-if="item.simpleUserInfoVO.nickName">{{ item.simpleUserInfoVO.nickName }}</div>
+            <div class="luck-title" v-else>Twitter User</div>
+            <div class="luck-time">{{ moment(item.receiveTimestamp).format('MM-DD HH:mm') }}</div>
+          </div>
+          <div class="luck-money" v-if="state.detail.rewardType === RewardType.money">
+            <img :src="state.detail.currencyIconPath" alt />
+            <div class="luck-money-txt">
+              <a-tooltip :title="item.amountValue">
+                {{ getBit(item.amountValue) }}
+              </a-tooltip>
+            </div>
+          </div>
+          <div class="luck-custom-prize" v-else>winner</div>
+          <div class="luck-king" v-if="state.detail.rewardType === RewardType.money && item.maxAmount">
+            <img :src="require('@/assets/svg/icon-king-hat.svg')" alt />
+            <span>Luckiest Draw</span>
+          </div>
+        </div>
+      </div>
+      <get-more :reportData="{
+        pageSource: Report.pageSource.received_success_page,
+        postId: state.postId,
+        redPacketType: Report.redPacketType.giveaway
+      }"></get-more>
+    </div>
+
+
+    <!-- no-open -->
+    <div v-else-if="state.status == 'not-open'" class="not-open">
+      <!-- <template v-if="state.detail.posterType === 2 && state.detail.customPosterInstalled">
+        <img class="customImg" :src="state.detail.customPosterInstalled" />
+        <div class="customBottom">
+            <div class="theme">
+                <span class="info">Instant Giveaway</span>
+            </div>
+            <div class="winner-info">
+                <span class="count">{{state.detail.totalCount}} Winners</span>
+                <span>to Share </span>
+                <span class="prize-name">{{state.detail.amountValue + ' ' + state.detail.currencySymbol}}</span>
+            </div>
+            <div class="open-red" @click="clickOpenRedPacket">
+                Open Now
+            </div>
+        </div>
+      </template>
+      <template v-else> -->
+      <custom-card-cover :data="{
+        totalCount: state.detail.totalCount,
+        amountValue: state.detail.amountValue,
+        tokenSymbol: state.detail.currencySymbol,
+        currencyCode: state.detail.amountCurrencyCode,
+        currencyIconUrl: state.detail.currencyIconPath,
+        type: PlayType.common,
+        validityDuration: state.detail.validityDuration,
+        userInfo: {
+          nickName: state.detail.postUserInfo.nickName,
+          avatarUrl: state.detail.postUserInfo.avatarUrl
+        },
+        rewardType: state.detail.rewardType,
+        customizedReward: state.detail.customizedReward,
+        customPosterUrl: state.detail.customPosterInstalled
+      }" @clickOpenRedPacket="clickOpenRedPacket"></custom-card-cover>
+      <!-- </template> -->
+    </div>
+
+
+    <!-- 领取列表 -->
+    <div v-else-if="state.status == 'luck-peopel-list'" class="luck-peopel-list">
+      <div class="head">
+        <img :src="require('@/assets/svg/icon-back.svg')" alt />
+      </div>
+      <div class="luck-list-title">
+        <div>{{ state.detail.receiveCount || 0 }}/{{ state.detail.totalCount || 0 }} Winners</div>
+        <div class="right" v-if="state.detail.rewardType === RewardType.money">
+          <span class="text">
+            <a-tooltip :title="state.detail.receiveAmountValue">
+              {{ getBit(state.detail.receiveAmountValue) }}
+            </a-tooltip>
+            /
+            <a-tooltip :title="state.detail.amountValue">
+              {{ getBit(state.detail.amountValue) || '' }}
+            </a-tooltip>
+          </span> {{
+              state.detail.currencySymbol || ''
+          }}
+        </div>
+      </div>
+      <div class="luck-list" @scroll="handleScroll">
+        <div class="luck-item" v-for="item, i in state.detail.allReceived" v-bind:key="i">
+          <img v-if="item.simpleUserInfoVO.avatarUrl" :src="item.simpleUserInfoVO.avatarUrl" alt
+            @click="openTwitterDetail(item)" />
+          <img v-else :src="require('@/assets/svg/icon-twitter.svg')" alt />
+          <div class="luck-content">
+            <div class="luck-title" v-if="item.simpleUserInfoVO.nickName">{{ item.simpleUserInfoVO.nickName }}</div>
+            <div class="luck-title" v-else>Twitter User</div>
+            <div class="luck-time">{{ moment(item.receiveTimestamp).format('MM-DD HH:mm:ss') }}</div>
+          </div>
+          <div class="luck-money" v-if="state.detail.rewardType === RewardType.money">
+            <img :src="state.detail.currencyIconPath" alt />
+            <div class="luck-money-txt">
+              <a-tooltip :title="item.amountValue">
+                {{ getBit(item.amountValue) }}
+              </a-tooltip>
+            </div>
+          </div>
+          <div class="luck-custom-prize" v-else>winner</div>
+          <div class="luck-king" v-if="state.detail.rewardType === RewardType.money && item.maxAmount">
+            <img :src="require('@/assets/svg/icon-king-hat.svg')" alt />
+            <span>Luckiest Draw</span>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 关闭状态 -->
+    <div v-else-if="state.status == 'close'" class="close">
+      <!-- 红包被领完了 -->
+      <div class="header" :style="{ 'backgroundImage': `url(${require('@/assets/subject/001-back-head-top.svg')})` }"
+        v-show="state.close_status == '红包过期了'">
+        <div class="close-title" v-for="item in state.close_text">{{ item }}</div>
+      </div>
+      <!-- 没有领取到钱 -->
+      <div class="header" :style="{ 'backgroundImage': `url(${require('@/assets/subject/001-back-head-top.svg')})` }"
+        v-show="state.close_status == '没有领到钱'">
+        <div class="rabbit">
+          <img :src="require('@/assets/subject/001-icon-rabbit.svg')" alt />
+          <p>Sorry, you missed this chance</p>
+          <p>Come Earlier Next Time!</p>
+        </div>
+      </div>
+
+      <div class="luck-list-title">
+        <div>{{ state.detail.receiveCount || 0 }}/{{ state.detail.totalCount || 0 }} Winners</div>
+        <div class="right" v-if="state.detail.rewardType === RewardType.money">
+          <span class="text">
+            <a-tooltip :title="state.detail.receiveAmountValue">
+              {{ getBit(state.detail.receiveAmountValue) }}
+            </a-tooltip>
+            /
+            <a-tooltip :title="state.detail.amountValue">
+              {{ getBit(state.detail.amountValue || '') }}
+            </a-tooltip>
+          </span> {{
+              state.detail.currencySymbol || ''
+          }}
+        </div>
+      </div>
+
+      <div class="luck-list max" @scroll="handleScroll">
+        <div class="luck-item" v-for="item, i in state.detail.allReceived" v-bind:key="i">
+          <img v-if="item.simpleUserInfoVO.avatarUrl" :src="item.simpleUserInfoVO.avatarUrl" alt
+            @click="openTwitterDetail(item)" />
+          <img v-else :src="require('@/assets/svg/icon-twitter.svg')" alt />
+          <div class="luck-content">
+            <div class="luck-title" v-if="item.simpleUserInfoVO.nickName">{{ item.simpleUserInfoVO.nickName }}</div>
+            <div class="luck-title" v-else>Twitter User</div>
+            <div class="luck-time">{{ moment(item.receiveTimestamp).format('MM-DD HH:mm:ss') }}</div>
+          </div>
+          <div class="luck-money" v-if="state.detail.rewardType === RewardType.money">
+            <img :src="state.detail.currencyIconPath" alt />
+            <div class="luck-money-txt">
+              <a-tooltip :title="item.amountValue">
+                {{ getBit(item.amountValue) }}
+              </a-tooltip>
+            </div>
+          </div>
+          <div class="luck-custom-prize" v-else>winner</div>
+          <div class="luck-king" v-if="state.detail.rewardType === RewardType.money && item.maxAmount">
+            <img :src="require('@/assets/svg/icon-king-hat.svg')" alt />
+            <span>Luckiest Draw</span>
+          </div>
+        </div>
+
+        <div class="empty" v-show="state.detail.allReceived && state.detail.allReceived.length == 0">
+          <img :src="require('@/assets/svg/icon-error.svg')" alt />
+        </div>
+      </div>
+      <get-more :reportData="{
+        pageSource: Report.pageSource.expiredPage,
+        postId: state.postId,
+        redPacketType: Report.redPacketType.giveaway
+      }"></get-more>
+    </div>
+
+
+    <!-- error -->
+    <div v-else-if="state.status == 'error'" class="error">
+      <img :src="require('@/assets/svg/icon-error.svg')" alt />
+      <div class="txt">
+        {{ state.error_txt }}
+      </div>
+      <div class="retry" v-show="state.retry" @click="clickRetry">
+        Retry
+      </div>
+    </div>
+
+
+    <!-- loading -->
+    <div v-show="state.loading_show" class="loading">
+      <img :src="require('@/assets/svg/icon-loading.svg')" alt />
+    </div>
+
+    <div v-show="state.loading_redbag" class="redbag">
+      <img :src="require('@/assets/img/icon-loading-redbag.png')" alt />
+    </div>
+
+  </div>
+  <div style="width: 100%; height: 30px; position: fixed; color: red; top:0;" v-if="state.process_mode != 'production'">
+    {{ state.detail.validity }}</div>
+</template>
+
+<script>
+export default {
+  name: 'redPacket',
+}
+</script>
+<script setup>
+import { onMounted, reactive, ref, computed } from "vue";
+import { getPostDetail, getRedPacket, finishRedPacket, oneKeyLike, oneKeyReTweet, oneKeyFollow, getTaskDetail, getReceivedList, addFinishEvent } from '@/http/redPacket.js'
+import { getQueryString, guid, getBit } from '@/uilts/help.js'
+import { message } from 'ant-design-vue';
+import FontAmount from '@/components/font-amount.vue'
+import FontZoom from '@/components/font-zoom.vue'
+import GetMore from '@/components/get-more.vue'
+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'
+import { discordAuthRedirectUri, faceShareRedirectUrl } from '@/http/configAPI'
+import { getFrontConfig } from "@/http/account";
+import { getInviteGuildInfo } from "@/http/discordApi";
+import GlobalTip from '@/components/global-tip.vue'
+import customCardCover from '@/components/custom-card-cover.vue';
+import { RewardType, PlayType } from '@/types';
+import { messageCenter } from '@/uilts/messageCenter';
+
+var moment = require('moment');
+
+let discordAuthorizeRequired = false;
+let joinDiscordActionState = 'default'; //authAndJoinIng  joinIng  reAuth
+let joinDiscordIng = ref(false);
+
+let facebookAppConfig = {
+  facebookAppId: "",
+  faceShareRedirectUrl
+};
+
+let reportParams = {
+  discordFans: '',
+  twitterFans: '',
+  done: {
+  },
+  hasReport: false,
+}
+
+let discordTaskDetail = null;
+
+let state = reactive({
+  status: '',
+  userId: '',
+  loading_show: false,
+  loading_redbag: true,
+  detail: {},
+  luck_list_end: false,
+  page_index: 1,
+  page_size: 20,
+  srcContentId: '',
+  customCover: '',
+  error_txt: `oops, new accounts cannot participate in this event,`,
+  receiveAmount: 0,
+  money: 0,
+  // 状态
+  done: {
+    follow: false,
+    like: false,
+    retweet: false,
+    join_discord: false,
+    repost_facebook: false,
+    reply: false
+  }
+})
+
+let fullName = '';
+
+let successTopBgCpd = computed(() => {
+  const { rewardType } = state.detail
+  switch (rewardType) {
+    case RewardType.custom:
+      return require('@/assets/subject/success-top-bg-2.svg');
+    default:
+      return require('@/assets/subject/002-back-head-top-180.svg');
+      break;
+  }
+});
+
+function clickRetry() {
+  init()
+}
+
+let follow_open_tabs = []
+
+async function clickLikeBtn() {
+  let _userInfo = await checkIsLogin()
+  if (!_userInfo) {
+    return
+  }
+  state.detail.finishTaskTypeV2 = state.detail.finishTaskTypeV2.toString() || ''
+  if (state.window_origin.indexOf('facebook.com') >= 0) {
+    state.detail.finishTaskTypeV2 = '2'
+  }
+  switch (state.detail.finishTaskTypeV2) {
+    case '1':
+      state.loading_show = true
+      oneKeyLike({
+        params: {
+          tweetId: state.srcContentId
+        }
+      }).then((res) => {
+        state.loading_show = false
+        if (res.code == 0) {
+          if (res.data.result) {
+            state.done.like = true
+          } else {
+            state.done.like = false
+            window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+          }
+        } else {
+          window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+          state.done.like = false
+        }
+      }).catch(() => {
+        state.loading_show = false
+      })
+      break
+    case '2':
+      window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+      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) });
+      })
+      break
+    default:
+      window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+      break
+  }
+
+  // 埋点
+  Report.reportLog({
+    objectType: Report.objectType.like,
+    pageSource: Report.pageSource.task_page,
+    businessType: Report.businessType.buttonClick,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    customCover: state.customCover,
+  });
+}
+function clickDone() {
+  window.open(`${chromeExtensionUrl + ('iframe/home.html')}`)
+  // 埋点
+  Report.reportLog({
+    objectType: Report.objectType.wallet_button,
+    pageSource: Report.pageSource.received_success_page,
+    businessType: Report.businessType.buttonClick,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    redPacketType: 0,
+    customCover: state.customCover,
+  });
+}
+function handleScroll(e) {
+  if (state.luck_list_end) {
+    return
+  }
+  e = e.target
+  if ((e.clientHeight + e.scrollTop) / e.scrollHeight > .8) {
+    state.luck_list_end = true
+    state.page_index++
+    handleReceivedList()
+  }
+}
+function handleReceivedList() {
+  getReceivedList({
+    params: {
+      pageNum: state.page_index,
+      pageSize: state.page_size,
+      postId: state.postId
+    }
+  }).then((res) => {
+    if (res.code == 0) {
+      if (res.data.length > 0) {
+        state.detail.allReceived = state.detail.allReceived.concat(res.data)
+        state.luck_list_end = false
+      } else {
+        state.luck_list_end = true
+      }
+    } else {
+      console.log('getReceivedList', res)
+    }
+  })
+}
+
+const openTwitterDetail = (item) => {
+  if (item.simpleUserInfoVO.nickName) {
+    window.open(`https://twitter.com/${item.simpleUserInfoVO.nickName}`)
+  }
+}
+
+async function clickRetweetBtn() {
+  let _userInfo = await checkIsLogin()
+  if (!_userInfo) {
+    return
+  }
+
+  state.detail.finishTaskTypeV2 = state.detail.finishTaskTypeV2.toString() || ''
+  if (state.window_origin.indexOf('facebook.com') >= 0) {
+    state.detail.finishTaskTypeV2 = '2'
+  }
+  switch (state.detail.finishTaskTypeV2) {
+    case '1':
+      state.loading_show = true
+      oneKeyReTweet({
+        params: {
+          tweetId: state.srcContentId
+        }
+      }).then((res) => {
+        state.loading_show = false
+        if (res.code == 0) {
+          if (res.data.result) {
+            state.done.retweet = true
+          } else {
+            window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
+            state.done.retweet = false
+          }
+        } else {
+          window.open(`https://twitter.com/retweet/like?tweet_id=${state.tweetId}`)
+          state.done.retweet = false
+        }
+      }).catch(() => {
+        state.loading_show = false
+      })
+      break;
+    case '2':
+      window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
+      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) });
+      })
+      break
+    default:
+      window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
+      break;
+  }
+
+  // 埋点
+  Report.reportLog({
+    objectType: Report.objectType.retweet,
+    pageSource: Report.pageSource.task_page,
+    businessType: Report.businessType.buttonClick,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    customCover: state.customCover,
+  });
+}
+
+function onTweetReplyClick(params) {
+  let replyData = {
+    postId: state.postId,
+    type: params.type,
+    taskLuckdropId: state.detail.taskLuckdropId
+  }
+
+  window.parent.postMessage({ actionType: "IFRAME_RED_PACKET_ON_TWEET_REPLY_CLICK", data: replyData }, "*");
+}
+
+async function clickReply(params) {
+  let _userInfo = await checkIsLogin()
+  if (!_userInfo) {
+    return
+  }
+
+  let replyData = {
+    postId: state.postId,
+    type: params.type,
+    taskLuckdropId: state.detail.taskLuckdropId
+  }
+  if (state.window_origin.indexOf('facebook.com') > -1) {
+    let url = `https://twitter.com/${state.tweet_author}/status/${state.tweetId}?actionType=denetFacebookToTwitterReply&deReplyParams=${JSON.stringify(replyData)}`
+    window.open(url)
+  } else {
+    window.parent.postMessage({ actionType: "IFRAME_RED_PACKET_REPLY_CLICK", data: replyData }, "*");
+  }
+  // 埋点
+  Report.reportLog({
+    objectType: Report.objectType.comment_and_tag,
+    pageSource: Report.pageSource.task_page,
+    businessType: Report.businessType.buttonClick,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    redPacketType: 0,
+    customCover: state.customCover,
+  });
+}
+
+/**
+ * 点击repost facebook
+ */
+async function clickRepostFacebook(params) {
+  let _userInfo = await checkIsLogin()
+  if (!_userInfo) {
+    return
+  }
+
+  let deUrlParams = {
+    fullName,
+    tweetId: state.tweetId
+  }
+  let href = `${state.postRedirectUrl}?deUrlParams=${JSON.stringify(deUrlParams)}`;
+  console.log(href);
+  let shareUrlparams = {
+    href,
+    type: params.type,
+    taskLuckdropId: state.detail.taskLuckdropId
+  }
+
+  setChromeStorage({
+    shareFacebookData: JSON.stringify({
+      contentStr: state.srcContent
+    })
+  })
+
+  let shareUrl = feacebookShareUrl(shareUrlparams);
+  openShareFacebookWindow({ url: shareUrl });
+
+  // 埋点
+  Report.reportLog({
+    objectType: Report.objectType.share_facebook,
+    pageSource: Report.pageSource.task_page,
+    businessType: Report.businessType.buttonClick,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    redPacketType: 0,
+    customCover: state.customCover,
+  });
+}
+
+/**
+ * 分享到facebook
+ */
+function openShareFacebookWindow({ url }) {
+  const width = 800;
+  chrome.windows.create({
+    width,
+    type: 'normal',
+    url
+  }, function (window) {
+
+  })
+}
+
+/**
+ * 分享fecebook 地址
+ */
+function feacebookShareUrl(params = {}) {
+  let { href = '', type = '', taskLuckdropId } = params;
+  let cbParams = JSON.stringify({
+    type,
+    taskLuckdropId
+  })
+  let shareUrl = `https://www.facebook.com/dialog/share?app_id=${facebookAppConfig.facebookAppId}&display=popup&href=${href}&redirect_uri=${facebookAppConfig.faceShareRedirectUrl}?params=${cbParams}`;
+
+  return shareUrl;
+}
+
+/**
+ * 分享成功
+ */
+function facebookShareSuccess(params) {
+  let { taskLuckdropId } = params;
+
+  if (taskLuckdropId == state.detail.taskLuckdropId) {
+    state.done.repost_facebook = true;
+    state.done.repost_facebook_red = false;
+  }
+}
+
+
+function getValidity() {
+  let _d1, _d2, _d3, _h, _m, _s
+  if (!state.detail.myReceived.taskEndTimestamp) {
+    return
+  }
+  let timer = setInterval(() => {
+    let _time = new Date().getTime()
+    _d3 = state.detail.myReceived.taskEndTimestamp - _time
+    if (_d3 > 0) {
+      _d1 = moment(state.detail.myReceived.taskEndTimestamp)
+      _d2 = moment(_time)
+      _h = moment.duration(_d1.diff(_d2)).hours()
+      if (_h < 10) {
+        _h = '0' + _h
+      }
+      _m = moment.duration(_d1.diff(_d2)).minutes()
+      if (_m < 10) {
+        _m = '0' + _m
+      }
+      _s = moment.duration(_d1.diff(_d2)).seconds()
+      if (_s < 10) {
+        _s = '0' + _s
+      }
+      state.detail.validity = `${_h}:${_m}:${_s}`
+    } else {
+      state.detail.validity = `00:00:00`
+      clearInterval(timer)
+    }
+  }, 1000)
+}
+
+const openFollowTabs = (arr_name) => {
+  let array_finish = arr_name.filter((item) => { return !item.finished })
+  // let array_finish = state.detail.taskCondition[0].relatedUsers.filter((item) => { return item.finished == false })
+  let url
+  if (array_finish.length > 0) {
+    state.done.follow = false
+    // 打开标签页的方法
+    array_finish.forEach((item) => {
+      url = `https://twitter.com/intent/follow?screen_name=${item.name}&tweet_id=${state.tweetId}`
+      chrome.tabs.create({ url }, (tab) => {
+        if (follow_open_tabs.filter((item) => { return item.url == tab.url }).length == 0) {
+          follow_open_tabs.push(tab)
+        }
+      })
+    })
+  }
+}
+
+async function clickFollowAll(item, is_all) {
+  let _userInfo = await checkIsLogin()
+  if (!_userInfo) {
+    return
+  }
+  let arr_name = []
+  for (let i in item) {
+    if (!item[i].finished) {
+      arr_name.push(item[i])
+    }
+  }
+  // ----
+  state.detail.finishTaskTypeV2 = state.detail.finishTaskTypeV2.toString() || ''
+  if (state.window_origin.indexOf('facebook.com') >= 0) {
+    state.detail.finishTaskTypeV2 = '2'
+  }
+  switch (state.detail.finishTaskTypeV2) {
+    case '1':
+      // openapi
+      state.loading_show = true
+      oneKeyFollow({
+        params: {
+          names: arr_name
+        }
+      }).then((res) => {
+        state.loading_show = false
+        if (res.code == 0) {
+          res.data.forEach((item1) => {
+            state.detail.taskCondition[0].relatedUsers.forEach(item2 => {
+              if (item1.name == item2.name && item1.finished) {
+                item2.finished = true
+              }
+            });
+          })
+          openFollowTabs(arr_name)
+        }
+      }).catch(() => {
+        state.loading_show = false
+      })
+      break
+    case '2':
+      openFollowTabs(arr_name)
+      break
+    case '3':
+      if (arr_name.filter((item) => { return !item.twitterUserId }).length > 0) {
+        openFollowTabs(arr_name)
+        return
+      }
+      let follow_data = []
+      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) });
+      })
+
+      break
+    default:
+      openFollowTabs(arr_name)
+      break
+  }
+  // -------- 埋点 --------
+  let _log_obj = {
+    pageSource: Report.pageSource.task_page,
+    businessType: Report.businessType.buttonClick,
+    objectType: Report.objectType.follow,
+    customCover: state.customCover,
+  }
+  if (is_all) {
+    _log_obj.objectType = Report.objectType.follow_button
+  }
+  Report.reportLog(_log_obj, {
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+  });
+}
+
+
+// 重新绑定
+const reSetBindTwtterId = (_params) => {
+  let postBizData = JSON.parse(_params.postBizData);
+  let { taskCondition } = postBizData;
+  let discordTask = JSON.parse(taskCondition).find(item => item.type == 7);
+
+  getChromeStorage('userInfo', (_userInfo = {}) => {
+    // if (_userInfo.uid == _params.uid) {
+    if (_userInfo.uid) {
+      srcPublishSuccess({
+        params: {
+          postId: state.postId,
+          srcContentId: state.tweetId
+        }
+      }).then((res) => {
+        if (res.code == 0 || res.code == 3003) {
+          init({ from: 'reSetBindTwtterId' })
+          reportBindTweetSuccess({ discordTask, ..._params });
+        }
+      })
+    }
+  })
+}
+
+const reportBindTweetSuccess = (params) => {
+  let { discordTask, srcUserId } = params || {};
+  discordTaskDetail = discordTask;
+  sendCurrentTabMessage({
+    actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
+    data: {
+      screen_name: srcUserId,
+      tweetId: state.tweetId
+    }
+  })
+
+  if (discordTask) {
+    getDiscordInfo({ inviteUrl: JSON.parse(discordTask.bizData).inviteUrl }, (res) => {
+      if (res.inviteCode == res.code) {
+        reportParams.discordFans = res.approximate_member_count;
+
+        if (reportParams.twitterFans !== '' && !reportParams.hasReport) {
+          reportParams.hasReport = true;
+          Report.reportLog({
+            objectType: Report.objectType.tweetPostBinded,
+            twitterFans: reportParams.twitterFans,
+            discordFans: reportParams.discordFans,
+            redPacketType: 0,
+            postId: state.postId
+          });
+        }
+      }
+    })
+  }
+}
+
+const getDiscordInfo = (params, cb) => {
+  let { inviteUrl } = params;
+  if (!inviteUrl) return;
+  let inviteCode = '';
+  let arr = inviteUrl.split('/');
+  if (arr.length > 0) {
+    inviteCode = arr[arr.length - 1];
+  }
+  if (!inviteCode) {
+    return;
+  }
+  getInviteGuildInfo({
+    inviteCode
+  }).then(res => {
+    cb && cb({
+      ...res,
+      inviteCode
+    })
+  }).catch((err) => {
+  });
+}
+
+const showCloseEndTimePage = () => {
+  state.status = 'close'
+  state.close_status = '红包过期了'
+  state.close_text = [`This Giveaways`, `expired on ${moment(state.detail.endTimestamp).format('MM-DD')}`]
+}
+
+const showCloseEndTimePageReport = () => {
+  // 埋点
+  Report.reportLog({
+    pageSource: Report.pageSource.expired_page,
+    businessType: Report.businessType.pageView,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+  });
+}
+
+const showSuccessPage = () => {
+  state.status = 'success'
+  // 埋点
+  Report.reportLog({
+    pageSource: Report.pageSource.received_success_page,
+    businessType: Report.businessType.pageView,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    isOldTwitterFans: reportParams.done.follow,
+    isOldDiscordFans: reportParams.done.join_discord,
+    redPacketType: 0,
+    customCover: state.customCover,
+  });
+}
+const showNotOpenPage = () => {
+  state.status = 'not-open'
+  Report.reportLog({
+    pageSource: Report.pageSource.pending_page,
+    businessType: Report.businessType.pageView,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    redPacketType: 0,
+    customCover: state.customCover,
+  });
+}
+const showOpenedPage = () => {
+  state.status = 'opened'
+  initTaskDetail(() => {
+    showOpenedPageReport()
+  })
+}
+const showOpenedPageReport = () => {
+  reportParams.done.follow = state.done.follow;
+  reportParams.done.join_discord = state.done.join_discord;
+  // 埋点
+  Report.reportLog({
+    pageSource: Report.pageSource.task_page,
+    businessType: Report.businessType.pageView,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    isOldTwitterFans: state.done.follow,
+    isOldDiscordFans: state.done.join_discord,
+    redPacketType: 0,
+    customCover: state.customCover,
+  });
+}
+
+const showRabbitPage = () => {
+  state.status = 'close'
+  state.close_status = '没有领到钱'
+
+
+}
+const showRabbitPageReport = () => {
+  Report.reportLog({
+    pageSource: Report.pageSource.received_empty_rewards_page,
+    businessType: Report.businessType.pageView,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+  });
+}
+
+const handleStatusPage = () => {
+  // status 红包状态(0:未开始,1:进行中,2:已结束,3:已终止,4:终止退款进行中)
+  // myReceived 我是否领取过
+  // taskFinishStatus 任务完成状态(0:未完成,1:已完成,2:已过期)
+  // receiveTimeExpired 是否已经过了红包的领取截止时间
+
+  // ---- 判断结构 ----
+  // 如果 红包状态 = 未开始
+  //    显示未打开页面 return
+  //
+  // 如果 我领取过了
+  //    如果 任务完成状态 = 未完成
+  //        显示任务未完成页面
+  //    如果 任务完成状态 = 已经完成
+  //        如果 (货币类奖品 && 领取到红包金额 = 0) || (自定义奖品 && winner = 0)
+  //            显示兔子页面
+  //        否则
+  //            显示成功页面
+  //    如果 任务完成状态 = 已经过期
+  //        如果 红包状态 = 进行中
+  //            显示未打开页面
+  //        否则
+  //            显示已经过期页面
+
+  // 如果 我没有领取过 & 红包状态 = 进行中
+  //    如果 过了红包的领取截止时间 = true
+  //        显示已经过期页面
+  //    如果 过了红包的领取截止时间 = false
+  //        显示未打开页面
+
+  // 如果 我没有领取过 & 红包状态 = 已结束 | 已终止 | 终止退款进行中
+  //    显示过期页面
+
+  // -------- 华丽的分割线 --------
+  // 如果 红包状态 = 未开始
+  if (state.detail.status == 0) {
+    showNotOpenPage()
+    return
+  }
+  // 如果 我领取过了
+  if (state.detail.myReceived) {
+    state.receiveAmount = state.detail.myReceived.amountValue || 0
+    state.detail.taskCondition = JSON.parse(state.detail.taskCondition)
+    // 如果 任务完成状态 = 未完成
+    if (state.detail.myReceived.taskFinishStatus == 0) {
+      // 显示任务未完成页面
+      showOpenedPage()
+      if (state.process_mode != 'production') {
+        getValidity()
+      }
+      //如果 任务完成状态 = 已经完成
+    } else if (state.detail.myReceived.taskFinishStatus == 1) {
+      // 领取到空红包
+      if ((state.detail.rewardType === RewardType.money && state.receiveAmount == 0) || (state.detail.rewardType === RewardType.custom && state.detail.myReceived.winner === 0)) {
+        showRabbitPage()
+        showRabbitPageReport()
+      } else {
+        // 显示成功页面
+        showSuccessPage()
+      }
+      // 如果 任务完成状态 = 已经过期
+    } else {
+      // 如果 红包状态 = 进行中
+      if (state.detail.status == 1) {
+        // 显示未打开页面
+        showNotOpenPage()
+        // 否则
+      } else {
+        // 显示已经过期页面
+        showCloseEndTimePage()
+        showCloseEndTimePageReport()
+      }
+    }
+    // 如果 我没有领取过
+  } else {
+    // 如果 红包状态 = 进行中
+    if (state.detail.status == 1) {
+      // 如果 过了红包的领取截止时间 = true
+      if (state.detail.receiveTimeExpired) {
+        // 显示过期页面
+        showCloseEndTimePage()
+        showCloseEndTimePageReport()
+        // 如果 过了红包的领取截止时间 = false
+      } else {
+        // 显示未打开页面
+        showNotOpenPage()
+      }
+      // 红包状态 = 已经结束了 | 已经终止 | 终止退款中
+    } else {
+      // 显示过期页面
+      showCloseEndTimePage()
+      showCloseEndTimePageReport()
+    }
+  }
+
+}
+
+function setFrontConfig() {
+  getFrontConfig({
+    params: {},
+  }).then((res) => {
+    if (res.code == 0) {
+      facebookAppConfig.facebookAppId = res.data.fbClientId;
+    }
+  });
+};
+
+function init(initParams) {
+  state.loading_show = true;
+  let { type } = initParams || {};
+  onPageVisbile();
+  onWindowMessage();
+  setFrontConfig();
+  getPostDetail({
+    params: {
+      postId: state.postId
+    }
+  }).then((res) => {
+    state.loading_show = false
+    // 领取0元为空红包继续流程
+    // ---- 完成任务接口 ----
+    // 如果金额是0
+    //    显示没有领到钱
+    if (res.code == 0) {
+      state.srcContent = res.data.srcContent;
+      state.postRedirectUrl = res.data.postRedirectUrl;
+
+      // 判断推特id,绑定逻辑
+      state.srcContentId = res.data.srcContentId
+
+      if (!state.srcContentId) {
+        reSetBindTwtterId(res.data)
+        return
+      }
+      state.detail = JSON.parse(res.data.postBizData)
+      state.detail.taskCondition = state.detail.taskCondition || []
+      state.tweetId = state.srcContentId;
+      state.userId = res.data.srcUserId;
+      state.tweet_author = state.detail.postUserInfo && state.detail.postUserInfo.nickName || '';
+      state.customCover = state.detail.posterType == 2 ? 1 : 0;
+      // 不要删除这个console
+      console.log('postBizData', state.detail)
+      checkFacebookReply();
+      handleStatusPage()
+    } else {
+      handleErrorCode(res)
+    }
+  }).finally(() => {
+    state.loading_show = false
+    state.loading_redbag = false
+  })
+}
+
+function initTaskDetail(cb) {
+  getChromeStorage('userInfo', (_userInfo) => {
+    if (_userInfo.uid) {
+      // 任务详情
+      getTaskDetail({
+        params: {
+          postId: state.postId
+        }
+      }).then((res) => {
+        if (res.code.toString()) {
+          for (let i in res.data) {
+            switch (res.data[i].type) {
+              case 1:
+                state.done.follow = res.data[i].finished
+                state.detail.taskCondition[0].relatedUsers = res.data[i].detail
+                break
+              case 2:
+                state.done.like = res.data[i].finished
+                break
+              case 3:
+                state.done.retweet = res.data[i].finished
+                break
+              case 7:
+                state.done.join_discord = res.data[i].finished
+                discordAuthorizeRequired = res.data[i].discordAuthorizeRequired
+                break
+              case 8:
+                state.done.repost_facebook = res.data[i].finished;
+                break;
+              case 9:
+                state.done.reply = res.data[i].finished;
+                if (!state.done.reply) {
+                  onTweetReplyClick({ type: 9 });
+                }
+                break;
+            }
+          }
+        } else {
+          handleErrorCode(res)
+        }
+        cb && cb()
+      })
+    }
+  })
+}
+
+let tab_index = 0
+const doTaskReport = (req, sender) => {
+  state.loading_show = false
+  let follow_name = req.task_data.follow_name || ''
+  // 1 Twitter follow Twitter ScreenName
+  // 2 Tweet like
+  // 3 Retweet
+  let event_type = 0
+  switch (req.task_type) {
+    case 'retweet':
+      event_type = 3
+      state.done.retweet = req.task_done
+      if (!req.task_done && req.do_type == 'api') {
+        window.open(`https://twitter.com/intent/retweet?tweet_id=${state.tweetId}`)
+      }
+      break;
+    case 'like':
+      event_type = 2
+      state.done.like = req.task_done
+      //
+      if (!req.task_done && req.do_type == 'api') {
+        window.open(`https://twitter.com/intent/like?tweet_id=${state.tweetId}`)
+      }
+      break
+    case 'follow':
+      event_type = 1
+      // for (let i = 0; i < follow_open_tabs.length; i++) {
+      //   if (follow_open_tabs[i].id == sender.tab.id) {
+      //     follow_open_tabs.splice(i, 1)
+      //     break
+      //   }
+      // }
+      // chrome.tabs.getCurrent((tab) => {
+      //   if (follow_open_tabs.length > 0) {
+      //     tab_index = follow_open_tabs[follow_open_tabs.length - 1].index
+      //   } else {
+      //     tab_index = tab.index
+      //   }
+      //   chrome.tabs.highlight({ windowId: tab.windowId, tabs: tab_index })
+      // })
+      let has_no_finished = false
+      state.detail.taskCondition[0].relatedUsers.forEach((item) => {
+        if (follow_name == item.name) {
+          item.finished = req.task_done
+        }
+      })
+      state.detail.taskCondition[0].relatedUsers.forEach((item) => {
+        if (!item.finished) {
+          has_no_finished = true
+        }
+      })
+      if (!has_no_finished) {
+        state.done.follow = true
+        state.done.follow_red = false
+        openFollowTabs(state.detail.taskCondition[0].relatedUsers)
+      }
+      break
+  }
+  if (req.do_type != 'api') {
+    chrome.tabs.remove(sender.tab.id)
+  }
+  if (req.task_done) {
+    addFinishEvent({
+      params: {
+        eventData: follow_name,
+        eventType: event_type,
+        luckdropId: state.detail.taskLuckdropId
+      }
+    })
+  }
+}
+
+onMounted(() => {
+  state.process_mode = process.env.NODE_ENV
+  state.postId = getQueryString('postId')
+  state.window_origin = getQueryString('window_origin') || '';
+  if (state.window_origin.indexOf('twitter.com') > -1) {
+    state.tweetId = getQueryString('tweetId')
+    state.tweet_author = getQueryString('tweet_author');
+  }
+
+  getTweetAuthor();
+  init()
+  // onRuntimeMsg();
+})
+
+function getTweetAuthor() {
+  if (state.window_origin.indexOf('twitter.com') > -1) {
+    window.parent.postMessage({
+      actionType: "IFRAME_RED_PACKET_GET_TWEET_AUTHOR", data: {
+        postId: state.postId,
+        taskLuckdropId: state.detail.taskLuckdropId
+      }
+    }, "*");
+  }
+}
+
+function checkFacebookReply() {
+  console.log('checkFacebookReply')
+  if (state.window_origin.indexOf('twitter.com') > -1) {
+    window.parent.postMessage({
+      actionType: "IFRAME_RED_PACKET_CHECK_FACEBOOK_REPLY", data: {
+        postId: state.postId
+      }
+    }, "*");
+  }
+}
+
+// 点击领取
+function clickOpenRedPacket() {
+  callEventPageMethod('CONTENT_GET_PINED', {})
+  handleRedPacket()
+}
+
+function handleRedPacket() {
+  state.loading_show = true
+  getRedPacket({
+    params: {
+      postId: state.postId
+    }
+  }).then((res) => {
+    state.loading_show = false
+    if (res.code == 0) {
+      showOpenedPage()
+      init()
+    } else {
+      handleErrorCode(res)
+    }
+  }).catch(() => {
+    state.loading_show = false
+  })
+  // 埋点
+  Report.reportLog({
+    pageSource: Report.pageSource.pending_page,
+    businessType: Report.businessType.buttonClick,
+    objectType: Report.objectType.open_button,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    redPacketType: 0,
+    customCover: state.customCover,
+  });
+}
+
+// chrome.storage.onChanged.addListener(changes => {
+//   if (changes.userInfo && changes.userInfo.newValue) {
+//     // let item = JSON.parse(changes.userInfo.newValue)
+//     state.loading_show = false
+//     init()
+//   }
+// })
+
+// 校验是否封路
+function checkIsLogin() {
+
+  return new Promise((resolve) => {
+    getChromeStorage('userInfo', (_userInfo) => {
+      if (!_userInfo) {
+        state.loading_show = true
+        setTimeout(() => {
+          state.loading_show = false
+        }, 3000)
+        chrome.runtime.sendMessage(
+          { actionType: "POPUP_LOGIN", data: "" },
+          (response) => {
+            console.log("res", response);
+          }
+        )
+        resolve(_userInfo)
+      } else {
+        resolve(_userInfo)
+      }
+    })
+  })
+}
+
+async function clickGetGiveaways() {
+  let _userInfo = await checkIsLogin()
+  if (_userInfo) {
+    handleFinishRedPacket()
+  }
+}
+
+function handleFinishRedPacket() {
+  state.loading_show = true
+  finishRedPacket({
+    params: {
+      postId: state.postId
+    }
+  }).then((res) => {
+    state.loading_show = false
+    if (res.code == 0) {
+      if (res.data.finished) {
+        state.receiveAmount = res.data.receiveAmount
+        // if (state.receiveAmount == 0) {
+        //   showRabbitPage()
+        // } else {
+        //   state.status = 'success'
+        // }
+        init()
+        // 埋点
+        Report.reportLog({
+          pageSource: Report.pageSource.task_page,
+          businessType: Report.businessType.buttonClick,
+          objectType: Report.objectType.get_giveaway,
+          postId: state.postId,
+          srcContentId: state.tweetId,
+          senderId: state.userId,
+          customCover: state.customCover,
+        }, {
+          get_giveaway_result: Report.extParams.success
+        });
+      } else {
+        let _data = res.data.conditionResult
+        for (let i in _data) {
+          switch (_data[i].type.toString()) {
+            case '1':
+              state.detail.taskCondition[0].relatedUsers = _data[i].detail
+              if (_data[i].finished) {
+                state.done.follow = true
+                state.done.follow_red = false
+              } else {
+                // alert('Please complete the task: follow')
+                state.done.follow = false
+                state.done.follow_red = true
+              }
+              break
+            case '2':
+              if (_data[i].finished) {
+                state.done.like = true
+                state.done.like_red = false
+              } else {
+                // alert('Please complete the task: like tweet')
+                state.done.like = false
+                state.done.like_red = true
+              }
+              break
+            case '3':
+              if (_data[i].finished) {
+                state.done.retweet = true
+                state.done.retweet_red = false
+              } else {
+                // alert('Please complete the task: Retweet')
+                state.done.retweet_red = true
+                state.done.retweet = false
+              }
+              break
+            case '7':
+              //join discord
+              discordAuthorizeRequired = _data[i].discordAuthorizeRequired;
+              if (_data[i].finished) {
+                state.done.join_discord = true
+                state.done.join_discord_red = false
+              } else {
+                state.done.join_discord = false;
+                state.done.join_discord_red = true
+              }
+              break
+            case '8':
+              //repost feacebook
+              if (_data[i].finished) {
+                state.done.repost_facebook = true
+                state.done.repost_facebook_red = false
+              } else {
+                state.done.repost_facebook = false;
+                state.done.repost_facebook_red = true
+              }
+              break
+            case '9':
+              //reply
+              if (_data[i].finished) {
+                state.done.reply = true
+                state.done.reply_red = false
+              } else {
+                state.done.reply = false;
+                state.done.reply_red = true
+              }
+              break
+          }
+        }
+        // 埋点
+        Report.reportLog({
+          pageSource: Report.pageSource.task_page,
+          businessType: Report.businessType.buttonClick,
+          objectType: Report.objectType.get_giveaway,
+          postId: state.postId,
+          srcContentId: state.tweetId,
+          senderId: state.userId,
+          customCover: state.customCover,
+        }, {
+          get_giveaway_result: Report.extParams.failure,
+        });
+        if (discordAuthorizeRequired) {
+          discordAuth('reAuth');
+        }
+      }
+    } else {
+      // 埋点
+      Report.reportLog({
+        pageSource: Report.pageSource.task_page,
+        businessType: Report.businessType.buttonClick,
+        objectType: Report.objectType.get_giveaway,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+        customCover: state.customCover,
+      }, {
+        get_giveaway_result: Report.extParams.failure,
+      });
+      handleErrorCode(res)
+    }
+  }).catch(() => {
+    state.loading_show = false
+  })
+}
+
+
+function handleErrorCode(res) {
+  switch (res.code.toString()) {
+    // 数据异常,请联系管理员
+    case '-102':
+
+      break
+    //系统错误
+    case '-101':
+
+      break
+
+    // 参数不对
+    case '-103':
+      break
+    // 接口被限流
+    case '-105':
+      break
+
+    // 访问凭证不存在
+    case '-107':
+      break
+    // 重复操作过于频繁
+    case '-106':
+      message.error('Clicking too often, wait a moment and click again')
+      state.loading_show = false
+      break
+    // 红包不存在
+    case '2001':
+      // message.error(res.msg)
+      break
+    // 还未到红包领取时间
+    case '2002':
+      // message.error(res.msg)
+      break
+    // 已超过红包领取时间
+    case '2003':
+      init()
+      break
+    // 红包支付状态异常 没有可提交的任务红包
+    case '2004':
+      init()
+      break
+    // 红包活动已结束
+    case '2006':
+      init()
+      break
+    // 红包金额已经被领取完了
+    case '2007':
+      state.status = 'close'
+      state.close_status = '红包过期了'
+      state.close_text = [`This Giveaways`, `expired on ${moment(state.detail.endTimestamp).format('MM-DD')}`]
+      init()
+      break
+    // 红包个数已经被领取完了
+    case '2008':
+      state.status = 'close'
+      state.close_status = '红包过期了'
+      state.close_text = [`This Giveaways`, `expired on ${moment(state.detail.endTimestamp).format('MM-DD')}`]
+      init()
+      break
+    // 该用户不满足领取条件
+    case '2009':
+      state.error_txt = [`oops, new accounts cannot participate in this event,`]
+      state.status = 'error'
+      state.retry = true
+      // 埋点
+      Report.reportLog({
+        pageSource: Report.pageSource.robot_detection_failed_page,
+        businessType: Report.businessType.pageView,
+        postId: state.postId,
+        srcContentId: state.tweetId,
+        senderId: state.userId,
+      });
+      break
+    // 无法校验用户Twitter信息
+    case '2010':
+      // message.error(res.msg)
+      break
+    // 用户已经领过该红包
+    case '2011':
+      // message.error(res.msg)
+      break
+    // 推文不存在
+    case '2022':
+      // message.error(res.msg)
+      break
+    // 推文未发布 and 不是红包任务的推文
+    case '2023':
+      // message.error(res.msg)
+      break
+    // 没有可提交的任务红包
+    case '2024':
+      state.status = 'not-open'
+      break
+    // 红包任务已完成
+    case '2025':
+      break
+    // 任务已经过期
+    case '2026':
+      break
+    // 任务未完成
+    case '2027':
+      break
+    // 红包金额每人不足1分钱
+    case '2028':
+      break
+    // 推文未发布
+    case '2029':
+      message.error('Tweet not posted')
+      break
+    // 不是红包任务的推文
+    case '2030':
+      break
+    case '2037':
+      showCloseEndTimePage()
+      init()
+      break
+    //用户没有领取过红包,无法重抽
+    case '2031':
+      break
+    // 需要重新授权 discord
+    case '1010':
+      discordAuth('reAuth');
+      break
+  }
+}
+
+// function clickBack() {
+//   state.status = 'opened'
+//   // 埋点
+//   Report.reportLog({
+//     pageSource: Report.pageSource.task_page,
+//     businessType: Report.businessType.pageView,
+//   });
+// }
+
+// function clickRoad() {
+//   state.status = 'luck-peopel-list'
+//   // 埋点
+//   Report.reportLog({
+//     pageSource: Report.pageSource.task_page,
+//     businessType: Report.businessType.buttonClick,
+//     objectType: Report.objectType.received_list
+//   });
+//   // 埋点
+//   Report.reportLog({
+//     pageSource: Report.pageSource.received_list_page,
+//     businessType: Report.businessType.pageView
+//   });
+// }
+function onWindowMessage() {
+  window.addEventListener("message", 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;
+          break;
+        case 'CONTENT_RED_PACKET_GET_TWEET_AUTHOR':
+          fullName = event.data.data.fullName
+          break;
+        case 'CONTENT_RED_PACKET_FACEBOOK_REPLY':
+          clickReply(event.data.data)
+          break;
+      }
+    }
+  });
+}
+
+function onPageVisbile() {
+  document.addEventListener('visibilitychange', function () {
+    let isHidden = document.hidden;
+    if (!isHidden) {
+      checkJoinDiscord();
+    }
+  });
+}
+
+function onRuntimeMsg() {
+  chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
+    switch (req.actionType) {
+      case 'BACK_DISCORD_LOGIN_SUCCESS':
+        discordLoginSuccess();
+        break;
+      case 'BG_FACEBOOK_SHARE_SUCCESS':
+        facebookShareSuccess(req.data);
+        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 (req.tweetId == state.tweetId && 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();
+  })
+}
+
+/**
+ * 检查是否加入discord
+ */
+function checkJoinDiscord() {
+  // 如果上次的状态是 joinIng 检查是否真正join
+  if (joinDiscordActionState == 'joinIng') {
+    joinDiscordActionState = 'default';
+    let url = getInviteUrl();
+    if (url) {
+      joinDiscordIng.value = true;
+      checkGuildJoinedStatus({ url }, (res = {}) => {
+        joinDiscordIng.value = false;
+        if (res.code == 0) {
+          let { joined } = res.data || {};
+          if (joined) {
+            state.done.join_discord = true;
+          } else {
+            state.done.join_discord = false;
+          }
+        } else if (res.code == 1010) {
+          discordAuth('reAuth');
+        }
+      })
+    }
+  }
+}
+
+
+const checkGuildJoinedStatus = ({ url }, cb) => {
+  checkGuildJoined({
+    params: {
+      inviteUrl: url
+    }
+  }).then(res => {
+    cb && cb(res);
+  }).catch(err => {
+    cb && cb({ catch: true })
+  })
+}
+
+/**
+ * 加入discord 事件
+ */
+async function joinDiscord() {
+  let _userInfo = await checkIsLogin();
+  if (!_userInfo) {
+    return
+  }
+  if (joinDiscordIng.value) {
+    return;
+  }
+
+  // 埋点
+  Report.reportLog({
+    objectType: Report.objectType.join_discord,
+    pageSource: Report.pageSource.task_page,
+    businessType: Report.businessType.buttonClick,
+    postId: state.postId,
+    srcContentId: state.tweetId,
+    senderId: state.userId,
+    redPacketType: 0,
+    customCover: state.customCover,
+  });
+
+  let url = getInviteUrl();
+  if (url) {
+    joinDiscordIng.value = true;
+    checkGuildJoinedStatus({ url }, (res) => {
+      setTimeout(() => {
+        joinDiscordIng.value = false;
+      }, 1500);
+      if (res.code == 0) {
+        let { joined } = res.data || {};
+        if (joined) {
+          state.done.join_discord = true;
+        } else {
+          state.done.join_discord = false;
+          if (discordAuthorizeRequired) {
+            discordAuth('authAndJoinIng');
+          } else {
+            openInviteUrl();
+          }
+        }
+      } else if (res.code == 1010) {
+        discordAuth('authAndJoinIng');
+      }
+      if (res.catch) {
+        //判断是否需要授权
+        if (discordAuthorizeRequired) {
+          discordAuth('authAndJoinIng');
+        } else {
+          openInviteUrl();
+        }
+      }
+    })
+  }
+}
+
+/**
+ * discord授权
+ */
+function discordAuth(actionState = 'default') {
+  let state = guid();
+  discordAuthUrl({
+    params: {
+      redirectUrl: discordAuthRedirectUri,
+      state
+    }
+  }).then(res => {
+    if (res.code == 0) {
+      let { authorizeUrl = '' } = res.data || {};
+      if (authorizeUrl) {
+        joinDiscordActionState = actionState;
+        const width = 500;
+        chrome.windows.create({
+          width,
+          type: 'normal',
+          url: authorizeUrl
+        }, function (window) {
+          let windowId = window.id;
+          callEventPageMethod("RED_PACKET_SAVE_DISCORD_AUTH_WINDOW_ID", {
+            windowId: windowId
+          });
+        })
+      }
+    }
+  })
+}
+
+/**
+ * sendMessage
+ */
+const callEventPageMethod = (actionType, data, callback) => {
+  chrome.runtime.sendMessage(
+    {
+      actionType: actionType,
+      data: data
+    },
+    function (response) {
+      if (typeof callback === "function") callback(response);
+    }
+  );
+};
+
+/**
+ * discord 授权成功
+ */
+function discordLoginSuccess() {
+  console.log('discordloginSuccess');
+  // 如果是授权并join 默认打开 邀请链接
+  if (joinDiscordActionState == 'authAndJoinIng') {
+    openInviteUrl();
+  }
+  if (discordAuthorizeRequired) {
+    discordAuthorizeRequired = false;
+  }
+}
+
+/**
+ * 获取discord邀请链接
+ */
+function getInviteUrl() {
+  let inviteData = state.detail.taskCondition.find(item => {
+    return item.type == 7;
+  });
+  let url;
+  if (inviteData && inviteData.bizData) {
+    url = JSON.parse(inviteData.bizData).inviteUrl;
+  }
+  return url;
+}
+
+/**
+ * 打开邀请discord链接
+ */
+function openInviteUrl() {
+  joinDiscordActionState = 'joinIng';
+  let url = getInviteUrl();
+  if (url) {
+    if (!url.startsWith('http')) {
+      url = 'https://' + url;
+    }
+    window.open(url);
+  }
+}
+
+</script>
+
+<style lang="scss" scoped>
+html,
+body {
+  margin: 0;
+  padding: 0;
+  width: 375px;
+  height: 500px;
+  background-color: unset !important;
+}
+
+.content {
+  position: relative;
+  width: 375px;
+  height: 500px;
+  background: #fafafa;
+  overflow: hidden;
+  box-sizing: border-box;
+  font-family: "SF Pro Display";
+  font-style: normal;
+
+  .loading {
+    background: #FFFFFF;
+    opacity: 0.8;
+    z-index: 222;
+    text-align: center;
+    width: 375px;
+    height: 500px;
+    position: fixed;
+    top: 0;
+    left: 0;
+
+    img {
+      margin-top: 216px;
+      width: 70px;
+      height: 70px;
+    }
+  }
+
+  .redbag {
+    z-index: 222;
+    text-align: center;
+    width: 375px;
+    height: 500px;
+    position: fixed;
+    top: 0;
+    left: 0;
+    user-select: none;
+
+    img {
+      margin-top: 172px;
+      width: 130px;
+      height: 130px;
+    }
+  }
+
+  .error {
+    width: 100%;
+    height: 100%;
+    text-align: center;
+    position: relative;
+
+    img {
+      width: 100px;
+      height: 100px;
+      margin-top: 100px;
+    }
+
+    .txt {
+      font-weight: 500;
+      font-size: 22px;
+      line-height: 26px;
+      text-align: center;
+      letter-spacing: 0.3px;
+      color: #a8a8a8;
+      margin: 34px 44px 0 44px;
+    }
+
+    .retry {
+      position: absolute;
+      bottom: 30px;
+      left: 50%;
+      margin-left: -167.5px;
+      width: 335px;
+      height: 46px;
+      line-height: 46px;
+      text-align: center;
+      border-radius: 100px;
+      border: 1px solid #1D9BF0;
+      background: rgba(196, 196, 196, 0.01);
+      color: #1D9BF0;
+      font-size: 16px;
+      font-weight: 500;
+      cursor: pointer;
+    }
+  }
+
+  .success,
+  .close,
+  .luck-peopel-list {
+    filter: drop-shadow(0px 4px 94px rgba(0, 0, 0, 0.3));
+    width: 100%;
+    height: 100%;
+    border-radius: 11px;
+    background: #fff;
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+
+    .close-title {
+      width: 100%;
+      font-weight: 600;
+      font-size: 27px;
+      line-height: 32px;
+      text-align: center;
+      letter-spacing: 0.3px;
+      font-weight: 800;
+      font-size: 22px;
+      color: #ffffff;
+    }
+
+    .head {
+      padding: 14px 16px;
+
+      img {
+        cursor: pointer;
+        width: 24px;
+        height: 24px;
+      }
+    }
+
+    .header {
+      text-align: center;
+      min-height: 150px;
+      width: 100%;
+      background: #fff;
+      // padding-top: 30px;
+      background-size: 100% 100%;
+      position: relative;
+      display: flex;
+      align-content: center;
+      flex-wrap: wrap;
+
+      .rabbit {
+        width: 100%;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        align-content: center;
+        flex-wrap: wrap;
+        justify-content: center;
+
+        img {
+          width: 150px;
+          height: 80px;
+          margin-bottom: 6px;
+        }
+
+        p {
+          width: 100%;
+          margin: 0;
+          padding: 0;
+          color: #fff;
+          text-align: center;
+          font-weight: 600;
+          font-size: 15px;
+          letter-spacing: 0.3px;
+        }
+      }
+
+      .done {
+        cursor: pointer;
+        position: absolute;
+        top: 107px;
+        left: 50%;
+        margin-left: -150px;
+        width: 300px;
+        height: 60px;
+        display: flex;
+        align-items: center;
+        border-radius: 100px;
+        background: #ffffff;
+        box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);
+        justify-content: center;
+
+        span {
+          color: #000000;
+          font-size: 14px;
+        }
+
+        .icon-done {
+          width: 24px;
+          height: 24px;
+          margin-right: 10px;
+        }
+
+        .icon-right {
+          margin-left: 5px;
+          width: 7px;
+          height: 14px;
+        }
+      }
+
+      .title {
+        margin-top: 30px;
+        color: #fff7e4;
+        opacity: 0.6;
+
+        font-weight: 700;
+        font-size: 18px;
+        line-height: 21px;
+        letter-spacing: -0.3px;
+      }
+
+      .money {
+        margin-bottom: 30px;
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        img {
+          width: 40px;
+          height: 40px;
+          margin-right: 9px;
+          border-radius: 50%;
+          border: solid 2px #fff;
+        }
+
+        .big {
+          font-weight: 700;
+          font-size: 46px;
+          line-height: 55px;
+          /* identical to box height */
+
+          letter-spacing: 0.3px;
+
+          color: #fff;
+        }
+
+        .small {
+          margin-left: 4px;
+
+          font-weight: 700;
+          font-size: 13px;
+          line-height: 16px;
+          /* identical to box height */
+
+          letter-spacing: 0.5px;
+
+          color: #fff;
+        }
+      }
+
+      .custom-prize-show {
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        height: 44px;
+        margin-top: 20px;
+
+        img {
+          width: 24px;
+          height: 24px;
+          margin-right: 9px;
+        }
+      }
+    }
+
+    .luck-list-title {
+      /*      margin-top: 47px;*/
+      margin: 0 16px;
+      padding: 14px 0 11px 0;
+      background: #fff;
+      display: flex;
+      justify-content: space-between;
+      color: #B0B0B0;
+      font-weight: 500;
+      border-bottom: 1px solid #F2F2F2;
+
+      div:last-child {
+        text-align: right;
+      }
+
+      .text {
+        cursor: pointer;
+      }
+    }
+
+    .header-custom-prize {
+      align-items: flex-start;
+      align-content: flex-start;
+
+      .success-title {
+        line-height: 21px;
+        margin-top: 23px;
+        font-size: 18px;
+      }
+    }
+
+    .luck-list {
+      background: #fff;
+      overflow: auto;
+
+      &.max {
+        height: 250px;
+      }
+
+      .empty {
+        width: 100%;
+        height: 100%;
+        text-align: center;
+
+        img {
+          margin-top: 70px;
+          width: 100px;
+          height: 100px;
+        }
+      }
+
+      .luck-item {
+        display: flex;
+        padding: 10px 0;
+        margin: 0 16px;
+        border-bottom: 1px solid #F2F2F2;
+        justify-content: space-between;
+        position: relative;
+
+        img:first-child {
+          border-radius: 50%;
+        }
+
+        .luck-king {
+          position: absolute;
+          top: 36px;
+          right: 0px;
+          display: flex;
+          align-items: center;
+
+          img {
+            width: 22px;
+            height: 19px;
+            margin: 0;
+          }
+
+          span {
+            font-weight: 500;
+            font-size: 12px;
+            line-height: 14px;
+            letter-spacing: 0.3px;
+            color: #f5b945;
+          }
+        }
+
+        img {
+          cursor: pointer;
+          width: 42px;
+          height: 42px;
+          margin-right: 12px;
+        }
+
+        .luck-content {
+          flex: auto;
+
+          .luck-title {
+            color: #444444;
+            font-weight: 500;
+            font-size: 16px;
+            letter-spacing: 0.3px;
+            margin-bottom: 5px;
+          }
+
+          .luck-time {
+            font-weight: 400;
+            font-size: 12px;
+            line-height: 14px;
+            color: #B0B0B0;
+          }
+        }
+
+        .luck-money {
+          display: flex;
+          height: 17px;
+          align-items: center;
+          height: 100%;
+
+          img {
+            width: 14px;
+            height: 14px;
+            margin-right: 6px;
+          }
+
+          .luck-money-txt {
+            font-weight: 500;
+            font-size: 14px;
+            word-break: break-all;
+            /* identical to box height */
+
+            text-align: right;
+            letter-spacing: 0.3px;
+
+            color: #444444;
+          }
+        }
+      }
+
+      .luck-custom-prize {
+        font-weight: 500;
+        font-size: 14px;
+        letter-spacing: 0.3px;
+        color: #F5B945;
+      }
+
+      .luck-item:last-child {
+        border: 0;
+      }
+    }
+  }
+
+  .success {
+
+    .success-title {
+      color: #FFFFFF;
+      font-weight: 800;
+      font-size: 21px;
+      line-height: 27px;
+      margin-top: 28px;
+      text-align: center;
+      width: 100%;
+    }
+
+    .luck-list-title {
+      margin-top: 17px;
+      border-bottom: 1px solid #ECECEC;
+    }
+  }
+
+  .opened {
+    filter: drop-shadow(0px 4px 94px rgba(0, 0, 0, 0.3));
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    border-radius: 11px;
+    overflow: hidden;
+
+    .header {
+      text-align: center;
+      min-height: 110px;
+      width: 100%;
+      background: #fff;
+      // padding-top: 30px;
+      background-size: 100% 100%;
+      display: flex;
+      flex-wrap: wrap;
+      align-content: center;
+      justify-content: center;
+
+      img {
+        width: 52px;
+        height: 52px;
+        margin-right: 14px;
+      }
+
+      .txt {
+        color: #FFFFFF;
+        font-weight: 700;
+        font-size: 18px;
+        letter-spacing: 0.3px;
+
+        p {
+          margin: 0;
+          padding: 0;
+          text-align: left;
+        }
+      }
+    }
+
+    .list {
+      overflow-y: auto;
+      padding: 0 16px 0 16px;
+      background: #ffffff;
+      flex: 1;
+
+      .item {
+        display: flex;
+        align-items: center;
+        // min-height: 50px;
+        border-bottom: 1px solid #f0f0f0;
+        padding: 12px 0;
+        box-sizing: border-box;
+
+        img {
+          width: 24px;
+          height: 24px;
+        }
+
+        .red-right {
+          width: 35px;
+          height: 24px;
+        }
+
+        .item-content {
+          width: 100%;
+          flex: 1;
+
+
+          .item-follow-title {
+            display: flex;
+            align-items: center;
+            margin-top: 20px;
+            margin-bottom: 11px;
+            position: relative;
+
+            .btn {
+              // position: absolute;
+              // right: 0;
+            }
+          }
+
+          .item-title {
+            flex: 1;
+            margin-left: 10px;
+            font-weight: 500;
+            font-size: 15px;
+            letter-spacing: 0.3px;
+            color: #000000;
+          }
+
+          .item-follow-area {
+            display: flex;
+            flex-wrap: wrap;
+
+            .item-follow {
+              cursor: pointer;
+              border: 1px solid #ebebeb;
+              border-radius: 1000px;
+              height: 26px;
+              margin-right: 5px;
+              margin-bottom: 5px;
+              display: flex;
+              align-items: center;
+
+              .finished {
+                text-decoration: line-through;
+                color: #949494;
+              }
+
+              span {
+                margin-left: 8px;
+                margin-right: 2px;
+                color: #1D9BF0;
+                opacity: 1;
+              }
+
+              img {
+                width: 16px;
+                height: 16px;
+                margin-right: 7px;
+              }
+            }
+          }
+
+          span {
+            font-weight: 400;
+            font-size: 11px;
+            line-height: 13px;
+            letter-spacing: 0.3px;
+
+            color: #000000;
+
+            opacity: 0.4;
+          }
+        }
+
+        .btn {
+          width: 90px;
+          height: 29px;
+          line-height: 29px;
+          background: rgba(56, 154, 255, 0.1);
+          border-radius: 500px;
+          text-align: center;
+          letter-spacing: 0.3px;
+          color: #1D9BF0;
+          cursor: pointer;
+        }
+
+        .loading-wrapper {
+          width: 90px;
+          text-align: center;
+
+          .icon-loading {
+            animation: loading 1s infinite linear;
+          }
+        }
+      }
+    }
+
+    .people {
+      cursor: pointer;
+      padding-left: 16px;
+      height: 38px;
+      line-height: 38px;
+      background: #fff;
+      box-shadow: 0px 1px 0px #f2f2f2;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+
+      .txt {
+        width: 90%;
+        font-weight: 400;
+        font-size: 12px;
+        line-height: 14px;
+        letter-spacing: 0.3px;
+        color: #000000;
+        opacity: 0.4;
+      }
+
+
+    }
+
+    .footer {
+      background: #ffffff;
+      display: flex;
+      padding: 15px 22px 15px 17px;
+
+      .winner {
+        flex: 1;
+        height: 100%;
+        background: #fff;
+        align-items: center;
+        display: flex;
+        align-content: center;
+        flex-wrap: wrap;
+
+        p {
+          color: #959595;
+          font-size: 12px;
+          margin: 0;
+          padding: 0;
+
+        }
+
+        .right {
+          width: 100%;
+          height: 22px;
+
+          position: relative;
+
+          img {
+            position: absolute;
+            width: 22px;
+            height: 22px;
+            border: 2px solid #fff;
+            border-radius: 50%;
+          }
+
+          .more {
+            border: 0;
+          }
+        }
+      }
+
+      .btn {
+        background: #1D9BF0;
+        border-radius: 100px;
+        color: #fff;
+        width: 258px;
+        height: 52px;
+        font-weight: 600;
+        font-size: 18px;
+        line-height: 52px;
+        text-align: center;
+        cursor: pointer;
+      }
+    }
+  }
+
+  .not-open {
+    width: 100%;
+    height: 100%;
+    filter: drop-shadow(0px 2px 20px rgba(0, 0, 0, 0.1));
+    position: relative;
+    overflow: hidden;
+    border-radius: 11px;
+
+    .customImg {
+      width: 100%;
+      min-height: 373px;
+    }
+
+    .customBottom {
+      width: 100%;
+      height: 125px;
+      background: #111214;
+      padding: 10px 16px;
+      font-weight: 500;
+      font-size: 12px;
+      line-height: 14px;
+      letter-spacing: 0.3px;
+      color: #838383;
+      line-height: 20px;
+
+      .theme {
+        display: flex;
+        height: 20px;
+        align-items: center;
+        justify-content: flex-start;
+
+        .icon {
+          width: 12px;
+        }
+
+        .time {
+          margin: 0 4px;
+          color: #1D9BF0;
+        }
+      }
+
+      .winner-info {
+        display: flex;
+        height: 20px;
+        align-items: center;
+        justify-content: flex-start;
+        margin-bottom: 13px;
+
+        .count {
+          color: #1D9BF0;
+          margin-right: 4px;
+        }
+
+        .prize-name {
+          color: #1D9BF0;
+          margin-left: 4px;
+        }
+      }
+
+      .open-red {
+        height: 45px;
+        background: linear-gradient(180deg, #4AB6FF 0%, #1D9BF0 100%, #1D9BF0 100%);
+        border: 1.5px solid rgba(255, 255, 255, 0.15);
+        border-radius: 52px;
+        line-height: 45px;
+        text-align: center;
+        cursor: pointer;
+        font-weight: 800;
+        font-size: 16px;
+        color: #FFFFFF;
+      }
+    }
+
+    .money-area {
+      width: 100%;
+      position: absolute;
+      top: 65px;
+      display: flex;
+      flex-wrap: wrap;
+      align-items: center;
+      justify-content: center;
+
+      .txt {
+        font-weight: 800;
+        font-size: 16px;
+        text-align: center;
+        letter-spacing: 0.3px;
+        color: #FFFFFF;
+      }
+
+      .coin {
+        text-align: center;
+        margin-top: 6px;
+        margin-bottom: 7px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: 90%;
+
+        img {
+          width: 46px;
+          height: 46px;
+          border-radius: 50%;
+          border: 3px solid #FFFFFF;
+        }
+
+        span {
+          margin-left: 12px;
+          font-weight: 800;
+          font-size: 60px;
+          line-height: 76px;
+          color: #FFFFFF;
+        }
+      }
+
+      .people {
+        font-weight: 800;
+        font-size: 13px;
+        line-height: 16px;
+        letter-spacing: 0.05em;
+        text-align: center;
+        color: #FFFFFF;
+      }
+    }
+
+    .title {
+      position: absolute;
+      top: 15px;
+      left: 15px;
+      z-index: 3;
+      display: flex;
+      align-items: center;
+
+      img {
+        width: 24px;
+        height: 24px;
+        border: 2px solid #FFF;
+        border-radius: 50%;
+      }
+
+      span {
+        margin-left: 10px;
+        font-weight: 600;
+        font-size: 16px;
+        letter-spacing: 0.3px;
+        color: #fff;
+      }
+    }
+
+    // .txt {
+    //   width: 100%;
+    //   position: absolute;
+    //   font-style: normal;
+    //   font-weight: 700;
+    //   font-size: 42px;
+    //   line-height: 50px;
+    //   text-align: center;
+
+    //   color: #FFF2D3;
+    //   top: 90px;
+    //   z-index: 3;
+    // }
+
+    img {
+      width: 100%;
+    }
+
+    .up {
+      position: absolute;
+      top: 0;
+      // box-shadow: 0px 4px 44px rgba(0, 0, 0, 0.1);
+      z-index: 1;
+    }
+
+    .down {
+      position: absolute;
+      top: 253px;
+    }
+
+    .open {
+      width: 335px;
+      height: 50px;
+      cursor: pointer;
+      position: absolute;
+      bottom: 28px;
+      left: 50%;
+      margin-left: -167.5px;
+      z-index: 4;
+    }
+
+    .open-gif {
+      width: 200px;
+      height: 200px;
+      text-align: center;
+      position: absolute;
+      bottom: 70px;
+      left: 50%;
+      margin-left: -100px;
+      z-index: 3;
+    }
+  }
+
+  @keyframes loading {
+    from {
+      transform: rotate(0deg);
+    }
+
+    to {
+      transform: rotate(360deg);
+    }
+  }
+}
+
+.none {
+  display: flex;
+  align-item: center;
+  justify-content: center;
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 10 - 3
src/pages/tab-group.vue

@@ -95,8 +95,11 @@ let listReqParams = {
 const clickItem = (data) => {
     if (data.srcContentId) {
         let url = `https://twitter.com/${data.screenName}/status/${data.srcContentId}`;
+        
         messageCenter.send({
-            actionType: MESSAGE_ENUM.IFRAME_PAGE_JUMP,
+            info: {
+                actionType: MESSAGE_ENUM.IFRAME_PAGE_JUMP
+            },
             data: {
                 url
             }
@@ -131,7 +134,9 @@ const nextPage = (params) => {
 
 const pageScroll = (e) => {
     messageCenter.send({
-        actionType: MESSAGE_ENUM.IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP,
+        info: {
+            actionType: MESSAGE_ENUM.IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP,
+        },
         data: {
             scrollTop: e.target.scrollTop
         }
@@ -250,7 +255,9 @@ onMounted(() => {
     onRuntimeMsg();
     initData();
     messageCenter.send({
-        actionType: MESSAGE_ENUM.IFREME_TAB_GROUP_SET_IFRAME_HEIGHT,
+        info: {
+            actionType: MESSAGE_ENUM.IFREME_TAB_GROUP_SET_IFRAME_HEIGHT,
+        },
         data: {
             height: listWrapperDom.value.offsetHeight + 10
         }

+ 5 - 0
src/router/index.js

@@ -3,6 +3,11 @@ import TabGroup from './../pages/tab-group';
 
 // 2. 定义路由配置
 const routes = [
+    {
+        path: '/red-pack',
+        name: 'redPack',
+        component: () => import('@/pages/red-packet')
+    },
     {
         path: '/tab-group',
         name: '',

+ 50 - 0
src/types/global.js

@@ -0,0 +1,50 @@
+/**
+ * 全局通用字段定义
+ */
+
+/**
+ * 玩法类型
+ * 普通任务:common=1;
+ * 抽奖:lottery=2
+ * 夺宝:treasure=3
+ */
+export const PlayType = {
+  common: 1,
+  lottery: 2,
+  treasure: 3,
+  postEditor: 4,
+};
+
+/**
+ * 奖品类型
+ * 货币:money=1;
+ * 自定义奖品:custom=2
+ */
+export const RewardType = {
+  money: 1,
+  custom: 2,
+};
+
+/**
+ * 任务类型
+ */
+export const TaskType = {
+  twitterFollow: 1,
+  twitterLikeTweet: 2,
+  twitterRetweet: 3,
+  joinDiscord: 7,
+  repostToFacebook: 8,
+  twitterCommentAndTag: 9,
+  twitterRePost: 10
+};
+
+/**
+ * 帖子类型
+ */
+
+export const PostType = {
+  giveaway: 1,
+  lottery: 2,
+  postEditor: 3,
+  treasure: 4
+}

+ 1 - 0
src/types/index.js

@@ -0,0 +1 @@
+export * from "@/types/global";

+ 41 - 12
src/uilts/chromeExtension.js

@@ -1,5 +1,5 @@
 import { pageUrl } from "@/http/configAPI.js"
-import { guid, iframeID } from "@/uilts/help";
+import { guid, iframeId } from "@/uilts/help";
 import messageCenter from '@/uilts/messageCenter';
 import MESSAGE_ENUM from "@/uilts/messageCenter/messageEnum";
 
@@ -39,37 +39,66 @@ export function setSessionStorge(key, value) {
     return sessionStorage.setItem(key, JSON.stringify(value));
 }
 
+export function setChromeStoragetoExtension(data) {
+    messageCenter.send({
+        info: {
+            actionType: MESSAGE_ENUM.IFRAME_SET_EXTENSION_STORGE_DATA,
+        },
+        data
+    })
+}
+
 export async function getChromeStorageFromExtension(key = '') {
     let params = {}
     params[key] = ''
-    const value = getSessionStorge(key);
-    if (value) {
-        return Promise.resolve(value);
-    } else { 
+    // const value = getSessionStorge(key);
+    // if (value) {
+    //     return Promise.resolve(value);
+    // } else { 
         return new Promise((res, rej) => {
             messageCenter.send({
-                actionType: MESSAGE_ENUM.IFRAME_GET_EXTENSION_STORGE_DATA,
+                info: {
+                    iframeId,//用于告诉父窗口会传消息给哪个iframe
+                    actionType: MESSAGE_ENUM.IFRAME_GET_EXTENSION_STORGE_DATA,
+                },
                 data: {
-                    iframeID,//用于告诉父窗口会传消息给哪个iframe
                     key,// storage key
-                    messageID: guid(), // 唯一的ID,用于标记回调函数
-                    overTime: 50
                 },
                 callback: (data) => {
                     setSessionStorge(key, data);
                     res(data);
                 },
                 failback: (e) => {
-                    setSessionStorge(key, {});
-                    rej(e)
+                    console.log('getChromeStorageFromExtension fail', e)
+                    rej(null)
                 }
             })
         })
-    }
+    // }
     // console.log(window.parent.window.atest)
     // window.postMessage({actionType: 'iframe_test', data: key})
 }
 
+export const openUrlInNewWindow = async (data, successCallback) => { 
+    return new Promise((res, rej) => {
+        messageCenter.send({
+            info: {
+                iframeId,//用于告诉父窗口会传消息给哪个iframe
+                actionType: 'OPEN_URL_IN_NEW_WINDOW',
+            },
+            data,
+            callback: (window) => {
+                successCallback && successCallback(data)
+                res(window);
+            },
+            failback: (e) => {
+                console.log('openUrlInNewWindow fail', e)
+                rej(null)
+            }
+        })
+    })
+}
+
 export function getChromeStorage(key = '', callback) {
     let params = {}
     params[key] = ''

+ 3 - 1
src/uilts/help.js

@@ -18,6 +18,8 @@ export function getQueryStringByUrl(url = "", name = "") {
 
 export const isInApp = !!navigator.userAgent.includes('denet');
 
+export const appVersionCode = +getQueryString('appVersionCode');
+
 export function debounce(fn, delay) {
   let timer; // 定时器
   return function (...args) {
@@ -261,4 +263,4 @@ export function $(key, cache = true) {
   return _dom
 }
 
-export const iframeID = getQueryString('iframeID');
+export const iframeId = getQueryString('iframeId');

+ 78 - 65
src/uilts/messageCenter/index.js

@@ -1,93 +1,106 @@
+import { guid } from '@/uilts/help'
 //  iframe 通信中心
-import { isInApp } from '@/uilts/help'
-class MessageCenter { 
-    constructor() { 
+class IframeMessageCenter {
+    constructor() {
         //  缓存事件队列
         this.messageCallbackMap = new Map();
         this.messageFailbackMap = new Map();
+        this.timer = null
         this.init()
     }
 
-    send({ actionType, data, callback, overTime, failback }) {
-        if (isInApp) {
-            window.ReactNativeWebView.postMessage({
-                actionType,
-                data
-            });
-        } else { 
-            window.parent.postMessage({
-                actionType,
-                data
-            }, '*');
+    send({ info = {}, data = {}, callback, overTime, failback }) {
+        if (callback) {
+            info.messageId = `${info.actionType}-${guid()}` // 唯一的ID,用于标记回调函数
         }
-        
-        if (data.messageID && callback) {
-            // 带回调callback 的message, 要求携带messageID,callback,failback等
-            this.listen(`${actionType}-${data.messageID}`, callback)
-            if (failback) { 
-                this.addFailback(`${actionType}-${data.messageID}`, overTime, failback)
+        window.parent.postMessage({
+            info,
+            data: JSON.parse(JSON.stringify(data))
+        }, '*');
+        if (callback) {
+            // 带回调callback 的message, 要求携带messageId,callback,failback等
+            this.listen(info.messageId, callback)
+            if (failback) {
+                this.addFailback(info.messageId, overTime, failback)
             }
         }
     }
 
-    listen(actionType, callback) {
-        let activeQuene = this.messageCallbackMap.get(actionType);
-        if (activeQuene?.length > 0) {
-            activeQuene.push(callback)
-        } else { 
-            this.messageCallbackMap.set(actionType, [callback])
-        }
+    listen(key, callback) {
+        // 序列添加失败回调
+        this.messageCallbackMap.set(key, { callback })
     }
 
-    addFailback(actionType, overTime=2000, failback) { 
-        let failbackQuene = this.messageFailbackMap.get(actionType);
-        if (failbackQuene && failbackQuene.failCallbackList) {
-            failbackQuene.failCallbackList.push(
-                failback
-                )
-            } else { 
-                this.messageFailbackMap.set(actionType, {
-                    time: new Date().getTime(),
-                    overTime,
-                    failCallbackList: [failback]
-                })
-            }
+    addFailback(key, overTime = 2000, failback) {
+        // 序列添加失败回调
+        this.messageFailbackMap.set(key, {
+            time: new Date().getTime(),
+            overTime,
+            failback
+        })
+        this.checkTimer()
     }
 
     init() {
-        window.addEventListener('message', (e) => { 
-            const { actionType, data } = e.data;
-            this.messageFailbackMap.delete(actionType);
-            const quene = this.messageCallbackMap.get(actionType) ||  [];
-            let index = 0;
-            while (index < quene.length) { 
-                const callback = quene[index];
+        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)
-                index++
+                // 序列删除 成功回调
+                this.messageCallbackMap.delete(key)
             }
         })
-        setInterval(() => { 
+
+        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信息
-            const now = new Date().getTime();
-            for (let item of this.messageFailbackMap.values()) { 
-                if (now - item.time > item.overTime) { 
-                    let index = 0;
-                    while (index < item.failCallbackList.length) { 
-                        const callback = item.failCallbackList[index];
-                        callback({
-                            error: 0,
-                            msg: "message 超时错误"
-                        })
-                        index++
-                    }
+            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)
                 }
             }
-
-        }, 500)
+        }, 1000)
     }
 }
 
 // messageCenter在每个iframe内实例化一次
-const messageCenter = new MessageCenter();
+const iframeMessageCenter = new IframeMessageCenter();
 
-export default messageCenter;
+export default iframeMessageCenter;

+ 2 - 1
src/uilts/messageCenter/messageEnum.js

@@ -5,7 +5,8 @@ const SEND_MESSAGE_ENUM =  {
     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_GET_EXTENSION_STORGE_DATA: 'IFRAME_GET_EXTENSION_STORGE_DATA',
+    IFRAME_SET_EXTENSION_STORGE_DATA: 'IFRAME_SET_EXTENSION_STORGE_DATA'
 }
 
 /** 接收父窗口的事件定义 */

+ 210 - 4
yarn.lock

@@ -19,6 +19,26 @@
     "@jridgewell/gen-mapping" "^0.1.0"
     "@jridgewell/trace-mapping" "^0.3.9"
 
+"@ant-design/colors@^6.0.0":
+  version "6.0.0"
+  resolved "https://registry.npmmirror.com/@ant-design/colors/-/colors-6.0.0.tgz#9b9366257cffcc47db42b9d0203bb592c13c0298"
+  integrity sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==
+  dependencies:
+    "@ctrl/tinycolor" "^3.4.0"
+
+"@ant-design/icons-svg@^4.2.1":
+  version "4.2.1"
+  resolved "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz#8630da8eb4471a4aabdaed7d1ff6a97dcb2cf05a"
+  integrity sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==
+
+"@ant-design/icons-vue@^6.0.0":
+  version "6.1.0"
+  resolved "https://registry.npmmirror.com/@ant-design/icons-vue/-/icons-vue-6.1.0.tgz#f9324fdc0eb4cea943cf626d2bf3db9a4ff4c074"
+  integrity sha512-EX6bYm56V+ZrKN7+3MT/ubDkvJ5rK/O2t380WFRflDcVFgsvl3NLH7Wxeau6R8DbrO5jWR6DSTC3B6gYFp77AA==
+  dependencies:
+    "@ant-design/colors" "^6.0.0"
+    "@ant-design/icons-svg" "^4.2.1"
+
 "@babel/code-frame@7.12.11":
   version "7.12.11"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
@@ -918,7 +938,7 @@
     "@babel/types" "^7.4.4"
     esutils "^2.0.2"
 
-"@babel/runtime@^7.12.13", "@babel/runtime@^7.8.4":
+"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.13", "@babel/runtime@^7.8.4":
   version "7.18.9"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
   integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
@@ -958,7 +978,7 @@
     "@babel/helper-validator-identifier" "^7.18.6"
     to-fast-properties "^2.0.0"
 
-"@ctrl/tinycolor@^3.4.1":
+"@ctrl/tinycolor@^3.4.0", "@ctrl/tinycolor@^3.4.1":
   version "3.4.1"
   resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz#75b4c27948c81e88ccd3a8902047bcd797f38d32"
   integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==
@@ -1112,6 +1132,69 @@
   resolved "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64"
   integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==
 
+"@sentry/browser@7.12.0":
+  version "7.12.0"
+  resolved "https://registry.npmmirror.com/@sentry/browser/-/browser-7.12.0.tgz#340151eb83b41a6c54fc91a75285f99e62a843a5"
+  integrity sha512-VoqZj3wJm5aUIDG+7LjeSHIw9/pujrUlA1QMu2YOY3LaP6UQsAAsOSo52brnaQQcwBrRySksaaaTxg6obJwInw==
+  dependencies:
+    "@sentry/core" "7.12.0"
+    "@sentry/types" "7.12.0"
+    "@sentry/utils" "7.12.0"
+    tslib "^1.9.3"
+
+"@sentry/core@7.12.0":
+  version "7.12.0"
+  resolved "https://registry.npmmirror.com/@sentry/core/-/core-7.12.0.tgz#14e75263b9c645ba5f314bb036d5cd1ac5aa621e"
+  integrity sha512-ERkeB/XdThvdSVZH4XysMPyWRG653HDq0AkJh8SgapExCZbwgj1lutCIpT1LIbZ8lUhRx5P+ua9OR2qj+vo5RA==
+  dependencies:
+    "@sentry/hub" "7.12.0"
+    "@sentry/types" "7.12.0"
+    "@sentry/utils" "7.12.0"
+    tslib "^1.9.3"
+
+"@sentry/hub@7.12.0":
+  version "7.12.0"
+  resolved "https://registry.npmmirror.com/@sentry/hub/-/hub-7.12.0.tgz#b30d04222fd4e1a920ace8482de3aa413e04ca43"
+  integrity sha512-UgpC9WiHQAfcoEIIgeIopp3jeabllK6beLl5vA4ei6ay2TDMjA4NqUpzGq/GWVG0ewnblvHkqmjwAls2AEMtWg==
+  dependencies:
+    "@sentry/types" "7.12.0"
+    "@sentry/utils" "7.12.0"
+    tslib "^1.9.3"
+
+"@sentry/tracing@^7.12.0":
+  version "7.12.0"
+  resolved "https://registry.npmmirror.com/@sentry/tracing/-/tracing-7.12.0.tgz#50fdb5aa64a211c6609ea44b7452149e26b5433d"
+  integrity sha512-TK30G/g15KplKOPncu61XvNLjaI+Kbe64UBTSTANMkidlEjiZ8N0P8L9AqUG+rUIk7YbIu11DS6edGY/LK0WEQ==
+  dependencies:
+    "@sentry/hub" "7.12.0"
+    "@sentry/types" "7.12.0"
+    "@sentry/utils" "7.12.0"
+    tslib "^1.9.3"
+
+"@sentry/types@7.12.0":
+  version "7.12.0"
+  resolved "https://registry.npmmirror.com/@sentry/types/-/types-7.12.0.tgz#108a995c77d133f22366e6976fefa0ca7f8dcf5d"
+  integrity sha512-ldcuRzEx2ccZvaJjTSemWj+7TiWCV5A/vV7fEtZeoETFI+SiVbmqI5whdH7ZVVfhRNFf25Ib+TfTeaM9PM7A1A==
+
+"@sentry/utils@7.12.0":
+  version "7.12.0"
+  resolved "https://registry.npmmirror.com/@sentry/utils/-/utils-7.12.0.tgz#dd00bed3908f31453f2362988e501f98d534c7dd"
+  integrity sha512-GVB8E0V3RJHQClvi0gsRRJvDXP5c7M5ByYAvspJDczOOxNF8LTjTYVkBXAUdR9kcs+nya1q1YVsKvde2WGORTA==
+  dependencies:
+    "@sentry/types" "7.12.0"
+    tslib "^1.9.3"
+
+"@sentry/vue@^7.12.0":
+  version "7.12.0"
+  resolved "https://registry.npmmirror.com/@sentry/vue/-/vue-7.12.0.tgz#a09a7a94efbf6e12f6081d75aafb621bde4f148d"
+  integrity sha512-dpma/hXAnB83kb+6H3xOUUoUDbfEG4iZvT/HfCC6nDTz++DywNYynLpZ3L3pUYSrKi1FoBQmAXgp3wzwo/dC5A==
+  dependencies:
+    "@sentry/browser" "7.12.0"
+    "@sentry/core" "7.12.0"
+    "@sentry/types" "7.12.0"
+    "@sentry/utils" "7.12.0"
+    tslib "^1.9.3"
+
 "@sideway/address@^4.1.3":
   version "4.1.4"
   resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0"
@@ -1129,6 +1212,14 @@
   resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
   integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
 
+"@simonwep/pickr@~1.8.0":
+  version "1.8.2"
+  resolved "https://registry.npmmirror.com/@simonwep/pickr/-/pickr-1.8.2.tgz#96dc86675940d7cad63d69c22083dd1cbb9797cb"
+  integrity sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==
+  dependencies:
+    core-js "^3.15.1"
+    nanopop "^2.1.0"
+
 "@soda/friendly-errors-webpack-plugin@^1.8.0":
   version "1.8.1"
   resolved "https://registry.yarnpkg.com/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz#4d4fbb1108993aaa362116247c3d18188a2c6c85"
@@ -1969,6 +2060,28 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
   dependencies:
     color-convert "^2.0.1"
 
+ant-design-vue@^2.2.8:
+  version "2.2.8"
+  resolved "https://registry.npmmirror.com/ant-design-vue/-/ant-design-vue-2.2.8.tgz#fa87cf6842d8ee9a0d8af393ff4099ecc4072f2b"
+  integrity sha512-3graq9/gCfJQs6hznrHV6sa9oDmk/D1H3Oo0vLdVpPS/I61fZPk8NEyNKCHpNA6fT2cx6xx9U3QS63uuyikg/Q==
+  dependencies:
+    "@ant-design/icons-vue" "^6.0.0"
+    "@babel/runtime" "^7.10.5"
+    "@simonwep/pickr" "~1.8.0"
+    array-tree-filter "^2.1.0"
+    async-validator "^3.3.0"
+    dom-align "^1.12.1"
+    dom-scroll-into-view "^2.0.0"
+    lodash "^4.17.21"
+    lodash-es "^4.17.15"
+    moment "^2.27.0"
+    omit.js "^2.0.0"
+    resize-observer-polyfill "^1.5.1"
+    scroll-into-view-if-needed "^2.2.25"
+    shallow-equal "^1.0.0"
+    vue-types "^3.0.0"
+    warning "^4.0.0"
+
 any-promise@^1.0.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@@ -2004,6 +2117,11 @@ array-flatten@^2.1.2:
   resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
   integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
 
+array-tree-filter@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/array-tree-filter/-/array-tree-filter-2.1.0.tgz#873ac00fec83749f255ac8dd083814b4f6329190"
+  integrity sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==
+
 array-union@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
@@ -2014,6 +2132,11 @@ astral-regex@^2.0.0:
   resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
   integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
 
+async-validator@^3.3.0:
+  version "3.5.2"
+  resolved "https://registry.npmmirror.com/async-validator/-/async-validator-3.5.2.tgz#68e866a96824e8b2694ff7a831c1a25c44d5e500"
+  integrity sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ==
+
 async-validator@^4.0.7:
   version "4.2.5"
   resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339"
@@ -2469,6 +2592,11 @@ compression@^1.7.4:
     safe-buffer "5.1.2"
     vary "~1.1.2"
 
+compute-scroll-into-view@^1.0.17:
+  version "1.0.17"
+  resolved "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab"
+  integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==
+
 concat-map@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -2535,6 +2663,11 @@ core-js-compat@^3.21.0, core-js-compat@^3.22.1, core-js-compat@^3.8.3:
     browserslist "^4.21.2"
     semver "7.0.0"
 
+core-js@^3.15.1:
+  version "3.25.0"
+  resolved "https://registry.npmmirror.com/core-js/-/core-js-3.25.0.tgz#be71d9e0dd648ffd70c44a7ec2319d039357eceb"
+  integrity sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==
+
 core-js@^3.8.3:
   version "3.24.0"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.24.0.tgz#4928d4e99c593a234eb1a1f9abd3122b04d3ac57"
@@ -2820,6 +2953,11 @@ doctrine@^3.0.0:
   dependencies:
     esutils "^2.0.2"
 
+dom-align@^1.12.1:
+  version "1.12.3"
+  resolved "https://registry.npmmirror.com/dom-align/-/dom-align-1.12.3.tgz#a36d02531dae0eefa2abb0c4db6595250526f103"
+  integrity sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA==
+
 dom-converter@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
@@ -2827,6 +2965,11 @@ dom-converter@^0.2.0:
   dependencies:
     utila "~0.4"
 
+dom-scroll-into-view@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.npmmirror.com/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz#0decc8522801fd8d3f1c6ba355a74d382c5f989b"
+  integrity sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==
+
 dom-serializer@^1.0.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
@@ -3859,6 +4002,11 @@ is-plain-obj@^3.0.0:
   resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7"
   integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==
 
+is-plain-object@3.0.1:
+  version "3.0.1"
+  resolved "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b"
+  integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==
+
 is-plain-object@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@@ -3942,7 +4090,7 @@ js-message@1.0.7:
   resolved "https://registry.yarnpkg.com/js-message/-/js-message-1.0.7.tgz#fbddd053c7a47021871bb8b2c95397cc17c20e47"
   integrity sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==
 
-js-tokens@^4.0.0:
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
   integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
@@ -4084,7 +4232,7 @@ locate-path@^5.0.0:
   dependencies:
     p-locate "^4.1.0"
 
-lodash-es@^4.17.21:
+lodash-es@^4.17.15, lodash-es@^4.17.21:
   version "4.17.21"
   resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
   integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
@@ -4156,6 +4304,13 @@ log-update@^2.3.0:
     cli-cursor "^2.0.0"
     wrap-ansi "^3.0.1"
 
+loose-envify@^1.0.0:
+  version "1.4.0"
+  resolved "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+  integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+  dependencies:
+    js-tokens "^3.0.0 || ^4.0.0"
+
 lower-case@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
@@ -4319,6 +4474,11 @@ module-alias@^2.2.2:
   resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0"
   integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==
 
+moment@^2.27.0, moment@^2.29.4:
+  version "2.29.4"
+  resolved "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
+  integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
+
 mrmime@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27"
@@ -4361,6 +4521,11 @@ nanoid@^3.3.4:
   resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
   integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
 
+nanopop@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/nanopop/-/nanopop-2.1.0.tgz#23476513cee2405888afd2e8a4b54066b70b9e60"
+  integrity sha512-jGTwpFRexSH+fxappnGQtN9dspgE2ipa1aOjtR24igG0pv6JCxImIAmrLRHX+zUF5+1wtsFVbKyfP51kIGAVNw==
+
 natural-compare@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -4492,6 +4657,11 @@ obuf@^1.0.0, obuf@^1.1.2:
   resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
   integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
 
+omit.js@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.npmmirror.com/omit.js/-/omit.js-2.0.2.tgz#dd9b8436fab947a5f3ff214cb2538631e313ec2f"
+  integrity sha512-hJmu9D+bNB40YpL9jYebQl4lsTW6yEHRTroJzNLqQJYHm7c+NQnJGfZmIWh8S3q3KoaxV1aLhV6B3+0N0/kyJg==
+
 on-finished@2.4.1:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
@@ -5212,6 +5382,11 @@ requires-port@^1.0.0:
   resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
   integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
 
+resize-observer-polyfill@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
+  integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
+
 resolve-from@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@@ -5326,6 +5501,13 @@ schema-utils@^4.0.0:
     ajv-formats "^2.1.1"
     ajv-keywords "^5.0.0"
 
+scroll-into-view-if-needed@^2.2.25:
+  version "2.2.29"
+  resolved "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885"
+  integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==
+  dependencies:
+    compute-scroll-into-view "^1.0.17"
+
 select-hose@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@@ -5426,6 +5608,11 @@ shallow-clone@^3.0.0:
   dependencies:
     kind-of "^6.0.2"
 
+shallow-equal@^1.0.0:
+  version "1.2.1"
+  resolved "https://registry.npmmirror.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
+  integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
+
 shebang-command@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -5821,6 +6008,11 @@ tr46@~0.0.3:
   resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
   integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
 
+tslib@^1.9.3:
+  version "1.14.1"
+  resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
 tslib@^2.0.3:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
@@ -5994,6 +6186,13 @@ vue-template-es2015-compiler@^1.9.0:
   resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
   integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
 
+vue-types@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.npmmirror.com/vue-types/-/vue-types-3.0.2.tgz#ec16e05d412c038262fc1efa4ceb9647e7fb601d"
+  integrity sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==
+  dependencies:
+    is-plain-object "3.0.1"
+
 vue@^3.2.13:
   version "3.2.37"
   resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.37.tgz#da220ccb618d78579d25b06c7c21498ca4e5452e"
@@ -6005,6 +6204,13 @@ vue@^3.2.13:
     "@vue/server-renderer" "3.2.37"
     "@vue/shared" "3.2.37"
 
+warning@^4.0.0:
+  version "4.0.3"
+  resolved "https://registry.npmmirror.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
+  integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
+  dependencies:
+    loose-envify "^1.0.0"
+
 watchpack@^2.4.0:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"

部分文件因为文件数量过多而无法显示