index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <template>
  2. <v-cover v-if="state.page == '封面页'"></v-cover>
  3. <v-invite v-if="state.page == '邀请页'"></v-invite>
  4. <v-result v-if="state.page == '开奖页'"></v-result>
  5. <open-box v-show="state.open_box.show"></open-box>
  6. <v-toast :show="state.toast.show" :txt="state.toast.txt" :has_icon="state.toast.has_icon"></v-toast>
  7. <div v-show="state.loading_redbag" class="redbag">
  8. <img :src="require('@/assets/img/icon-loading-redbag.png')" alt />
  9. </div>
  10. </template>
  11. <script setup>
  12. import { reactive, provide, onMounted, ref } from 'vue'
  13. import VCover from '@/view/iframe/treasure-hunt/cover.vue'
  14. import VInvite from '@/view/iframe/treasure-hunt/invite.vue'
  15. import VResult from '@/view/iframe/treasure-hunt/result.vue'
  16. import { inviteDetail, treasureDetail, treasureOpen } from '@/http/treasure.js'
  17. import { reSetBindTwtterId, reSetBindPostContent, reSetBindRepost } from '@/http/help.js'
  18. import { getQueryString } from '@/uilts/help'
  19. import { getChromeStorage, sendCurrentTabMessage } from '@/uilts/chromeExtension.js'
  20. import VToast from '@/view/iframe/treasure-hunt/components/toast.vue'
  21. import OpenBox from '@/view/iframe/treasure-hunt/components/open-box.vue'
  22. import Report from "@/log-center/log"
  23. let state = reactive({
  24. loading_redbag: true,
  25. page: '',
  26. page_status: '',
  27. detail: {},
  28. oldDetail: {},
  29. btn_loading: false,
  30. timer: null,
  31. open_box: {
  32. showed: false,
  33. show: false,
  34. clicked: false,
  35. data: {}
  36. },
  37. open_btn: {
  38. txt: '',
  39. disabled: false
  40. },
  41. dialog: {
  42. show: false,
  43. },
  44. start_task: {},
  45. toast: {},
  46. iframeId: ''
  47. })
  48. let global_refresh = ref(false)
  49. provide('global_refresh', global_refresh)
  50. provide('state', state)
  51. let params = {}
  52. onMounted(() => {
  53. params = JSON.parse(getQueryString('params') || '{}')
  54. state.iframeId = getQueryString('iframeId') || ''
  55. state.postId = params.post_Id || ''
  56. state.tweetId = params.tweet_Id || ''
  57. state.invite_code = params.invite_code || ''
  58. state.page_type = params.page_type || ''
  59. state.init();
  60. onRuntimeMsg();
  61. })
  62. state.checkIsLogin = () => {
  63. return new Promise((resolve) => {
  64. getChromeStorage('userInfo', (_userInfo) => {
  65. if (!_userInfo) {
  66. state.btn_loading = true
  67. setTimeout(() => {
  68. state.btn_loading = false
  69. }, 3000)
  70. chrome.runtime.sendMessage({ actionType: "POPUP_LOGIN", data: "" })
  71. resolve(_userInfo)
  72. } else {
  73. resolve(_userInfo)
  74. }
  75. })
  76. })
  77. }
  78. state.init = (callback) => {
  79. if (params.page_type == '邀请链接') {
  80. // 邀请链接
  81. inviteDetail({
  82. params: {
  83. inviteCode: params.invite_code
  84. }
  85. }).then((res) => {
  86. if (res.code == 0) {
  87. state.loading_redbag = false
  88. handleCommon(res, callback)
  89. // 绑定repostSrcContentId
  90. if (!res.data.repostSrcContentId) {
  91. reSetBindRepost({
  92. inviteCode: state.invite_code,
  93. tweetId: state.tweetId
  94. })
  95. }
  96. }
  97. })
  98. } else if (params.page_type == '原始链接') {
  99. // 原始链接
  100. treasureDetail({
  101. params: {
  102. postId: params.post_Id
  103. }
  104. }).then((res) => {
  105. if (res.code == 0) {
  106. state.loading_redbag = false
  107. handleCommon(res, callback)
  108. // 原始链接绑定post content
  109. if (!res.data.postSrcContent) {
  110. sendCurrentTabMessage({
  111. actionType: "GET_CONTENT_BY_TWITTER_ID",
  112. data: {
  113. tweet_Id: state.tweetId
  114. }
  115. })
  116. }
  117. }
  118. })
  119. }
  120. }
  121. const reportOpenBoxLog = () => {
  122. if (state.open_box.showed) {
  123. Report.reportLog({
  124. businessType: Report.businessType.pageView,
  125. pageSource: Report.pageSource.openTreasurePage,
  126. redPacketType: Report.redPacketType.treasure,
  127. shareLinkId: state.invite_code,
  128. myShareLinkId: state.detail.inviteCopyUrl,
  129. currentInvitedNum: state.inviteCount,
  130. postId: state.postId
  131. });
  132. state.open_box.showed = false
  133. }
  134. if (state.open_box.clicked) {
  135. Report.reportLog({
  136. businessType: Report.businessType.buttonClick,
  137. pageSource: Report.pageSource.openTreasurePage,
  138. objectType: Report.objectType.nextButton,
  139. redPacketType: Report.redPacketType.treasure,
  140. shareLinkId: state.invite_code,
  141. myShareLinkId: state.detail.inviteCopyUrl,
  142. currentInvitedNum: state.inviteCount,
  143. postId: state.postId
  144. });
  145. state.open_box.clicked = false
  146. }
  147. }
  148. const handleCommon = (res, callback) => {
  149. state.detail = res.data
  150. state.postId = state.detail.postId
  151. reportOpenBoxLog()
  152. try {
  153. state.tasks = JSON.parse(state.detail.startCondition)
  154. let follows = state.tasks.filter((item) => { return item.type == 1 })
  155. if (follows.length) {
  156. state.follows = follows[0].relatedUsers
  157. }
  158. }
  159. catch (error) {
  160. console.error('catch', error)
  161. }
  162. if (!res.data.srcContentId) {
  163. reSetBindTwtterId({
  164. postId: state.postId || '',
  165. tweetId: state.tweetId || ''
  166. }, () => {
  167. sendCurrentTabMessage({
  168. actionType: "IFRAME_API_GET_TWEET_USER_INFO_REQ",
  169. data: {
  170. screen_name: state.detail.postUserInfo.nickName,
  171. tweetId: state.tweetId,
  172. objectType: Report.objectType.tweetPostBinded,
  173. iframeId: state.iframeId
  174. }
  175. })
  176. state.init()
  177. })
  178. }
  179. handleStatus(callback)
  180. }
  181. let silver_open_box_big = require('@/assets/img/icon-silver-open-box-big.png')
  182. let gold_open_box_big = require('@/assets/img/icon-gold-open-box-big.png')
  183. let purple_open_box_big = require('@/assets/img/icon-purple-open-big.png')
  184. state.refreshInit = () => {
  185. state.init(() => {
  186. global_refresh.value = true
  187. setTimeout(() => {
  188. global_refresh.value = false
  189. }, 1000)
  190. })
  191. }
  192. state.treasureOpen = () => {
  193. treasureOpen({
  194. params: {
  195. postId: state.postId,
  196. treasureId: state.treasureId,
  197. }
  198. }).then((res) => {
  199. state.btn_loading = false
  200. if (res.code == 0) {
  201. // icon
  202. for (let i in state.boxs) {
  203. if (state.boxs[i].id == state.treasureId) {
  204. if (i == 0) {
  205. state.open_box.icon = silver_open_box_big
  206. } else if (i == 1 || i == 2) {
  207. state.open_box.icon = gold_open_box_big
  208. } else if (i == 3) {
  209. state.open_box.icon = purple_open_box_big
  210. }
  211. break
  212. }
  213. }
  214. state.open_box.show = true
  215. state.open_box.showed = true
  216. state.open_box.data = res.data
  217. state.refreshInit()
  218. } else {
  219. switch (String(res.code)) {
  220. case '2037':
  221. state.dialog.show = true
  222. break;
  223. case '2203':
  224. state.toast.txt = 'You have already opened the treasure chest'
  225. state.toast.show = true
  226. break
  227. case '2208':
  228. state.toast.txt = 'No treasure chests to open'
  229. state.toast.show = true
  230. break
  231. default:
  232. state.toast.txt = 'System Error'
  233. state.toast.show = true
  234. break
  235. }
  236. state.toast.has_icon = false
  237. setTimeout(() => {
  238. state.toast.show = false
  239. }, 2000)
  240. state.refreshInit()
  241. }
  242. }).catch(() => {
  243. state.btn_loading = false
  244. })
  245. }
  246. const handleStatus = (callback) => {
  247. // 如果 夺宝状态 = 未开始
  248. // 显示未开始页面
  249. // 如果 夺宝状态 = 进行中
  250. // 如果 夺宝参与状态 = 未参与夺宝
  251. // 显示封面页
  252. // 如果 夺宝参与状态 = 已参与夺宝
  253. // 显示邀请页
  254. // 如果 夺宝状态 = 已结束
  255. // 显示结束页面
  256. let { status, joinStatus } = state.detail || {}
  257. // 如果 夺宝状态 = 未开始
  258. if (status == 0) {
  259. // 未做处理
  260. }
  261. // 如果 夺宝状态 = 进行中
  262. else if (status == 1) {
  263. // 如果 夺宝参与状态 = 未参与夺宝
  264. if (joinStatus == 0) {
  265. // 显示封面页
  266. state.page = '封面页'
  267. state.cover_status = '有邀请人'
  268. state.open_btn.txt = 'Start'
  269. // state.cover_status = '无邀请人'
  270. // state.cover_status = '奖励已被领光'
  271. }
  272. // 如果 夺宝参与状态 = 已参与夺宝
  273. else if (joinStatus == 1) {
  274. if (state.page_show != '总邀请者页') {
  275. state.page = '邀请页'
  276. }
  277. }
  278. }
  279. // 如果 夺宝状态 = 已结束
  280. else {
  281. state.open_btn.txt = 'Look for more treasures'
  282. state.page = '封面页'
  283. state.cover_status = '奖励已被领光'
  284. state.btn_loading = false
  285. Report.reportLog({
  286. pageSource: Report.pageSource.expiredPage,
  287. businessType: Report.businessType.pageView,
  288. postId: state.postId,
  289. shareLinkId: state.invite_code,
  290. myShareLinkId: state.detail.inviteCopyUrl,
  291. currentInvitedNum: state.inviteCount,
  292. redPacketType: Report.redPacketType.treasure
  293. });
  294. return
  295. }
  296. callback && callback()
  297. }
  298. function onRuntimeMsg() {
  299. chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
  300. switch (req.actionType) {
  301. case 'CONTENT_GET_TWEET_TXT':
  302. if (req.data.tweet_Id == state.tweetId && !state.detail.postSrcContent) {
  303. state.detail.postSrcContent = req.data.txt
  304. reSetBindPostContent({
  305. postId: state.postId || '',
  306. postSrcContent: req.data.txt,
  307. })
  308. }
  309. break
  310. case 'CONTENT_API_GET_TWEET_USER_INFO_RES':
  311. if (state.iframeId != req.iframeId) {
  312. return;
  313. }
  314. let twitterFans = 0;
  315. let { user } = req.data || {};
  316. if (user && user.result && user.result.legacy) {
  317. let legacy = user.result.legacy;
  318. twitterFans = legacy ? legacy.followers_count : 0;
  319. }
  320. if (state.tweetId == req.tweetId && req.objectType == Report.objectType.tweetPostBinded) {
  321. Report.reportLog({
  322. objectType: Report.objectType.tweetPostBinded,
  323. twitterFans: twitterFans,
  324. redPacketType: Report.redPacketType.treasure,
  325. postId: state.postId
  326. });
  327. }
  328. break;
  329. }
  330. sendResponse && sendResponse();
  331. })
  332. }
  333. </script>
  334. <style lang="scss" >
  335. html,
  336. body {
  337. margin: 0;
  338. padding: 0;
  339. width: 100%;
  340. height: 100%;
  341. overflow: hidden;
  342. .redbag {
  343. z-index: 222;
  344. text-align: center;
  345. width: 375px;
  346. height: 580px;
  347. position: fixed;
  348. top: 0;
  349. left: 0;
  350. user-select: none;
  351. img {
  352. position: absolute;
  353. top: 50%;
  354. left: 50%;
  355. margin-top: -65px;
  356. margin-left: -65px;
  357. width: 130px;
  358. height: 130px;
  359. }
  360. }
  361. }
  362. </style>