@hlw-uni/mp-vue 2.1.54 → 2.1.56
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.
- package/dist/composables/ad/index.d.ts +16 -0
- package/dist/composables/index.d.ts +1 -0
- package/dist/index.js +135 -2
- package/dist/index.mjs +135 -2
- package/package.json +1 -1
- package/src/components/hlw-ad/index.vue +20 -6
- package/src/composables/ad/README.md +58 -0
- package/src/composables/ad/index.ts +153 -0
- package/src/composables/device/README.md +50 -0
- package/src/composables/index.ts +1 -0
- package/src/composables/msg/README.md +79 -0
- package/src/composables/navigator/README.md +71 -0
- package/src/composables/refs/README.md +40 -0
- package/src/composables/request/README.md +124 -0
- package/src/composables/request/adapters/oss.ts +1 -0
- package/src/composables/share/README.md +53 -0
- package/src/composables/theme/README.md +131 -0
- package/src/composables/utils/README.md +81 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 小程序广告工具。
|
|
3
|
+
*/
|
|
4
|
+
export interface AdRes {
|
|
5
|
+
ok: boolean;
|
|
6
|
+
isEnded?: boolean;
|
|
7
|
+
err?: unknown;
|
|
8
|
+
}
|
|
9
|
+
type AdDone = (res: AdRes) => void;
|
|
10
|
+
export declare function useHlwAd(): {
|
|
11
|
+
setAdPopup: (adId: string, done?: ((ok: boolean) => void) | undefined) => boolean;
|
|
12
|
+
showAdPopup: (delay?: number) => Promise<boolean>;
|
|
13
|
+
setAdReward: (adId: string, done?: AdDone) => Promise<AdRes>;
|
|
14
|
+
showAdReward: () => Promise<AdRes>;
|
|
15
|
+
};
|
|
16
|
+
export {};
|
|
@@ -6,6 +6,7 @@ export { useMsg, type HlwMsg, type ToastOptions, type ModalOptions, type ToastIc
|
|
|
6
6
|
export { useDevice, clearDeviceCache, type DeviceInfo, type DeviceQueryInfo, } from './device';
|
|
7
7
|
export { useRefs } from './refs';
|
|
8
8
|
export { useShare, type ShareConfig, } from './share';
|
|
9
|
+
export { useHlwAd, type AdRes } from './ad';
|
|
9
10
|
export { useUtils, type DownloadOpt, type DownloadRes } from './utils';
|
|
10
11
|
export { useNavigate, type NavigateType, type NavigateOptions } from './navigator';
|
|
11
12
|
export type { FontScale, FontPreset } from './theme';
|
package/dist/index.js
CHANGED
|
@@ -34,6 +34,7 @@ var __publicField = (obj, key, value) => {
|
|
|
34
34
|
buildFormData(ctx) {
|
|
35
35
|
const c = ctx.credentials ?? {};
|
|
36
36
|
return {
|
|
37
|
+
key: c["key"] ?? ctx.fileName,
|
|
37
38
|
policy: c["policy"] ?? "",
|
|
38
39
|
signature: c["signature"] ?? "",
|
|
39
40
|
OSSAccessKeyId: c["accessKeyId"] ?? "",
|
|
@@ -630,8 +631,8 @@ var __publicField = (obj, key, value) => {
|
|
|
630
631
|
}
|
|
631
632
|
function showShareMenu() {
|
|
632
633
|
var _a;
|
|
633
|
-
const
|
|
634
|
-
(_a =
|
|
634
|
+
const api2 = typeof uni !== "undefined" ? uni : void 0;
|
|
635
|
+
(_a = api2 == null ? void 0 : api2.showShareMenu) == null ? void 0 : _a.call(api2, {
|
|
635
636
|
withShareTicket: true,
|
|
636
637
|
menus: ["shareAppMessage", "shareTimeline"],
|
|
637
638
|
fail: () => void 0
|
|
@@ -670,6 +671,137 @@ var __publicField = (obj, key, value) => {
|
|
|
670
671
|
showShareMenu
|
|
671
672
|
};
|
|
672
673
|
}
|
|
674
|
+
let popupAd = null;
|
|
675
|
+
let popupDone;
|
|
676
|
+
let popupClose = null;
|
|
677
|
+
let popupError = null;
|
|
678
|
+
let rewardAd = null;
|
|
679
|
+
let rewardDone;
|
|
680
|
+
let rewardPromise = null;
|
|
681
|
+
let rewardResolve = null;
|
|
682
|
+
let rewardClose = null;
|
|
683
|
+
let rewardError = null;
|
|
684
|
+
function api() {
|
|
685
|
+
return typeof wx === "undefined" ? null : wx;
|
|
686
|
+
}
|
|
687
|
+
function finish(res) {
|
|
688
|
+
rewardDone == null ? void 0 : rewardDone(res);
|
|
689
|
+
rewardResolve == null ? void 0 : rewardResolve(res);
|
|
690
|
+
rewardResolve = null;
|
|
691
|
+
rewardPromise = null;
|
|
692
|
+
}
|
|
693
|
+
function clearReward() {
|
|
694
|
+
var _a, _b;
|
|
695
|
+
if (!rewardAd)
|
|
696
|
+
return;
|
|
697
|
+
if (rewardClose)
|
|
698
|
+
(_a = rewardAd.offClose) == null ? void 0 : _a.call(rewardAd, rewardClose);
|
|
699
|
+
if (rewardError)
|
|
700
|
+
(_b = rewardAd.offError) == null ? void 0 : _b.call(rewardAd, rewardError);
|
|
701
|
+
rewardClose = null;
|
|
702
|
+
rewardError = null;
|
|
703
|
+
}
|
|
704
|
+
function useHlwAd() {
|
|
705
|
+
function clearPopup() {
|
|
706
|
+
var _a, _b;
|
|
707
|
+
if (!popupAd)
|
|
708
|
+
return;
|
|
709
|
+
if (popupClose)
|
|
710
|
+
(_a = popupAd.offClose) == null ? void 0 : _a.call(popupAd, popupClose);
|
|
711
|
+
if (popupError)
|
|
712
|
+
(_b = popupAd.offError) == null ? void 0 : _b.call(popupAd, popupError);
|
|
713
|
+
popupClose = null;
|
|
714
|
+
popupError = null;
|
|
715
|
+
}
|
|
716
|
+
function setAdPopup(adId, done) {
|
|
717
|
+
var _a, _b, _c;
|
|
718
|
+
popupDone = done;
|
|
719
|
+
const wxApi = api();
|
|
720
|
+
if (!adId || !(wxApi == null ? void 0 : wxApi.createInterstitialAd))
|
|
721
|
+
return false;
|
|
722
|
+
clearPopup();
|
|
723
|
+
popupAd = wxApi.createInterstitialAd({ adUnitId: adId });
|
|
724
|
+
(_a = popupAd.onLoad) == null ? void 0 : _a.call(popupAd, () => {
|
|
725
|
+
});
|
|
726
|
+
popupError = (err) => {
|
|
727
|
+
console.error("插屏广告加载失败", err);
|
|
728
|
+
popupDone == null ? void 0 : popupDone(false);
|
|
729
|
+
};
|
|
730
|
+
popupClose = () => {
|
|
731
|
+
popupDone == null ? void 0 : popupDone(true);
|
|
732
|
+
};
|
|
733
|
+
(_b = popupAd.onError) == null ? void 0 : _b.call(popupAd, popupError);
|
|
734
|
+
(_c = popupAd.onClose) == null ? void 0 : _c.call(popupAd, popupClose);
|
|
735
|
+
return true;
|
|
736
|
+
}
|
|
737
|
+
function showAdPopup(delay = 3e3) {
|
|
738
|
+
return new Promise((resolve) => {
|
|
739
|
+
if (!popupAd) {
|
|
740
|
+
resolve(false);
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
const done = popupDone;
|
|
744
|
+
popupDone = (ok) => {
|
|
745
|
+
done == null ? void 0 : done(ok);
|
|
746
|
+
resolve(ok);
|
|
747
|
+
};
|
|
748
|
+
setTimeout(() => {
|
|
749
|
+
popupAd.show().catch((err) => {
|
|
750
|
+
console.error("插屏广告显示失败", err);
|
|
751
|
+
popupDone == null ? void 0 : popupDone(false);
|
|
752
|
+
});
|
|
753
|
+
}, Math.max(0, delay));
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
function setAdReward(adId, done) {
|
|
757
|
+
var _a, _b, _c;
|
|
758
|
+
rewardDone = done;
|
|
759
|
+
rewardPromise = new Promise((resolve) => {
|
|
760
|
+
rewardResolve = resolve;
|
|
761
|
+
});
|
|
762
|
+
const wxApi = api();
|
|
763
|
+
if (!adId || !(wxApi == null ? void 0 : wxApi.createRewardedVideoAd)) {
|
|
764
|
+
finish({ ok: false });
|
|
765
|
+
return rewardPromise;
|
|
766
|
+
}
|
|
767
|
+
clearReward();
|
|
768
|
+
rewardAd = wxApi.createRewardedVideoAd({ adUnitId: adId });
|
|
769
|
+
(_a = rewardAd.onLoad) == null ? void 0 : _a.call(rewardAd, () => {
|
|
770
|
+
});
|
|
771
|
+
rewardClose = (res) => {
|
|
772
|
+
finish({ ok: !!(res == null ? void 0 : res.isEnded), isEnded: !!(res == null ? void 0 : res.isEnded) });
|
|
773
|
+
};
|
|
774
|
+
rewardError = (err) => {
|
|
775
|
+
console.error("激励视频广告加载失败", err);
|
|
776
|
+
finish({ ok: false, err });
|
|
777
|
+
};
|
|
778
|
+
(_b = rewardAd.onClose) == null ? void 0 : _b.call(rewardAd, rewardClose);
|
|
779
|
+
(_c = rewardAd.onError) == null ? void 0 : _c.call(rewardAd, rewardError);
|
|
780
|
+
return rewardPromise;
|
|
781
|
+
}
|
|
782
|
+
function showAdReward() {
|
|
783
|
+
if (!rewardAd) {
|
|
784
|
+
return Promise.resolve({ ok: false });
|
|
785
|
+
}
|
|
786
|
+
const current = rewardPromise || new Promise((resolve) => {
|
|
787
|
+
rewardResolve = resolve;
|
|
788
|
+
});
|
|
789
|
+
rewardPromise = current;
|
|
790
|
+
rewardAd.show().catch(() => {
|
|
791
|
+
rewardAd.load().then(() => rewardAd.show()).catch((err) => {
|
|
792
|
+
console.error("激励视频广告显示失败", err);
|
|
793
|
+
finish({ ok: false, err });
|
|
794
|
+
});
|
|
795
|
+
});
|
|
796
|
+
return current;
|
|
797
|
+
}
|
|
798
|
+
return {
|
|
799
|
+
setAdPopup,
|
|
800
|
+
showAdPopup,
|
|
801
|
+
setAdReward,
|
|
802
|
+
showAdReward
|
|
803
|
+
};
|
|
804
|
+
}
|
|
673
805
|
function fail(message, options = {}) {
|
|
674
806
|
var _a;
|
|
675
807
|
if (!options.silent) {
|
|
@@ -1200,6 +1332,7 @@ var __publicField = (obj, key, value) => {
|
|
|
1200
1332
|
exports2.resolveAppearance = resolveAppearance;
|
|
1201
1333
|
exports2.useApp = useApp;
|
|
1202
1334
|
exports2.useDevice = useDevice;
|
|
1335
|
+
exports2.useHlwAd = useHlwAd;
|
|
1203
1336
|
exports2.useMsg = useMsg;
|
|
1204
1337
|
exports2.useNavigate = useNavigate;
|
|
1205
1338
|
exports2.useRefs = useRefs;
|
package/dist/index.mjs
CHANGED
|
@@ -33,6 +33,7 @@ const ossAdapter = {
|
|
|
33
33
|
buildFormData(ctx) {
|
|
34
34
|
const c = ctx.credentials ?? {};
|
|
35
35
|
return {
|
|
36
|
+
key: c["key"] ?? ctx.fileName,
|
|
36
37
|
policy: c["policy"] ?? "",
|
|
37
38
|
signature: c["signature"] ?? "",
|
|
38
39
|
OSSAccessKeyId: c["accessKeyId"] ?? "",
|
|
@@ -629,8 +630,8 @@ function buildPayload(base, extra) {
|
|
|
629
630
|
}
|
|
630
631
|
function showShareMenu() {
|
|
631
632
|
var _a;
|
|
632
|
-
const
|
|
633
|
-
(_a =
|
|
633
|
+
const api2 = typeof uni !== "undefined" ? uni : void 0;
|
|
634
|
+
(_a = api2 == null ? void 0 : api2.showShareMenu) == null ? void 0 : _a.call(api2, {
|
|
634
635
|
withShareTicket: true,
|
|
635
636
|
menus: ["shareAppMessage", "shareTimeline"],
|
|
636
637
|
fail: () => void 0
|
|
@@ -669,6 +670,137 @@ function useShare(config = {}) {
|
|
|
669
670
|
showShareMenu
|
|
670
671
|
};
|
|
671
672
|
}
|
|
673
|
+
let popupAd = null;
|
|
674
|
+
let popupDone;
|
|
675
|
+
let popupClose = null;
|
|
676
|
+
let popupError = null;
|
|
677
|
+
let rewardAd = null;
|
|
678
|
+
let rewardDone;
|
|
679
|
+
let rewardPromise = null;
|
|
680
|
+
let rewardResolve = null;
|
|
681
|
+
let rewardClose = null;
|
|
682
|
+
let rewardError = null;
|
|
683
|
+
function api() {
|
|
684
|
+
return typeof wx === "undefined" ? null : wx;
|
|
685
|
+
}
|
|
686
|
+
function finish(res) {
|
|
687
|
+
rewardDone == null ? void 0 : rewardDone(res);
|
|
688
|
+
rewardResolve == null ? void 0 : rewardResolve(res);
|
|
689
|
+
rewardResolve = null;
|
|
690
|
+
rewardPromise = null;
|
|
691
|
+
}
|
|
692
|
+
function clearReward() {
|
|
693
|
+
var _a, _b;
|
|
694
|
+
if (!rewardAd)
|
|
695
|
+
return;
|
|
696
|
+
if (rewardClose)
|
|
697
|
+
(_a = rewardAd.offClose) == null ? void 0 : _a.call(rewardAd, rewardClose);
|
|
698
|
+
if (rewardError)
|
|
699
|
+
(_b = rewardAd.offError) == null ? void 0 : _b.call(rewardAd, rewardError);
|
|
700
|
+
rewardClose = null;
|
|
701
|
+
rewardError = null;
|
|
702
|
+
}
|
|
703
|
+
function useHlwAd() {
|
|
704
|
+
function clearPopup() {
|
|
705
|
+
var _a, _b;
|
|
706
|
+
if (!popupAd)
|
|
707
|
+
return;
|
|
708
|
+
if (popupClose)
|
|
709
|
+
(_a = popupAd.offClose) == null ? void 0 : _a.call(popupAd, popupClose);
|
|
710
|
+
if (popupError)
|
|
711
|
+
(_b = popupAd.offError) == null ? void 0 : _b.call(popupAd, popupError);
|
|
712
|
+
popupClose = null;
|
|
713
|
+
popupError = null;
|
|
714
|
+
}
|
|
715
|
+
function setAdPopup(adId, done) {
|
|
716
|
+
var _a, _b, _c;
|
|
717
|
+
popupDone = done;
|
|
718
|
+
const wxApi = api();
|
|
719
|
+
if (!adId || !(wxApi == null ? void 0 : wxApi.createInterstitialAd))
|
|
720
|
+
return false;
|
|
721
|
+
clearPopup();
|
|
722
|
+
popupAd = wxApi.createInterstitialAd({ adUnitId: adId });
|
|
723
|
+
(_a = popupAd.onLoad) == null ? void 0 : _a.call(popupAd, () => {
|
|
724
|
+
});
|
|
725
|
+
popupError = (err) => {
|
|
726
|
+
console.error("插屏广告加载失败", err);
|
|
727
|
+
popupDone == null ? void 0 : popupDone(false);
|
|
728
|
+
};
|
|
729
|
+
popupClose = () => {
|
|
730
|
+
popupDone == null ? void 0 : popupDone(true);
|
|
731
|
+
};
|
|
732
|
+
(_b = popupAd.onError) == null ? void 0 : _b.call(popupAd, popupError);
|
|
733
|
+
(_c = popupAd.onClose) == null ? void 0 : _c.call(popupAd, popupClose);
|
|
734
|
+
return true;
|
|
735
|
+
}
|
|
736
|
+
function showAdPopup(delay = 3e3) {
|
|
737
|
+
return new Promise((resolve) => {
|
|
738
|
+
if (!popupAd) {
|
|
739
|
+
resolve(false);
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
const done = popupDone;
|
|
743
|
+
popupDone = (ok) => {
|
|
744
|
+
done == null ? void 0 : done(ok);
|
|
745
|
+
resolve(ok);
|
|
746
|
+
};
|
|
747
|
+
setTimeout(() => {
|
|
748
|
+
popupAd.show().catch((err) => {
|
|
749
|
+
console.error("插屏广告显示失败", err);
|
|
750
|
+
popupDone == null ? void 0 : popupDone(false);
|
|
751
|
+
});
|
|
752
|
+
}, Math.max(0, delay));
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
function setAdReward(adId, done) {
|
|
756
|
+
var _a, _b, _c;
|
|
757
|
+
rewardDone = done;
|
|
758
|
+
rewardPromise = new Promise((resolve) => {
|
|
759
|
+
rewardResolve = resolve;
|
|
760
|
+
});
|
|
761
|
+
const wxApi = api();
|
|
762
|
+
if (!adId || !(wxApi == null ? void 0 : wxApi.createRewardedVideoAd)) {
|
|
763
|
+
finish({ ok: false });
|
|
764
|
+
return rewardPromise;
|
|
765
|
+
}
|
|
766
|
+
clearReward();
|
|
767
|
+
rewardAd = wxApi.createRewardedVideoAd({ adUnitId: adId });
|
|
768
|
+
(_a = rewardAd.onLoad) == null ? void 0 : _a.call(rewardAd, () => {
|
|
769
|
+
});
|
|
770
|
+
rewardClose = (res) => {
|
|
771
|
+
finish({ ok: !!(res == null ? void 0 : res.isEnded), isEnded: !!(res == null ? void 0 : res.isEnded) });
|
|
772
|
+
};
|
|
773
|
+
rewardError = (err) => {
|
|
774
|
+
console.error("激励视频广告加载失败", err);
|
|
775
|
+
finish({ ok: false, err });
|
|
776
|
+
};
|
|
777
|
+
(_b = rewardAd.onClose) == null ? void 0 : _b.call(rewardAd, rewardClose);
|
|
778
|
+
(_c = rewardAd.onError) == null ? void 0 : _c.call(rewardAd, rewardError);
|
|
779
|
+
return rewardPromise;
|
|
780
|
+
}
|
|
781
|
+
function showAdReward() {
|
|
782
|
+
if (!rewardAd) {
|
|
783
|
+
return Promise.resolve({ ok: false });
|
|
784
|
+
}
|
|
785
|
+
const current = rewardPromise || new Promise((resolve) => {
|
|
786
|
+
rewardResolve = resolve;
|
|
787
|
+
});
|
|
788
|
+
rewardPromise = current;
|
|
789
|
+
rewardAd.show().catch(() => {
|
|
790
|
+
rewardAd.load().then(() => rewardAd.show()).catch((err) => {
|
|
791
|
+
console.error("激励视频广告显示失败", err);
|
|
792
|
+
finish({ ok: false, err });
|
|
793
|
+
});
|
|
794
|
+
});
|
|
795
|
+
return current;
|
|
796
|
+
}
|
|
797
|
+
return {
|
|
798
|
+
setAdPopup,
|
|
799
|
+
showAdPopup,
|
|
800
|
+
setAdReward,
|
|
801
|
+
showAdReward
|
|
802
|
+
};
|
|
803
|
+
}
|
|
672
804
|
function fail(message, options = {}) {
|
|
673
805
|
var _a;
|
|
674
806
|
if (!options.silent) {
|
|
@@ -1200,6 +1332,7 @@ export {
|
|
|
1200
1332
|
resolveAppearance,
|
|
1201
1333
|
useApp,
|
|
1202
1334
|
useDevice,
|
|
1335
|
+
useHlwAd,
|
|
1203
1336
|
useMsg,
|
|
1204
1337
|
useNavigate,
|
|
1205
1338
|
useRefs,
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
------------------------------------------------------------------
|
|
4
4
|
用法(业务方从自己的接口配置取对应 unit_id 传入):
|
|
5
5
|
hlw-ad type="banner" :unit-id="config.banner_unit_id"
|
|
6
|
-
hlw-ad type="grid" :unit-id="config.grid_unit_id"
|
|
6
|
+
hlw-ad type="grid" :unit-id="config.grid_unit_id" placement="right-middle"
|
|
7
7
|
hlw-ad type="custom" :unit-id="config.custom_unit_id"
|
|
8
8
|
|
|
9
9
|
渲染分支:
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
<template>
|
|
18
18
|
<view
|
|
19
19
|
v-if="visible"
|
|
20
|
-
:class="['hlw-ad', `hlw-ad--${type}`, customClass]"
|
|
21
|
-
:style="
|
|
20
|
+
:class="['hlw-ad', `hlw-ad--${type}`, type === 'grid' ? `hlw-ad--${placement}` : '', customClass]"
|
|
21
|
+
:style="style"
|
|
22
22
|
>
|
|
23
23
|
<ad
|
|
24
24
|
v-if="type === 'banner'"
|
|
@@ -41,11 +41,15 @@ import { computed } from "vue";
|
|
|
41
41
|
|
|
42
42
|
defineOptions({ name: "HlwAd" });
|
|
43
43
|
|
|
44
|
+
type GridPlacement = "left-top" | "right-top" | "left-middle" | "right-middle" | "left-bottom" | "right-bottom" | "center";
|
|
45
|
+
|
|
44
46
|
interface Props {
|
|
45
47
|
/** 广告类型 — 仅展示型(banner / grid / custom) */
|
|
46
48
|
type: "banner" | "grid" | "custom";
|
|
47
49
|
/** 微信广告单元 id;空字符串 → 不渲染 */
|
|
48
50
|
unitId: string;
|
|
51
|
+
/** grid 广告悬浮位置 */
|
|
52
|
+
placement?: GridPlacement;
|
|
49
53
|
/** 自定义样式(合并到根元素) */
|
|
50
54
|
customStyle?: string;
|
|
51
55
|
/** 自定义 class */
|
|
@@ -53,6 +57,7 @@ interface Props {
|
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
const props = withDefaults(defineProps<Props>(), {
|
|
60
|
+
placement: "right-middle",
|
|
56
61
|
customStyle: "",
|
|
57
62
|
customClass: "",
|
|
58
63
|
});
|
|
@@ -64,6 +69,17 @@ const emit = defineEmits<{
|
|
|
64
69
|
|
|
65
70
|
/** 有 unit_id 才渲染 */
|
|
66
71
|
const visible = computed(() => !!props.unitId);
|
|
72
|
+
const style = computed(() => [props.type === "grid" ? styleMap[props.placement] : "", props.customStyle].filter(Boolean).join(";"));
|
|
73
|
+
const safe = "24rpx";
|
|
74
|
+
const styleMap: Record<GridPlacement, string> = {
|
|
75
|
+
"left-top": `top:${safe};left:${safe};right:auto;bottom:auto;transform:none;`,
|
|
76
|
+
"right-top": `top:${safe};right:${safe};left:auto;bottom:auto;transform:none;`,
|
|
77
|
+
"left-middle": `top:50%;left:${safe};right:auto;bottom:auto;transform:translateY(-50%);`,
|
|
78
|
+
"right-middle": `top:50%;right:${safe};left:auto;bottom:auto;transform:translateY(-50%);`,
|
|
79
|
+
"left-bottom": `left:${safe};bottom:200rpx;right:auto;top:auto;transform:none;`,
|
|
80
|
+
"right-bottom": `right:${safe};bottom:200rpx;left:auto;top:auto;transform:none;`,
|
|
81
|
+
center: "top:50%;left:50%;right:auto;bottom:auto;transform:translate(-50%, -50%);",
|
|
82
|
+
};
|
|
67
83
|
|
|
68
84
|
function onLoad(event: any) {
|
|
69
85
|
emit("load", event);
|
|
@@ -81,11 +97,9 @@ function onError(event: any) {
|
|
|
81
97
|
background: var(--surface-card, #ffffff);
|
|
82
98
|
}
|
|
83
99
|
|
|
84
|
-
/*
|
|
100
|
+
/* 格子广告:默认居中悬浮;微信硬性规则要求 wrapper 透明无圆角,customStyle 可覆盖 */
|
|
85
101
|
.hlw-ad--grid {
|
|
86
102
|
position: fixed;
|
|
87
|
-
right: 20rpx;
|
|
88
|
-
bottom: 200rpx;
|
|
89
103
|
z-index: 99;
|
|
90
104
|
border-radius: 0;
|
|
91
105
|
overflow: visible;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# ad 调用文档
|
|
2
|
+
|
|
3
|
+
`useHlwAd` 封装微信小程序插屏广告和激励视频广告。仅在存在 `wx` 且对应广告 API 可用时生效。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { useHlwAd } from "@hlw-uni/mp-vue";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 插屏广告
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const ad = useHlwAd();
|
|
15
|
+
|
|
16
|
+
ad.setAdPopup("adunit-popup-id", (ok) => {
|
|
17
|
+
console.log("插屏广告关闭", ok);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await ad.showAdPopup(1000);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 激励视频
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
const ad = useHlwAd();
|
|
27
|
+
|
|
28
|
+
ad.setAdReward("adunit-reward-id", (res) => {
|
|
29
|
+
if (res.ok) {
|
|
30
|
+
// 用户完整看完激励视频
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const result = await ad.showAdReward();
|
|
35
|
+
|
|
36
|
+
if (result.ok) {
|
|
37
|
+
// 发放奖励
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## API
|
|
42
|
+
|
|
43
|
+
| 方法 | 说明 |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `setAdPopup(adId, done?)` | 创建插屏广告实例 |
|
|
46
|
+
| `showAdPopup(delay?)` | 延迟展示插屏广告,默认 3000ms |
|
|
47
|
+
| `setAdReward(adId, done?)` | 创建激励视频实例 |
|
|
48
|
+
| `showAdReward()` | 展示激励视频,失败时会尝试 load 后再 show |
|
|
49
|
+
|
|
50
|
+
## 类型
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
interface AdRes {
|
|
54
|
+
ok: boolean;
|
|
55
|
+
isEnded?: boolean;
|
|
56
|
+
err?: unknown;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 小程序广告工具。
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
declare const wx: any;
|
|
6
|
+
|
|
7
|
+
export interface AdRes {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
isEnded?: boolean;
|
|
10
|
+
err?: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type AdDone = (res: AdRes) => void;
|
|
14
|
+
|
|
15
|
+
let popupAd: any = null;
|
|
16
|
+
let popupDone: ((ok: boolean) => void) | undefined;
|
|
17
|
+
let popupClose: (() => void) | null = null;
|
|
18
|
+
let popupError: ((err: unknown) => void) | null = null;
|
|
19
|
+
|
|
20
|
+
let rewardAd: any = null;
|
|
21
|
+
let rewardDone: AdDone | undefined;
|
|
22
|
+
let rewardPromise: Promise<AdRes> | null = null;
|
|
23
|
+
let rewardResolve: ((res: AdRes) => void) | null = null;
|
|
24
|
+
let rewardClose: ((res: { isEnded?: boolean }) => void) | null = null;
|
|
25
|
+
let rewardError: ((err: unknown) => void) | null = null;
|
|
26
|
+
|
|
27
|
+
function api() {
|
|
28
|
+
return typeof wx === "undefined" ? null : wx;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function finish(res: AdRes) {
|
|
32
|
+
rewardDone?.(res);
|
|
33
|
+
rewardResolve?.(res);
|
|
34
|
+
rewardResolve = null;
|
|
35
|
+
rewardPromise = null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function clearReward() {
|
|
39
|
+
if (!rewardAd) return;
|
|
40
|
+
if (rewardClose) rewardAd.offClose?.(rewardClose);
|
|
41
|
+
if (rewardError) rewardAd.offError?.(rewardError);
|
|
42
|
+
rewardClose = null;
|
|
43
|
+
rewardError = null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function useHlwAd() {
|
|
47
|
+
function clearPopup() {
|
|
48
|
+
if (!popupAd) return;
|
|
49
|
+
if (popupClose) popupAd.offClose?.(popupClose);
|
|
50
|
+
if (popupError) popupAd.offError?.(popupError);
|
|
51
|
+
popupClose = null;
|
|
52
|
+
popupError = null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function setAdPopup(adId: string, done?: (ok: boolean) => void): boolean {
|
|
56
|
+
popupDone = done;
|
|
57
|
+
const wxApi = api();
|
|
58
|
+
if (!adId || !wxApi?.createInterstitialAd) return false;
|
|
59
|
+
|
|
60
|
+
clearPopup();
|
|
61
|
+
popupAd = wxApi.createInterstitialAd({ adUnitId: adId });
|
|
62
|
+
popupAd.onLoad?.(() => {});
|
|
63
|
+
popupError = (err: unknown) => {
|
|
64
|
+
console.error("插屏广告加载失败", err);
|
|
65
|
+
popupDone?.(false);
|
|
66
|
+
};
|
|
67
|
+
popupClose = () => {
|
|
68
|
+
popupDone?.(true);
|
|
69
|
+
};
|
|
70
|
+
popupAd.onError?.(popupError);
|
|
71
|
+
popupAd.onClose?.(popupClose);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function showAdPopup(delay = 3000): Promise<boolean> {
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
if (!popupAd) {
|
|
78
|
+
resolve(false);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const done = popupDone;
|
|
83
|
+
popupDone = (ok: boolean) => {
|
|
84
|
+
done?.(ok);
|
|
85
|
+
resolve(ok);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
popupAd.show().catch((err: unknown) => {
|
|
90
|
+
console.error("插屏广告显示失败", err);
|
|
91
|
+
popupDone?.(false);
|
|
92
|
+
});
|
|
93
|
+
}, Math.max(0, delay));
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
function setAdReward(adId: string, done?: AdDone): Promise<AdRes> {
|
|
99
|
+
rewardDone = done;
|
|
100
|
+
rewardPromise = new Promise((resolve) => {
|
|
101
|
+
rewardResolve = resolve;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const wxApi = api();
|
|
105
|
+
if (!adId || !wxApi?.createRewardedVideoAd) {
|
|
106
|
+
finish({ ok: false });
|
|
107
|
+
return rewardPromise;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
clearReward();
|
|
111
|
+
rewardAd = wxApi.createRewardedVideoAd({ adUnitId: adId });
|
|
112
|
+
rewardAd.onLoad?.(() => {});
|
|
113
|
+
rewardClose = (res: { isEnded?: boolean }) => {
|
|
114
|
+
finish({ ok: !!res?.isEnded, isEnded: !!res?.isEnded });
|
|
115
|
+
};
|
|
116
|
+
rewardError = (err: unknown) => {
|
|
117
|
+
console.error("激励视频广告加载失败", err);
|
|
118
|
+
finish({ ok: false, err });
|
|
119
|
+
};
|
|
120
|
+
rewardAd.onClose?.(rewardClose);
|
|
121
|
+
rewardAd.onError?.(rewardError);
|
|
122
|
+
return rewardPromise;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function showAdReward(): Promise<AdRes> {
|
|
126
|
+
if (!rewardAd) {
|
|
127
|
+
return Promise.resolve({ ok: false });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const current = rewardPromise || new Promise<AdRes>((resolve) => {
|
|
131
|
+
rewardResolve = resolve;
|
|
132
|
+
});
|
|
133
|
+
rewardPromise = current;
|
|
134
|
+
|
|
135
|
+
rewardAd.show().catch(() => {
|
|
136
|
+
rewardAd.load()
|
|
137
|
+
.then(() => rewardAd.show())
|
|
138
|
+
.catch((err: unknown) => {
|
|
139
|
+
console.error("激励视频广告显示失败", err);
|
|
140
|
+
finish({ ok: false, err });
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return current;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
setAdPopup,
|
|
149
|
+
showAdPopup,
|
|
150
|
+
setAdReward,
|
|
151
|
+
showAdReward,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# device 调用文档
|
|
2
|
+
|
|
3
|
+
`useDevice` 采集并缓存设备、窗口、宿主和小程序信息,同时提供常用设备字段组成的 query 字符串。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { useDevice, clearDeviceCache } from "@hlw-uni/mp-vue";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 基础用法
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const { info, query } = useDevice();
|
|
15
|
+
|
|
16
|
+
console.log(info.appid);
|
|
17
|
+
console.log(info.device_model);
|
|
18
|
+
console.log(query);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`useDevice` 内部会优先读取 `uni.getDeviceInfo`、`uni.getWindowInfo`、`uni.getAppBaseInfo`,旧环境会回退到 `uni.getSystemInfoSync`。
|
|
22
|
+
|
|
23
|
+
## 清除缓存
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
clearDeviceCache();
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
切换账号、切换宿主环境或需要重新采集设备信息时可以手动清理缓存。
|
|
30
|
+
|
|
31
|
+
## 返回值
|
|
32
|
+
|
|
33
|
+
| 字段 | 说明 |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `info` | 完整 `DeviceInfo` |
|
|
36
|
+
| `query` | 常用设备字段组成的 URL query 字符串 |
|
|
37
|
+
|
|
38
|
+
## 常用字段
|
|
39
|
+
|
|
40
|
+
| 字段 | 说明 |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `appid` | 小程序 appId |
|
|
43
|
+
| `device_brand` | 设备品牌 |
|
|
44
|
+
| `device_model` | 设备型号 |
|
|
45
|
+
| `device_id` | 设备 ID |
|
|
46
|
+
| `platform` | 平台类型 |
|
|
47
|
+
| `system` | 系统版本 |
|
|
48
|
+
| `sdk_version` | 基础库版本 |
|
|
49
|
+
| `screen_width` | 屏幕宽度 |
|
|
50
|
+
| `screen_height` | 屏幕高度 |
|
package/src/composables/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ export {
|
|
|
14
14
|
useShare,
|
|
15
15
|
type ShareConfig,
|
|
16
16
|
} from "./share";
|
|
17
|
+
export { useHlwAd, type AdRes } from "./ad";
|
|
17
18
|
export { useUtils, type DownloadOpt, type DownloadRes } from "./utils";
|
|
18
19
|
export { useNavigate, type NavigateType, type NavigateOptions } from "./navigator";
|
|
19
20
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# msg 调用文档
|
|
2
|
+
|
|
3
|
+
`useMsg` 统一封装 toast、loading、modal 和简单进度展示。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { useMsg } from "@hlw-uni/mp-vue";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 基础用法
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const msg = useMsg();
|
|
15
|
+
|
|
16
|
+
msg.toast("保存中");
|
|
17
|
+
msg.success("保存成功");
|
|
18
|
+
msg.error("保存失败");
|
|
19
|
+
|
|
20
|
+
msg.showLoading("加载中...");
|
|
21
|
+
msg.hideLoading();
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 确认弹窗
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const ok = await msg.confirm({
|
|
28
|
+
title: "删除确认",
|
|
29
|
+
content: "确定删除这条记录吗?",
|
|
30
|
+
confirmText: "删除",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (ok) {
|
|
34
|
+
// 用户点击确认
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`modal` 是 `confirm` 的语义别名。
|
|
39
|
+
|
|
40
|
+
## API
|
|
41
|
+
|
|
42
|
+
| 方法 | 说明 |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `toast(opts | string)` | 普通提示 |
|
|
45
|
+
| `success(message)` | 成功提示 |
|
|
46
|
+
| `error(message)` | 失败提示 |
|
|
47
|
+
| `fail(message)` | `error` 的别名 |
|
|
48
|
+
| `showLoading(message?)` | 显示全局 loading |
|
|
49
|
+
| `hideLoading()` | 关闭全局 loading |
|
|
50
|
+
| `confirm(opts)` | 确认弹窗,返回 `Promise<boolean>` |
|
|
51
|
+
| `modal(opts)` | `confirm` 的别名 |
|
|
52
|
+
| `setLoadingBar(progress)` | 用导航标题模拟进度 |
|
|
53
|
+
|
|
54
|
+
## ToastOptions
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
interface ToastOptions {
|
|
58
|
+
message: string;
|
|
59
|
+
icon?: "success" | "fail" | "exception" | "none";
|
|
60
|
+
image?: string;
|
|
61
|
+
duration?: number;
|
|
62
|
+
mask?: boolean;
|
|
63
|
+
position?: "top" | "center" | "bottom";
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## ModalOptions
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
interface ModalOptions {
|
|
71
|
+
title?: string;
|
|
72
|
+
content: string;
|
|
73
|
+
confirmText?: string;
|
|
74
|
+
cancelText?: string;
|
|
75
|
+
confirmColor?: string;
|
|
76
|
+
cancelColor?: string;
|
|
77
|
+
showCancel?: boolean;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# navigator 调用文档
|
|
2
|
+
|
|
3
|
+
`useNavigate` 统一封装 uni-app 页面跳转、tab 跳转、返回和打开其他小程序。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { useNavigate } from "@hlw-uni/mp-vue";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 基础用法
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const nav = useNavigate();
|
|
15
|
+
|
|
16
|
+
nav.to("/pages/detail/index?id=1");
|
|
17
|
+
nav.redirect("/pages/login/index");
|
|
18
|
+
nav.tab("/pages/index/index");
|
|
19
|
+
nav.reLaunch("/pages/index/index");
|
|
20
|
+
nav.back();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 打开其他小程序
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
nav.miniProgram("wx1234567890", {
|
|
27
|
+
path: "pages/index/index?id=1",
|
|
28
|
+
envVersion: "release",
|
|
29
|
+
extraData: {
|
|
30
|
+
from: "hlw",
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 通用跳转
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
nav.navigate("navigateTo", "/pages/detail/index?id=1", {
|
|
39
|
+
silent: true,
|
|
40
|
+
onFail: (message) => {
|
|
41
|
+
console.log(message);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## API
|
|
47
|
+
|
|
48
|
+
| 方法 | 说明 |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `navigate(type, url, options?)` | 通用跳转入口 |
|
|
51
|
+
| `to(url, options?)` | `uni.navigateTo` |
|
|
52
|
+
| `redirect(url, options?)` | `uni.redirectTo` |
|
|
53
|
+
| `tab(url, options?)` | `uni.switchTab` |
|
|
54
|
+
| `reLaunch(url, options?)` | `uni.reLaunch` |
|
|
55
|
+
| `back(delta?, options?)` | `uni.navigateBack` |
|
|
56
|
+
| `miniProgram(appId, options?)` | `uni.navigateToMiniProgram` |
|
|
57
|
+
|
|
58
|
+
## NavigateOptions
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
interface NavigateOptions {
|
|
62
|
+
silent?: boolean;
|
|
63
|
+
onFail?: (message: string) => void;
|
|
64
|
+
delta?: number;
|
|
65
|
+
path?: string;
|
|
66
|
+
envVersion?: "develop" | "trial" | "release";
|
|
67
|
+
extraData?: Record<string, unknown>;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`webview` 类型当前只提示 `H5:{url}`,具体 web-view 承载页由业务项目实现。
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# refs 调用文档
|
|
2
|
+
|
|
3
|
+
`useRefs` 用于 `v-for` 场景批量收集组件或元素引用。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { useRefs } from "@hlw-uni/mp-vue";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 基础用法
|
|
12
|
+
|
|
13
|
+
```vue
|
|
14
|
+
<template>
|
|
15
|
+
<hlw-popup
|
|
16
|
+
v-for="item in list"
|
|
17
|
+
:key="item.id"
|
|
18
|
+
:ref="setRefs(item.id)"
|
|
19
|
+
/>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import { useRefs } from "@hlw-uni/mp-vue";
|
|
24
|
+
|
|
25
|
+
const { refs, setRefs } = useRefs();
|
|
26
|
+
|
|
27
|
+
function open(id: string) {
|
|
28
|
+
refs.value[id]?.open?.();
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 返回值
|
|
34
|
+
|
|
35
|
+
| 字段 | 说明 |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `refs` | `Record<string, any>` 的响应式引用集合 |
|
|
38
|
+
| `setRefs(key)` | 返回可绑定到模板 `ref` 的回调函数 |
|
|
39
|
+
|
|
40
|
+
组件更新前和卸载时,内部会自动清空引用集合,避免旧引用残留。
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# request 调用文档
|
|
2
|
+
|
|
3
|
+
`request` 模块封装 `uni.request`、请求拦截器、响应拦截器、错误拦截器、上传和服务类组织方式。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import {
|
|
9
|
+
useRequest,
|
|
10
|
+
useUpload,
|
|
11
|
+
BaseService,
|
|
12
|
+
ServiceNamespace,
|
|
13
|
+
ServicePrefix,
|
|
14
|
+
} from "@hlw-uni/mp-vue";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## useRequest
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
const request = useRequest();
|
|
21
|
+
|
|
22
|
+
request.setBaseURL("https://api.example.com");
|
|
23
|
+
|
|
24
|
+
const offRequest = request.onRequest((config) => {
|
|
25
|
+
config.headers = {
|
|
26
|
+
...config.headers,
|
|
27
|
+
"x-token": uni.getStorageSync("token"),
|
|
28
|
+
};
|
|
29
|
+
return config;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const res = await request.get<{ name: string }>("/user/profile");
|
|
33
|
+
|
|
34
|
+
offRequest();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
| 方法 | 说明 |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `request(config)` | 发起完整配置请求 |
|
|
42
|
+
| `get(url, data?)` | GET 请求 |
|
|
43
|
+
| `post(url, data?)` | POST 请求 |
|
|
44
|
+
| `put(url, data?)` | PUT 请求 |
|
|
45
|
+
| `del(url, data?)` | DELETE 请求 |
|
|
46
|
+
| `setBaseURL(url)` | 设置全局基础地址 |
|
|
47
|
+
| `onRequest(fn)` | 注册请求拦截器,返回取消函数 |
|
|
48
|
+
| `onResponse(fn)` | 注册响应拦截器,返回取消函数 |
|
|
49
|
+
| `onError(fn)` | 注册错误拦截器,返回取消函数 |
|
|
50
|
+
| `upload(config)` | 上传文件 |
|
|
51
|
+
| `resolveServiceUrl(namespace, url, servicePrefix?)` | 生成服务类请求地址 |
|
|
52
|
+
|
|
53
|
+
## 响应格式
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
interface ApiResponse<T = unknown> {
|
|
57
|
+
code: number;
|
|
58
|
+
data: T;
|
|
59
|
+
info: string;
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## useUpload
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
const { uploading, upload } = useUpload();
|
|
67
|
+
|
|
68
|
+
const result = await upload({
|
|
69
|
+
type: "local",
|
|
70
|
+
server: "https://api.example.com/upload",
|
|
71
|
+
url: "https://api.example.com/upload",
|
|
72
|
+
filePath: tempFilePath,
|
|
73
|
+
header: {
|
|
74
|
+
"x-token": uni.getStorageSync("token"),
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
console.log(uploading.value, result.data);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
上传类型:
|
|
82
|
+
|
|
83
|
+
| 类型 | 说明 |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `local` | 直接上传到业务接口 |
|
|
86
|
+
| `cos` | 腾讯云 COS 表单上传 |
|
|
87
|
+
| `oss` | 阿里云 OSS 表单上传 |
|
|
88
|
+
| `qiniu` | 七牛云表单上传 |
|
|
89
|
+
| `alist` | Alist 上传 |
|
|
90
|
+
|
|
91
|
+
## BaseService
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
@ServicePrefix("api")
|
|
95
|
+
@ServiceNamespace("user")
|
|
96
|
+
class UserService extends BaseService {
|
|
97
|
+
profile() {
|
|
98
|
+
return this.get<{ nickname: string }>("/profile");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
update(data: { nickname: string }) {
|
|
102
|
+
return this.post("/update", data);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const userService = new UserService();
|
|
107
|
+
const profile = await userService.profile();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
上面的 `profile()` 会请求 `/api/user/profile`。如果传入绝对地址,例如 `https://example.com/a`,则不会拼接前缀。
|
|
111
|
+
|
|
112
|
+
## UploadConfig
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
interface UploadConfig {
|
|
116
|
+
server: string;
|
|
117
|
+
filePath: string;
|
|
118
|
+
fileName?: string;
|
|
119
|
+
type: string;
|
|
120
|
+
credentials?: Record<string, string>;
|
|
121
|
+
header?: Record<string, string>;
|
|
122
|
+
url?: string;
|
|
123
|
+
}
|
|
124
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# share 调用文档
|
|
2
|
+
|
|
3
|
+
`useShare` 注册微信小程序分享给好友和分享到朋友圈,并尝试打开分享菜单。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { useShare } from "@hlw-uni/mp-vue";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 基础用法
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
useShare({
|
|
15
|
+
title: "好用的小程序",
|
|
16
|
+
path: "/pages/index/index?from=share",
|
|
17
|
+
imageUrl: "https://example.com/share.png",
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 动态分享内容
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
const share = useShare(() => ({
|
|
25
|
+
title: detail.value.title,
|
|
26
|
+
path: `/pages/detail/index?id=${detail.value.id}`,
|
|
27
|
+
imageUrl: detail.value.cover,
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
share.onShareAppMessage({
|
|
31
|
+
title: "覆盖好友分享标题",
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## API
|
|
36
|
+
|
|
37
|
+
| 方法 | 说明 |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `onShareAppMessage(config?)` | 注册好友分享 |
|
|
40
|
+
| `onShareTimeline(config?)` | 注册朋友圈分享 |
|
|
41
|
+
| `showShareMenu()` | 主动显示分享菜单 |
|
|
42
|
+
|
|
43
|
+
同一个 `useShare` 实例中,好友分享和朋友圈分享各只注册一次。
|
|
44
|
+
|
|
45
|
+
## ShareConfig
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
interface ShareConfig {
|
|
49
|
+
title?: string;
|
|
50
|
+
path?: string;
|
|
51
|
+
imageUrl?: string;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# theme 调用文档
|
|
2
|
+
|
|
3
|
+
`theme` 模块提供字体档位、主题色、外观模式、排版 token 和 `page-meta` 样式注入能力。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import {
|
|
9
|
+
useThemePageStyle,
|
|
10
|
+
getCurrentFontScale,
|
|
11
|
+
getCurrentFontVars,
|
|
12
|
+
getCurrentThemeColor,
|
|
13
|
+
getCurrentThemeVars,
|
|
14
|
+
getCurrentAppearance,
|
|
15
|
+
getCurrentAppearanceMode,
|
|
16
|
+
getCurrentAppearanceVars,
|
|
17
|
+
getCurrentTypographyVars,
|
|
18
|
+
} from "@hlw-uni/mp-vue";
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## useThemePageStyle
|
|
22
|
+
|
|
23
|
+
页面需要把主题 CSS 变量注入到小程序 page 根时使用。
|
|
24
|
+
|
|
25
|
+
```vue
|
|
26
|
+
<template>
|
|
27
|
+
<page-meta :page-style="themePageStyle" />
|
|
28
|
+
<hlw-page>
|
|
29
|
+
页面内容
|
|
30
|
+
</hlw-page>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import { useThemePageStyle } from "@hlw-uni/mp-vue";
|
|
35
|
+
|
|
36
|
+
const { themePageStyle } = useThemePageStyle();
|
|
37
|
+
</script>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
如果项目启用了 `@hlw-uni/mp-vite-plugin` 的 `themePageMeta`,页面可由插件自动注入 `<page-meta>` 和 `useThemePageStyle`。
|
|
41
|
+
|
|
42
|
+
## 字体档位
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const scale = getCurrentFontScale();
|
|
46
|
+
const vars = getCurrentFontVars();
|
|
47
|
+
|
|
48
|
+
console.log(scale, vars["--font-base"]);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
支持的 `FontScale`:
|
|
52
|
+
|
|
53
|
+
| 值 | 说明 |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| `small` | 较小 |
|
|
56
|
+
| `compact` | 略小 |
|
|
57
|
+
| `normal` | 标准 |
|
|
58
|
+
| `medium` | 适中 |
|
|
59
|
+
| `large` | 较大 |
|
|
60
|
+
| `xlarge` | 超大 |
|
|
61
|
+
| `xxlarge` | 特大 |
|
|
62
|
+
|
|
63
|
+
## 主题色
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
const color = getCurrentThemeColor();
|
|
67
|
+
const vars = getCurrentThemeVars();
|
|
68
|
+
|
|
69
|
+
console.log(color, vars["--primary-color"]);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
常用导出:
|
|
73
|
+
|
|
74
|
+
| 导出 | 说明 |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| `THEME_COLOR_KEY` | 主题色 storage key |
|
|
77
|
+
| `THEME_SEMANTIC_COLORS` | 语义色 |
|
|
78
|
+
| `DEFAULT_THEMES` | 内置主题色列表 |
|
|
79
|
+
| `getCurrentThemeColor()` | 读取当前主题色 |
|
|
80
|
+
| `getCurrentThemeVars()` | 生成主题色 CSS 变量 |
|
|
81
|
+
|
|
82
|
+
## 外观模式
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const appearance = getCurrentAppearance();
|
|
86
|
+
const mode = getCurrentAppearanceMode();
|
|
87
|
+
const vars = getCurrentAppearanceVars();
|
|
88
|
+
|
|
89
|
+
console.log(appearance, mode, vars["--bg-page"]);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`Appearance` 支持:
|
|
93
|
+
|
|
94
|
+
| 值 | 说明 |
|
|
95
|
+
| --- | --- |
|
|
96
|
+
| `light` | 浅色模式 |
|
|
97
|
+
| `dark` | 深色模式 |
|
|
98
|
+
| `auto` | 跟随系统 |
|
|
99
|
+
|
|
100
|
+
## 排版 token
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const vars = getCurrentTypographyVars();
|
|
104
|
+
|
|
105
|
+
console.log(vars["--text-title-size"]);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
内置语义角色:
|
|
109
|
+
|
|
110
|
+
| 角色 | 用途 |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| `title-lg` | 页面大标题 |
|
|
113
|
+
| `title` | 卡片或分区主标题 |
|
|
114
|
+
| `subtitle` | 次级标题 |
|
|
115
|
+
| `body` | 正文 |
|
|
116
|
+
| `desc` | 描述文字 |
|
|
117
|
+
| `caption` | 角标、时间戳等小字 |
|
|
118
|
+
|
|
119
|
+
## 切换主题
|
|
120
|
+
|
|
121
|
+
主题状态由 `useThemeStore` 管理,store 会写入 storage,`useThemePageStyle` 会响应 `scale` 和 `primaryColor` 变化。
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { useThemeStore } from "@hlw-uni/mp-vue";
|
|
125
|
+
|
|
126
|
+
const theme = useThemeStore();
|
|
127
|
+
|
|
128
|
+
theme.setScale("large");
|
|
129
|
+
theme.setTheme("#3b82f6");
|
|
130
|
+
theme.setAppearance("auto");
|
|
131
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# utils 调用文档
|
|
2
|
+
|
|
3
|
+
`useUtils` 提供剪贴板、下载、保存相册、query 拼接和基础类型转换工具。
|
|
4
|
+
|
|
5
|
+
## 引入
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { useUtils } from "@hlw-uni/mp-vue";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 基础用法
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const utils = useUtils();
|
|
15
|
+
|
|
16
|
+
await utils.copy("要复制的文本");
|
|
17
|
+
const text = await utils.paste();
|
|
18
|
+
|
|
19
|
+
const qs = utils.toQuery({ id: 1, keyword: "测试" });
|
|
20
|
+
const url = utils.withQuery("/pages/search/index", qs);
|
|
21
|
+
|
|
22
|
+
const age = utils.toNumber("18", 0);
|
|
23
|
+
const enabled = utils.toBoolean("1", false);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 下载和保存
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
const res = await utils.download({
|
|
30
|
+
url: "https://example.com/a.png",
|
|
31
|
+
progress: (value, done, total) => {
|
|
32
|
+
console.log(value, done, total);
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if (res.ok && res.path) {
|
|
37
|
+
await utils.saveImage(res.path);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await utils.saveImageUrl("https://example.com/a.png");
|
|
41
|
+
await utils.saveVideoUrl("https://example.com/a.mp4");
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## API
|
|
45
|
+
|
|
46
|
+
| 方法 | 说明 |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `withQuery(url, qs)` | 为 URL 追加 query |
|
|
49
|
+
| `toQuery(data)` | 对象转 URL query |
|
|
50
|
+
| `signText(url)` | 生成签名原文,query 会排序 |
|
|
51
|
+
| `toNumber(value, defaultValue)` | 安全转数字 |
|
|
52
|
+
| `toBoolean(value, defaultValue)` | 安全转布尔 |
|
|
53
|
+
| `copy(text, tip?)` | 复制文本 |
|
|
54
|
+
| `paste()` | 读取剪贴板 |
|
|
55
|
+
| `saveImage(path)` | 保存本地图片到相册 |
|
|
56
|
+
| `saveVideo(path)` | 保存本地视频到相册 |
|
|
57
|
+
| `download(options)` | 下载文件 |
|
|
58
|
+
| `saveImageUrl(url, progress?)` | 下载远程图片并保存 |
|
|
59
|
+
| `saveVideoUrl(url, progress?)` | 下载远程视频并保存 |
|
|
60
|
+
|
|
61
|
+
## DownloadOpt
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
interface DownloadOpt {
|
|
65
|
+
url: string;
|
|
66
|
+
path?: string;
|
|
67
|
+
header?: Record<string, string>;
|
|
68
|
+
progress?: (value: number, done: number, total: number) => void;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## DownloadRes
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
interface DownloadRes {
|
|
76
|
+
ok: boolean;
|
|
77
|
+
path?: string;
|
|
78
|
+
code?: number;
|
|
79
|
+
msg?: string;
|
|
80
|
+
}
|
|
81
|
+
```
|