activity-host.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <template>
  2. <view>
  3. <UpsellShare v-if="enableUpsell" ref="shareRef" @viewRules="emitViewRules" />
  4. <ReduceShare v-if="enableReduce" ref="reduceShareRef" @viewRules="emitViewRules" />
  5. </view>
  6. </template>
  7. <script>
  8. import UpsellShare from "@/pages/home/components/upsell-share.vue";
  9. import ReduceShare from "@/pages/home/components/reduce-share.vue";
  10. import { eventBus } from "@/utils/event-bus";
  11. import { shouldBlockMarketingPopup } from "@/utils/policy-consent-manager.js";
  12. export default {
  13. name: "ActivityHost",
  14. props: {
  15. enableUpsell: {
  16. type: Boolean,
  17. default: true,
  18. },
  19. enableReduce: {
  20. type: Boolean,
  21. default: true,
  22. },
  23. },
  24. components: {
  25. UpsellShare,
  26. ReduceShare,
  27. },
  28. data() {
  29. return {
  30. loginSuccessHandler: null,
  31. appShowActivityHandler: null,
  32. policyAcceptedHandler: null,
  33. pendingLoginData: null,
  34. pendingPageOptions: null,
  35. };
  36. },
  37. mounted() {
  38. this.bindLoginSuccess();
  39. this.bindAppShowActivity();
  40. this.bindPolicyAccepted();
  41. this.tryOpenPendingActivity();
  42. },
  43. beforeDestroy() {
  44. this.unbindLoginSuccess();
  45. this.unbindAppShowActivity();
  46. this.unbindPolicyAccepted();
  47. },
  48. methods: {
  49. bindLoginSuccess() {
  50. if (this.loginSuccessHandler) return;
  51. this.loginSuccessHandler = (data) => {
  52. if (shouldBlockMarketingPopup()) {
  53. this.pendingLoginData = data || null;
  54. return;
  55. }
  56. const app = getApp();
  57. if (app && app.globalData) {
  58. app.globalData.isColdLaunch = false;
  59. }
  60. // 优先处理带参数的入口(如分享减价链接),避免与 storage 重复弹窗
  61. if (this.pendingPageOptions) {
  62. const options = this.pendingPageOptions;
  63. this.pendingPageOptions = null;
  64. this.openByPageOptions(options);
  65. return;
  66. }
  67. this.openByLoginSuccess(data);
  68. };
  69. eventBus.on("loginSuccess", this.loginSuccessHandler);
  70. },
  71. bindAppShowActivity() {
  72. if (this.appShowActivityHandler) return;
  73. this.appShowActivityHandler = (data) => {
  74. if (shouldBlockMarketingPopup()) {
  75. this.pendingLoginData = data || null;
  76. return;
  77. }
  78. this.openByLoginSuccess(data);
  79. };
  80. eventBus.on("appShowActivity", this.appShowActivityHandler);
  81. },
  82. unbindLoginSuccess() {
  83. if (!this.loginSuccessHandler) return;
  84. eventBus.off("loginSuccess", this.loginSuccessHandler);
  85. this.loginSuccessHandler = null;
  86. },
  87. unbindAppShowActivity() {
  88. if (!this.appShowActivityHandler) return;
  89. eventBus.off("appShowActivity", this.appShowActivityHandler);
  90. this.appShowActivityHandler = null;
  91. },
  92. bindPolicyAccepted() {
  93. if (this.policyAcceptedHandler) return;
  94. this.policyAcceptedHandler = () => {
  95. this.flushPendingMarketingPopups();
  96. };
  97. eventBus.on("policyAccepted", this.policyAcceptedHandler);
  98. },
  99. unbindPolicyAccepted() {
  100. if (!this.policyAcceptedHandler) return;
  101. eventBus.off("policyAccepted", this.policyAcceptedHandler);
  102. this.policyAcceptedHandler = null;
  103. },
  104. tryOpenPendingActivity() {
  105. if (shouldBlockMarketingPopup()) return;
  106. const token = uni.getStorageSync("token");
  107. const upsellCode = uni.getStorageSync("upsellCode");
  108. const reduceCode = uni.getStorageSync("reduceCode");
  109. if (!token || (!upsellCode && !reduceCode)) return;
  110. this.openByLoginSuccess();
  111. },
  112. openByLoginSuccess(data) {
  113. if (shouldBlockMarketingPopup()) {
  114. this.pendingLoginData = data || null;
  115. return;
  116. }
  117. const upsellCode = uni.getStorageSync("upsellCode") || data?.params?.upsellCode;
  118. const reduceCode = uni.getStorageSync("reduceCode") || data?.params?.reduceCode;
  119. if (this.enableUpsell && upsellCode) {
  120. this.$refs.shareRef?.open(upsellCode);
  121. }
  122. if (this.enableReduce && reduceCode) {
  123. this.$refs.reduceShareRef?.open(reduceCode);
  124. }
  125. this.$emit("refresh-order");
  126. },
  127. handlePageOptions(options = {}, isColdLaunch = false) {
  128. if (isColdLaunch) return;
  129. if (shouldBlockMarketingPopup()) {
  130. this.pendingPageOptions = options;
  131. return;
  132. }
  133. this.openByPageOptions(options);
  134. },
  135. openByPageOptions(options = {}) {
  136. const params = this.parseEntryParams(options);
  137. if (this.enableUpsell && params.upsellCode) {
  138. this.$refs.shareRef?.open(params.upsellCode);
  139. this.$emit("refresh-order");
  140. return;
  141. }
  142. if (this.enableReduce && params.reduceCode) {
  143. this.$refs.reduceShareRef?.open(params.reduceCode);
  144. return;
  145. }
  146. this.$emit("refresh-order");
  147. },
  148. flushPendingMarketingPopups() {
  149. if (shouldBlockMarketingPopup()) return;
  150. if (this.pendingPageOptions) {
  151. const options = this.pendingPageOptions;
  152. this.pendingPageOptions = null;
  153. this.openByPageOptions(options);
  154. return;
  155. }
  156. const token = uni.getStorageSync("token");
  157. if (!token) return;
  158. this.openByLoginSuccess(this.pendingLoginData);
  159. this.pendingLoginData = null;
  160. },
  161. parseEntryParams(options = {}) {
  162. if (!options.scene) return options;
  163. const params = {};
  164. const decodeScene = decodeURIComponent(options.scene);
  165. const paramPairs = decodeScene.split("&");
  166. paramPairs.forEach((pair) => {
  167. const [key, value] = pair.split("=");
  168. params[key] = value;
  169. });
  170. return params;
  171. },
  172. emitViewRules() {
  173. this.$emit("view-rules");
  174. },
  175. getShareAppMessage(res) {
  176. if (this.enableUpsell && res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "upsell") {
  177. const upsellCode = uni.getStorageSync("upsellCodeShare");
  178. uni.$u.http.get("/token/order/goToShare?upsellCode=" + upsellCode);
  179. return {
  180. title: "书嗨",
  181. path: "/pages/home/index?upsellCode=" + upsellCode,
  182. imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
  183. desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
  184. };
  185. }
  186. if (this.enableReduce && res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
  187. const reduceCode = uni.getStorageSync("reduceCodeShare");
  188. if (uni.$u && uni.$u.api && uni.$u.api.goToReduceShareAjax) {
  189. uni.$u.api.goToReduceShareAjax({ reduceCode: reduceCode });
  190. } else {
  191. uni.$u && uni.$u.http && uni.$u.http.get("/token/shop/order/goToShare", { reduceCode: reduceCode });
  192. }
  193. return {
  194. title: "快来帮我减钱买书吧!",
  195. path: "/pages/sell/index?reduceCode=" + reduceCode,
  196. imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
  197. desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
  198. };
  199. }
  200. return null;
  201. },
  202. getShareTimeline(res) {
  203. if (this.enableUpsell && res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "upsell") {
  204. const upsellCode = uni.getStorageSync("upsellCodeShare");
  205. uni.$u.http.get("/token/order/goToShare?upsellCode=" + upsellCode);
  206. return {
  207. title: "书嗨",
  208. path: "/pages/home/index?upsellCode=" + upsellCode,
  209. imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
  210. desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
  211. };
  212. }
  213. if (this.enableReduce && res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
  214. const reduceCode = uni.getStorageSync("reduceCodeShare");
  215. if (uni.$u && uni.$u.api && uni.$u.api.goToReduceShareAjax) {
  216. uni.$u.api.goToReduceShareAjax({ reduceCode: reduceCode });
  217. } else {
  218. uni.$u && uni.$u.http && uni.$u.http.get("/token/shop/order/goToShare", { reduceCode: reduceCode });
  219. }
  220. return {
  221. title: "快来帮我减钱买书吧!",
  222. path: "/pages/sell/index?reduceCode=" + reduceCode,
  223. imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
  224. desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
  225. };
  226. }
  227. return null;
  228. },
  229. },
  230. };
  231. </script>