浏览代码

merge dev_1.1.7

nieyuge 2 年之前
父节点
当前提交
f9976a6b49
共有 90 个文件被更改,包括 3456 次插入751 次删除
  1. 2 1
      .env.development
  2. 2 1
      .env.pre
  3. 2 1
      .env.production
  4. 2 0
      .env.test
  5. 2 1
      package.json
  6. 二进制
      src/assets/img/icon-card-cover-treasure-big.png
  7. 二进制
      src/assets/img/icon-flash-active.png
  8. 二进制
      src/assets/img/icon-gold-close-box.png
  9. 二进制
      src/assets/img/icon-gold-open-box.png
  10. 二进制
      src/assets/img/icon-silver-close-box.png
  11. 二进制
      src/assets/img/icon-silver-open-box.png
  12. 二进制
      src/assets/img/icon-treasure-box.png
  13. 二进制
      src/assets/img/img-preview-treasure-link-bg.png
  14. 2 0
      src/assets/svg/icon-big-treasure.svg
  15. 2 0
      src/assets/svg/icon-btn-box.svg
  16. 2 0
      src/assets/svg/icon-card-cover-treasure-small.svg
  17. 1 0
      src/assets/svg/icon-card-cover-treasure-tasks.svg
  18. 3 0
      src/assets/svg/icon-custom-cover-btn.svg
  19. 3 0
      src/assets/svg/icon-form-amount.svg
  20. 4 0
      src/assets/svg/icon-form-cost.svg
  21. 3 0
      src/assets/svg/icon-form-custom-cover.svg
  22. 1 0
      src/assets/svg/icon-form-follow.svg
  23. 3 0
      src/assets/svg/icon-form-task.svg
  24. 8 0
      src/assets/svg/icon-form-time.svg
  25. 1 0
      src/assets/svg/icon-form-winners.svg
  26. 4 0
      src/assets/svg/icon-green-yes.svg
  27. 5 0
      src/assets/svg/icon-silver-open-box.svg
  28. 1 0
      src/assets/svg/icon-small-treasure.svg
  29. 1 0
      src/assets/svg/icon-three-line.svg
  30. 3 0
      src/assets/svg/icon-tip-arrow.svg
  31. 4 0
      src/assets/svg/icon-treasure-return.svg
  32. 3 0
      src/assets/svg/icon-while-user.svg
  33. 3 0
      src/assets/svg/icon-while-yes.svg
  34. 0 19
      src/assets/svg/img-A0.svg
  35. 0 19
      src/assets/svg/img-A1.svg
  36. 0 44
      src/assets/svg/img-B0.svg
  37. 0 44
      src/assets/svg/img-B1.svg
  38. 3 0
      src/assets/svg/img-LT0.svg
  39. 3 0
      src/assets/svg/img-LT1.svg
  40. 3 0
      src/assets/svg/img-P1.svg
  41. 3 0
      src/assets/svg/img-P2.svg
  42. 3 0
      src/assets/svg/img-P3.svg
  43. 2 0
      src/assets/svg/img-T0.svg
  44. 2 0
      src/assets/svg/img-T1.svg
  45. 11 0
      src/assets/svg/img-preview-treasure-01-bg.svg
  46. 195 192
      src/entry/background.js
  47. 14 5
      src/entry/content.js
  48. 3 1
      src/http/configAPI.js
  49. 68 0
      src/http/treasure.js
  50. 9 0
      src/http/treasureApi.js
  51. 1 2
      src/iframe/tool-box.js
  52. 5 0
      src/iframe/treasure-hunt.js
  53. 21 1
      src/log-center/logger.js
  54. 9 0
      src/logic/background/twitter.js
  55. 30 0
      src/logic/content/ParseCard.js
  56. 198 82
      src/logic/content/twitter.js
  57. 2 1
      src/manifest.json
  58. 6 2
      src/types/global.js
  59. 50 0
      src/uilts/messageCenter/index.js
  60. 19 7
      src/view/components/component-zoom.vue
  61. 0 1
      src/view/components/currency-list.vue
  62. 152 14
      src/view/components/custom-card-cover.vue
  63. 112 28
      src/view/components/custom-card-horizontal-cover.vue
  64. 32 9
      src/view/components/popup-transactions.vue
  65. 11 3
      src/view/iframe/publish/components/follow-input.vue
  66. 61 0
      src/view/iframe/publish/components/form-input.vue
  67. 6 0
      src/view/iframe/publish/components/preview-card.vue
  68. 8 2
      src/view/iframe/publish/components/preview-sheet.vue
  69. 523 205
      src/view/iframe/publish/give-dialog.vue
  70. 3 1
      src/view/iframe/publish/publish.vue
  71. 1 2
      src/view/iframe/publish/tool-box/child/preview.vue
  72. 6 3
      src/view/iframe/red-packet/luck-draw.vue
  73. 6 3
      src/view/iframe/red-packet/red-packet.vue
  74. 3 26
      src/view/iframe/test/index.vue
  75. 3 3
      src/view/iframe/tool-box/card.vue
  76. 96 0
      src/view/iframe/treasure-hunt/components/btn.vue
  77. 74 0
      src/view/iframe/treasure-hunt/components/dialog.vue
  78. 72 0
      src/view/iframe/treasure-hunt/components/head.vue
  79. 57 0
      src/view/iframe/treasure-hunt/components/hover-tip.vue
  80. 160 0
      src/view/iframe/treasure-hunt/components/invite-friends.vue
  81. 159 0
      src/view/iframe/treasure-hunt/components/invite-list.vue
  82. 114 0
      src/view/iframe/treasure-hunt/components/open-box.vue
  83. 80 0
      src/view/iframe/treasure-hunt/components/toast.vue
  84. 285 0
      src/view/iframe/treasure-hunt/cover.vue
  85. 126 0
      src/view/iframe/treasure-hunt/index.vue
  86. 369 0
      src/view/iframe/treasure-hunt/invite.vue
  87. 118 0
      src/view/iframe/treasure-hunt/result.vue
  88. 72 18
      src/view/popup/tabbar-page/message/index.vue
  89. 7 4
      src/view/popup/withdraw/info.vue
  90. 13 6
      vue.config.js

+ 2 - 1
.env.development

@@ -1 +1,2 @@
-NODE_ENV='development'
+NODE_ENV='development'
+VUE_APP_IFRAME_HOST='https://localhost:3000'

+ 2 - 1
.env.pre

@@ -1 +1,2 @@
-NODE_ENV='pre'
+NODE_ENV='pre'
+VUE_APP_IFRAME_HOST='https://iframe-pre.denet.me'

+ 2 - 1
.env.production

@@ -1 +1,2 @@
-NODE_ENV='production'
+NODE_ENV='production'
+VUE_APP_IFRAME_HOST='https://iframe.denet.me'

+ 2 - 0
.env.test

@@ -0,0 +1,2 @@
+NODE_ENV='development'
+VUE_APP_IFRAME_HOST='https://iframe-test.denet.me'

+ 2 - 1
package.json

@@ -4,7 +4,7 @@
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",
-    "build-test": "vue-cli-service build --mode development",
+    "build-test": "vue-cli-service build --mode test",
     "build-local": "sh buildTestApp.sh",
     "build-pre": "vue-cli-service build --mode pre",
     "build-prod": "vue-cli-service build --mode production",
@@ -23,6 +23,7 @@
     "eslint-plugin-vue": "^8.7.0",
     "mathjs": "^10.5.0",
     "moment": "^2.29.1",
+    "node-polyfill-webpack-plugin": "^2.0.1",
     "node-sass": "^7.0.1",
     "postcss-import": "^14.0.2",
     "postcss-url": "^10.1.3",

二进制
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.png


二进制
src/assets/img/icon-silver-close-box.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


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


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

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


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

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

+ 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 fill-rule="evenodd" clip-rule="evenodd" d="M7.5 15C11.6421 15 15 11.6421 15 7.5C15 3.35786 11.6421 0 7.5 0C3.35786 0 0 3.35786 0 7.5C0 11.6421 3.35786 15 7.5 15ZM3.96965 8.83499L6.50193 11.3675L7.1218 11.9874L7.6383 11.2791L12.219 4.99666L11.007 4.11293L6.94276 9.68696L5.03035 7.77438L3.96965 8.83499Z" fill="white"/>
+</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>

+ 195 - 192
src/entry/background.js

@@ -35,207 +35,210 @@ import {
 import {
     closeAchPayNoticeHandler
 } from "@/logic/background/denet";
-try {
-    //加载bg.js 执行
-    setMessageCount();
-
-    // 消息通讯
-    chrome.runtime.onConnect.addListener(function (port) {
-        port.onDisconnect.addListener(function () {
-            onDisconnectHandler(port);
-        });
-    });
 
-    // 当有可用更新时触发
-    chrome.runtime.onUpdateAvailable.addListener(() => {
-        try {
-            setChromeStorage({ onUpdateAvailable: JSON.stringify({ onUpdateAvailable: '1' }) }, () => {
-                chrome.runtime.reload()
-            })
-        } catch (error) {
-            Report.reportLog({
-                objectType: Report.objectType.background_function_catch,
-                funcName: 'onUpdateAvailable',
-                errMsg: error.message
-            });
-        }
-    })
-
-    chrome.runtime.onInstalled.addListener(onInstalledMethod);
-
-    chrome.runtime.onMessage.addListener(onMessageMethod);
-
-    // 定时器
-    chrome.alarms.onAlarm.addListener(function (alarm) {
-        // console.log("onAlarm-", alarm);
-        switch (alarm.name) {
-            case 'denetChromeAlarm':
-                getMessageInfo();
-                break
-            case 'PingPong':
-                PingPong()
-                break;
-            case 'LuckMessage':
-                getSysMessage()
-                break
-        }
-    });
+//加载bg.js 执行
+setMessageCount();
 
-    chrome.action.onClicked.addListener(function (tab) {
-        injectExtensionPopup(tab);
+// 消息通讯
+chrome.runtime.onConnect.addListener(function (port) {
+    port.onDisconnect.addListener(function () {
+        onDisconnectHandler(port);
     });
+});
 
-    chrome.tabs.onActivated.addListener(function (activeInfo) {
-        setPopupConfig(activeInfo);
-    })
-
-    function thenInstalledMethod() {
-        try {
-
-            onInstalledCreateTab()
-            onInstalledMid()
-            onInstalledUserSet()
-            // pingpang
-            chrome.alarms.create('PingPong', {
-                //1分鐘之後開始(該值不能小於1) 
-                delayInMinutes: 2,
-                //開始後每一分鐘執行一次(該值不能小于1) 
-                periodInMinutes: 4
-            });
-            chrome.alarms.create('LuckMessage', {
-                //1分鐘之後開始(該值不能小於1) 
-                delayInMinutes: 1,
-                //開始後每一分鐘執行一次(該值不能小于1) 
-                periodInMinutes: 1
-            });
-        } catch (error) {
-            Report.reportLog({
-                objectType: Report.objectType.background_function_catch,
-                funcName: 'thenInstalledMethod',
-                errMsg: error.message
-            });
-        }
+// 当有可用更新时触发
+chrome.runtime.onUpdateAvailable.addListener(() => {
+    try {
+        Report.reportLog({
+            objectType: Report.objectType.background_function_try,
+            funcName: 'onUpdateAvailable'
+        });
+        chrome.runtime.reload()
+    } catch (error) {
+        Report.reportLog({
+            objectType: Report.objectType.background_function_catch,
+            funcName: 'onUpdateAvailable',
+            errMsg: error.message
+        });
     }
-    function onInstalledMethod() {
-        try {
-            // 3.onInstalledMethod 执行了那个
-            // 版本更新判断
-            getChromeStorage('baseInfo', (info) => {
-                if (!info || !info.appVersionCode) {
-                    setChromeStorage({ onInstalledMethod: JSON.stringify({ onInstalledMethod: '1' }) })
-                    setChromeStorage({ baseInfo: JSON.stringify({ appVersionCode }) })
-                    thenInstalledMethod()
-                } else if (appVersionCode != info.appVersionCode) {
-                    setChromeStorage({ onInstalledMethod: JSON.stringify({ onInstalledMethod: '2' }) }, () => {
-                        setChromeStorage({ baseInfo: JSON.stringify({ appVersionCode }) }, () => {
-                            chrome.runtime.reload()
-                        })
-                    })
-                } else {
-                    setChromeStorage({ onInstalledMethod: JSON.stringify({ onInstalledMethod: '3' }) })
-                    thenInstalledMethod()
-                }
-            })
-
-            // 1.onUpdateAvailable 存储到本地,再上报
-            getChromeStorage('onUpdateAvailable', (res) => {
-                if (res && res.onUpdateAvailable) {
-                    Report.reportLog({
-                        objectType: Report.objectType.background_function_try,
-                        funcName: 'onUpdateAvailable',
+})
+
+chrome.runtime.onInstalled.addListener(onInstalledMethod);
+
+chrome.runtime.onMessage.addListener(onMessageMethod);
+
+// 定时器
+chrome.alarms.onAlarm.addListener(function (alarm) {
+    // console.log("onAlarm-", alarm);
+    switch (alarm.name) {
+        case 'denetChromeAlarm':
+            getMessageInfo();
+            break
+        case 'PingPong':
+            PingPong()
+            break;
+        case 'LuckMessage':
+            getSysMessage()
+            break
+    }
+});
+
+chrome.action.onClicked.addListener(function (tab) {
+    injectExtensionPopup(tab);
+});
+
+chrome.tabs.onActivated.addListener(function (activeInfo) {
+    setPopupConfig(activeInfo);
+})
+
+function thenInstalledMethod() {
+    try {
+
+        onInstalledCreateTab()
+        onInstalledMid()
+        onInstalledUserSet()
+        // pingpang
+        chrome.alarms.create('PingPong', {
+            //1分鐘之後開始(該值不能小於1) 
+            delayInMinutes: 2,
+            //開始後每一分鐘執行一次(該值不能小于1) 
+            periodInMinutes: 4
+        });
+        chrome.alarms.create('LuckMessage', {
+            //1分鐘之後開始(該值不能小於1) 
+            delayInMinutes: 1,
+            //開始後每一分鐘執行一次(該值不能小于1) 
+            periodInMinutes: 1
+        });
+    } catch (error) {
+        Report.reportLog({
+            objectType: Report.objectType.background_function_catch,
+            funcName: 'thenInstalledMethod',
+            errMsg: error.message
+        });
+    }
+}
+
+// 2.reportLog 异常 存储到本地,再上报
+// 3.onInstalledMethod 执行了那个
+
+function onInstalledMethod() {
+    try {
+        // 3.onInstalledMethod 执行了那个
+        // 版本更新判断
+        getChromeStorage('baseInfo', (info) => {
+            if (!info || !info.appVersionCode) {
+                setChromeStorage({ onInstalledMethod: JSON.stringify({ onInstalledMethod: '1' }) })
+                setChromeStorage({ baseInfo: JSON.stringify({ appVersionCode }) })
+                thenInstalledMethod()
+            } else if (appVersionCode != info.appVersionCode) {
+                setChromeStorage({ onInstalledMethod: JSON.stringify({ onInstalledMethod: '2' }) }, () => {
+                    setChromeStorage({ baseInfo: JSON.stringify({ appVersionCode }) }, () => {
+                        chrome.runtime.reload()
                     })
-                }
-            })
-        } catch (error) {
-            Report.reportLog({
-                objectType: Report.objectType.background_function_catch,
-                funcName: 'onInstalledMethod',
-                errMsg: error.message
-            })
-        }
+                })
+            } else {
+                setChromeStorage({ onInstalledMethod: JSON.stringify({ onInstalledMethod: '3' }) })
+                thenInstalledMethod()
+            }
+        })
+
+        // 1.onUpdateAvailable 存储到本地,再上报
+        getChromeStorage('onUpdateAvailable', (res) => {
+            if (res && res.onUpdateAvailable) {
+                Report.reportLog({
+                    objectType: Report.objectType.background_function_try,
+                    funcName: 'onUpdateAvailable',
+                })
+            }
+        })
+    } catch (error) {
+        Report.reportLog({
+            objectType: Report.objectType.background_function_catch,
+            funcName: 'onInstalledMethod',
+            errMsg: error.message
+        })
     }
+}
 
-    function onMessageMethod(req, sender, sendResponse) {
-        try {
-            if (req) {
-                switch (req.actionType) {
-                    case "POPUP_LOGIN":
-                        twitterPinLoginToken();
-                        break;
-                    case "POPUP_PUBLISH_TWITTER_RED_PACK":
-                        popupRePublish(req);
-                        break;
-                    case "POPUP_SHOW_DENET_PUBLISH_DIALOG":
-                        checkShowPublishDialog();
-                        break;
-                    case 'CONTENT_GET_PINED':
-                        checkPined();
-                        break;
-                    case 'CONTENT_SET_BADGE':
-                        setBadgeInfo(req);
-                        break;
-                    case 'CONTENT_HIDE_BADGE':
-                        hideBadge();
-                        break
-                    case 'CONTENT_SEND_CODE':
-                        twitterPinLoginCode(sender, req.code);
-                        break;
-                    case 'CONTENT_TWITTER_LOGIN':
-                        if (req.data) {
-                            twitterPinLoginToken()
+function onMessageMethod(req, sender, sendResponse) {
+    try {
+        if (req) {
+            switch (req.actionType) {
+                case "POPUP_LOGIN":
+                    twitterPinLoginToken();
+                    break;
+                case "POPUP_PUBLISH_TWITTER_RED_PACK":
+                    popupRePublish(req);
+                    break;
+                case "POPUP_SHOW_DENET_PUBLISH_DIALOG":
+                    checkShowPublishDialog();
+                    break;
+                case 'CONTENT_GET_PINED':
+                    checkPined();
+                    break;
+                case 'CONTENT_SET_BADGE':
+                    setBadgeInfo(req);
+                    break;
+                case 'CONTENT_HIDE_BADGE':
+                    hideBadge();
+                    break
+                case 'CONTENT_SEND_CODE':
+                    twitterPinLoginCode(sender, req.code);
+                    break;
+                case 'CONTENT_TWITTER_LOGIN':
+                    if (req.data) {
+                        twitterPinLoginToken()
+                    }
+                    break
+                case "CONTENT_SEND_DISCORD_AUTH_CODE":
+                    discordLoginCode(req, sender);
+                    break
+                case 'RED_PACKET_SAVE_DISCORD_AUTH_WINDOW_ID':
+                    saveDiscordAuthWindowId(req);
+                    break;
+                case 'CONTENT_FACEBOOK_SHARE_SUCCESS':
+                    facebookShareSuccess(req, sender);
+                    break;
+                case 'CONTENT_PONG':
+                    console.log('CONTENT_PONG')
+                    break
+                case 'CONTENT_WINDOW_LOADED_SET_POPUP_PAGE':
+                    // windwoLoadSetPopupPage(req, sender);
+                    break;
+                case 'CONTENT_SET_POPUP_CONFIG':
+                    setActionPopup(req, sender);
+                    break;
+                case 'CONTENT_GET_TWITTER_NFT_POST_PRE':
+                    getTwitterNftPostPre(req.data, sender)
+                    break
+                case 'CONTENT_NFT_TXT_PUBLISH':
+                    nftTxtPublish(req.data, sender)
+                    break
+                case 'CONTENT_HTTP_NET_WORK':
+                    httpNetWork(req.funcName, req.data, sender)
+                    break
+                case 'HTTP_CONTENT_TO_BACK':
+                    httpContentToBack(req, sender)
+                    break
+                case 'CONTENT_TWITTER_SHORT_LINK':
+                    sendResponse('ok')
+                    req.arr_url.forEach(item => {
+                        if (item) {
+                            twitterShortUrl(sender, item)
                         }
-                        break
-                    case "CONTENT_SEND_DISCORD_AUTH_CODE":
-                        discordLoginCode(req, sender);
-                        break
-                    case 'RED_PACKET_SAVE_DISCORD_AUTH_WINDOW_ID':
-                        saveDiscordAuthWindowId(req);
-                        break;
-                    case 'CONTENT_FACEBOOK_SHARE_SUCCESS':
-                        facebookShareSuccess(req, sender);
-                        break;
-                    case 'CONTENT_PONG':
-                        console.log('CONTENT_PONG')
-                        break
-                    case 'CONTENT_WINDOW_LOADED_SET_POPUP_PAGE':
-                        // windwoLoadSetPopupPage(req, sender);
-                        break;
-                    case 'CONTENT_SET_POPUP_CONFIG':
-                        setActionPopup(req, sender);
-                        break;
-                    case 'CONTENT_GET_TWITTER_NFT_POST_PRE':
-                        getTwitterNftPostPre(req.data, sender)
-                        break
-                    case 'CONTENT_NFT_TXT_PUBLISH':
-                        nftTxtPublish(req.data, sender)
-                        break
-                    case 'CONTENT_HTTP_NET_WORK':
-                        httpNetWork(req.funcName, req.data, sender)
-                        break
-                    case 'HTTP_CONTENT_TO_BACK':
-                        httpContentToBack(req, sender)
-                        break
-                    case 'CONTENT_TWITTER_SHORT_LINK':
-                        sendResponse('ok')
-                        req.arr_url.forEach(item => {
-                            if (item) {
-                                twitterShortUrl(sender, item)
-                            }
-                        });
-                        break
-                    case 'CONTENT_CLOSE_ACH_PAY_NOTICE':
-                        closeAchPayNoticeHandler();
-                        break;
-                }
+                    });
+                    break
+                case 'CONTENT_CLOSE_ACH_PAY_NOTICE':
+                    closeAchPayNoticeHandler();
+                    break;
             }
-        } catch (error) {
-            Report.reportLog({
-                objectType: Report.objectType.background_function_catch,
-                funcName: 'onMessageMethod',
-                errMsg: error.message
-            });
         }
+    } catch (error) {
+        Report.reportLog({
+            objectType: Report.objectType.background_function_catch,
+            funcName: 'onMessageMethod',
+            errMsg: error.message
+        });
     }
-} catch (error) {
-    console.log('error', error)
-}
+}

+ 14 - 5
src/entry/content.js

@@ -105,6 +105,15 @@ window.onmessage = (res) => {
             // case "IFRAME_DO_TASK":
             //     findTweetByIdDoTask(res.data.task_data, res.data.task_type)
             //     break
+            case 'IFREME_TAB_GROUP_SET_IFRAME_HEIGHT':
+                setTabGroupIframeStyle(res.data.data);
+                break
+            case 'IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP':
+                getTweetProfileNavTop(res.data.data);
+                break;
+            case 'IFRAME_PAGE_JUMP':
+                pageJumpHandler(res.data.data);
+                break;
         }
     }
 };
@@ -149,11 +158,11 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
         case 'BG_SET_POPUP_CONFIG':
             setPopupConfByPopupPage();
             break
-        case 'IFREME_TAB_GROUP_SET_IFRAME_HEIGHT':
-            setTabGroupIframeStyle(req.data);
-            break
-        case 'IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP':
-            getTweetProfileNavTop(req.data);
+        // case 'IFREME_TAB_GROUP_SET_IFRAME_HEIGHT':
+        //     setTabGroupIframeStyle(req.data);
+        //     break
+        // case 'IFREME_TAB_GROUP_CONTENT_GET_NAV_TOP':
+        //     getTweetProfileNavTop(req.data);
         case 'IFRAME_PAGE_JUMP':
 
             pageJumpHandler(req.data);

+ 3 - 1
src/http/configAPI.js

@@ -38,4 +38,6 @@ export const discordAuthRedirectUri = `${pageUrl}/auth/discordCallback`;
 
 export const faceShareRedirectUrl = `${pageUrl}/facebook/shareCallback`;
 
-export const payAchNoticeUrl = `${pageUrl}/ach_pay/pay_notice`;
+export const payAchNoticeUrl = `${pageUrl}/ach_pay/pay_notice`;
+
+export const iframeHost = process.env.VUE_APP_IFRAME_HOST;

+ 68 - 0
src/http/treasure.js

@@ -0,0 +1,68 @@
+import { service } from "./request";
+
+export function treasureDetail(params) {
+    return service({
+        url: `/post/treasure/detail`,
+        method: "post",
+        data: params,
+    });
+}
+
+
+export function inviteChannel(params) {
+    return service({
+        url: `/post/treasure/invite/channel`,
+        method: "post",
+        data: params,
+    });
+}
+
+export function inviteDetail(params) {
+    return service({
+        url: `/post/treasure/invite/detail`,
+        method: "post",
+        data: params,
+    });
+}
+
+export function inviteList(params) {
+    return service({
+        url: `/post/treasure/invite/list`,
+        method: "post",
+        data: params,
+    });
+}
+
+export function treasureOpen(params) {
+    return service({
+        url: `/post/treasure/open`,
+        method: "post",
+        data: params,
+    });
+}
+
+export function prepareStart(params) {
+    return service({
+        url: `/post/treasure/prepareStart`,
+        method: "post",
+        data: params,
+    });
+}
+
+
+export function receiveList(params) {
+    return service({
+        url: `/post/treasure/receive/list`,
+        method: "post",
+        data: params,
+    });
+}
+
+
+export function treasureStart(params) {
+    return service({
+        url: `/post/treasure/start`,
+        method: "post",
+        data: params,
+    });
+}

+ 9 - 0
src/http/treasureApi.js

@@ -0,0 +1,9 @@
+import { service } from "./request";
+
+export function upGainCalculate(params) {
+    return service({
+        url: `/post/treasure/upGainCalculate`,
+        method: 'post',
+        data: params
+    })
+}

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

@@ -1,5 +1,4 @@
 import { createApp } from 'vue'
 import App from '@/view/iframe/tool-box/index.vue'
-
 const app = createApp(App);
-app.mount('#app');
+app.mount('#app');

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

@@ -0,0 +1,5 @@
+import { createApp } from 'vue'
+import App from '@/view/iframe/test/index.vue'
+
+const app = createApp(App);
+app.mount('#app');

+ 21 - 1
src/log-center/logger.js

@@ -97,4 +97,24 @@ function wrapObject(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;
+}

+ 9 - 0
src/logic/background/twitter.js

@@ -405,6 +405,15 @@ export function onInstalledCreateTab() {
                         });
                     }
                     break
+                case 'treasure_info':
+                  if (res && res.postNickName && res.srcContentId) {
+                      created_detail = true
+                      url = `https://twitter.com/${res.postNickName}/status/${res.srcContentId}`
+                      chrome.tabs.create({
+                          url
+                      });
+                  }
+                  break;
             }
 
             if (created_detail == false) {

+ 30 - 0
src/logic/content/ParseCard.js

@@ -285,6 +285,13 @@ class ParseCard {
         _iframe.style.cssText = 'border:medium none; width:505px; min-height:180px;'
         return _iframe
     }
+    createTreasureIframe(params = { page_type, tweet_Id, post_Id, invite_code }) {
+        let _iframe = document.createElement('iframe')
+        _iframe.id = params.post_Id
+        _iframe.src = chrome.runtime.getURL('/iframe/treasure-hunt.html') + `?params=${JSON.stringify(params)}`;
+        _iframe.style.cssText = 'border:medium none; width:375px; min-height:500px;'
+        return _iframe
+    }
     isHasIframeByArticle(dom_card) {
         if (!dom_card || !dom_card.parentElement) {
             return
@@ -473,6 +480,29 @@ class ParseCard {
             dom.appendChild(this.createIframe({ post_Id, tweet_Id, page_type }))
         }
     }
+    replaceDOMRreasureCard({ invite_code, dom_card, tweet_Id, post_Id, time, short_url, page_type = '' }) {
+        if (!dom_card || !dom_card.parentElement) {
+            return
+        }
+        let type
+        let dom = dom_card.querySelector('div[aria-labelledby]')
+        if (dom) {
+            type = 'card'
+            for (let i = 0; i < dom.childNodes.length; i++) {
+                if (dom.childNodes[i].dataset && dom.childNodes[i].dataset.testid && dom.childNodes[i].dataset.testid == 'card.wrapper') {
+                    dom.children[i].style.display = 'none'
+                }
+            }
+        } else {
+            type = 'txt'
+            dom = dom_card.querySelector('div[lang][dir=auto]').parentElement
+        }
+
+        dom.style = 'min-height:500px'
+        if (dom) {
+            dom.appendChild(this.createTreasureIframe({ post_Id, tweet_Id, page_type, invite_code }))
+        }
+    }
     replaceNftDomRedPacket({ dom_card, tweet_Id, post_Id, time, short_url }) {
         if (!dom_card || !dom_card.parentElement) {
             return

+ 198 - 82
src/logic/content/twitter.js

@@ -1,6 +1,6 @@
 import { getChromeStorage, setChromeStorage } from '@/uilts/chromeExtension.js'
 import { throttle, getQueryString, getCookie, nextTick, getQueryStringByUrl } from '@/uilts/help'
-import { discordAuthRedirectUri } from '@/http/configAPI'
+import { discordAuthRedirectUri, iframeHost } from '@/http/configAPI'
 import { reportSrcPublishEvent } from '@/http/publishApi'
 import Report from "@/log-center/log"
 import { fetchAddFinishEvent } from '@/logic/background/fetch/facebook';
@@ -9,6 +9,7 @@ import { jumpTwitterDetailByAlert, showEditTweet } from '@/logic/content/help/tw
 import { clearPostContent, setGroupIconStatus } from '@/logic/content/nft.js'
 import { toolBox } from '@/logic/content/ToolBox'
 import axios from 'axios';
+import messageCenter from '@/uilts/messageCenter';
 
 let dom = {};
 
@@ -275,66 +276,64 @@ function checkIsShowReSend(dom, params) {
  * @param isClick
  * @private
  */
-function _addDeNetEditBtn(params = {}) {
-    setTimeout(() => {
-        let toolElem = document.querySelector('div[data-testid="toolBar"]');
-        if (toolElem) {
-            let innerDeIcon = document.getElementById('de-btn1');
-            if (!innerDeIcon) {
-                toolElem.firstChild.appendChild(createTweetToolbarDenet());
-                popupShowGiveawayDialog();
-                Report.reportLog({
-                    pageSource: Report.pageSource.mainPage,
-                    businessType: Report.businessType.buttonView,
-                    objectType: Report.objectType.buttonSecond
-                }, {
-                    type: 0
-                });
-            }
+ function _addDeNetEditBtn(params = {}) {
+    let toolElem = document.querySelector('div[data-testid="toolBar"]');
+    if (toolElem) {
+        let innerDeIcon = toolElem.querySelector('#de-btn1');
+        if (!innerDeIcon) {
+            toolElem.firstChild.appendChild(createTweetToolbarDenet());
+            popupShowGiveawayDialog();
+            Report.reportLog({
+                pageSource: Report.pageSource.mainPage,
+                businessType: Report.businessType.buttonView,
+                objectType: Report.objectType.buttonSecond
+            }, {
+                type: 0
+            });
+        }
 
-            let innerToolBoxIcon = document.getElementById('de-tool-box-btn-01');
-            if (!innerToolBoxIcon) {
-                toolElem.firstChild.appendChild(createTweetToolbarToolBox())
-                Report.reportLog({
-                    pageSource: Report.pageSource.mainPage,
-                    businessType: Report.businessType.buttonView,
-                    objectType: Report.objectType.buttonSecond
-                }, {
-                    type: 1
-                });
-            }
-        } else {
-            setTimeout(() => {
-                let toolElem = document.querySelector('div[data-testid="toolBar"]');
-                if (toolElem) {
-                    let innerDeIcon = document.getElementById('de-btn1');
-                    if (!innerDeIcon) {
-                        toolElem.firstChild.appendChild(createTweetToolbarDenet());
-                        popupShowGiveawayDialog();
-                        Report.reportLog({
-                            pageSource: Report.pageSource.mainPage,
-                            businessType: Report.businessType.buttonView,
-                            objectType: Report.objectType.buttonSecond
-                        }, {
-                            type: 0
-                        });
-                    }
+        let innerToolBoxIcon = toolElem.querySelector('#de-tool-box-btn-01');
+        if (!innerToolBoxIcon) {
+            toolElem.firstChild.appendChild(createTweetToolbarToolBox())
+            Report.reportLog({
+                pageSource: Report.pageSource.mainPage,
+                businessType: Report.businessType.buttonView,
+                objectType: Report.objectType.buttonSecond
+            }, {
+                type: 1
+            });
+        }
+    } else {
+        setTimeout(() => {
+            let toolElem = document.querySelector('div[data-testid="toolBar"]');
+            if (toolElem) {
+                let innerDeIcon = toolElem.querySelector('#de-btn1');
+                if (!innerDeIcon) {
+                    toolElem.firstChild.appendChild(createTweetToolbarDenet());
+                    popupShowGiveawayDialog();
+                    Report.reportLog({
+                        pageSource: Report.pageSource.mainPage,
+                        businessType: Report.businessType.buttonView,
+                        objectType: Report.objectType.buttonSecond
+                    }, {
+                        type: 0
+                    });
+                }
 
-                    let innerToolBoxIcon = document.getElementById('de-tool-box-btn-01');
-                    if (!innerToolBoxIcon) {
-                        toolElem.firstChild.appendChild(createTweetToolbarToolBox())
-                        Report.reportLog({
-                            pageSource: Report.pageSource.mainPage,
-                            businessType: Report.businessType.buttonView,
-                            objectType: Report.objectType.buttonSecond
-                        }, {
-                            type: 1
-                        });
-                    }
+                let innerToolBoxIcon = toolElem.querySelector('#de-tool-box-btn-01');
+                if (!innerToolBoxIcon) {
+                    toolElem.firstChild.appendChild(createTweetToolbarToolBox())
+                    Report.reportLog({
+                        pageSource: Report.pageSource.mainPage,
+                        businessType: Report.businessType.buttonView,
+                        objectType: Report.objectType.buttonSecond
+                    }, {
+                        type: 1
+                    });
                 }
-            }, 1000)
-        }
-    })
+            }
+        }, 1000)
+    }
 }
 
 const popupShowGiveawayDialog = async () => {
@@ -717,8 +716,9 @@ function onWindowResize() {
 function checkHasDeBtn() {
     try {
         let toolBar = document.querySelector('div[data-testid="toolBar"]');
-        let innerDeIcon = document.getElementById('de-btn1');
-        if (toolBar && !innerDeIcon) {
+        let append = toolBar && !toolBar.querySelector('#de-btn1');
+
+        if (append) {
             _addDeNetEditBtn();
         }
     } catch (e) {
@@ -741,9 +741,9 @@ export function bindTwitterArtMethod() {
             }
         }).then((res) => {
             if (res.code == 0) {
-                Report.reportLog({
-                    objectType: Report.objectType.tweetPostBinded
-                });
+                // Report.reportLog({
+                //     objectType: Report.objectType.tweetPostBinded
+                // });
                 bindTwitterArt.needBind = false;
                 bindTwitterArt.postId = '';
                 bindTwitterArt.isBindIng = false;
@@ -830,6 +830,26 @@ function setIframeRedPacket(type = 'twitter') {
                     } else if (item && item.post_Id && !item.post_Id.includes('/')) {
                         item.page_type = '红包'
                         parseCard.replaceDOMRedPacket(item)
+                        // 夺宝链接
+                    } else if (item && item.post_Id && item.post_Id.includes('treasure/')) {
+                        // https://testh5.denetme.net/treasure/{postid}
+                        // https://testh5.denetme.net/treasure/invite/{inviteCode}
+                        // 邀请链接 
+                        if (item.post_Id.includes('invite/')) {
+                            item.invite_code = item.post_Id.split('invite/')[1] || ''
+                            item.page_type = '邀请链接'
+                            if (item.invite_code) {
+                                item.post_Id = ''
+                                parseCard.replaceDOMRreasureCard(item)
+                            }
+                        } else {
+                            // 原始链接
+                            item.page_type = '原始链接'
+                            item.post_Id = item.post_Id.split('treasure/')[1] || ''
+                            if (item.post_Id) {
+                                parseCard.replaceDOMRreasureCard(item)
+                            }
+                        }
                     }
                 }
                 if (res.need_net_short_url.length > 0) {
@@ -902,6 +922,7 @@ function initParseCard() {
             clearInterval(timer)
             setInterval(() => {
                 onChangePageMain(inTwitterNode)
+                checkHasDeBtn()
                 twitterPinLogin()
                 showNFTGroupIcon()
                 if (queue_num <= 0) {
@@ -909,7 +930,6 @@ function initParseCard() {
                 }
                 initGroupTip()
                 setIframeRedPacket()
-                checkHasDeBtn()
                 checkHasSliderDeBtn();
                 changeQueueNum(-1)
                 showNFTCard()
@@ -1314,7 +1334,7 @@ export function getTweetAuthorByDom(params) {
         }
     }
 }
-export function doTaskTwitterAPI({ task_data, task_type }) {
+export function doTaskTwitterAPI({ task_data, task_type, tasks }) {
     switch (task_type) {
         case 'like':
             TwitterLikeAPI(task_data.tweet_Id)
@@ -1329,6 +1349,32 @@ export function doTaskTwitterAPI({ task_data, task_type }) {
                 }
             })
             break
+        case 'tasks':
+            tasks.forEach((item) => {
+                // 
+                switch (String(item.type)) {
+                    // 关注指定用户
+                    case '1':
+                        item.relatedUsers.forEach((item) => {
+                            if (item.name && item.twitterUserId) {
+                                TwitterFollowAPI(item, task_data.tweet_Id)
+                            }
+                        })
+                        break
+                    // 点赞
+                    case '2':
+                        TwitterLikeAPI(task_data.tweet_Id)
+                        break
+
+                    // 推文发推
+                    case '10':
+                        // 发推
+                        TwitterApiCreateTweet({ text: task_data.tweet_text, tweet_Id: task_data.tweet_Id })
+                        break
+                }
+
+            })
+            break
     }
 }
 
@@ -1431,6 +1477,60 @@ const TwitterLikeAPI = (tweet_Id) => {
     })
 }
 
+
+const TwitterApiCreateTweet = ({ text, tweet_Id }) => {
+    let data = {
+        queryId: "hC1nuE-2d1NX5LYBuuAvtQ",
+        features: {
+            "dont_mention_me_view_api_enabled": true,
+            "interactive_text_enabled": true,
+            "responsive_web_uc_gql_enabled": false,
+            "vibe_api_enabled": true,
+            "responsive_web_edit_tweet_api_enabled": false,
+            "standardized_nudges_misinfo": true,
+            "responsive_web_enhance_cards_enabled": false
+        },
+        variables: {
+            "tweet_text": text,
+            "media": {
+                "media_entities": [],
+                "possibly_sensitive": false
+            },
+            "withDownvotePerspective": true,
+            "withReactionsMetadata": false,
+            "withReactionsPerspective": false,
+            "withSuperFollowsTweetFields": true,
+            "withSuperFollowsUserFields": true,
+            "semantic_annotation_ids": [],
+            "dark_request": false
+        }
+    };
+    axios.post(`https://twitter.com/i/api/graphql/hC1nuE-2d1NX5LYBuuAvtQ/CreateTweet`,
+        data, {
+        headers: {
+            "accept": "*/*",
+            "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
+            "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
+            "content-type": "application/json",
+            "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"101\", \"Google Chrome\";v=\"101\"",
+            "sec-ch-ua-mobile": "?0",
+            "sec-ch-ua-platform": "\"Windows\"",
+            "sec-fetch-dest": "empty",
+            "sec-fetch-mode": "cors",
+            "sec-fetch-site": "same-origin",
+            "x-csrf-token": getCookie('ct0'),
+            "x-twitter-active-user": "yes",
+            "x-twitter-auth-type": "OAuth2Session",
+            "x-twitter-client-language": "en"
+        },
+    }).then(function (response) {
+        chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'createTweet', task_data: '', task_done: true })
+    }).catch(function (err) {
+        chrome.runtime.sendMessage({ actionType: "DO_TASK", do_type: 'api', tweet_Id, task_type: 'createTweet', task_data: '', task_done: false })
+    });
+}
+
+
 export const TwitterApiUserByScreenName = (params) => {
     let { screen_name } = params;
     axios.get(`https://twitter.com/i/api/graphql/mCbpQvZAw6zu_4PvuAUVVQ/UserByScreenName?variables=%7B%22screen_name%22%3A%22${screen_name}%22%2C%22withSafetyModeUserFields%22%3Atrue%2C%22withSuperFollowsUserFields%22%3Atrue%7D`, {
@@ -2004,7 +2104,7 @@ const hiddenMaskWeb3Tab = (count) => {
  * 跳转到个人主页 检查是否需要选中 Group tab
  */
 const checkNeedSelectGroupTab = () => {
-    if (window.location.pathname != '/home') {
+    if (window.location.pathname != '/home' && !document.hidden) {
         setTimeout(() => {
             getChromeStorage('groupTabData', (res) => {
                 console.log('groupTabData', res);
@@ -2107,10 +2207,12 @@ const addPageScrollEvent = () => {
         contentHeight: contentDom.offsetHeight
     }
 
-    chrome.runtime.sendMessage({
-        actionType: "CONTENT_GROUP_LIST_SCROLL",
-        data: data
-    }, () => { });
+    messageCenter.send('de-tab-group-content', 'CONTENT_GROUP_LIST_SCROLL', data)
+
+    // chrome.runtime.sendMessage({
+    //     actionType: "CONTENT_GROUP_LIST_SCROLL",
+    //     data: data
+    // }, () => { });
 };
 
 const removeTweetTabEvent = (params) => {
@@ -2191,10 +2293,11 @@ const setGroupTabSelfStyle = (params = {}) => {
  * 切换到 Group tab时 刷新列表
  */
 export const refreshTabGroup = () => {
-    chrome.runtime.sendMessage({
-        actionType: "CONTENT_REFRESH_TAB_GROUP_LIST",
-        data: {}
-    }, () => { });
+    messageCenter.send('de-tab-group-content', 'CONTENT_REFRESH_TAB_GROUP_LIST', {})
+    //     chrome.runtime.sendMessage({
+    //         actionType: "CONTENT_REFRESH_TAB_GROUP_LIST",
+    //         data: {}
+    //     }, () => { });
 }
 
 /**
@@ -2271,7 +2374,7 @@ const addTabGroupContent = (cb) => {
     }
     let iframe = document.createElement('iframe');
     iframe.id = 'de-tab-group-content';
-    iframe.src = chrome.runtime.getURL('/iframe/tab-group.html') + `?params=${JSON.stringify(params)}`;
+    iframe.src = `${iframeHost}/tab-group` + `?params=${JSON.stringify(params)}`;
     iframe.style.cssText = `border: medium none; height: 500px;display: none`
 
     let iframeContent = getGroupTabContentNode();
@@ -2372,12 +2475,19 @@ export const pageJumpHandler = (params) => {
 export const getTweetProfileNavTop = (params) => {
     let top = document.querySelector('div[role="tablist"]').closest('nav').getBoundingClientRect().top;
 
-    chrome.runtime.sendMessage({
-        actionType: "CONTENT_SEND_GROUP_NAV_TOP", data: {
+    messageCenter.send({
+        actionType: "CONTENT_SEND_GROUP_NAV_TOP",
+        data: {
             top,
             scrollTop: params.scrollTop
         }
-    }, () => { })
+    })
+    // chrome.runtime.sendMessage({
+    //     actionType: "CONTENT_SEND_GROUP_NAV_TOP", data: {
+    //         top,
+    //         scrollTop: params.scrollTop
+    //     }
+    // }, () => { })
 }
 
 
@@ -2432,13 +2542,19 @@ const getSysTheme = () => {
 const sysThemeChange = () => {
     setTimeout(() => {
         let bgColor = document.querySelector('body').style.backgroundColor;
-
-        chrome.runtime.sendMessage({
-            actionType: "CONTENT_SYS_THEME_CHANGE", data: {
+        messageCenter.send({
+            actionType: "CONTENT_SYS_THEME_CHANGE",
+            data: {
                 theme: systemInfo.theme,
                 twitterTheme: bgColor == 'rgb(0, 0, 0)' ? 'dark' : 'light'
             }
-        }, () => { })
+        })
+        // chrome.runtime.sendMessage({
+        //     actionType: "CONTENT_SYS_THEME_CHANGE", data: {
+        //         theme: systemInfo.theme,
+        //         twitterTheme: bgColor == 'rgb(0, 0, 0)' ? 'dark' : 'light'
+        //     }
+        // }, () => { })
     }, 800)
 }
 

+ 2 - 1
src/manifest.json

@@ -98,7 +98,8 @@
                 "/iframe/tool-box-buy-nft.html",
                 "/iframe/test.html",
                 "/iframe/ach-cashier.html",
-                "/img/icon-denet-logo.svg"
+                "/img/icon-denet-logo.svg",
+                "/iframe/treasure-hunt.html"
             ],
             "matches": [
                 "<all_urls>"

+ 6 - 2
src/types/global.js

@@ -6,10 +6,12 @@
  * 玩法类型
  * 普通任务:common=1;
  * 抽奖:lottery=2
+ * 夺宝:treasure=3
  */
 export const PlayType = {
   common: 1,
   lottery: 2,
+  treasure: 3
 };
 
 /**
@@ -32,6 +34,7 @@ export const TaskType = {
   joinDiscord: 7,
   repostToFacebook: 8,
   twitterCommentAndTag: 9,
+  twitterRePost: 10
 };
 
 /**
@@ -40,6 +43,7 @@ export const TaskType = {
 
 export const PostType = {
   giveaway: 1,
-  nftGroup: 2,
-  postEditor: 3
+  lottery: 2,
+  postEditor: 3,
+  treasure: 4
 }

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

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

+ 19 - 7
src/view/components/component-zoom.vue

@@ -5,26 +5,38 @@
     </span>
 </template>
 <script setup>
-import { ref, defineProps, onMounted, getCurrentInstance } from 'vue'
+import { ref, defineProps, onMounted, watch } from 'vue'
 
 let props = defineProps({
     width: {
-        type: String,
+        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 currentInstance;
+let zoomDom = ref({});
 
-const setFontZoom = () => {
-    const currentInstance = getCurrentInstance()
-    let offsetWidth = currentInstance.ctx.$refs.zoomDom.offsetWidth;
-    zoom.value = offsetWidth > props.width ? +props.width / offsetWidth : 1
+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(() => {

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

@@ -356,7 +356,6 @@ defineExpose({
     .list-wrapper {
         height: calc(100% - 60px);
         overflow-y: auto;
-        padding-bottom: 50px;
 
         .list-item {
             .item-title {

+ 152 - 14
src/view/components/custom-card-cover.vue

@@ -21,51 +21,83 @@
         </div>
     </div>
     <div class="not-open" v-else-if="isMoneyRewardCpd">
-        <img class="cover" v-if="data.type == 2" :src="require('@/assets/svg/img-preview-draw-bg.svg')"  />
-        <img class="cover" v-else :src="require('@/assets/subject/001-card.png')"  />
+        <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 == 2"
+            v-if="data.type == PlayType.lottery"
             src="@/assets/img/img-preview-draw-box.png" />
         <img class="open-gif"
-            v-else
+            v-else-if="data.type == PlayType.common"
             :src="require('@/assets/gif/001.gif')" />
 
-        <img v-if="data.type == 2"
+        <img v-if="data.type == PlayType.lottery"
             :src="require('@/assets/svg/img-preview-draw-open.svg')"
             class="open"
             @click="open" />
-        <img v-else
+        <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>{{
-                data.userInfo.nickName || ""
-            }}</span>
+            <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">
+
+        <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">
-                <img :src="data.currencyIconUrl || imgHeaderCover" />
+                <img v-if="data.currencyIconUrl" :src="data.currencyIconUrl || imgHeaderCover" />
                 <span id="preview-after-amount"
                     :style="{
                         fontSize: amount_font_size + 'px'
-                    }">{{ data.amountValue }}</span>
+                    }">{{ data.amountValue || 0 }}</span>
             </div>
-            <div class="time-area" v-if="data.type == 2">
+            <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>
+            <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 $ <div class="amount">{{data.upGainAmountUsdValue}}</div>
+            </div>
+
+            <div class="treasure-row-3" :style="{'visibility': data.currencyCode? 'visible' : 'hidden'}">
+                <img class="img" :src="data.currencyIconUrl" /> <span class="txt"> {{data.tokenSymbol}} equivalent (Crypto)</span>
+            </div>
+
+            <img class="img-treasure-big" :src="require('@/assets/img/icon-card-cover-treasure-big.png')">
+
+            <div class="treasure-row-4">
+               <img class="img" :src="require('@/assets/svg/icon-card-cover-treasure-tasks.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>
 
     <!-- 改版之后的卡片 -->
@@ -130,6 +162,7 @@ const props = defineProps({
                 },
                 rewardType: RewardType.money,
                 customizedReward: "",
+                upGainAmountUsdValue: ""
             };
         },
     },
@@ -250,6 +283,105 @@ onMounted(() => {
         }
     }
 
+    .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;
+            }
+        }
+
+        .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;
@@ -273,6 +405,12 @@ onMounted(() => {
             letter-spacing: 0.3px;
             color: #fff;
         }
+
+        .treasure-info {
+            color: #fff; 
+            opacity: 0.7;
+            font-weight: 300;
+        }
     }
 
     // .txt {

+ 112 - 28
src/view/components/custom-card-horizontal-cover.vue

@@ -6,47 +6,83 @@
         </template>
         <template v-else-if="isMoneyRewardCpd">
             <img :src="require('@/assets/img/img-preview-draw-after-bg.png')"
-                v-if="data.type == 2"
+                v-if="data.type == PlayType.lottery"
                 class="card-cover">
             <img :src="require('@/assets/subject/img-card-cover-blue.png')"
-                v-else
+                v-else-if="data.type == PlayType.common"
                 class="card-cover"/>
+            <img :src="require('@/assets/img/img-preview-treasure-link-bg.png')"
+                v-else-if="data.type == PlayType.treasure"
+                class="card-cover"/>
+
             <div class="bottom-bar">
                 <div class="title">
                     DeNet.me
                 </div>
                 <div class="desc">
-                    🎁 <template v-if="data.tokenSymbol=='USD'">$</template>{{data.amountValue}} GIVEAWAY
+                    DeNet: An Easy Web3 Tool For GIVEAWAY / AIRDROP
+                    <!-- 🎁 <template v-if="data.tokenSymbol=='USD'">$</template>{{data.amountValue}} GIVEAWAY -->
                 </div>
             </div>
+
             <div class="user-info">
                 <img :src="data.userInfo.avatarUrl" 
-                class="avatar"/> {{data.userInfo.name}}
+                class="avatar"/> 
+                <template v-if="data.type != PlayType.treasure">
+                    {{data.userInfo.nickName}}
+                </template>
+                <span class="treasure-info" style="color: #fff; opacity: 0.7;font-weight: 300;" v-else>
+                    from @{{data.userInfo.nickName || ""}}
+                </span>
             </div>
+
             <div class="content-text">
-                <div class="title">
-                    <span>{{data.currencyCode == 'USD' ? 'US Dollar' : data.tokenSymbol}} </span>
-                    &nbsp;GIVEAWAY
-                </div>
-                <div class="center"
-                    :style="{
-                        fontSize: amountFontSize + 'px'
-                    }">
-                    <img :src="data.currencyIconUrl" class="icon">
-                    <span id="preview-before-amount">
-                        {{data.amountValue}}
-                    </span>
-                </div>
-                <div class="desc">
-                    <template  v-if="data.type == 2">
-                        <img class="icon-clock" 
-                        :src="require('@/assets/svg/icon-preview-clock.svg')" />  {{data.validityDuration}} H
-                        <img class="icon-trophy" 
-                        :src="require('@/assets/svg/icon-preview-trophy.svg')" /> <span class="trophy-count">{{data.totalCount}} WINNERS</span>
-                    </template>
-                    <template v-else>
-                        {{data.totalCount}} WINNERS TO SHARE
-                    </template>
+                <template v-if="data.type != PlayType.treasure">
+                    <div class="title">
+                        <span>{{data.currencyCode == 'USD' ? 'US Dollar' : data.tokenSymbol}} </span>
+                        &nbsp;GIVEAWAY
+                    </div>
+
+                    <div class="center"
+                        :style="{
+                            fontSize: amountFontSize + 'px'
+                        }">
+                        <img :src="data.currencyIconUrl" class="icon">
+                        <span id="preview-before-amount">
+                            {{data.amountValue}}
+                        </span>
+                    </div>
+
+                    <div class="desc">
+                        <template  v-if="data.type == PlayType.lottery">
+                            <img class="icon-clock" 
+                            :src="require('@/assets/svg/icon-preview-clock.svg')" />  {{data.validityDuration}} H
+                            <img class="icon-trophy" 
+                            :src="require('@/assets/svg/icon-preview-trophy.svg')" /> <span class="trophy-count">{{data.totalCount}} WINNERS</span>
+                        </template>
+                        <template v-else-if="data.type == PlayType.common">
+                            {{data.totalCount}} WINNERS TO SHARE
+                        </template>
+                    </div>
+                </template>
+                <div class="treasure-layout" v-else>
+                    <div class="treasure-row-1">
+                        <span class="left">Treasure</span>
+                        <component-zoom width="160">
+                            <span class="right">${{data.amountValue}}</span>
+                        </component-zoom>
+                    </div>
+                    <div class="treasure-desc-data">
+                        <div class="item">
+                            <img class="icon" 
+                                :src="require('@/assets/svg/icon-preview-trophy.svg')" />
+                            {{data.totalCount}} Winners
+                        </div>
+                        <div class="item">
+                            <img class="icon" :src="data.currencyIconUrl">
+                            {{data.currencyCode == 'USD' ? 'US Dollar' : data.tokenSymbol}} equivalent
+                        </div>
+                    </div>
                 </div>
             </div>
         </template>
@@ -62,7 +98,7 @@
                 </div>
             </div>
             <div class="custom-card-prize">
-                <component-zoom :width="showBottom ? 210 : 300">
+                <component-zoom width="showBottom ? 210 : 300">
                     <span class="custom-card-prize-name" id="custom-name" >
                         <img class="custom-card-prize-gift-inline" :src="require('@/assets/subject/icon-gift-inline.svg')" />
                         {{data.customizedReward}}
@@ -169,6 +205,12 @@ watch(() => props.data, () => {
             border-radius: 50%;
             margin-right: 10px;
         }
+
+        .treasure-info {
+            color: #fff; 
+            opacity: 0.7;
+            font-weight: 300;
+        }
     }
     .content-text {
         position: absolute;
@@ -219,6 +261,48 @@ watch(() => props.data, () => {
                 color: #FFCC4D;
             }
         }
+
+        .treasure-layout {
+            margin-top: -8px;
+
+            .treasure-row-1 {
+                display: flex; 
+                align-items: center;
+                justify-content: center;
+                font-weight: 900;
+                font-size: 35px;
+                color: #fff;
+
+                .left {
+                    margin-right: 7px;
+                    color: #FFC83A;
+                }
+
+                .right {
+                    font-weight: 900;
+                    font-size: 35px;
+                    color: #fff;
+                }
+            }
+
+            .treasure-desc-data {
+                margin-top: 18px;
+
+                .item {
+                    font-weight: 500;
+                    font-size: 14px;
+                    color: #E1D4C5;
+                    margin-bottom: 10px;
+                    display: flex; 
+                    align-items: center;
+
+                    .icon {
+                        width: 20px;
+                        margin-right: 8px;
+                    }
+                }
+            }
+        }
     }
     .card-cover {
         width: 100%;

+ 32 - 9
src/view/components/popup-transactions.vue

@@ -18,12 +18,15 @@
                     <red-dot class="red-dots" v-if="item.unReadMsgCount > 0 && isReadMsg"></red-dot>
                     <div class="img-wrapper">
                         <!-- 收入- 任务红包领取 -->
-                        <template v-if="item.bizType == 1 || item.bizType == 5">
-                            <img class="icon-avatar" :src="item.bizData.avatarUrl" />
-                            <img class="icon-give" :src="
+                        <template v-if="item.bizType == 1 || item.bizType == 5 || item.bizType == 10 || item.bizType == 11 || item.bizType == 12">
+                            <img class="icon-avatar" v-if="item.bizType != 12" :src="item.bizData.avatarUrl" />
+                            <img class="icon-avatar" v-else :src="require('@/assets/svg/icon-treasure-return.svg')" />
+                            <img class="icon-give" v-if="item.bizType == 10 || item.bizType == 11" :src="require('@/assets/svg/icon-small-treasure.svg')" />
+                            <img class="icon-give" v-else :src="
                                 require('@/assets/svg/icon-get-giveaways-s.svg')
                             " />
                         </template>
+
                         <!-- 收入- 任务红包结余退款, -->
                         <template v-else-if="item.bizType == 2 || item.bizType == 6">
                             <img style="margin-left:-4px" :src="
@@ -66,8 +69,11 @@
                         </template>
                         <!-- 支出-任务红包余额支付 -->
                         <template v-else-if="item.bizType == -2">
-                            <img style="margin-left:-4px" :src="
-                                require('@/assets/svg/icon-big-give.svg')
+                            <img class="icon-avatar" style="margin-left:-4px" :src="
+                                        require('@/assets/svg/icon-big-give.svg')
+                            " />
+                            <img class="icon-give" :src="
+                                require('@/assets/svg/icon-list-withdraw-s.svg')
                             " />
                         </template>
                         <!-- 支出-买盲盒 -->
@@ -92,6 +98,15 @@
                                 :src="require('@/assets/img/icon-box2.png')" v-else />
                             <img class="icon-give" :src="require('@/assets/svg/icon-transaction-s.svg')" />
                         </template>
+                        <!-- 支出-夺宝 -->
+                        <template v-else-if="item.bizType == -6">
+                            <img class="icon-avatar" style="margin-left:-4px" :src="
+                                        require('@/assets/svg/icon-big-give.svg')
+                            " />
+                            <img class="icon-give" :src="
+                                require('@/assets/svg/icon-list-withdraw-s.svg')
+                            " />
+                        </template>
                     </div>
                     <div class="info-wrapper">
                         <div class="left">
@@ -120,6 +135,12 @@
                                 <template v-else-if="item.bizType == 8">
                                     NFT Refund
                                 </template>
+                                <template v-else-if="item.bizType == 10 || item.bizType == 11">
+                                    Get Treasure Chest
+                                </template>
+                                <template v-else-if="item.bizType == 12">
+                                    Treasure Chest Refund
+                                </template>
                                 <template v-else-if="item.bizType == -1">
                                     Withdrawal
                                 </template>
@@ -135,6 +156,9 @@
                                 <template v-else-if="item.bizType == -5">
                                     Transaction Royalties
                                 </template>
+                                <template v-else-if="item.bizType == -6">
+                                    Send Treasure Chest
+                                </template>
                             </div>
                             <div class="time">{{ moment(item.createTimestamp).format('MM-DD HH:mm:ss') }}</div>
                         </div>
@@ -180,9 +204,9 @@
                                     <template v-else-if="item.bizData.withdrawStatus == 3">
                                         <div>
                                             <div class="balance"
-                                                :class="{ 'balance-direction': item.trxAmountCurrencyInfo.tokenSymbol.length + ('' + item.trxAmountValue).length > 12 }">
+                                                :class="{'balance-direction': item.trxAmountCurrencyInfo.tokenSymbol.length + ('' + item.trxAmountValue).length > 12}">
                                                 <span class="amount">
-                                                    <a-tooltip :title="'-' + item.trxAmountValue">
+                                                    <a-tooltip :title="'-'+item.trxAmountValue">
                                                         -{{ getBit(item.trxAmountValue) || 0 }}
                                                     </a-tooltip>
                                                 </span>
@@ -218,8 +242,7 @@
                                         :class="{ 'balance-direction': item.trxAmountCurrencyInfo.tokenSymbol.length + ('' + item.trxAmountValue).length > 12 }">
 
                                         <!--支出—— -2:零钱余额支付 、-3: NFT盲盒余额支付 -->
-                                        <span class="amount"
-                                            v-if="item.bizType == -2 || item.bizType == -3 || item.bizType == -4 || item.bizType == -5">
+                                        <span class="amount" v-if="item.bizType == -2 || item.bizType == -3 || item.bizType == -4 || item.bizType == -5 || item.bizType == -6">
                                             <a-tooltip :title="'-' + item.trxAmountValue">
                                                 -{{ getBit(item.trxAmountValue) || 0 }}
                                             </a-tooltip>

+ 11 - 3
src/view/iframe/publish/components/follow-input.vue

@@ -1,14 +1,16 @@
 <template>
 <!-- 发布器-@关注人 输入组件 -->
     <div class="follow-input-wrapper">
-        <div class="at-user-item" v-for="(item, index) in pageAtUserList" :key="index">
+        <div class="at-user-item" :style="{'padding': padding}" v-for="(item, index) in pageAtUserList" :key="index">
             <img :src="require('@/assets/svg/icon-del-follows-user.svg')" 
                 class="icon-del"
+                v-if="!isRequire || isRequire && index > 0"
                 @click="delUser(item, index)">
             <pre :id='"pre" + index' class="at-user-input-placeholder">{{item.name}}</pre>
             @<input class="at-user-input" 
                     :id='"input" + index' 
                     v-model="item.name" 
+                    :readonly="index == 0 && isRequire"
                     @change="onIptChange(item, index)"
                     @input="onInput(item, index)"
                     @keydown="onKeydown(item, index)"
@@ -72,6 +74,13 @@ const props = defineProps({
     isAddSelf: {
         type: Boolean,
         default: true
+    },
+    isRequire: {
+        type: Boolean,
+        default: false
+    },
+    padding: {
+        type: String,
     }
 })
 
@@ -273,7 +282,6 @@ const onUserMouseLeave = (params, index) => {
             color: #1D9BF0;
             font-weight: 500;
             font-size: 15px;
-            padding: 4px 12px;
             position: relative;
             margin-right: 10px;
             background-color: #fff;
@@ -308,7 +316,7 @@ const onUserMouseLeave = (params, index) => {
                 overflow-y: auto;
                 background-color: #fff; 
                 top: 30px;
-                left: -150px;
+                left: 0px;
                 z-index: 1000;
                 border-radius: 10px;
 

+ 61 - 0
src/view/iframe/publish/components/form-input.vue

@@ -0,0 +1,61 @@
+<template>
+    <div class="form-input-wrapper">
+        <div class="prefix" v-if="prefix">
+            {{prefix}}
+        </div>
+        <slot name="content"></slot>
+        <component-zoom width="50" fontSize="14" :txt="suffix" v-if="suffix">
+            <div class="suffix">
+                {{suffix}}
+            </div>
+        </component-zoom>
+    </div>
+</template>
+
+<script setup>
+import { onMounted, ref, defineProps, defineEmits } from "vue";
+import ComponentZoom from '@/view/components/component-zoom.vue'
+
+const props = defineProps({
+    prefix: {
+        type: String,
+        default: '',
+    },
+    suffix: {
+        type: String,
+        default: '',
+    },
+});
+const emits = defineEmits(["close", "confirm", "postPublishFinish"]);
+
+onMounted(() => {
+}) 
+</script>
+
+<style scoped lang="scss">
+.form-input-wrapper {
+    width: max-content;
+    height: 38px;
+    border: 1px solid #D9D9D9;
+    border-radius: 5px;
+    padding: 0 10px;
+    box-sizing: border-box;
+    display: flex;
+    align-items: center;
+    color: #999999;
+    font-weight: 500;
+    font-size: 12px;
+
+    .prefix {
+        margin-right: 4px;
+    }
+
+    .suffix {
+        margin-left: 4px;
+        white-space: nowrap;
+        color: #999999;
+        font-weight: 500;
+        font-size: 12px;
+    }
+}
+</style>

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

@@ -33,6 +33,7 @@
                             },
                             rewardType: baseFormData.rewardType,
                             customizedReward: baseFormData.customizedReward,
+                            upGainAmountUsdValue: upGainAmountUsdValue
                         }"></custom-card-cover>
                     </div>
                 </div>
@@ -68,6 +69,7 @@
                             type: baseFormData.type,
                             validityDuration: baseFormData.validityDuration,
                             customPosterUrl: customPosterInfo && customPosterInfo.before && customPosterInfo.before.imagePath || '',
+                            addFans: baseFormData.addFans,
                             userInfo: {
                                 nickName: userInfo.name,
                                 avatarUrl: userInfo.avatarUrl
@@ -134,6 +136,10 @@ defineProps({
             }
         }
     },
+    upGainAmountUsdValue: {
+        type: String,
+        default: ''
+    }
 })
 
 const getUserInfo = (cb) => {

+ 8 - 2
src/view/iframe/publish/components/preview-sheet.vue

@@ -23,7 +23,8 @@
                     :postData="publishRes"
                     :baseFormData="baseFormData" 
                     :amountFontSize="previewFontSize" 
-                    :customPosterInfo="customPosterData">
+                    :customPosterInfo="customPosterData"
+                    :upGainAmountUsdValue="upGainAmountUsdValue">
                 </preview-card>
             </div>
         </div>
@@ -118,7 +119,8 @@ const props = defineProps({
                 validityDuration: "",
                 type: selectModeInfo.type,
                 rewardType: RewardType.money,
-                customizedReward: ""
+                customizedReward: "",
+                addFans: ''
             }
         },
     },
@@ -160,6 +162,10 @@ const props = defineProps({
                 requestAmountValue: 0,
             }
         }
+    },
+    upGainAmountUsdValue: {
+        type: String, 
+        default: ''
     }
 });
 

文件差异内容过多而无法显示
+ 523 - 205
src/view/iframe/publish/give-dialog.vue


+ 3 - 1
src/view/iframe/publish/publish.vue

@@ -26,7 +26,9 @@ let selectVisible = ref(false);
 
 const close = () => {
     dialogData.visible = false;
-    hideIframe();
+    setTimeout(() => {
+        hideIframe();
+    }, 500)
 };
 
 const finish = (params) => {

+ 1 - 2
src/view/iframe/publish/tool-box/child/preview.vue

@@ -205,8 +205,7 @@ const publishHandler = () => {
     if (loadingHide) {
         return;
     }
-    if ((!appId || appId && !props.previewData.linkImagePath) &&
-        (!props.screenshotWebsiteData.url && !props.screenshotWebsiteData.status)) {
+    if ((!appId || appId && !props.previewData.linkImagePath) && (!props.screenshotWebsiteData.url && !props.screenshotWebsiteData.status)) {
         loadingHide = message.loading('loading...', 0);
         return;
     }

+ 6 - 3
src/view/iframe/red-packet/luck-draw.vue

@@ -1085,7 +1085,8 @@ const reportBindTweetSuccess = (params) => {
                         objectType: Report.objectType.tweetPostBinded,
                         twitterFans: reportParams.twitterFans,
                         discordFans: reportParams.discordFans,
-                        redPacketType: 1
+                        redPacketType: 1,
+                        postId: state.postId
                     });
                 }
             }
@@ -2016,7 +2017,8 @@ function onRuntimeMsg() {
                         Report.reportLog({
                             objectType: Report.objectType.tweetPostBinded,
                             twitterFans: reportParams.twitterFans,
-                            redPacketType: 1
+                            redPacketType: 1,
+                            postId: state.postId
                         });
                     } else {
                         if (reportParams.discordFans !== '') {
@@ -2026,7 +2028,8 @@ function onRuntimeMsg() {
                                 objectType: Report.objectType.tweetPostBinded,
                                 twitterFans: reportParams.twitterFans,
                                 discordFans: reportParams.discordFans,
-                                redPacketType: 1
+                                redPacketType: 1,
+                                postId: state.postId
                             });
                         }
                     }

+ 6 - 3
src/view/iframe/red-packet/red-packet.vue

@@ -968,7 +968,8 @@ const reportBindTweetSuccess = (params) => {
             objectType: Report.objectType.tweetPostBinded,
             twitterFans: reportParams.twitterFans,
             discordFans: reportParams.discordFans,
-            redPacketType: 0
+            redPacketType: 0,
+            postId: state.postId
           });
         }
       }
@@ -1811,7 +1812,8 @@ function onRuntimeMsg() {
             Report.reportLog({
               objectType: Report.objectType.tweetPostBinded,
               twitterFans: reportParams.twitterFans,
-              redPacketType: 0
+              redPacketType: 0,
+              postId: state.postId
             });
           } else {
             if (reportParams.discordFans !== '') {
@@ -1821,7 +1823,8 @@ function onRuntimeMsg() {
                 objectType: Report.objectType.tweetPostBinded,
                 twitterFans: reportParams.twitterFans,
                 discordFans: reportParams.discordFans,
-                redPacketType: 0
+                redPacketType: 0,
+                postId: state.postId
               });
             }
           }

+ 3 - 26
src/view/iframe/test/index.vue

@@ -1,31 +1,8 @@
 <template>
-    <!-- <div class="denet-toolbox" @click.stop="clickHead">
-        
-    </div> -->
-    <input type="button" value="点击" @click="state.show = !state.show">
-    <p v-if="state.show" :data-view="1" :data-click="'按钮'" @click.stop="clickTest">1</p>
-    <p v-else :data-view="2">2</p>
-
+    <treasure-hunt></treasure-hunt>
 </template>
 <script setup>
-import { onMounted, reactive } from "vue";
-
-let state = reactive({
-    show: false
-})
-onMounted(() => {
-    var io = new IntersectionObserver((e) => {
-        console.log(e[0].target)
-    });
-    io.observe(document.querySelector('p[data-view]'))
-
-})
-
-function clickTest() {
-    console.log('clickTest')
-}
-
+import TreasureHunt from '@/view/iframe/treasure-hunt/index.vue'
 </script>
-
-<style lang="scss">
+<style lang="scss" scoped>
 </style>

+ 3 - 3
src/view/iframe/tool-box/card.vue

@@ -204,9 +204,9 @@ const getDetail = () => {
             }
             console.log('postBizData', state.detail)
             // 加载iframe
-            // if (state.detail.viewBgImagePath) {
-            //     state.cover_url = state.detail.viewBgImagePath
-            // }
+            if (state.detail.viewBgImagePath) {
+                state.cover_url = state.detail.viewBgImagePath
+            }
             state.iframe_url = state.detail.convertUrl
             state.show_btn = true
             state.status = 'iframe'

+ 96 - 0
src/view/iframe/treasure-hunt/components/btn.vue

@@ -0,0 +1,96 @@
+<template>
+    <div class="btn-submit" @click="clickBtn" :class="{ 'no': loading, 'disabled': disabled }">
+        <img :src="require('@/assets/svg/icon-iframe-loading.svg')" alt="" class="loading" v-if="loading && icon" />
+        <img :src="require('@/assets/svg/icon-btn-box.svg')" alt="" v-if="!loading && icon" />
+        <span :style="{ 'font-size': fontSize, 'color': txtCorlor }">{{ txt }}</span>
+    </div>
+</template>
+<script setup>
+import { defineProps, defineEmits } from 'vue'
+defineProps({
+    txt: {
+        type: String,
+        default: ''
+    },
+    loading: {
+        type: Boolean,
+        default: false
+    },
+    fontSize: {
+        type: String,
+        default: '20px'
+    },
+    icon: {
+        type: Boolean,
+        default: true
+    },
+    disabled: {
+        type: Boolean,
+        default: false
+    },
+    txtCorlor: {
+        type: String
+    }
+})
+const emit = defineEmits(['on-click'])
+const clickBtn = () => {
+    emit('on-click')
+}
+</script>
+<style scoped lang="scss">
+.btn-submit {
+    background: #1D9BF0;
+    border-radius: 100px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 53px;
+    width: 343px;
+    margin: 0 auto;
+    cursor: pointer;
+    user-select: none;
+
+    span {
+        font-weight: 800;
+        color: #FFFFFF;
+        font-size: 20px;
+        line-height: 24px;
+        margin-left: 6px;
+
+    }
+
+    img {
+        width: 20px;
+        height: 20px;
+    }
+
+
+
+    .loading {
+        animation: loading 1s infinite linear;
+    }
+}
+
+.no {
+    cursor: no-drop;
+}
+
+.disabled {
+    cursor: no-drop;
+    background: #F1F1F1;
+
+    span {
+        color: #AFAFAF;
+    }
+}
+
+@keyframes loading {
+    from {
+        transform: rotate(0deg);
+    }
+
+    to {
+        transform: rotate(360deg);
+    }
+}
+</style>

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

@@ -0,0 +1,74 @@
+<template>
+    <div class="content" v-show="">
+        <div class="background"></div>
+        <!-- 开奖页 -->
+        <div class="dialog">
+            <div class="txt">{{ txt }}</div>
+            <div class="btn" @click="clickBtn">OK</div>
+        </div>
+    </div>
+</template>
+<script setup>
+import { inject, defineProps, defineEmits } from 'vue'
+
+let state = inject('state')
+defineProps({
+    txt: {
+        type: String,
+        default: 'All treasures are hunted, good luck next time!'
+    }
+})
+const clickBtn = () => {
+
+}
+</script>
+<style lang="scss" scoped>
+.content {
+    width: 375px;
+    height: 500px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: fixed;
+    top: 0;
+    left: 0;
+    z-index: 999;
+
+    .background {
+        background: #000000;
+        opacity: .9;
+        position: fixed;
+        width: 375px;
+        height: 500px;
+    }
+
+    .dialog {
+        z-index: 1;
+        width: 335px;
+        background: #FFFFFF;
+        border-radius: 15px;
+
+        .txt {
+            color: #000000;
+            font-weight: 500;
+            font-size: 16px;
+            padding: 27px 30px 16px 30px;
+            text-align: center;
+
+        }
+
+        .btn {
+            cursor: pointer;
+            border-top: 1px solid #EEEEEE;
+            width: 100%;
+            height: 52px;
+            color: #1D9BF0;
+            font-weight: 500;
+            font-size: 17px;
+            line-height: 52px;
+            text-align: center;
+
+        }
+    }
+}
+</style>

+ 72 - 0
src/view/iframe/treasure-hunt/components/head.vue

@@ -0,0 +1,72 @@
+<template>
+    <div class="head">
+        <div class="left" v-if="leftData">
+            <img :src="leftData.avatarUrl" alt="" />
+            <span>from</span>
+            <span>{{ leftData.nickName || '' }}</span>
+        </div>
+        <div class="right" v-if="rightData">
+            <span>
+                Remaining
+            </span>
+            <span>{{ rightData }}</span>
+        </div>
+
+    </div>
+</template>
+<script setup>
+import { defineProps } from 'vue'
+defineProps({
+    leftData: {
+        type: Object,
+        default: null
+    },
+    rightData: {
+        type: String,
+        default: ''
+    }
+})
+</script>
+<style lang="scss" scoped>
+.head {
+    padding: 10px;
+    display: flex;
+    justify-content: space-between;
+
+    .left {
+        display: flex;
+        align-items: center;
+
+        img {
+            width: 16px;
+            height: 16px;
+            border-radius: 100px;
+        }
+
+        span {
+            color: #B69882;
+            font-weight: 400;
+            margin-left: 5px;
+            font-size: 11px;
+            flex-grow: 0;
+        }
+    }
+
+    .right {
+        span {
+            font-weight: 400;
+            font-size: 11px;
+            line-height: 15px;
+        }
+
+        span:first-child {
+            color: #FFFFFF;
+            opacity: 0.7;
+        }
+
+        span:last-child {
+            color: #FFD23B;
+        }
+    }
+}
+</style>

+ 57 - 0
src/view/iframe/treasure-hunt/components/hover-tip.vue

@@ -0,0 +1,57 @@
+<template>
+    <div class="hover-tip">
+        <img :src="icon" alt="" />
+        <span>{{ txt }}</span>
+        <img :src="require('@/assets/svg/icon-tip-arrow.svg')" alt="" class="arrow" />
+    </div>
+</template>
+<script setup>
+import { defineProps } from 'vue'
+defineProps({
+    txt: {
+        type: String,
+        default: ''
+    },
+    icon: {
+        type: String,
+        default: require('@/assets/svg/icon-green-yes.svg')
+    }
+})
+</script>
+<style lang="scss">
+.hover-tip {
+    width: fit-content;
+    height: 20px;
+    line-height: 20px;
+    padding: 0 7px;
+    background: rgba(0, 0, 0, 0.6);
+    border-radius: 3px;
+    display: flex;
+    align-items: center;
+    position: relative;
+    margin-bottom: 5px;
+    position: absolute;
+    top: -20px;
+
+    img {
+        width: 12px;
+        height: 12px;
+    }
+
+    span {
+        margin-left: 4px;
+        font-weight: 500;
+        font-size: 12px;
+        color: #FFFFFF;
+    }
+
+    .arrow {
+        position: absolute;
+        width: 9px;
+        height: 5px;
+        bottom: -5px;
+        left: 50%;
+        margin-left: -4.5px;
+    }
+}
+</style>

+ 160 - 0
src/view/iframe/treasure-hunt/components/invite-friends.vue

@@ -0,0 +1,160 @@
+<template>
+    <div class="invite-friends">
+        <div class="txt">To open the treasure chest you need to share the URL to your friends. Make sure they finish
+            the
+            tasks.</div>
+        <div class="area-url">
+            <div class="url">{{ state.detail.inviteUrl }}</div>
+            <div class="btn copy-btn" @click="clickCopy" :data-clipboard-text="state.detail.inviteCopyUrl">
+                Copy
+            </div>
+        </div>
+        <div class="share-list">
+            <img :src="item.iconPath" alt="" v-for="item in state.share_list" @click="clickShare(item)" />
+        </div>
+        <v-btn :txt="state.open_btn.txt" :font-size="'17px'" class="btn" :icon="false"
+            :disabled="state.open_btn.disabled" @onClick="clickBtn"></v-btn>
+        <v-toast :show="state.toast.show" :txt="state.toast.txt"></v-toast>
+        <open-box v-if="state.open_box.show"></open-box>
+    </div>
+</template>
+<script setup>
+import VBtn from '@/view/iframe/treasure-hunt/components/btn.vue'
+import VToast from '@/view/iframe/treasure-hunt/components/toast.vue'
+import OpenBox from '@/view/iframe/treasure-hunt/components/dialog.vue'
+import { inviteChannel } from '@/http/treasure'
+import { treasureOpen } from '@/http/treasure'
+import { inject, onMounted } from 'vue'
+let ClipboardJS = require('clipboard');
+let state = inject('state')
+state.toast = {}
+
+onMounted(() => {
+    inviteChannel({
+        params: {
+            postId: state.postId
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            state.share_list = res.data
+        }
+    })
+})
+
+const clickBtn = () => {
+    treasureOpen({
+        params: {
+            postId: state.postId,
+            treasureId: state.treasureId,
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            state.open_box.show = true
+            state.open_box = res.data
+        }
+    })
+}
+
+const clickShare = (item) => {
+    window.open(item.redirectPath)
+}
+var clipboard = new ClipboardJS('.copy-btn');
+
+const clickCopy = () => {
+    clipboard.on('success', function (e) {
+        state.toast.txt = 'Copy Successfully'
+        state.toast.show = true
+        setTimeout(() => {
+            state.toast.show = false
+        }, 2000)
+        e.clearSelection();
+    });
+
+    clipboard.on('error', function (e) {
+        state.toast.txt = 'Copy Error'
+        state.toast.show = true
+        setTimeout(() => {
+            state.toast.show = false
+        }, 2000)
+    });
+
+}
+</script>
+<style lang="scss" scoped>
+.invite-friends {
+    padding: 18px 16px 25px 16px;
+    background: #fff;
+
+    .txt {
+        font-style: normal;
+        font-weight: 500;
+        font-size: 14px;
+        line-height: 18px;
+        /* or 129% */
+
+        letter-spacing: 0.3px;
+
+        color: #000000;
+    }
+
+    .area-url {
+        height: 70px;
+        background: rgba(29, 155, 240, 0.01);
+        border: 1px solid #1D9BF0;
+        border-radius: 5px;
+        display: flex;
+        align-items: center;
+        padding-left: 15px;
+        padding-right: 11px;
+        justify-content: space-between;
+
+        .url {
+            display: -webkit-box;
+            -webkit-box-orient: vertical;
+            -webkit-line-clamp: 3;
+            overflow: hidden;
+            width: 194px;
+
+            color: #737373;
+            font-weight: 400;
+            font-size: 13px;
+            white-space: normal;
+
+            word-wrap: break-word;
+
+            word-break: break-all;
+        }
+
+        .btn {
+            user-select: none;
+            background: #1D9BF0;
+            border-radius: 35px;
+            width: 100px;
+            text-align: center;
+            line-height: 37px;
+            height: 37px;
+            font-weight: 700;
+            font-size: 15px;
+            color: #fff;
+            cursor: pointer;
+        }
+    }
+
+    .share-list {
+        margin-top: 20px;
+        text-align: center;
+        margin-bottom: 14px;
+
+        img {
+            user-select: none;
+            cursor: pointer;
+            width: 33px;
+            height: 33px;
+            margin-right: 14px;
+            border-radius: 100px;
+        }
+    }
+
+
+}
+</style>

+ 159 - 0
src/view/iframe/treasure-hunt/components/invite-list.vue

@@ -0,0 +1,159 @@
+<template>
+    <div class="content">
+        <div class="error" v-if="state.invited_list.length == 0">
+            Invite people to hunt treasure with you!
+        </div>
+        <div class="list" v-else>
+            <div class="item" v-for="item in state.invited_list">
+                <div class="left">
+                    <img :src="require('@/assets/svg/icon-btn-box.svg')" alt="" />
+                </div>
+                <div class="right">
+                    <div>{{ item.userInfo.nickName }}</div>
+                    <div>{{ getTime(item.timestamp) }}</div>
+                </div>
+            </div>
+        </div>
+        <div class="footer">
+            <v-btn :txt="state.open_btn.txt" :font-size="'17px'" class="btn" :icon="false"
+                :disabled="state.open_btn.disabled" @onClick="clickBtn"></v-btn>
+        </div>
+    </div>
+</template>
+<script setup>
+import VBtn from '@/view/iframe/treasure-hunt/components/btn.vue'
+import { inviteList } from '@/http/treasure'
+import { inject, onMounted } from 'vue'
+import { treasureOpen } from '@/http/treasure'
+
+var moment = require('moment')
+let state = inject('state')
+state.invited_list = [
+]
+
+onMounted(() => {
+    inviteList({
+        params: {
+            postId: state.postId,
+            pageNum: 1,
+            pageSize: 10,
+        }
+
+    }).then((res) => {
+        if (res.code == 0) {
+            state.invited_list = res.data
+        }
+    })
+
+    // btnStatus()
+})
+
+
+const getTime = (timestamp) => {
+    let _d1 = moment(new Date().getTime())
+    let _d2 = moment(timestamp)
+    const plural = (n, s) => {
+        let _str = `${n} ${s} ago`
+        if (n > 1) {
+            _str = `${n} ${s}s ago`
+        }
+        return _str
+    }
+    let _d = moment.duration(_d1.diff(_d2)).days()
+    if (_d) {
+        return plural(_d, 'day')
+    }
+    let _h = moment.duration(_d1.diff(_d2)).hours()
+    if (_h) {
+        return plural(_h, 'hour')
+    }
+    let _m = moment.duration(_d1.diff(_d2)).minutes()
+    if (_m) {
+        return plural(_m, 'min')
+    }
+    let _s = moment.duration(_d1.diff(_d2)).seconds()
+    return plural(_s, 'sec')
+}
+
+const clickBtn = () => {
+    treasureOpen({
+        params: {
+            postId: state.postId,
+            treasureId: state.treasureId,
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            state.open_box.show = true
+            state.open_box = res.data
+        }
+    })
+}
+
+</script>
+<style lang="scss" scoped>
+.content {
+    position: relative;
+    height: 292px;
+
+    .footer {
+        background: #fff;
+        padding: 10px 16px 25px 16px;
+    }
+
+    .error {
+        height: 204px;
+        color: #BABABA;
+        background-color: #fff;
+        font-weight: 500;
+        font-size: 15px;
+        line-height: 204px;
+        text-align: center;
+
+    }
+
+    .list {
+        height: 204px;
+        overflow-y: auto;
+
+        .item {
+            height: 60px;
+            display: flex;
+            align-items: center;
+
+            .left {
+                width: 58px;
+                text-align: center;
+
+                img {
+                    width: 30px;
+                    height: 30px;
+                }
+            }
+
+            .right {
+                flex: 1;
+                border-bottom: 1px solid #D9D9D9;
+                display: flex;
+                align-items: center;
+                height: 100%;
+                justify-content: space-between;
+
+                div:nth-child(1) {
+                    color: #000000;
+                    font-weight: 500;
+                    font-size: 15px;
+
+                }
+
+                div:nth-child(2) {
+                    color: #A6A6A6;
+                    font-weight: 400;
+                    font-size: 12px;
+                    margin-right: 17px;
+
+                }
+            }
+        }
+    }
+}
+</style>

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

@@ -0,0 +1,114 @@
+<template>
+    <div>
+        <div class="background"></div>
+        <!-- 开奖页 -->
+        <div class="content">
+
+            <img :src="require('@/assets/img/icon-silver-open-box.png')" alt="" />
+            <div class="mark">
+                <p>You Win</p>
+                <div class="money">{{ state.open_box.usdAmountValue }}</div>
+                <div class="mark2">
+                    <img :src="state.open_box.currencyIcon" alt="" />
+                    <div>{{ state.open_box.amountValue }} {{ state.open_box.currencySymbol }} stored in your DeNet
+                        account
+                    </div>
+                </div>
+
+            </div>
+            <v-btn :txt="'OK'" :font-size="'16px'" class="btn" :icon="false" @onClick="clickBtn"></v-btn>
+        </div>
+    </div>
+</template>
+<script setup>
+import { inject } from 'vue'
+import VBtn from '@/view/iframe/treasure-hunt/components/btn.vue'
+let state = inject('state')
+
+const clickBtn = () => {
+    state.open_box.show = false
+}
+</script>
+<style lang="scss" scoped>
+.background {
+    background: #000000;
+    opacity: .9;
+    position: fixed;
+    width: 100%;
+    height: 100%;
+    z-index: 1;
+}
+
+.content {
+    z-index: 2;
+    width: 375px;
+    height: 500px;
+    text-align: center;
+    position: relative;
+
+
+
+    img {
+        margin-top: 15px;
+    }
+
+    .mark {
+        position: absolute;
+        top: 246px;
+        width: 375px;
+
+        p {
+            margin: 0;
+            padding: 0;
+            text-align: center;
+
+        }
+
+
+        p:nth-child(1) {
+            margin-bottom: 10px;
+            color: #FFFFFF;
+            font-weight: 800;
+            font-size: 18px;
+        }
+
+        .txt {
+            color: #FFC83A;
+            font-weight: 800;
+            font-size: 24px;
+
+        }
+
+        .money {
+            color: #FFC83A;
+            font-weight: 800;
+            font-size: 34px;
+        }
+
+        .mark2 {
+            margin-top: 10px;
+            display: flex;
+            justify-content: center;
+
+            img {
+                width: 17px;
+                height: 17px;
+                margin: 0;
+            }
+
+            div {
+                color: #A9A49F;
+                font-weight: 400;
+                font-size: 12px;
+
+            }
+        }
+    }
+
+    .btn {
+        position: absolute;
+        bottom: 25px;
+        left: 15px;
+    }
+}
+</style>

+ 80 - 0
src/view/iframe/treasure-hunt/components/toast.vue

@@ -0,0 +1,80 @@
+<template>
+    <div class="content" v-show="show">
+        <div class="mark">
+            <div class="background"></div>
+            <img :src="icon" alt="">
+            <span>{{ txt }}</span>
+        </div>
+    </div>
+</template>
+<script setup>
+import { defineProps, watch, reactive } from "vue";
+
+let props = defineProps({
+    txt: {
+        type: String,
+        default: ''
+    },
+
+    icon: {
+        type: String,
+        default: require('@/assets/svg/icon-while-yes.svg')
+    },
+    show: {
+        type: Boolean,
+        default: false
+    },
+})
+
+
+</script>
+<style lang="scss" scoped>
+.content {
+    position: fixed;
+    width: 375px;
+    height: 500px;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    top: 0;
+
+    .mark {
+        height: 39px;
+        top: 50%;
+        width: fit-content;
+        color: #FFFFFF;
+        border-radius: 44px;
+        overflow: hidden;
+        position: relative;
+
+        display: flex;
+        align-items: center;
+        padding: 0 13px;
+
+        img {
+            z-index: 2;
+            width: 15px;
+            height: 15px;
+            margin-right: 6px;
+        }
+
+        span {
+            z-index: 2;
+            font-weight: 600;
+            font-size: 14px;
+            color: #fff;
+        }
+
+        .background {
+            z-index: 1;
+            width: 100%;
+            left: 0;
+            top: 0;
+            height: 100%;
+            position: absolute;
+            background: rgba(0, 0, 0, 0.8);
+        }
+    }
+
+}
+</style>

+ 285 - 0
src/view/iframe/treasure-hunt/cover.vue

@@ -0,0 +1,285 @@
+<template>
+    <!-- 封面页 -->
+    <div class="cover">
+        <v-head :left-data="state.detail.postUserInfo || null"></v-head>
+        <div class="waring" v-if="state.cover_status == '奖励已被领光'">
+            <div>All treasures</div>
+            <div>are hunted</div>
+        </div>
+        <!-- 邀请人 -->
+        <template v-else>
+            <div class="invite" v-if="state.detail.inviteUserInfo">
+                <img :src="state.detail.inviteUserInfo.avatarUrl" alt="" />
+                <span>{{ state.detail.inviteUserInfo.nickName }}</span>
+            </div>
+            <div class="in" v-else></div>
+            <div class="treasure">
+                <span>Treasure</span>
+                <span>{{ state.detail.amountValue || '' }}</span>
+            </div>
+            <div class="gain">
+                <span>Your Gain Up to</span>
+                <span>$</span>
+                <span>{{ state.detail.remainAmountValue }}</span>
+            </div>
+            <div class="coin">
+                <img :src="require('@/assets/svg/icon-warning.svg')" alt="" />
+                <span>{{ state.detail.amountCurrencyCode }}</span>
+            </div>
+        </template>
+
+        <div class="box">
+            <img :src="require('@/assets/img/icon-gold-close-box.png')" alt="" v-if="state.cover_status == '奖励已被领光'" />
+            <img :src="require('@/assets/img/icon-treasure-box.png')" alt="" v-else />
+        </div>
+        <div class="mark">
+            <img :src="require('@/assets/svg/icon-three-line.svg')" alt="" />
+            <span>to Hunt Treasure</span>
+        </div>
+        <v-btn :txt="state.open_btn.txt" :font-size="'17px'" class="btn" :icon="true"
+            :disabled="state.open_btn.disabled" @onClick="clickBtn" :loading="state.btn_loading"></v-btn>
+    </div>
+
+</template>
+<script setup>
+import { inject } from 'vue'
+import VBtn from '@/view/iframe/treasure-hunt/components/btn.vue'
+import VHead from '@/view/iframe/treasure-hunt/components/head.vue'
+
+import { prepareStart, treasureStart } from '@/http/treasure.js'
+
+chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
+    switch (req.actionType) {
+        case 'DO_TASK':
+            if (!req.task_type || state.tweetId != req.tweet_Id || !req.task_done) {
+                return
+            }
+            if (req.task_type == 'createTweet') {
+                treasureStart({
+                    params: {
+                        postId: state.postId || '',
+                        inviteCode: state.invite_code || ''
+                    }
+                }).then((res) => {
+                    if (res.code == 0) {
+                        state.page = '开奖页'
+                        state.start_task = res.data
+                        state.btn_loading = false
+                    }
+                })
+            }
+            break
+    }
+})
+
+let state = inject('state')
+state.btn_loading = false
+
+const clickBtn = () => {
+    if (state.cover_status == '奖励已被领光') {
+        window.open('https://twitter.com/search?q=%23denet')
+        return
+    }
+
+    state.btn_loading = true
+    setTimeout(() => {
+        if (state.btn_loading == true) {
+            state.btn_loading = false
+        }
+    }, 10000)
+
+    // four_task
+    // 获取文章
+    prepareStart({
+        params: {
+            postId: state.postId || '',
+            inviteCode: state.invite_code || ''
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            let text = res.data.rePostTweetContent
+            // 发送推文
+            chrome.tabs.getCurrent((tab) => {
+                chrome.tabs.sendMessage(tab.id, {
+                    actionType: "IFRAME_TWITTER_API_DO_TASK",
+                    task_data: {
+                        tweet_Id: state.tweetId,
+                        tweet_text: text
+                    },
+                    task_type: 'tasks',
+                    tasks: JSON.parse(state.detail.startCondition),
+                }, (res) => { console.log(res) });
+            })
+        } else {
+            console.log(res)
+        }
+    })
+}
+</script>
+<style lang="scss" scoped>
+.cover {
+    width: 375px;
+    height: 500px;
+    background: linear-gradient(179.96deg, #25180D 38.82%, #5E4025 55.4%, #876635 61.6%, #24180C 71.59%);
+    border-radius: 20px;
+
+    .head {
+        padding: 10px;
+        display: flex;
+        align-items: center;
+
+        img {
+            width: 16px;
+            height: 16px;
+            border-radius: 100px;
+        }
+
+        span {
+            color: #B69882;
+            font-weight: 400;
+            margin-left: 5px;
+            font-size: 11px;
+            flex-grow: 0;
+        }
+    }
+
+    .waring {
+        margin-top: 54px;
+        font-weight: 900;
+        font-size: 34px;
+        color: #FFFFFF;
+        text-align: center;
+        opacity: 0.7;
+        margin-bottom: 35px;
+    }
+
+    .in {
+        height: 58px;
+    }
+
+    .invite {
+        background: rgba(255, 255, 255, 0.1);
+        height: 28px;
+        display: flex;
+        align-items: center;
+        margin: 0 auto;
+        margin-top: 20px;
+        margin-bottom: 10px;
+        border-radius: 100px;
+        width: fit-content;
+        padding-right: 11px;
+
+
+        img {
+            width: 18px;
+            height: 18px;
+            border-radius: 100px;
+            margin-left: 11px;
+            margin-right: 6px;
+        }
+
+        span {
+            color: #BE9F89;
+        }
+    }
+
+    .treasure {
+        text-align: center;
+
+        span {
+            font-size: 34px;
+            font-weight: 900;
+            line-height: 40px;
+        }
+
+        span:first-child {
+            color: #FFC83A;
+            margin-right: 10px;
+        }
+
+        span:last-child {
+            color: #FFFFFF;
+        }
+    }
+
+    .gain {
+        width: 100%;
+        background: #332319;
+        height: 37px;
+        margin-top: 10px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        span {
+            color: #fff;
+            font-weight: 500;
+            font-size: 16px;
+            line-height: 16px;
+
+        }
+
+        span:first-child {
+            font-size: 15px;
+            line-height: 15px;
+            margin-right: 10px;
+        }
+
+        span:last-child {
+            margin-left: 2px;
+            font-weight: 800;
+            font-size: 24px;
+            line-height: 24px;
+        }
+    }
+
+    .coin {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-top: 10px;
+
+        img {
+            width: 17px;
+            height: 17px;
+        }
+
+        span {
+            margin-left: 4px;
+            font-weight: 400;
+            font-size: 11px;
+            line-height: 15px;
+            color: #FFFFFF;
+
+            opacity: 0.7;
+        }
+    }
+
+    .box {
+        text-align: center;
+
+        img {
+            width: 160px;
+            height: 160px;
+        }
+
+    }
+
+    .mark {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-top: 24px;
+        margin-bottom: 15px;
+
+        span {
+            font-weight: 500;
+            font-size: 12px;
+            line-height: 17px;
+            color: #65C1FF;
+
+        }
+    }
+
+}
+</style>

+ 126 - 0
src/view/iframe/treasure-hunt/index.vue

@@ -0,0 +1,126 @@
+<template>
+    <v-cover v-if="state.page == '封面页'"></v-cover>
+    <v-invite v-if="state.page == '邀请页'"></v-invite>
+    <v-result v-if="state.page == '开奖页'"></v-result>
+</template>
+<script setup>
+import { reactive, provide, onMounted } from 'vue'
+import VCover from '@/view/iframe/treasure-hunt/cover.vue'
+import VInvite from '@/view/iframe/treasure-hunt/invite.vue'
+import VResult from '@/view/iframe/treasure-hunt/result.vue'
+import { inviteDetail, treasureDetail } from '@/http/treasure.js'
+import { reSetBindTwtterId } from '@/http/help.js'
+import { getQueryString } from '@/uilts/help'
+
+let state = reactive({
+    page: '',
+    detail: {},
+    open_box: {
+        show: false
+    },
+    open_btn: {
+        txt: '',
+        disabled: false
+    },
+    start_task: {}
+})
+provide('state', state)
+
+onMounted(() => {
+    let params = JSON.parse(getQueryString('params') || '{}')
+    state.postId = params.post_Id || ''
+    state.tweetId = params.tweet_Id || ''
+    state.invite_code = params.invite_code || ''
+
+    if (params.page_type == '邀请链接') {
+        // 邀请链接
+        inviteDetail({
+            params: {
+                inviteCode: params.invite_code
+            }
+
+        }).then((res) => {
+            if (res.code == 0) {
+                state.detail = res.data
+                handleStatus()
+                if (!res.data.srcContentId) {
+                    reSetBindTwtterId({
+                        postId: state.postId || '',
+                        tweetId: state.tweetId || ''
+                    })
+                }
+            }
+        })
+
+    } else if (params.page_type == '原始链接') {
+        // 原始链接
+        treasureDetail({
+            params: {
+                postId: params.post_Id
+            }
+        }).then((res) => {
+            if (res.code == 0) {
+                state.detail = res.data
+                handleStatus()
+
+                if (!res.data.srcContentId) {
+                    reSetBindTwtterId({
+                        postId: state.postId || '',
+                        tweetId: state.tweetId || ''
+                    })
+                }
+            }
+        })
+    }
+
+})
+
+const handleStatus = () => {
+    // 如果 夺宝状态 = 未开始
+    //   显示未开始页面
+    // 如果 夺宝状态 = 进行中
+    //   如果 夺宝参与状态 = 未参与夺宝
+    //      显示封面页
+    //   如果 夺宝参与状态 = 已参与夺宝
+    //      显示邀请页
+    // 如果 夺宝状态 = 已结束
+    //  显示结束页面
+
+    let { status, joinStatus } = state.detail || {}
+    state.open_btn.txt = 'Start'
+    // 如果 夺宝状态 = 未开始
+    if (status == 0) {
+        state.page = '封面页'
+
+    }
+    // 如果 夺宝状态 = 进行中
+    else if (status == 1) {
+        // 如果 夺宝参与状态 = 未参与夺宝
+        if (joinStatus == 0) {
+            // 显示封面页
+            state.page = '封面页'
+            state.cover_status = '有邀请人'
+            state.open_btn.txt = 'Start'
+            // state.cover_status = '无邀请人'
+            // state.cover_status = '奖励已被领光'
+        }
+        // 如果 夺宝参与状态 = 已参与夺宝
+        else if (joinStatus == 1) {
+            state.page = '邀请页'
+        }
+    }
+    // 如果 夺宝状态 = 已结束
+    else {
+        state.page = '封面页'
+        state.cover_status = '奖励已被领光'
+        state.open_btn.txt = 'Look for more treasures'
+    }
+}
+</script>
+<style lang="scss" >
+html,
+body {
+    margin: 0;
+    padding: 0;
+}
+</style>

+ 369 - 0
src/view/iframe/treasure-hunt/invite.vue

@@ -0,0 +1,369 @@
+<template>
+    <!-- 邀请页 -->
+    <div class="area-process">
+        <v-head :left-data="state.detail.postUserInfo || null" :rightData="state.detail.remainAmountValue"></v-head>
+        <div class="box-process">
+            <div class="item" v-for="item, i in state.boxs">
+                <hover-tip :txt="item.txt" v-show="item.show || item.openStatus" :icon="item.hover_icon"></hover-tip>
+                <img :src="item.icon" alt="" @mouseenter="mouseItem(i)" @mouseleave="mouseLeaveItem(i)" />
+                <img :src="require('@/assets/img/icon-flash-active.png')" alt="" class="flash"
+                    v-if="item.openStatus == 0 && item.taskFinishStatus == 1" />
+            </div>
+            <div class="line">
+                <div class="full" ref="line_full"></div>
+            </div>
+        </div>
+        <div class="area-success-message" @mouseover="mouseOver" @mouseleave="mouseLeave">
+            <div class="content-success-message" ref="content_success_message">
+                <div class="success-message" v-for="item, index in state.success_message_list" :key="index">
+                    <img :src="item.userInfo.avatarUrl" alt="" />
+                    <span>{{ item.userInfo.nickName }} </span> &nbsp;
+                    <span>Opened Treasure Chest</span>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="area-nav">
+        <div class="item" :class="{ active: state.tab_index == i }" @click="state.tab_index = i"
+            v-for="item, i in state.tabs">
+            {{ item.txt }}
+        </div>
+    </div>
+    <div class="area-info">
+        <invite-friends v-show="state.tab_index == 0"></invite-friends>
+        <invite-list v-show="state.tab_index == 1"></invite-list>
+    </div>
+
+</template>
+<script setup>
+import { reactive, ref, onMounted, watch, inject } from 'vue'
+import { receiveList } from '@/http/treasure.js'
+import VHead from '@/view/iframe/treasure-hunt/components/head.vue'
+import InviteList from '@/view/iframe/treasure-hunt/components/invite-list.vue'
+import HoverTip from '@/view/iframe/treasure-hunt/components/hover-tip.vue'
+import InviteFriends from '@/view/iframe/treasure-hunt/components/invite-friends.vue'
+let content_success_message = ref(null)
+let state = inject('state')
+
+// ---- 走马灯
+state.success_message_list = []
+
+
+// ---- box 区域
+let silver_close_box = require('@/assets/img/icon-silver-close-box.png')
+let silver_open_box = require('@/assets/img/icon-silver-open-box.png')
+let gold_open_box = require('@/assets/img/icon-gold-open-box.png')
+let gold_close_box = require('@/assets/img/icon-gold-close-box.png')
+
+
+// ---- tab区域 ----
+state.tab_index = 0
+state.tabs = [{
+    txt: 'invite friends'
+}, {
+    txt: 'invited'
+}]
+
+
+watch(state, () => {
+    if (content_success_message && content_success_message.value) {
+        let dom = content_success_message.value
+        let width = dom.clientWidth
+        let s = parseInt(width / 80)
+        dom.style.animationDuration = s + 's'
+    }
+})
+
+state.boxs = []
+
+let line_full = ref(null)
+onMounted(() => {
+    if (state.detail.inviteCount > 0) {
+        state.tabs[1].txt = `invited(${state.detail.inviteCount})`
+    }
+
+    state.detail.treasureRecords.forEach((item, index) => {
+        if (item.openStatus == 0) {
+            item.hover_icon = require('@/assets/svg/icon-user.svg')
+            // 最后一条
+            if ((index + 1) == state.detail.treasureRecords.length) {
+                item.icon = gold_close_box
+            } else {
+                item.icon = silver_close_box
+            }
+            item.txt = item.inviteProgress
+        } else {
+            item.icon = silver_open_box
+            item.hover_icon = require('@/assets/svg/icon-green-yes.svg')
+            // 最后一条
+            if ((index + 1) == state.detail.treasureRecords.length) {
+                item.icon = gold_open_box
+            } else {
+                item.icon = silver_open_box
+            }
+            item.txt = '$' + item.amountValue
+        }
+
+        state.boxs.push(item)
+    })
+
+    receiveList({
+        params: {
+            postId: state.postId,
+            pageNum: 1,
+            pageSize: 10,
+        }
+    }).then((res) => {
+        if (res.code == 0) {
+            state.success_message_list = res.data
+            state.success_message_list = state.success_message_list.concat(state.success_message_list)
+            state.success_message_list = state.success_message_list.concat(state.success_message_list)
+        }
+    })
+    btnStatus()
+})
+
+const setLineFull = (box_num = 0, needInviteCount = 0, successInviteCount = 0) => {
+    if (box_num == 0) {
+        line_full.value.style.width = (successInviteCount / needInviteCount) * 80 + 'px'
+    } else if (box_num = 1) {
+        line_full.value.style.width = ((successInviteCount / needInviteCount) * 100 + 80) + 'px'
+    } else if (box_num = 2) {
+        line_full.value.style.width = ((successInviteCount / needInviteCount) * 100 + 180) + 'px'
+    }
+}
+
+const btnStatus = () => {
+
+
+    for (let i in state.boxs) {
+        if (state.boxs[i].taskFinishStatus == 0) {
+            let num = state.boxs[i].needInviteCount - state.boxs[i].successInviteCount
+            if (num == 1) {
+                state.open_btn.txt = 'Invite a friend to open the chest'
+            } else {
+                state.open_btn.txt = `Invite ${num} friends to open the chest`
+            }
+            state.open_btn.disabled = true
+            break
+        }
+    }
+
+    state.treasureId = ''
+    let open_num = 0
+    // 有打开的箱子 Open the chest 
+    state.boxs.forEach((item, index) => {
+        if (item.taskFinishStatus == 1 && item.openStatus == 0) {
+            state.open_btn.txt = 'Open the Chest'
+            state.open_btn.disabled = false
+            if (!state.treasureId) {
+                state.treasureId = item.id
+            }
+        }
+        if (item.taskFinishStatus == 1) {
+            setLineFull(index, item.needInviteCount, item.successInviteCount)
+        }
+        // 三个箱子全部打开了 
+        if (item.openStatus == 1) {
+            open_num++
+        }
+        if (open_num == state.boxs.length) {
+            state.open_btn.txt = 'All Chests are Open'
+            state.open_btn.disabled = true
+        }
+    })
+}
+
+const mouseItem = (i) => {
+    state.boxs[i].show = true
+}
+const mouseLeaveItem = (i) => {
+    state.boxs[i].show = false
+}
+
+const mouseOver = () => {
+    if (content_success_message && content_success_message.value && content_success_message.value.style) {
+        content_success_message.value.style.animationPlayState = 'paused'
+    }
+}
+const mouseLeave = () => {
+    if (content_success_message && content_success_message.value && content_success_message.value.style) {
+        content_success_message.value.style.animationPlayState = 'running'
+    }
+}
+
+</script>
+<style lang="scss"  scoped>
+.area-process {
+    width: 375px;
+    height: 170px;
+    background: linear-gradient(179.96deg, #735931 0.04%, #0E0803 53.64%);
+    position: relative;
+
+    .box-process {
+        width: 350px;
+        height: 90px;
+        margin: 0 auto;
+        display: flex;
+        align-items: center;
+        position: absolute;
+        top: 32px;
+        left: 13px;
+
+        img {
+            width: 60px;
+            height: 60px;
+            z-index: 2;
+        }
+
+        .item {
+            z-index: 2;
+            display: flex;
+            justify-content: center;
+            position: relative;
+
+            .flash {
+                position: absolute;
+                top: 0;
+                left: 0;
+                z-index: 0;
+                width: 100%;
+                height: 100%;
+            }
+        }
+
+        .item:nth-child(1) {
+
+            margin-left: 56px;
+        }
+
+        .item:nth-child(2) {
+            width: 60px;
+            height: 60px;
+            margin-left: 40px;
+        }
+
+        .item:nth-child(3) {
+            img {
+                width: 90px;
+                height: 90px;
+            }
+
+            margin-left: 40px;
+        }
+
+        .line {
+            width: 300px;
+            height: 4px;
+            background: rgba(255, 210, 59, 0.2);
+            position: absolute;
+            border-radius: 100px;
+            overflow: hidden;
+            left: 13px;
+            top: 45px;
+
+            .full {
+                position: absolute;
+                left: 0;
+                top: 0;
+                height: 4px;
+                width: 0px;
+                background: #FFD23B;
+            }
+        }
+
+    }
+
+    .area-success-message {
+        height: 30px;
+        width: 100%;
+        position: absolute;
+        bottom: 13px;
+        overflow: hidden;
+
+        .content-success-message {
+
+            width: fit-content;
+            display: flex;
+            animation: rolling 18s linear infinite;
+
+            .success-message {
+                cursor: default;
+                width: fit-content;
+                height: 30px;
+                padding: 0 9px;
+                border-radius: 100px;
+                background: rgba(255, 255, 255, 0.1);
+                display: flex;
+                align-items: center;
+                overflow: hidden;
+                margin-right: 15px;
+
+                img {
+                    width: 20px;
+                    height: 20px;
+                    border-radius: 100px;
+                    margin-right: 8px;
+
+                }
+
+                span {
+                    font-style: normal;
+                    font-weight: 500;
+                    font-size: 12px;
+                    line-height: 14px;
+                    white-space: nowrap;
+                }
+
+                span:nth-child(2) {
+                    color: #1D9BF0;
+                }
+
+                span:nth-child(3) {
+                    color: #A8A8A8;
+                }
+            }
+        }
+    }
+}
+
+@keyframes rolling {
+    from {
+        transform: translateX(0);
+    }
+
+    to {
+        transform: translateX(-50%);
+    }
+}
+
+.area-nav {
+    width: 375px;
+    height: 38px;
+    display: flex;
+
+    .item {
+        user-select: none;
+        color: #757575;
+        background: #F0F0F0;
+        text-align: center;
+        width: 50%;
+        font-weight: 500;
+        font-size: 14px;
+        line-height: 38px;
+        cursor: pointer;
+    }
+
+    .active {
+        background: #FFFFFF;
+        color: #000000;
+    }
+}
+
+.area-info {
+    width: 375px;
+
+
+}
+</style>

+ 118 - 0
src/view/iframe/treasure-hunt/result.vue

@@ -0,0 +1,118 @@
+<template>
+    <!-- 开奖页 -->
+    <div class="content">
+        <img :src="require('@/assets/img/icon-silver-open-box.png')" alt="" />
+        <div class="mark">
+            <p>You already followed Younan111 </p>
+            <!-- 新粉 -->
+            <template v-if="state.start_task.amountValue > 0">
+                <p>You Win</p>
+                <div class="money">${{ state.start_task.usdAmountValue }}</div>
+                <div class="mark2">
+                    <img :src="state.start_task.currencyIcon" alt="" />
+                    <div>{{ state.start_task.amountValue }} {{ state.start_task.currencySymbol }} stored in your DeNet
+                        account</div>
+                </div>
+            </template>
+            <!-- 老粉不给钱 -->
+            <template v-else>
+                <p>Only new followers open silver chest</p>
+                <p class="txt">Invite people to</p>
+                <p class="txt">open golden chest!</p>
+            </template>
+        </div>
+        <v-btn :txt="'Invite friends for more treasures'" :font-size="'16px'" class="btn"
+            v-if="state.start_task.amountValue > 0" @onClick="clickBtn"></v-btn>
+        <v-btn :txt="'Invite'" :font-size="'16px'" class="btn" v-else @onClick="clickBtn"></v-btn>
+    </div>
+</template>
+<script setup>
+import { inject } from 'vue'
+import VBtn from '@/view/iframe/treasure-hunt/components/btn.vue'
+let state = inject('state')
+
+const clickBtn = () => {
+    state.page = '邀请页'
+}
+
+</script>
+<style lang="scss" scoped>
+.content {
+    width: 375px;
+    height: 500px;
+    background: linear-gradient(179.96deg, #876635 20.15%, #31251A 44.61%, #24180C 78.18%);
+    text-align: center;
+    position: relative;
+
+    img :first-child {
+        margin-top: 15px;
+        width: 250px;
+        height: 250px;
+    }
+
+    .mark {
+        position: absolute;
+        top: 246px;
+        width: 375px;
+
+        p {
+            margin: 0;
+            padding: 0;
+            text-align: center;
+
+        }
+
+        p:nth-child(1) {
+            color: #A9A49F;
+            font-weight: 400;
+            font-size: 12px;
+            margin-bottom: 10px;
+        }
+
+        p:nth-child(2) {
+            margin-bottom: 10px;
+            color: #FFFFFF;
+            font-weight: 800;
+            font-size: 18px;
+        }
+
+        .txt {
+            color: #FFC83A;
+            font-weight: 800;
+            font-size: 24px;
+
+        }
+
+        .money {
+            color: #FFC83A;
+            font-weight: 800;
+            font-size: 34px;
+        }
+
+        .mark2 {
+            margin-top: 10px;
+            display: flex;
+            justify-content: center;
+
+            img {
+                width: 17px;
+                height: 17px;
+                margin: 0;
+            }
+
+            div {
+                color: #A9A49F;
+                font-weight: 400;
+                font-size: 12px;
+
+            }
+        }
+    }
+
+    .btn {
+        position: absolute;
+        bottom: 25px;
+        left: 15px;
+    }
+}
+</style>

+ 72 - 18
src/view/popup/tabbar-page/message/index.vue

@@ -4,20 +4,27 @@
       <div class="list-wrapper" ref="pageGiveListDom">
         <div class="give-list" v-if="currentTabIndex == 0">
           <template v-if="giveList.length">
-            <div class="cell" :class="{ 'cell-center': item.type == 1 || item.type == 3 }"
+            <div class="cell" :class="{ 'cell-center': item.type == 1 || item.type == 3 || item.type == 5 }"
               v-for="(item, index) in giveList" :key="index" @click="clickListItem(item, index)">
               <red-dot class="red-dots" v-if="item.unReadMsgCount > 0 && isReadMsg"></red-dot>
 
               <div class="img-wrapper">
                 <!-- 收到红包 -->
-                <template v-if="item.type == 1 || item.type == 3">
+                <template v-if="item.type == 1 || item.type == 3 || item.type == 5">
                   <img class="icon-avatar" :src="item.userInfo.avatarUrl" />
-                  <img class="icon-give" :src="require('@/assets/svg/icon-get-giveaways-s.svg')" />
+                  <img class="icon-give" v-if="item.type == 5" :src="require('@/assets/svg/icon-small-treasure.svg')" />
+                  <img class="icon-give" v-else :src="require('@/assets/svg/icon-get-giveaways-s.svg')" />
                 </template>
                 <!-- 发出去红包 -->
                 <template v-else-if="item.type == 2">
-                  <img class="icon-big-give" :src="require('@/assets/svg/icon-send-giveaways-s.svg')" />
-                  <img class="icon-mark-give" :src="require('@/assets/svg/icon-send-giveaways-mark.svg')" />
+                  <template v-if="item.postTaskLuckdrop.luckdropType === PlayType.treasure">
+                    <img class="icon-big-give" :src="require('@/assets/svg/icon-big-treasure.svg')" />
+                    <img class="icon-mark-give" :src="require('@/assets/svg/icon-send-giveaways-mark.svg')" />
+                  </template>
+                  <template v-else>
+                    <img class="icon-big-give" :src="require('@/assets/svg/icon-send-giveaways-s.svg')" />
+                    <img class="icon-mark-give" :src="require('@/assets/svg/icon-send-giveaways-mark.svg')" />
+                  </template>
                 </template>
                 <!-- 转出NFT记录 -->
                 <template v-else-if="item.type == 4">
@@ -28,14 +35,22 @@
                   </div>
                 </template>
               </div>
-              <div class="info-wrapper" :class="{ 'info-center': item.type == 1 }">
+              <div class="info-wrapper" :class="{ 'info-center': item.type == 1 || item.type == 5 }">
                 <div class="left">
                   <div class="nickname">
                     <template v-if="item.type == 1">
                       Get Giveaway
                     </template>
                     <template v-else-if="item.type == 2">
-                      {{ item.postTaskLuckdrop.luckdropType === 1 ? 'Send Giveaway' : 'Lottery Giveaway' }}
+                        <template v-if="item.postTaskLuckdrop.luckdropType === PlayType.common">
+                          Send Giveaway
+                        </template>
+                        <template v-else-if="item.postTaskLuckdrop.luckdropType === PlayType.lottery">
+                          Lottery Giveaway
+                        </template>
+                        <template v-else-if="item.postTaskLuckdrop.luckdropType === PlayType.treasure">
+                          Treasure Hunt
+                        </template>
                     </template>
                     <template v-else-if="item.type == 3">
                       Lottery
@@ -43,6 +58,9 @@
                     <template v-else-if="item.type == 4">
                       Transfer NFT
                     </template>
+                    <template v-else-if="item.type == 5">
+                      Treasure Hunt
+                    </template>
                   </div>
                   <div class="time">
                     {{ moment(item.timestamp).format("MM-DD HH:mm:ss") }}
@@ -53,11 +71,11 @@
                     <div class="bold" :class="{
                       'align-content':
                         (item.type == 2 ||
-                          (item.type == 1 && item.status == 1)) &&
+                          (item.type == 1 && item.status == 1 || item.type == 5 && item.status == 1)) &&
                         item?.amount?.length + item?.currencySymbol?.length > 12,
                       'custom-bold': item.rewardType === RewardType.custom
                     }">
-                      <!-- 收到的 -->
+                      <!-- 领取的普通红包 -->
                       <template v-if="item.type == 1">
                         <!-- 进行中-->
                         <template v-if="item.status == 0">
@@ -114,6 +132,7 @@
 
                         </template>
                       </template>
+                      <!-- 抽奖 -->
                       <template v-else-if="item.type == 3">
                         <template v-if="item.status == 1">In Progress</template>
                         <template v-else-if="item.status == 2">
@@ -150,12 +169,38 @@
                           Giveaway Expired
                         </template>
                       </template>
+                      <!-- NFT 转出记录 -->
                       <template v-else-if="item.type == 4">
                         <template v-if="item.status == 0 || item.status == 1">Transferring</template>
                         <template v-else-if="item.status == 2">Successful</template>
                         <template v-else-if="item.status == 3">Transfe Failed</template>
                       </template>
+                      <!-- 领取的夺宝红包 -->
+                      <template v-else-if="item.type == 5">
+                        <!-- 进行中-->
+                        <template v-if="item.status == 0">
+                          In Progress
+                        </template>
+                        <!-- 已完成 -->
+                        <template v-else-if="item.status == 2">
+                            <span class="blance">
+                              <a-tooltip :title="item.amount">
+                                {{ getBit(item.amount) }}</a-tooltip>
+                            </span>
+                            <div class="coin-type-wrapper">
+                              <span class="coin-type">{{
+                                  item.currencySymbol || ""
+                              }}</span>
+                              <img :src="item.currencyIconPath" alt="" />
+                            </div>
+                        </template>
+                        <!-- 已过期 -->
+                        <template v-else-if="item.status == 3">
+                          Giveaway Expired
+                        </template>
+                      </template>
                     </div>
+
                     <!-- 发出的红包显示 -->
                     <div class="desc" v-if="item.type == 2">
                       <!-- 未发送-->
@@ -164,7 +209,7 @@
                       </template>
                       <!-- 进行中 -->
                       <template v-else-if="item.status == 1">
-                        <template v-if="item.postTaskLuckdrop && item.postTaskLuckdrop.luckdropType == 2">
+                        <template v-if="item.postTaskLuckdrop && item.postTaskLuckdrop.luckdropType == PlayType.lottery">
                           {{ item.downTime || '' }}
                         </template>
                         <template v-else>
@@ -173,12 +218,13 @@
                           }}
                         </template>
                       </template>
+
                       <!-- 2:已结束; 3:提前终止-->
                       <template v-else-if="item.status == 2 || item.status == 3">
                         <!-- 普通红包 -->
-                        <template v-if="item.postTaskLuckdrop && item.postTaskLuckdrop.luckdropType == 1">
+                        <template v-if="item.postTaskLuckdrop.luckdropType == PlayType.common || item.postTaskLuckdrop.luckdropType == PlayType.treasure">
                           <template v-if="item.status == 2">
-                            (Time expired)
+                            {{item.postTaskLuckdrop.luckdropType == PlayType.common ? '(Time expired)': 'Complete'}}
                           </template>
                           <template v-if="item.status == 3">
                             {{ item.srcContentId ? '(Termination)' : 'Termination' }}
@@ -202,8 +248,7 @@
                         }}
                       </template>
 
-                      <!-- 进行中或者未发送成功时显示 
-                                                v-if="item.status == 1 || item.postTaskLuckdrop.reSendAvailable"-->
+                      <!-- 进行中或者未发送成功时显示 -->
                       <div class="desc-bottom-bar">
                         <!-- 没有终止红包时显示 -->
                         <div v-if="item.postTaskLuckdrop.terminatedAvailable" class="btn"
@@ -254,7 +299,7 @@ import { terminatedLuckdrop } from "@/http/redPacket";
 import { readAllMsgByType, getAllMessageInfo } from "@/http/messageApi"
 import { setBadgeInfo, hideBadge } from "@/logic/background/twitter";
 import { getChromeStorage } from "@/uilts/chromeExtension";
-import { RewardType } from "@/types";
+import { PlayType, RewardType } from '@/types';
 
 var moment = require("moment");
 
@@ -407,13 +452,22 @@ const terminaHandler = (params, index) => {
   terminaTask.index = index;
 
   // set font
-  if (params && params.postTaskLuckdrop && params.postTaskLuckdrop.luckdropType == 2) {
-    modalTitle.value = `Early Termination of Lottery?`
-    modalContent.value = `This operation will terminate the lottery process and refund the lottery prizes.`
+  if(params && params.postTaskLuckdrop) {
+    if (params.postTaskLuckdrop.luckdropType == PlayType.lottery) {
+      modalTitle.value = `Early Termination of Lottery?`
+      modalContent.value = `This operation will terminate the lottery process and refund the lottery prizes.`
+    } else if(params.postTaskLuckdrop.luckdropType == PlayType.treasure) {
+      modalTitle.value = `Early Termination of treasure Hunt?`
+      modalContent.value = `This operation will stop the treasure hunt and refund the remaining amount within 2 days`
+    } else{
+      modalTitle.value = `Early termination of Giveaway?`
+      modalContent.value = `The remaining amount will be returned to your wallet within 1 day.`
+    }
   } else {
     modalTitle.value = `Early termination of Giveaway?`
     modalContent.value = `The remaining amount will be returned to your wallet within 1 day.`
   }
+  
   modalVisible.value = true;
 };
 

+ 7 - 4
src/view/popup/withdraw/info.vue

@@ -93,6 +93,9 @@ let state = reactive({
 })
 
 const inputWithdrawCalcFee = () => {
+  if(!state.input_amount) {
+    return;
+  }
   withdrawCalcFee({
     params: {
       "amountValue": state.input_amount,
@@ -104,7 +107,7 @@ const inputWithdrawCalcFee = () => {
       if (res.data) {
         state.currency_code = res.data.currencyCode || ''
         state.fee_amount = res.data.feeAmountValue || 0
-        state.amount = res.data.finalAmountValue || 111
+        state.amount = res.data.finalAmountValue > 0 ? res.data.finalAmountValue : 0
         state.is_enter_state = true
         inputText('yes')
       }
@@ -114,6 +117,9 @@ const inputWithdrawCalcFee = () => {
 }
 
 const inputText = (is_check_input) => {
+  if (is_check_input != 'yes') {
+    inputWithdrawCalcFee()
+  }
   if (!state.withdraw_switch) {
     return
   }
@@ -144,9 +150,6 @@ const inputText = (is_check_input) => {
     return
   } else {
     state.error_msg = ''
-    if (is_check_input != 'yes') {
-      inputWithdrawCalcFee()
-    }
   }
 }
 

+ 13 - 6
vue.config.js

@@ -1,6 +1,6 @@
 const path = require('path')
 const fs = require('fs')
-
+const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
 // webpack.config.js
 const AutoImport = require('unplugin-auto-import/webpack')
 const Components = require('unplugin-vue-components/webpack')
@@ -8,6 +8,7 @@ const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
 const CopyWebpackPlugin = require('copy-webpack-plugin');
 
 
+
 // Generate pages object
 const pages = {}
 
@@ -76,14 +77,20 @@ module.exports = {
     resolve: {
       alias: {
         '@': path.resolve('src')
+      },
+      fallback: {
+        fs: false
       }
     },
+
+
     output: {
       filename: `js/[name].js`,
       chunkFilename: `[name].js`
     },
     devtool: isDevMode ? 'inline-source-map' : false,
     plugins: [
+      new NodePolyfillPlugin(),
       AutoImport({
         resolvers: [ElementPlusResolver()],
       }),
@@ -109,9 +116,9 @@ module.exports = {
     ],
   },
   // 配置 content.css
-	css: {
-		extract: {
-			filename: "css/[name].css"
-		}
-	}
+  css: {
+    extract: {
+      filename: "css/[name].css"
+    }
+  }
 }

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