@hlw-uni/mp-vue 2.1.10 → 2.1.12

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.
@@ -62,7 +62,7 @@ export declare function useAd(): {
62
62
  loadConfig: (force?: boolean) => Promise<void>;
63
63
  getUnitId: (type: AdType) => string;
64
64
  showReward: (onClose?: ((res: AdCloseResult) => void | Promise<void>) | undefined) => Promise<void>;
65
- showPopup: () => Promise<boolean>;
65
+ showPopup: (delayMs?: number) => Promise<boolean>;
66
66
  confirm: typeof confirmModal;
67
67
  };
68
68
  /**
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 算法集:把通用算法包成 useXxx composable,业务侧统一从这里取。
3
+ *
4
+ * 已有:
5
+ * - useUuid RFC 4122 v4,32 字符 hex
6
+ */
7
+ export { useUuid } from './uuid';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * UUID v4 生成器(RFC 4122 v4 算法),返回 32 字符 hex(无连字符)。
3
+ *
4
+ * 用途:当 nonce、idempotency key、临时唯一标识用。
5
+ *
6
+ * 算法:
7
+ * 1. 生成 16 字节随机源
8
+ * 2. byte 6 高 4 位置成 0100 标版本号 v4
9
+ * 3. byte 8 高 2 位置成 10 标变体(RFC 4122)
10
+ * 4. 16 字节转 hex 拼成 32 字符串
11
+ *
12
+ * 注意:随机源用 Math.random(小程序兼容兜底),加密强度有限,
13
+ * 不能用于密钥派生 / token 签发,只能挡重放。
14
+ */
15
+ export declare function useUuid(): {
16
+ v4: () => string;
17
+ };
@@ -16,6 +16,7 @@ export { useContact, setConfigContact, type ContactConfig, type ContactAdapter,
16
16
  export { useUtils, type DownloadFileOptions, type DownloadFileResult, type TapEvent } from './utils';
17
17
  export { useColor } from './color';
18
18
  export { useRouter, type NavigateType, type NavigateOptions } from './navigator';
19
+ export { useUuid } from './algo';
19
20
  export type { FontScale, FontPreset } from './theme';
20
21
  export { FONT_SCALE_KEY, FONT_PRESETS, getCurrentFontScale, getCurrentFontVars, THEME_CHANGE_EVENT, buildThemeStyle, useThemePageStyle, } from './theme';
21
22
  export type { ThemeColor } from './theme';
@@ -15,12 +15,12 @@ export interface NavigateOptions {
15
15
  onFail?: (errMsg: string) => void;
16
16
  /** 是否禁用默认的 Toast 错误提示,默认 false */
17
17
  silent?: boolean;
18
- /** 仅 miniprogram:目标小程序的页面路径(如 pages/index/index?id=1),留空则打开首页 */
19
- path?: string;
18
+ /** 仅 miniprogram:目标小程序的页面路径(如 pages/index/index?id=1),留空/null 则打开首页 */
19
+ path?: string | null;
20
20
  /** 仅 miniprogram:目标小程序版本,默认 release */
21
21
  envVersion?: "develop" | "trial" | "release";
22
22
  /** 仅 miniprogram:传给目标小程序的额外数据,对方从 onLaunch/onShow 读取 */
23
- extraData?: Record<string, unknown>;
23
+ extraData?: Record<string, unknown> | null;
24
24
  }
25
25
  /**
26
26
  * 根据 type + value 调用对应的 uni API,屏蔽参数差异。
package/dist/index.js CHANGED
@@ -630,6 +630,7 @@ var __publicField = (obj, key, value) => {
630
630
  }
631
631
  return raw;
632
632
  }
633
+ const DEFAULT_POPUP_DELAY_MS = 3e3;
633
634
  const EMPTY = {
634
635
  banner_unit_id: "",
635
636
  grid_unit_id: "",
@@ -686,7 +687,6 @@ var __publicField = (obj, key, value) => {
686
687
  return store.config[`${type}_unit_id`] || "";
687
688
  }
688
689
  async function showReward(onClose) {
689
- await loadConfig2();
690
690
  const unitId = getUnitId("reward");
691
691
  if (!unitId) {
692
692
  msg().toast("激励广告未配置");
@@ -700,12 +700,19 @@ var __publicField = (obj, key, value) => {
700
700
  if (onClose)
701
701
  await onClose(closeRes);
702
702
  }
703
- async function showPopup() {
704
- await loadConfig2();
705
- const unitId = getUnitId("popup");
706
- if (!unitId)
707
- return false;
708
- return await showInterstitialAd(unitId);
703
+ function showPopup(delayMs = DEFAULT_POPUP_DELAY_MS) {
704
+ return new Promise((resolve) => {
705
+ setTimeout(() => {
706
+ loadConfig2().then(() => {
707
+ const unitId = getUnitId("popup");
708
+ if (!unitId) {
709
+ resolve(false);
710
+ return;
711
+ }
712
+ showInterstitialAd(unitId).then(resolve);
713
+ });
714
+ }, delayMs);
715
+ });
709
716
  }
710
717
  return {
711
718
  // 状态
@@ -1115,7 +1122,7 @@ var __publicField = (obj, key, value) => {
1115
1122
  appId: value,
1116
1123
  path: options.path || "",
1117
1124
  envVersion: options.envVersion,
1118
- extraData: options.extraData,
1125
+ extraData: options.extraData ?? void 0,
1119
1126
  fail
1120
1127
  });
1121
1128
  break;
@@ -1131,6 +1138,18 @@ var __publicField = (obj, key, value) => {
1131
1138
  navigate: doNavigate
1132
1139
  };
1133
1140
  }
1141
+ function useUuid() {
1142
+ function v4() {
1143
+ const bytes = [];
1144
+ for (let i = 0; i < 16; i++) {
1145
+ bytes.push(Math.floor(Math.random() * 256));
1146
+ }
1147
+ bytes[6] = bytes[6] & 15 | 64;
1148
+ bytes[8] = bytes[8] & 63 | 128;
1149
+ return bytes.map((b) => b.toString(16).padStart(2, "0")).join("");
1150
+ }
1151
+ return { v4 };
1152
+ }
1134
1153
  const useThemeStore = pinia.defineStore(
1135
1154
  "theme",
1136
1155
  () => {
@@ -1933,6 +1952,7 @@ var __publicField = (obj, key, value) => {
1933
1952
  exports2.useThemeStore = useThemeStore;
1934
1953
  exports2.useUpload = useUpload;
1935
1954
  exports2.useUtils = useUtils;
1955
+ exports2.useUuid = useUuid;
1936
1956
  exports2.useValidate = useValidate;
1937
1957
  exports2.vCopy = vCopy;
1938
1958
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
package/dist/index.mjs CHANGED
@@ -629,6 +629,7 @@ function unwrapPayload(raw) {
629
629
  }
630
630
  return raw;
631
631
  }
632
+ const DEFAULT_POPUP_DELAY_MS = 3e3;
632
633
  const EMPTY = {
633
634
  banner_unit_id: "",
634
635
  grid_unit_id: "",
@@ -685,7 +686,6 @@ function useAd() {
685
686
  return store.config[`${type}_unit_id`] || "";
686
687
  }
687
688
  async function showReward(onClose) {
688
- await loadConfig2();
689
689
  const unitId = getUnitId("reward");
690
690
  if (!unitId) {
691
691
  msg().toast("激励广告未配置");
@@ -699,12 +699,19 @@ function useAd() {
699
699
  if (onClose)
700
700
  await onClose(closeRes);
701
701
  }
702
- async function showPopup() {
703
- await loadConfig2();
704
- const unitId = getUnitId("popup");
705
- if (!unitId)
706
- return false;
707
- return await showInterstitialAd(unitId);
702
+ function showPopup(delayMs = DEFAULT_POPUP_DELAY_MS) {
703
+ return new Promise((resolve) => {
704
+ setTimeout(() => {
705
+ loadConfig2().then(() => {
706
+ const unitId = getUnitId("popup");
707
+ if (!unitId) {
708
+ resolve(false);
709
+ return;
710
+ }
711
+ showInterstitialAd(unitId).then(resolve);
712
+ });
713
+ }, delayMs);
714
+ });
708
715
  }
709
716
  return {
710
717
  // 状态
@@ -1114,7 +1121,7 @@ function doNavigate(type, value, options = {}) {
1114
1121
  appId: value,
1115
1122
  path: options.path || "",
1116
1123
  envVersion: options.envVersion,
1117
- extraData: options.extraData,
1124
+ extraData: options.extraData ?? void 0,
1118
1125
  fail
1119
1126
  });
1120
1127
  break;
@@ -1130,6 +1137,18 @@ function useRouter() {
1130
1137
  navigate: doNavigate
1131
1138
  };
1132
1139
  }
1140
+ function useUuid() {
1141
+ function v4() {
1142
+ const bytes = [];
1143
+ for (let i = 0; i < 16; i++) {
1144
+ bytes.push(Math.floor(Math.random() * 256));
1145
+ }
1146
+ bytes[6] = bytes[6] & 15 | 64;
1147
+ bytes[8] = bytes[8] & 63 | 128;
1148
+ return bytes.map((b) => b.toString(16).padStart(2, "0")).join("");
1149
+ }
1150
+ return { v4 };
1151
+ }
1133
1152
  const useThemeStore = defineStore(
1134
1153
  "theme",
1135
1154
  () => {
@@ -1933,6 +1952,7 @@ export {
1933
1952
  useThemeStore,
1934
1953
  useUpload,
1935
1954
  useUtils,
1955
+ useUuid,
1936
1956
  useValidate,
1937
1957
  vCopy
1938
1958
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hlw-uni/mp-vue",
3
- "version": "2.1.10",
3
+ "version": "2.1.12",
4
4
  "description": "hlw-uni 小程序运行时 — Vue 组件 + composables + theme + http + 工具集(合并自原 mp-core)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -47,6 +47,9 @@ import { ref } from "vue";
47
47
  import { useMsg, type HlwMsg } from "../msg";
48
48
  import { unwrapPayload, type AdapterPayload } from "../_internal/unwrap";
49
49
 
50
+ /** showPopup 默认延迟(ms):避免一进页面就弹打扰用户 */
51
+ const DEFAULT_POPUP_DELAY_MS = 3000;
52
+
50
53
  /** 6 种广告类型 */
51
54
  export type AdType = "banner" | "grid" | "custom" | "video" | "reward" | "popup";
52
55
 
@@ -184,7 +187,6 @@ export function useAd() {
184
187
  * @param onClose 关闭回调;不传则只播。retry / toast / 发奖全在业务侧自己写。
185
188
  */
186
189
  async function showReward(onClose?: (res: AdCloseResult) => void | Promise<void>): Promise<void> {
187
- await loadConfig();
188
190
  const unitId = getUnitId("reward");
189
191
  if (!unitId) {
190
192
  msg().toast("激励广告未配置");
@@ -202,11 +204,28 @@ export function useAd() {
202
204
  * 显示插屏广告
203
205
  * @returns true=展示成功;false=配置缺失 / show 失败(如近期已展示过)
204
206
  */
205
- async function showPopup(): Promise<boolean> {
206
- await loadConfig();
207
- const unitId = getUnitId("popup");
208
- if (!unitId) return false;
209
- return await showInterstitialAd(unitId);
207
+ /**
208
+ * 显示插屏广告,默认延迟 3000ms 避免一进页面就弹打扰;传 0 立即弹。
209
+ * @returns true=展示成功;false=配置缺失 / show 失败(如近期已展示过)
210
+ *
211
+ * 实现注意:用 setTimeout + .then() 串接而非 async/await,保持 WX 插屏
212
+ * ad.show() 的调用栈跟 setTimeout 回调一致 —— 小程序引擎对插屏的合法
213
+ * 触发时机敏感,async/await 多插的 microtask 会被判为"非合法触发"导致
214
+ * 静默不弹。
215
+ */
216
+ function showPopup(delayMs: number = DEFAULT_POPUP_DELAY_MS): Promise<boolean> {
217
+ return new Promise<boolean>((resolve) => {
218
+ setTimeout(() => {
219
+ loadConfig().then(() => {
220
+ const unitId = getUnitId("popup");
221
+ if (!unitId) {
222
+ resolve(false);
223
+ return;
224
+ }
225
+ showInterstitialAd(unitId).then(resolve);
226
+ });
227
+ }, delayMs);
228
+ });
210
229
  }
211
230
 
212
231
  return {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 算法集:把通用算法包成 useXxx composable,业务侧统一从这里取。
3
+ *
4
+ * 已有:
5
+ * - useUuid RFC 4122 v4,32 字符 hex
6
+ */
7
+ export { useUuid } from "./uuid";
@@ -0,0 +1,27 @@
1
+ /**
2
+ * UUID v4 生成器(RFC 4122 v4 算法),返回 32 字符 hex(无连字符)。
3
+ *
4
+ * 用途:当 nonce、idempotency key、临时唯一标识用。
5
+ *
6
+ * 算法:
7
+ * 1. 生成 16 字节随机源
8
+ * 2. byte 6 高 4 位置成 0100 标版本号 v4
9
+ * 3. byte 8 高 2 位置成 10 标变体(RFC 4122)
10
+ * 4. 16 字节转 hex 拼成 32 字符串
11
+ *
12
+ * 注意:随机源用 Math.random(小程序兼容兜底),加密强度有限,
13
+ * 不能用于密钥派生 / token 签发,只能挡重放。
14
+ */
15
+ export function useUuid() {
16
+ function v4(): string {
17
+ const bytes: number[] = [];
18
+ for (let i = 0; i < 16; i++) {
19
+ bytes.push(Math.floor(Math.random() * 256));
20
+ }
21
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
22
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
23
+ return bytes.map((b) => b.toString(16).padStart(2, "0")).join("");
24
+ }
25
+
26
+ return { v4 };
27
+ }
@@ -45,6 +45,7 @@ export {
45
45
  export { useUtils, type DownloadFileOptions, type DownloadFileResult, type TapEvent } from "./utils";
46
46
  export { useColor } from "./color";
47
47
  export { useRouter, type NavigateType, type NavigateOptions } from "./navigator";
48
+ export { useUuid } from "./algo";
48
49
 
49
50
  // Theme(mp-vue 自带)
50
51
  export type { FontScale, FontPreset } from "./theme";
@@ -24,12 +24,12 @@ export interface NavigateOptions {
24
24
  onFail?: (errMsg: string) => void;
25
25
  /** 是否禁用默认的 Toast 错误提示,默认 false */
26
26
  silent?: boolean;
27
- /** 仅 miniprogram:目标小程序的页面路径(如 pages/index/index?id=1),留空则打开首页 */
28
- path?: string;
27
+ /** 仅 miniprogram:目标小程序的页面路径(如 pages/index/index?id=1),留空/null 则打开首页 */
28
+ path?: string | null;
29
29
  /** 仅 miniprogram:目标小程序版本,默认 release */
30
30
  envVersion?: "develop" | "trial" | "release";
31
31
  /** 仅 miniprogram:传给目标小程序的额外数据,对方从 onLaunch/onShow 读取 */
32
- extraData?: Record<string, unknown>;
32
+ extraData?: Record<string, unknown> | null;
33
33
  }
34
34
 
35
35
  /**
@@ -78,7 +78,7 @@ function doNavigate(type: NavigateType, value: string, options: NavigateOptions
78
78
  appId: value,
79
79
  path: options.path || "",
80
80
  envVersion: options.envVersion,
81
- extraData: options.extraData,
81
+ extraData: options.extraData ?? undefined,
82
82
  fail,
83
83
  });
84
84
  break;