@hlw-uni/mp-vue 2.1.12 → 2.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { AdapterPayload } from '../_internal/unwrap';
2
- import { Ref } from 'vue';
2
+ import { ComputedRef, Ref } from 'vue';
3
3
 
4
4
  /** 6 种广告类型 */
5
5
  export type AdType = "banner" | "grid" | "custom" | "video" | "reward" | "popup";
@@ -11,6 +11,8 @@ export interface AdConfig {
11
11
  video_unit_id: string;
12
12
  reward_unit_id: string;
13
13
  popup_unit_id: string;
14
+ /** VIP 屏蔽展示型广告(reward 除外):0=否,1=屏蔽 banner/grid/custom/video/popup */
15
+ vip_no_ad?: 0 | 1;
14
16
  }
15
17
  /** 广告错误对象(onError 回调参数) */
16
18
  export interface AdError {
@@ -31,6 +33,13 @@ export interface AdAdapter {
31
33
  getConfig: () => Promise<AdapterPayload<AdConfig>>;
32
34
  /** 是否已登录;不传 = 不校验(showReward 调用前会问一次) */
33
35
  isAuth?: () => boolean;
36
+ /** 是否 VIP;配合 config.vip_no_ad=1 时屏蔽展示型广告(reward 不受影响) */
37
+ isVip?: () => boolean;
38
+ /**
39
+ * 用户级强制屏蔽:返回 true 直接屏蔽展示型广告(reward 不受影响),
40
+ * 优先级高于 mp.vip_no_ad + isVip 的联合判断;不传 = 不强制。
41
+ */
42
+ userNoAd?: () => boolean;
34
43
  }
35
44
  /** 激励视频关闭回调返回 */
36
45
  export interface AdCloseResult {
@@ -43,21 +52,7 @@ export interface AdCloseResult {
43
52
  */
44
53
  export declare function setConfigAd(a: AdAdapter): void;
45
54
  export declare function useAd(): {
46
- config: Ref<{
47
- banner_unit_id: string;
48
- grid_unit_id: string;
49
- custom_unit_id: string;
50
- video_unit_id: string;
51
- reward_unit_id: string;
52
- popup_unit_id: string;
53
- }, AdConfig | {
54
- banner_unit_id: string;
55
- grid_unit_id: string;
56
- custom_unit_id: string;
57
- video_unit_id: string;
58
- reward_unit_id: string;
59
- popup_unit_id: string;
60
- }>;
55
+ config: ComputedRef<AdConfig>;
61
56
  loaded: Ref<boolean, boolean>;
62
57
  loadConfig: (force?: boolean) => Promise<void>;
63
58
  getUnitId: (type: AdType) => string;
package/dist/index.js CHANGED
@@ -637,7 +637,8 @@ var __publicField = (obj, key, value) => {
637
637
  custom_unit_id: "",
638
638
  video_unit_id: "",
639
639
  reward_unit_id: "",
640
- popup_unit_id: ""
640
+ popup_unit_id: "",
641
+ vip_no_ad: 0
641
642
  };
642
643
  let adapter$1 = null;
643
644
  let pending$1 = null;
@@ -655,7 +656,17 @@ var __publicField = (obj, key, value) => {
655
656
  const interstitialCache = /* @__PURE__ */ new Map();
656
657
  function useAd() {
657
658
  const store = useAdStore();
658
- const { config: config2, loaded } = pinia.storeToRefs(store);
659
+ const { loaded } = pinia.storeToRefs(store);
660
+ const config2 = vue.computed(() => {
661
+ var _a, _b;
662
+ const raw = store.config;
663
+ const userForce = ((_a = adapter$1 == null ? void 0 : adapter$1.userNoAd) == null ? void 0 : _a.call(adapter$1)) === true;
664
+ const vipHide = raw.vip_no_ad === 1 && ((_b = adapter$1 == null ? void 0 : adapter$1.isVip) == null ? void 0 : _b.call(adapter$1)) === true;
665
+ if (userForce || vipHide) {
666
+ return { ...EMPTY, reward_unit_id: raw.reward_unit_id, vip_no_ad: 1 };
667
+ }
668
+ return raw;
669
+ });
659
670
  async function loadConfig2(force = false) {
660
671
  if (loaded.value && !force)
661
672
  return;
@@ -684,7 +695,7 @@ var __publicField = (obj, key, value) => {
684
695
  return flight;
685
696
  }
686
697
  function getUnitId(type) {
687
- return store.config[`${type}_unit_id`] || "";
698
+ return config2.value[`${type}_unit_id`] || "";
688
699
  }
689
700
  async function showReward(onClose) {
690
701
  const unitId = getUnitId("reward");
@@ -1806,6 +1817,14 @@ var __publicField = (obj, key, value) => {
1806
1817
  _interceptorCleanup.forEach((dispose) => dispose());
1807
1818
  _interceptorCleanup = [];
1808
1819
  const offRequest = http.onRequest((config2) => {
1820
+ const method = (config2.method ?? "GET").toUpperCase();
1821
+ if (method === "GET" && config2.data && typeof config2.data === "object") {
1822
+ const qs = Object.entries(config2.data).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
1823
+ if (qs) {
1824
+ config2.url = config2.url + (config2.url.includes("?") ? "&" : "?") + qs;
1825
+ }
1826
+ config2.data = void 0;
1827
+ }
1809
1828
  const device = useDevice();
1810
1829
  if (device.value) {
1811
1830
  const d = device.value;
package/dist/index.mjs CHANGED
@@ -636,7 +636,8 @@ const EMPTY = {
636
636
  custom_unit_id: "",
637
637
  video_unit_id: "",
638
638
  reward_unit_id: "",
639
- popup_unit_id: ""
639
+ popup_unit_id: "",
640
+ vip_no_ad: 0
640
641
  };
641
642
  let adapter$1 = null;
642
643
  let pending$1 = null;
@@ -654,7 +655,17 @@ const rewardedCache = /* @__PURE__ */ new Map();
654
655
  const interstitialCache = /* @__PURE__ */ new Map();
655
656
  function useAd() {
656
657
  const store = useAdStore();
657
- const { config: config2, loaded } = storeToRefs(store);
658
+ const { loaded } = storeToRefs(store);
659
+ const config2 = computed(() => {
660
+ var _a, _b;
661
+ const raw = store.config;
662
+ const userForce = ((_a = adapter$1 == null ? void 0 : adapter$1.userNoAd) == null ? void 0 : _a.call(adapter$1)) === true;
663
+ const vipHide = raw.vip_no_ad === 1 && ((_b = adapter$1 == null ? void 0 : adapter$1.isVip) == null ? void 0 : _b.call(adapter$1)) === true;
664
+ if (userForce || vipHide) {
665
+ return { ...EMPTY, reward_unit_id: raw.reward_unit_id, vip_no_ad: 1 };
666
+ }
667
+ return raw;
668
+ });
658
669
  async function loadConfig2(force = false) {
659
670
  if (loaded.value && !force)
660
671
  return;
@@ -683,7 +694,7 @@ function useAd() {
683
694
  return flight;
684
695
  }
685
696
  function getUnitId(type) {
686
- return store.config[`${type}_unit_id`] || "";
697
+ return config2.value[`${type}_unit_id`] || "";
687
698
  }
688
699
  async function showReward(onClose) {
689
700
  const unitId = getUnitId("reward");
@@ -1805,6 +1816,14 @@ function setupInterceptors(options = {}) {
1805
1816
  _interceptorCleanup.forEach((dispose) => dispose());
1806
1817
  _interceptorCleanup = [];
1807
1818
  const offRequest = http.onRequest((config2) => {
1819
+ const method = (config2.method ?? "GET").toUpperCase();
1820
+ if (method === "GET" && config2.data && typeof config2.data === "object") {
1821
+ const qs = Object.entries(config2.data).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
1822
+ if (qs) {
1823
+ config2.url = config2.url + (config2.url.includes("?") ? "&" : "?") + qs;
1824
+ }
1825
+ config2.data = void 0;
1826
+ }
1808
1827
  const device = useDevice();
1809
1828
  if (device.value) {
1810
1829
  const d = device.value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hlw-uni/mp-vue",
3
- "version": "2.1.12",
3
+ "version": "2.1.14",
4
4
  "description": "hlw-uni 小程序运行时 — Vue 组件 + composables + theme + http + 工具集(合并自原 mp-core)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/app.ts CHANGED
@@ -102,6 +102,21 @@ export function setupInterceptors(options: InterceptorOptions & { sigSecret?: st
102
102
  * 请求拦截:注入设备信息、签名和 token。
103
103
  */
104
104
  const offRequest = http.onRequest((config: RequestConfig) => {
105
+ // GET 请求:把 cfg.data 合并到 url query,并清空 cfg.data。
106
+ // 否则 uni.request 会在 sig 之后再把 data 自动拼到 URL,导致后端 raw query
107
+ // 多了未参与签名的字段(如 id/cate_id),sig 校验必然失败。
108
+ const method = (config.method ?? 'GET').toUpperCase();
109
+ if (method === 'GET' && config.data && typeof config.data === 'object') {
110
+ const qs = Object.entries(config.data as Record<string, unknown>)
111
+ .filter(([, v]) => v !== undefined && v !== null)
112
+ .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
113
+ .join('&');
114
+ if (qs) {
115
+ config.url = config.url + (config.url.includes('?') ? '&' : '?') + qs;
116
+ }
117
+ config.data = undefined;
118
+ }
119
+
105
120
  const device = useDevice();
106
121
  if (device.value) {
107
122
  const d = device.value;
@@ -43,7 +43,7 @@
43
43
  */
44
44
 
45
45
  import { defineStore, storeToRefs } from "pinia";
46
- import { ref } from "vue";
46
+ import { ref, computed } from "vue";
47
47
  import { useMsg, type HlwMsg } from "../msg";
48
48
  import { unwrapPayload, type AdapterPayload } from "../_internal/unwrap";
49
49
 
@@ -61,6 +61,8 @@ export interface AdConfig {
61
61
  video_unit_id: string;
62
62
  reward_unit_id: string;
63
63
  popup_unit_id: string;
64
+ /** VIP 屏蔽展示型广告(reward 除外):0=否,1=屏蔽 banner/grid/custom/video/popup */
65
+ vip_no_ad?: 0 | 1;
64
66
  }
65
67
 
66
68
  /** 广告错误对象(onError 回调参数) */
@@ -83,6 +85,13 @@ export interface AdAdapter {
83
85
  getConfig: () => Promise<AdapterPayload<AdConfig>>;
84
86
  /** 是否已登录;不传 = 不校验(showReward 调用前会问一次) */
85
87
  isAuth?: () => boolean;
88
+ /** 是否 VIP;配合 config.vip_no_ad=1 时屏蔽展示型广告(reward 不受影响) */
89
+ isVip?: () => boolean;
90
+ /**
91
+ * 用户级强制屏蔽:返回 true 直接屏蔽展示型广告(reward 不受影响),
92
+ * 优先级高于 mp.vip_no_ad + isVip 的联合判断;不传 = 不强制。
93
+ */
94
+ userNoAd?: () => boolean;
86
95
  }
87
96
 
88
97
  /** 激励视频关闭回调返回 */
@@ -98,6 +107,7 @@ const EMPTY: AdConfig = {
98
107
  video_unit_id: "",
99
108
  reward_unit_id: "",
100
109
  popup_unit_id: "",
110
+ vip_no_ad: 0,
101
111
  };
102
112
 
103
113
  let adapter: AdAdapter | null = null;
@@ -140,7 +150,22 @@ const interstitialCache = new Map<string, any>();
140
150
 
141
151
  export function useAd() {
142
152
  const store = useAdStore();
143
- const { config, loaded } = storeToRefs(store);
153
+ const { loaded } = storeToRefs(store);
154
+
155
+ /**
156
+ * 真实生效的广告配置;以下任一命中即屏蔽展示型 unit_id(reward 保留):
157
+ * 1. adapter.userNoAd() === true —— 用户级强制屏蔽,优先级最高
158
+ * 2. raw.vip_no_ad === 1 && adapter.isVip() —— 小程序级 VIP 隐藏开关
159
+ */
160
+ const config = computed<AdConfig>(() => {
161
+ const raw = store.config;
162
+ const userForce = adapter?.userNoAd?.() === true;
163
+ const vipHide = raw.vip_no_ad === 1 && adapter?.isVip?.() === true;
164
+ if (userForce || vipHide) {
165
+ return { ...EMPTY, reward_unit_id: raw.reward_unit_id, vip_no_ad: 1 };
166
+ }
167
+ return raw;
168
+ });
144
169
 
145
170
  /**
146
171
  * 拉取广告配置(小程序冷启动后调一次即可)。
@@ -171,9 +196,9 @@ export function useAd() {
171
196
  return flight;
172
197
  }
173
198
 
174
- /** 取指定类型的 unit_id(hlw-ad 组件 / 业务直接调时用) */
199
+ /** 取指定类型的 unit_id(hlw-ad 组件 / 业务直接调时用),自动应用 VIP 屏蔽 */
175
200
  function getUnitId(type: AdType): string {
176
- return store.config[`${type}_unit_id` as keyof AdConfig] || "";
201
+ return (config.value[`${type}_unit_id` as keyof AdConfig] as string) || "";
177
202
  }
178
203
 
179
204
  /**