@hlw-uni/mp-vue 2.1.60 → 2.1.69
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/core/theme.d.ts +15 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +123 -2
- package/dist/index.mjs +123 -1
- package/dist/stores/index.d.ts +1 -0
- package/dist/stores/theme.d.ts +27 -0
- package/package.json +1 -1
- package/src/components/hlw-add-mini/index.vue +147 -77
- package/src/components/hlw-avatar/index.vue +28 -20
- package/src/components/hlw-card-header/index.vue +3 -0
- package/src/components/hlw-cell/index.vue +6 -0
- package/src/components/hlw-custom/hlw-custom.vue +6 -5
- package/src/components/hlw-menu/index.vue +9 -3
- package/src/components/hlw-nav-bar/index.vue +75 -15
- package/src/components/hlw-page/index.vue +69 -3
- package/src/core/theme.ts +54 -4
- package/src/index.ts +10 -3
- package/src/stores/index.ts +1 -0
- package/src/stores/theme.ts +126 -0
package/dist/core/theme.d.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { ComputedRef } from 'vue';
|
|
2
|
+
import { Store } from 'pinia';
|
|
2
3
|
|
|
4
|
+
export { themePresets, type ThemePreset, fontSizePresets, type FontSizePreset, fontFamilyPresets, type FontFamilyPreset } from '../stores/theme';
|
|
3
5
|
export declare function useTheme(): {
|
|
4
6
|
theme: ComputedRef<string>;
|
|
5
|
-
|
|
7
|
+
fontSize: ComputedRef<string>;
|
|
8
|
+
fontSizeClass: ComputedRef<string>;
|
|
9
|
+
setFontSize: (size: string) => void;
|
|
10
|
+
fontFamily: ComputedRef<string>;
|
|
11
|
+
fontFamilyClass: ComputedRef<string>;
|
|
12
|
+
setFontFamily: (font: string) => void;
|
|
13
|
+
store: Store<"theme", {
|
|
6
14
|
theme: string;
|
|
7
|
-
|
|
15
|
+
fontSize: string;
|
|
16
|
+
fontFamily: string;
|
|
17
|
+
}, {}, {
|
|
18
|
+
setFontSize(size: string): void;
|
|
19
|
+
setFontFamily(font: string): void;
|
|
20
|
+
}>;
|
|
8
21
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 2.0 起合并了原 @hlw-uni/mp-core 全部内容。
|
|
5
5
|
* 业务方一处 import,无需再分包:
|
|
6
|
-
* import { useMsg,
|
|
6
|
+
* import { useMsg, useTheme, ... } from "@hlw-uni/mp-vue";
|
|
7
7
|
*
|
|
8
8
|
* UI 组件(hlw-page / hlw-button / hlw-ad 等)走 easycom 自动注册,不在这里 export。
|
|
9
9
|
*/
|
|
10
10
|
export * from './composables';
|
|
11
|
+
export { useTheme, themePresets, type ThemePreset, fontFamilyPresets, type FontFamilyPreset, fontSizePresets, type FontSizePreset } from './core/theme';
|
|
11
12
|
export type { HlwMenuItem } from './components/hlw-menu/types';
|
|
12
13
|
export type { HlwPagingRef, HlwPagingInstance } from './components/hlw-paging/types';
|
|
13
14
|
export { useApp } from './app';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function(global, factory) {
|
|
2
|
-
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("vue"), require("@dcloudio/uni-app")) : typeof define === "function" && define.amd ? define(["exports", "vue", "@dcloudio/uni-app"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.HlwUniVue = {}, global.vue, global.uniApp));
|
|
3
|
-
})(this, function(exports2, vue, uniApp) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("vue"), require("@dcloudio/uni-app"), require("pinia")) : typeof define === "function" && define.amd ? define(["exports", "vue", "@dcloudio/uni-app", "pinia"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.HlwUniVue = {}, global.vue, global.uniApp, global.pinia));
|
|
3
|
+
})(this, function(exports2, vue, uniApp, pinia) {
|
|
4
4
|
"use strict";var __defProp = Object.defineProperty;
|
|
5
5
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
6
|
var __publicField = (obj, key, value) => {
|
|
@@ -969,6 +969,123 @@ var __publicField = (obj, key, value) => {
|
|
|
969
969
|
miniProgram: (appId, options) => navigate("miniprogram", appId, options)
|
|
970
970
|
};
|
|
971
971
|
}
|
|
972
|
+
const themePresets = [
|
|
973
|
+
{
|
|
974
|
+
id: "white-theme",
|
|
975
|
+
name: "白色主题",
|
|
976
|
+
color: "#ffffff"
|
|
977
|
+
},
|
|
978
|
+
{
|
|
979
|
+
id: "light-theme",
|
|
980
|
+
name: "简洁主题",
|
|
981
|
+
color: "var(--bg-page, #f8f8f8)"
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
id: "mono-theme",
|
|
985
|
+
name: "单色主题",
|
|
986
|
+
color: "var(--primary-color, #3b82f6)"
|
|
987
|
+
},
|
|
988
|
+
{
|
|
989
|
+
id: "color-theme",
|
|
990
|
+
name: "颜色主题",
|
|
991
|
+
color: "var(--primary-color, #3b82f6)"
|
|
992
|
+
}
|
|
993
|
+
];
|
|
994
|
+
const fontSizePresets = [
|
|
995
|
+
{
|
|
996
|
+
id: "small",
|
|
997
|
+
name: "较小",
|
|
998
|
+
class: "font-size-small"
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
id: "standard",
|
|
1002
|
+
name: "标准",
|
|
1003
|
+
class: "font-size-standard"
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
id: "large",
|
|
1007
|
+
name: "较大",
|
|
1008
|
+
class: "font-size-large"
|
|
1009
|
+
},
|
|
1010
|
+
{
|
|
1011
|
+
id: "extra-large",
|
|
1012
|
+
name: "超大",
|
|
1013
|
+
class: "font-size-extra-large"
|
|
1014
|
+
}
|
|
1015
|
+
];
|
|
1016
|
+
const fontFamilyPresets = [
|
|
1017
|
+
{
|
|
1018
|
+
id: "system",
|
|
1019
|
+
name: "系统默认",
|
|
1020
|
+
class: "font-family-system"
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
id: "sans",
|
|
1024
|
+
name: "现代黑体",
|
|
1025
|
+
class: "font-family-sans"
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
id: "serif",
|
|
1029
|
+
name: "经典宋体",
|
|
1030
|
+
class: "font-family-serif"
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
id: "kaiti",
|
|
1034
|
+
name: "优雅楷体",
|
|
1035
|
+
class: "font-family-kaiti"
|
|
1036
|
+
}
|
|
1037
|
+
];
|
|
1038
|
+
const useThemeStore = pinia.defineStore("theme", {
|
|
1039
|
+
state: () => ({
|
|
1040
|
+
theme: "white-theme",
|
|
1041
|
+
fontSize: "standard",
|
|
1042
|
+
fontFamily: "system"
|
|
1043
|
+
}),
|
|
1044
|
+
getters: {},
|
|
1045
|
+
actions: {
|
|
1046
|
+
setFontSize(size) {
|
|
1047
|
+
if (["small", "standard", "large", "extra-large"].includes(size)) {
|
|
1048
|
+
this.fontSize = size;
|
|
1049
|
+
}
|
|
1050
|
+
},
|
|
1051
|
+
setFontFamily(font) {
|
|
1052
|
+
if (["system", "sans", "serif", "kaiti"].includes(font)) {
|
|
1053
|
+
this.fontFamily = font;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
},
|
|
1057
|
+
unistorage: true
|
|
1058
|
+
});
|
|
1059
|
+
function useTheme() {
|
|
1060
|
+
const store = useThemeStore();
|
|
1061
|
+
const theme = vue.computed(() => store.theme);
|
|
1062
|
+
const fontSize = vue.computed(() => store.fontSize);
|
|
1063
|
+
const fontSizeClass = vue.computed(() => {
|
|
1064
|
+
const found = fontSizePresets.find((p) => p.id === store.fontSize);
|
|
1065
|
+
return found ? found.class : "font-size-standard";
|
|
1066
|
+
});
|
|
1067
|
+
const fontFamily = vue.computed(() => store.fontFamily);
|
|
1068
|
+
const fontFamilyClass = vue.computed(() => {
|
|
1069
|
+
const found = fontFamilyPresets.find((p) => p.id === store.fontFamily);
|
|
1070
|
+
return found ? found.class : "font-family-system";
|
|
1071
|
+
});
|
|
1072
|
+
function setFontSize(size) {
|
|
1073
|
+
store.setFontSize(size);
|
|
1074
|
+
}
|
|
1075
|
+
function setFontFamily(font) {
|
|
1076
|
+
store.setFontFamily(font);
|
|
1077
|
+
}
|
|
1078
|
+
return {
|
|
1079
|
+
theme,
|
|
1080
|
+
fontSize,
|
|
1081
|
+
fontSizeClass,
|
|
1082
|
+
setFontSize,
|
|
1083
|
+
fontFamily,
|
|
1084
|
+
fontFamilyClass,
|
|
1085
|
+
setFontFamily,
|
|
1086
|
+
store
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
972
1089
|
let _msg = null;
|
|
973
1090
|
let _utils = null;
|
|
974
1091
|
const hlw = {
|
|
@@ -1054,6 +1171,8 @@ var __publicField = (obj, key, value) => {
|
|
|
1054
1171
|
exports2.copy = copy;
|
|
1055
1172
|
exports2.cosAdapter = cosAdapter;
|
|
1056
1173
|
exports2.download = download;
|
|
1174
|
+
exports2.fontFamilyPresets = fontFamilyPresets;
|
|
1175
|
+
exports2.fontSizePresets = fontSizePresets;
|
|
1057
1176
|
exports2.getAdapter = getAdapter;
|
|
1058
1177
|
exports2.hlw = hlw;
|
|
1059
1178
|
exports2.ossAdapter = ossAdapter;
|
|
@@ -1064,6 +1183,7 @@ var __publicField = (obj, key, value) => {
|
|
|
1064
1183
|
exports2.saveVideoFile = saveVideoFile;
|
|
1065
1184
|
exports2.saveVideoUrl = saveVideoUrl;
|
|
1066
1185
|
exports2.signText = signText;
|
|
1186
|
+
exports2.themePresets = themePresets;
|
|
1067
1187
|
exports2.toBoolean = toBoolean;
|
|
1068
1188
|
exports2.toNumber = toNumber;
|
|
1069
1189
|
exports2.toQuery = toQuery;
|
|
@@ -1075,6 +1195,7 @@ var __publicField = (obj, key, value) => {
|
|
|
1075
1195
|
exports2.useRefs = useRefs;
|
|
1076
1196
|
exports2.useRequest = useRequest;
|
|
1077
1197
|
exports2.useShare = useShare;
|
|
1198
|
+
exports2.useTheme = useTheme;
|
|
1078
1199
|
exports2.useUpload = useUpload;
|
|
1079
1200
|
exports2.useUtils = useUtils;
|
|
1080
1201
|
exports2.vCopy = vCopy;
|
package/dist/index.mjs
CHANGED
|
@@ -4,8 +4,9 @@ var __publicField = (obj, key, value) => {
|
|
|
4
4
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
|
-
import { ref, onBeforeUpdate, onUnmounted, createSSRApp } from "vue";
|
|
7
|
+
import { ref, onBeforeUpdate, onUnmounted, computed, createSSRApp } from "vue";
|
|
8
8
|
import { onShareAppMessage, onShareTimeline } from "@dcloudio/uni-app";
|
|
9
|
+
import { defineStore } from "pinia";
|
|
9
10
|
const cosAdapter = {
|
|
10
11
|
name: "cos",
|
|
11
12
|
/**
|
|
@@ -967,6 +968,123 @@ function useNavigate() {
|
|
|
967
968
|
miniProgram: (appId, options) => navigate("miniprogram", appId, options)
|
|
968
969
|
};
|
|
969
970
|
}
|
|
971
|
+
const themePresets = [
|
|
972
|
+
{
|
|
973
|
+
id: "white-theme",
|
|
974
|
+
name: "白色主题",
|
|
975
|
+
color: "#ffffff"
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
id: "light-theme",
|
|
979
|
+
name: "简洁主题",
|
|
980
|
+
color: "var(--bg-page, #f8f8f8)"
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
id: "mono-theme",
|
|
984
|
+
name: "单色主题",
|
|
985
|
+
color: "var(--primary-color, #3b82f6)"
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
id: "color-theme",
|
|
989
|
+
name: "颜色主题",
|
|
990
|
+
color: "var(--primary-color, #3b82f6)"
|
|
991
|
+
}
|
|
992
|
+
];
|
|
993
|
+
const fontSizePresets = [
|
|
994
|
+
{
|
|
995
|
+
id: "small",
|
|
996
|
+
name: "较小",
|
|
997
|
+
class: "font-size-small"
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
id: "standard",
|
|
1001
|
+
name: "标准",
|
|
1002
|
+
class: "font-size-standard"
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
id: "large",
|
|
1006
|
+
name: "较大",
|
|
1007
|
+
class: "font-size-large"
|
|
1008
|
+
},
|
|
1009
|
+
{
|
|
1010
|
+
id: "extra-large",
|
|
1011
|
+
name: "超大",
|
|
1012
|
+
class: "font-size-extra-large"
|
|
1013
|
+
}
|
|
1014
|
+
];
|
|
1015
|
+
const fontFamilyPresets = [
|
|
1016
|
+
{
|
|
1017
|
+
id: "system",
|
|
1018
|
+
name: "系统默认",
|
|
1019
|
+
class: "font-family-system"
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
id: "sans",
|
|
1023
|
+
name: "现代黑体",
|
|
1024
|
+
class: "font-family-sans"
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
id: "serif",
|
|
1028
|
+
name: "经典宋体",
|
|
1029
|
+
class: "font-family-serif"
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
id: "kaiti",
|
|
1033
|
+
name: "优雅楷体",
|
|
1034
|
+
class: "font-family-kaiti"
|
|
1035
|
+
}
|
|
1036
|
+
];
|
|
1037
|
+
const useThemeStore = defineStore("theme", {
|
|
1038
|
+
state: () => ({
|
|
1039
|
+
theme: "white-theme",
|
|
1040
|
+
fontSize: "standard",
|
|
1041
|
+
fontFamily: "system"
|
|
1042
|
+
}),
|
|
1043
|
+
getters: {},
|
|
1044
|
+
actions: {
|
|
1045
|
+
setFontSize(size) {
|
|
1046
|
+
if (["small", "standard", "large", "extra-large"].includes(size)) {
|
|
1047
|
+
this.fontSize = size;
|
|
1048
|
+
}
|
|
1049
|
+
},
|
|
1050
|
+
setFontFamily(font) {
|
|
1051
|
+
if (["system", "sans", "serif", "kaiti"].includes(font)) {
|
|
1052
|
+
this.fontFamily = font;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
},
|
|
1056
|
+
unistorage: true
|
|
1057
|
+
});
|
|
1058
|
+
function useTheme() {
|
|
1059
|
+
const store = useThemeStore();
|
|
1060
|
+
const theme = computed(() => store.theme);
|
|
1061
|
+
const fontSize = computed(() => store.fontSize);
|
|
1062
|
+
const fontSizeClass = computed(() => {
|
|
1063
|
+
const found = fontSizePresets.find((p) => p.id === store.fontSize);
|
|
1064
|
+
return found ? found.class : "font-size-standard";
|
|
1065
|
+
});
|
|
1066
|
+
const fontFamily = computed(() => store.fontFamily);
|
|
1067
|
+
const fontFamilyClass = computed(() => {
|
|
1068
|
+
const found = fontFamilyPresets.find((p) => p.id === store.fontFamily);
|
|
1069
|
+
return found ? found.class : "font-family-system";
|
|
1070
|
+
});
|
|
1071
|
+
function setFontSize(size) {
|
|
1072
|
+
store.setFontSize(size);
|
|
1073
|
+
}
|
|
1074
|
+
function setFontFamily(font) {
|
|
1075
|
+
store.setFontFamily(font);
|
|
1076
|
+
}
|
|
1077
|
+
return {
|
|
1078
|
+
theme,
|
|
1079
|
+
fontSize,
|
|
1080
|
+
fontSizeClass,
|
|
1081
|
+
setFontSize,
|
|
1082
|
+
fontFamily,
|
|
1083
|
+
fontFamilyClass,
|
|
1084
|
+
setFontFamily,
|
|
1085
|
+
store
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
970
1088
|
let _msg = null;
|
|
971
1089
|
let _utils = null;
|
|
972
1090
|
const hlw = {
|
|
@@ -1053,6 +1171,8 @@ export {
|
|
|
1053
1171
|
copy,
|
|
1054
1172
|
cosAdapter,
|
|
1055
1173
|
download,
|
|
1174
|
+
fontFamilyPresets,
|
|
1175
|
+
fontSizePresets,
|
|
1056
1176
|
getAdapter,
|
|
1057
1177
|
hlw,
|
|
1058
1178
|
ossAdapter,
|
|
@@ -1063,6 +1183,7 @@ export {
|
|
|
1063
1183
|
saveVideoFile,
|
|
1064
1184
|
saveVideoUrl,
|
|
1065
1185
|
signText,
|
|
1186
|
+
themePresets,
|
|
1066
1187
|
toBoolean,
|
|
1067
1188
|
toNumber,
|
|
1068
1189
|
toQuery,
|
|
@@ -1074,6 +1195,7 @@ export {
|
|
|
1074
1195
|
useRefs,
|
|
1075
1196
|
useRequest,
|
|
1076
1197
|
useShare,
|
|
1198
|
+
useTheme,
|
|
1077
1199
|
useUpload,
|
|
1078
1200
|
useUtils,
|
|
1079
1201
|
vCopy,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './theme';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { StoreDefinition } from 'pinia';
|
|
2
|
+
export interface ThemePreset {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
color: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const themePresets: ThemePreset[];
|
|
8
|
+
export interface FontSizePreset {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
class: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const fontSizePresets: FontSizePreset[];
|
|
14
|
+
export interface FontFamilyPreset {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
class: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const fontFamilyPresets: FontFamilyPreset[];
|
|
20
|
+
export declare const useThemeStore: StoreDefinition<"theme", {
|
|
21
|
+
theme: string;
|
|
22
|
+
fontSize: string;
|
|
23
|
+
fontFamily: string;
|
|
24
|
+
}, {}, {
|
|
25
|
+
setFontSize(size: string): void;
|
|
26
|
+
setFontFamily(font: string): void;
|
|
27
|
+
}>;
|
package/package.json
CHANGED
|
@@ -1,137 +1,207 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
<view v-if="props.show" class="hlw-add-mini" :style="{ top }">
|
|
3
|
+
<view class="hlw-add-mini__arrow" :style="arrowStyle" />
|
|
4
|
+
<view class="hlw-add-mini__content">
|
|
5
|
+
<view class="hlw-add-mini__text">
|
|
6
|
+
<view class="hlw-add-mini__title">{{ props.title }}</view>
|
|
7
|
+
<view v-if="props.desc" class="hlw-add-mini__desc">{{ props.desc }}</view>
|
|
8
|
+
</view>
|
|
9
|
+
<view class="hlw-add-mini__close" @tap="close">×</view>
|
|
10
|
+
</view>
|
|
11
|
+
</view>
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
14
|
<script setup lang="ts">
|
|
15
15
|
/**
|
|
16
16
|
* HlwAddMini - 添加小程序提示气泡组件
|
|
17
|
-
*
|
|
17
|
+
*
|
|
18
18
|
* 用于提示用户点击右上角将当前小程序“添加到我的小程序”中,以提升用户留存。
|
|
19
19
|
* 会根据是否为自定义导航栏(custom),自动调整气泡浮动位置(避开胶囊按钮与状态栏)。
|
|
20
20
|
*/
|
|
21
|
-
import { computed } from "vue";
|
|
21
|
+
import { computed, ref, onMounted } from "vue";
|
|
22
22
|
import { useDevice } from "../../composables/device";
|
|
23
23
|
|
|
24
24
|
defineOptions({ name: "HlwAddMini" });
|
|
25
25
|
|
|
26
26
|
interface Props {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/** 气泡副标题/描述文字 */
|
|
34
|
-
desc?: string;
|
|
27
|
+
/** 是否显示提示气泡 */
|
|
28
|
+
show?: boolean;
|
|
29
|
+
/** 气泡主标题文字 */
|
|
30
|
+
title?: string;
|
|
31
|
+
/** 气泡副标题/描述文字 */
|
|
32
|
+
desc?: string;
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
const props = withDefaults(defineProps<Props>(), {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
desc: "点击右上角 ··· 添加",
|
|
36
|
+
show: false,
|
|
37
|
+
title: "添加到我的小程序",
|
|
38
|
+
desc: "点击右上角 ··· 添加",
|
|
42
39
|
});
|
|
43
40
|
|
|
44
41
|
const emit = defineEmits<{
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
/** 点击关闭按钮时触发 */
|
|
43
|
+
close: [];
|
|
47
44
|
}>();
|
|
48
45
|
|
|
49
46
|
// 从 useDevice 获取缓存的设备系统信息,规避在 computed 中频繁调用同步系统 API 的性能问题
|
|
50
47
|
const { info } = useDevice();
|
|
51
48
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
)
|
|
49
|
+
const isCustomNav = ref(false);
|
|
50
|
+
|
|
51
|
+
onMounted(() => {
|
|
52
|
+
// 1. 全局配置探测(针对全局自定义导航样式,可立即识别,免去生命周期时序竞态问题)
|
|
53
|
+
try {
|
|
54
|
+
if (typeof __wxConfig !== "undefined") {
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
const globalStyle = __wxConfig.globalStyle?.navigationStyle || __wxConfig.global?.window?.navigationStyle;
|
|
57
|
+
if (globalStyle === "custom") {
|
|
58
|
+
isCustomNav.value = true;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} catch (e) {
|
|
63
|
+
// 容错
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 2. 延迟探测(避开组件挂载时 getCurrentPages 尚未完全初始化的竞态,并且使用非破坏性读取)
|
|
67
|
+
setTimeout(() => {
|
|
68
|
+
try {
|
|
69
|
+
const pages = getCurrentPages();
|
|
70
|
+
if (pages && pages.length > 0) {
|
|
71
|
+
const page = pages[pages.length - 1];
|
|
72
|
+
// @ts-ignore - 微信小程序原生属性或 uni-app 底层元数据配置
|
|
73
|
+
const style = page.__wxConfig?.navigationStyle || page?.$page?.meta?.navigationStyle;
|
|
74
|
+
if (style === "custom") {
|
|
75
|
+
isCustomNav.value = true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
// 容错
|
|
80
|
+
}
|
|
81
|
+
}, 100);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const top = computed(() => {
|
|
85
|
+
if (isCustomNav.value) {
|
|
86
|
+
try {
|
|
87
|
+
const menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
88
|
+
if (menuButtonInfo && menuButtonInfo.bottom > 0) {
|
|
89
|
+
// 胶囊底部高度 + 16px 作为气泡定位的顶部基准,保证指向绝对精确且避开胶囊
|
|
90
|
+
return `${menuButtonInfo.bottom + 16}px`;
|
|
91
|
+
}
|
|
92
|
+
} catch (e) {
|
|
93
|
+
// 跨端环境不支持或报错时,执行安全降级计算
|
|
94
|
+
}
|
|
95
|
+
return `${info.status_bar_height + 50}px`;
|
|
96
|
+
}
|
|
97
|
+
return "12px";
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const arrowStyle = computed(() => {
|
|
101
|
+
try {
|
|
102
|
+
const menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
103
|
+
if (menuButtonInfo && menuButtonInfo.width > 0) {
|
|
104
|
+
// 胶囊左边缘 + 胶囊宽度的 28% (即三点按钮的中心点)
|
|
105
|
+
const dotsCenterX = menuButtonInfo.left + menuButtonInfo.width * 0.28;
|
|
106
|
+
// 屏幕宽度 - 胶囊三点中心点 = 三点中心点到屏幕右边缘的像素距离
|
|
107
|
+
const arrowRightPx = info.window_width - dotsCenterX;
|
|
108
|
+
// 气泡右边缘到屏幕右边缘的像素距离 (22rpx)
|
|
109
|
+
const bubbleRightPx = uni.upx2px(22);
|
|
110
|
+
// 箭头相对于气泡右侧边缘的像素偏移 (再减去箭头自身半宽 12rpx 对应的 px 像素)
|
|
111
|
+
const arrowHalfWidthPx = uni.upx2px(12);
|
|
112
|
+
const rightOffset = arrowRightPx - bubbleRightPx - arrowHalfWidthPx;
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
right: `${rightOffset}px`,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
} catch (e) {
|
|
119
|
+
// 容错降级
|
|
120
|
+
}
|
|
121
|
+
return {};
|
|
122
|
+
});
|
|
55
123
|
|
|
56
124
|
/**
|
|
57
125
|
* 触发关闭气泡事件。
|
|
58
126
|
*/
|
|
59
127
|
function close() {
|
|
60
|
-
|
|
128
|
+
emit("close");
|
|
61
129
|
}
|
|
62
130
|
</script>
|
|
63
131
|
|
|
64
132
|
<style lang="scss" scoped>
|
|
65
133
|
.hlw-add-mini {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
134
|
+
position: fixed;
|
|
135
|
+
right: 22rpx;
|
|
136
|
+
z-index: 99999;
|
|
137
|
+
width: 340rpx;
|
|
138
|
+
animation: hlw-add-mini-in 0.22s ease-out both;
|
|
71
139
|
}
|
|
72
140
|
|
|
73
141
|
.hlw-add-mini__arrow {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
142
|
+
position: absolute;
|
|
143
|
+
right: 92rpx;
|
|
144
|
+
top: -13rpx;
|
|
145
|
+
width: 0;
|
|
146
|
+
height: 0;
|
|
147
|
+
z-index: 99999;
|
|
148
|
+
border-left: 12rpx solid transparent;
|
|
149
|
+
border-right: 12rpx solid transparent;
|
|
150
|
+
border-bottom: 14rpx solid rgba(17, 24, 39, 0.82);
|
|
81
151
|
}
|
|
82
152
|
|
|
83
153
|
.hlw-add-mini__content {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
154
|
+
display: flex;
|
|
155
|
+
align-items: center;
|
|
156
|
+
gap: 12rpx;
|
|
157
|
+
padding: 16rpx 14rpx 16rpx 20rpx;
|
|
158
|
+
border-radius: 14rpx;
|
|
159
|
+
background: rgba(17, 24, 39, 0.82);
|
|
160
|
+
box-shadow: 0 12rpx 34rpx rgba(15, 23, 42, 0.22);
|
|
91
161
|
}
|
|
92
162
|
|
|
93
163
|
.hlw-add-mini__text {
|
|
94
|
-
|
|
95
|
-
|
|
164
|
+
flex: 1;
|
|
165
|
+
min-width: 0;
|
|
96
166
|
}
|
|
97
167
|
|
|
98
168
|
.hlw-add-mini__title {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
169
|
+
color: #ffffff;
|
|
170
|
+
font-size: 25rpx;
|
|
171
|
+
font-weight: 400;
|
|
172
|
+
line-height: 1.3;
|
|
103
173
|
letter-spacing: 1rpx;
|
|
104
174
|
}
|
|
105
175
|
|
|
106
176
|
.hlw-add-mini__desc {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
177
|
+
margin-top: 4rpx;
|
|
178
|
+
color: rgba(255, 255, 255, 0.72);
|
|
179
|
+
font-size: 21rpx;
|
|
180
|
+
line-height: 1.3;
|
|
111
181
|
letter-spacing: 1rpx;
|
|
112
182
|
}
|
|
113
183
|
|
|
114
184
|
.hlw-add-mini__close {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
185
|
+
display: flex;
|
|
186
|
+
align-items: center;
|
|
187
|
+
justify-content: center;
|
|
188
|
+
flex-shrink: 0;
|
|
189
|
+
width: 36rpx;
|
|
190
|
+
height: 36rpx;
|
|
191
|
+
color: rgba(255, 255, 255, 0.72);
|
|
192
|
+
font-size: 30rpx;
|
|
193
|
+
line-height: 1;
|
|
124
194
|
}
|
|
125
195
|
|
|
126
196
|
@keyframes hlw-add-mini-in {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
197
|
+
0% {
|
|
198
|
+
opacity: 0;
|
|
199
|
+
transform: translateY(-8rpx);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
100% {
|
|
203
|
+
opacity: 1;
|
|
204
|
+
transform: translateY(0);
|
|
205
|
+
}
|
|
136
206
|
}
|
|
137
207
|
</style>
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view :class="`hlw-avatar hlw-avatar--${size ?? 'medium'}`" :style="avatarStyle">
|
|
3
|
-
<image
|
|
4
|
-
v-if="src && !loadError"
|
|
5
|
-
class="hlw-avatar__image"
|
|
6
|
-
:src="src"
|
|
7
|
-
mode="aspectFill"
|
|
8
|
-
@error="loadError = true"
|
|
9
|
-
/>
|
|
3
|
+
<image v-if="src && !loadError" class="hlw-avatar__image" :src="src" mode="aspectFill" @error="loadError = true" />
|
|
10
4
|
<view v-else class="hlw-avatar__placeholder">
|
|
11
5
|
<text class="hlw-avatar__initial">{{ initial }}</text>
|
|
12
6
|
</view>
|
|
@@ -30,12 +24,12 @@
|
|
|
30
24
|
* <HlwAvatar src="/avatar.png" name="张三" size="large" />
|
|
31
25
|
* ```
|
|
32
26
|
*/
|
|
33
|
-
import { ref, computed } from
|
|
27
|
+
import { ref, computed } from "vue";
|
|
34
28
|
|
|
35
29
|
const props = defineProps<{
|
|
36
30
|
src?: string;
|
|
37
31
|
name?: string;
|
|
38
|
-
size?:
|
|
32
|
+
size?: "small" | "medium" | "large";
|
|
39
33
|
border?: number;
|
|
40
34
|
}>();
|
|
41
35
|
|
|
@@ -43,11 +37,11 @@ const loadError = ref(false);
|
|
|
43
37
|
const avatarStyle = computed(() => {
|
|
44
38
|
const border = Math.max(0, Number(props.border ?? 0));
|
|
45
39
|
return {
|
|
46
|
-
border: border > 0 ? `${border}px solid #fff` :
|
|
40
|
+
border: border > 0 ? `${border}px solid #fff` : "0",
|
|
47
41
|
};
|
|
48
42
|
});
|
|
49
43
|
const initial = computed(() => {
|
|
50
|
-
if (!props.name) return
|
|
44
|
+
if (!props.name) return "?";
|
|
51
45
|
return props.name.charAt(0).toUpperCase();
|
|
52
46
|
});
|
|
53
47
|
</script>
|
|
@@ -60,9 +54,18 @@ const initial = computed(() => {
|
|
|
60
54
|
flex-shrink: 0;
|
|
61
55
|
}
|
|
62
56
|
|
|
63
|
-
.hlw-avatar--small
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
.hlw-avatar--small {
|
|
58
|
+
width: 56rpx;
|
|
59
|
+
height: 56rpx;
|
|
60
|
+
}
|
|
61
|
+
.hlw-avatar--medium {
|
|
62
|
+
width: 80rpx;
|
|
63
|
+
height: 80rpx;
|
|
64
|
+
}
|
|
65
|
+
.hlw-avatar--large {
|
|
66
|
+
width: 120rpx;
|
|
67
|
+
height: 120rpx;
|
|
68
|
+
}
|
|
66
69
|
|
|
67
70
|
.hlw-avatar__image {
|
|
68
71
|
width: 100%;
|
|
@@ -72,18 +75,23 @@ const initial = computed(() => {
|
|
|
72
75
|
.hlw-avatar__placeholder {
|
|
73
76
|
width: 100%;
|
|
74
77
|
height: 100%;
|
|
75
|
-
background: #
|
|
78
|
+
background: #f1f5f9;
|
|
76
79
|
display: flex;
|
|
77
80
|
align-items: center;
|
|
78
81
|
justify-content: center;
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
.hlw-avatar__initial {
|
|
82
|
-
color: #
|
|
83
|
-
font-weight: bold;
|
|
85
|
+
color: #94a3b8;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
.hlw-avatar--small
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
.hlw-avatar--small .hlw-avatar__initial {
|
|
89
|
+
font-size: var(--font-xs, 20rpx);
|
|
90
|
+
}
|
|
91
|
+
.hlw-avatar--medium .hlw-avatar__initial {
|
|
92
|
+
font-size: var(--font-base, 28rpx);
|
|
93
|
+
}
|
|
94
|
+
.hlw-avatar--large .hlw-avatar__initial {
|
|
95
|
+
font-size: var(--font-xl, 40rpx);
|
|
96
|
+
}
|
|
89
97
|
</style>
|
|
@@ -105,6 +105,12 @@ defineEmits<{ click: [] }>();
|
|
|
105
105
|
font-size: var(--font-lg, 36rpx);
|
|
106
106
|
color: var(--primary-color, #3b82f6);
|
|
107
107
|
flex-shrink: 0;
|
|
108
|
+
|
|
109
|
+
view {
|
|
110
|
+
width: var(--font-lg, 36rpx);
|
|
111
|
+
height: var(--font-lg, 36rpx);
|
|
112
|
+
display: inline-block;
|
|
113
|
+
}
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
.hlw-cell-body {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
:send-message-img="resolvedContact.img"
|
|
13
13
|
:show-message-card="resolvedContact.show"
|
|
14
14
|
>
|
|
15
|
-
<text class="
|
|
15
|
+
<text class="i-ri-customer-service-line contact-button-icon" />
|
|
16
16
|
<text class="contact-button-text">{{ resolvedBtnTitle }}</text>
|
|
17
17
|
</button>
|
|
18
18
|
</view>
|
|
@@ -64,7 +64,7 @@ const resolvedContact = computed(() => {
|
|
|
64
64
|
padding: var(--card-padding);
|
|
65
65
|
border: 1rpx solid var(--border-color-light);
|
|
66
66
|
border-radius: var(--card-radius);
|
|
67
|
-
background: linear-gradient(135deg, #ffffff 0%, rgba(
|
|
67
|
+
background: linear-gradient(135deg, #ffffff 0%, var(--primary-light, rgba(76, 68, 239, 0.05)) 100%);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
.contact-copy {
|
|
@@ -100,14 +100,15 @@ const resolvedContact = computed(() => {
|
|
|
100
100
|
flex-shrink: 0;
|
|
101
101
|
margin: 0;
|
|
102
102
|
border-radius: var(--radius-full);
|
|
103
|
-
background: #
|
|
103
|
+
background: var(--primary-color, #3b82f6);
|
|
104
104
|
color: #ffffff;
|
|
105
105
|
font: inherit;
|
|
106
106
|
line-height: 68rpx;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
.contact-button
|
|
110
|
-
|
|
109
|
+
.contact-button-icon {
|
|
110
|
+
width: var(--font-sm);
|
|
111
|
+
height: var(--font-sm);
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
.contact-button-text {
|
|
@@ -335,7 +335,10 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
335
335
|
flex-shrink: 0;
|
|
336
336
|
|
|
337
337
|
text {
|
|
338
|
+
width: var(--hlw-menu-icon-size);
|
|
339
|
+
height: var(--hlw-menu-icon-size);
|
|
338
340
|
font-size: var(--hlw-menu-icon-size);
|
|
341
|
+
display: inline-block;
|
|
339
342
|
}
|
|
340
343
|
|
|
341
344
|
&--grid {
|
|
@@ -343,7 +346,10 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
343
346
|
height: var(--hlw-menu-grid-icon-box-size);
|
|
344
347
|
border-radius: var(--radius-lg, 24rpx);
|
|
345
348
|
text {
|
|
349
|
+
width: var(--hlw-menu-grid-icon-size);
|
|
350
|
+
height: var(--hlw-menu-grid-icon-size);
|
|
346
351
|
font-size: var(--hlw-menu-grid-icon-size);
|
|
352
|
+
display: inline-block;
|
|
347
353
|
}
|
|
348
354
|
}
|
|
349
355
|
|
|
@@ -376,8 +382,8 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
376
382
|
color: #f43f5e;
|
|
377
383
|
}
|
|
378
384
|
&--blue {
|
|
379
|
-
background:
|
|
380
|
-
color: #3b82f6;
|
|
385
|
+
background: var(--primary-light, rgba(76, 68, 239, 0.12));
|
|
386
|
+
color: var(--primary-color, #3b82f6);
|
|
381
387
|
}
|
|
382
388
|
&--red {
|
|
383
389
|
background: #fef2f2;
|
|
@@ -418,7 +424,7 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
418
424
|
background: #f43f5e;
|
|
419
425
|
}
|
|
420
426
|
.hlw-menu-tag--blue {
|
|
421
|
-
background: #3b82f6;
|
|
427
|
+
background: var(--primary-color, #3b82f6);
|
|
422
428
|
}
|
|
423
429
|
|
|
424
430
|
.hlw-menu-tag-pulse {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view class="navbar">
|
|
2
|
+
<view class="navbar" :class="theme">
|
|
3
3
|
<view :style="bar_style"></view>
|
|
4
4
|
<view class="header" :style="{ height: header_height + 'px' }">
|
|
5
5
|
<view @tap="tapBack" class="left" v-if="props.isBack">
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</view>
|
|
8
8
|
<text class="title">{{ title }}</text>
|
|
9
9
|
</view>
|
|
10
|
-
<view class="status-bar" v-if="theme
|
|
10
|
+
<view class="status-bar" v-if="theme === 'color-theme'">
|
|
11
11
|
<view class="within"></view>
|
|
12
12
|
</view>
|
|
13
13
|
</view>
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
<script lang="ts" setup>
|
|
18
18
|
import { computed, ref } from "vue";
|
|
19
19
|
import { useTheme } from "@/core";
|
|
20
|
+
|
|
20
21
|
const { theme } = useTheme();
|
|
21
22
|
|
|
22
23
|
const statusBarHeight: number = uni.getSystemInfoSync()?.statusBarHeight || 0;
|
|
@@ -48,7 +49,7 @@ if (props.isBar) {
|
|
|
48
49
|
status_bar_height = 15;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
const header_height = ref<number>(menuButtonInfo.bottom - statusBarHeight +
|
|
52
|
+
const header_height = ref<number>(menuButtonInfo.bottom - statusBarHeight + 6);
|
|
52
53
|
const navbar_height = ref(header_height.value + statusBarHeight);
|
|
53
54
|
const status_bar_height_style = `${status_bar_height}px`;
|
|
54
55
|
|
|
@@ -67,11 +68,69 @@ function tapBack() {
|
|
|
67
68
|
.navbar {
|
|
68
69
|
display: flex;
|
|
69
70
|
flex-direction: column;
|
|
70
|
-
background-color: var(--navbar-bg-color);
|
|
71
71
|
position: fixed;
|
|
72
72
|
width: 750rpx;
|
|
73
73
|
z-index: 999;
|
|
74
|
-
border-bottom:
|
|
74
|
+
border-bottom: 1rpx solid rgba(226, 232, 240, 0);
|
|
75
|
+
transition:
|
|
76
|
+
background-color 0.2s ease,
|
|
77
|
+
border-bottom 0.2s ease;
|
|
78
|
+
|
|
79
|
+
/* 白色主题:白色导航栏,下方加一条灰色的细边框 */
|
|
80
|
+
&.white-theme {
|
|
81
|
+
background-color: var(--navbar-bg-color, #ffffff);
|
|
82
|
+
border-bottom: var(--navbar-border-bottom, 1rpx solid #e7e7e7);
|
|
83
|
+
|
|
84
|
+
.title {
|
|
85
|
+
color: var(--font-color, #303048);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.icon-left {
|
|
89
|
+
color: var(--font-color, #303048);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* 简洁主题:背景色与页面全局背景色一致,无明显界限,无边框 */
|
|
94
|
+
&.light-theme {
|
|
95
|
+
background-color: var(--bg-page, #f8f8f8);
|
|
96
|
+
border-bottom: 1rpx solid rgba(226, 232, 240, 0);
|
|
97
|
+
|
|
98
|
+
.title {
|
|
99
|
+
color: var(--font-color, #303048);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.icon-left {
|
|
103
|
+
color: var(--font-color, #303048);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* 单色主题:纯主题色导航栏,无边框,无圆角 */
|
|
108
|
+
&.mono-theme {
|
|
109
|
+
background-color: var(--primary-color, #3b82f6);
|
|
110
|
+
border-bottom: 1rpx solid rgba(226, 232, 240, 0);
|
|
111
|
+
|
|
112
|
+
.title {
|
|
113
|
+
color: #ffffff;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.icon-left {
|
|
117
|
+
color: #ffffff;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* 颜色主题:导航栏使用立体光影感的主题色渐变背景(反向:左上偏深,右下偏亮),下方带有白色圆角过渡 */
|
|
122
|
+
&.color-theme {
|
|
123
|
+
background: linear-gradient(135deg, rgba(0, 0, 0, 0.15) 0%, rgba(255, 255, 255, 0.15) 100%), var(--primary-color, #3b82f6);
|
|
124
|
+
border-bottom: 1rpx solid rgba(226, 232, 240, 0);
|
|
125
|
+
|
|
126
|
+
.title {
|
|
127
|
+
color: #ffffff;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.icon-left {
|
|
131
|
+
color: #ffffff;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
75
134
|
|
|
76
135
|
.header {
|
|
77
136
|
display: flex;
|
|
@@ -90,31 +149,32 @@ function tapBack() {
|
|
|
90
149
|
height: 100%;
|
|
91
150
|
|
|
92
151
|
.icon-left {
|
|
93
|
-
|
|
152
|
+
font-size: 30rpx;
|
|
94
153
|
}
|
|
95
154
|
}
|
|
96
155
|
|
|
97
156
|
.title {
|
|
98
|
-
font-size: var(--navbar-font-size);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
font-weight: bold;
|
|
157
|
+
font-size: var(--navbar-font-size, 26rpx);
|
|
158
|
+
letter-spacing: 1rpx;
|
|
159
|
+
font-weight: normal;
|
|
102
160
|
}
|
|
103
161
|
}
|
|
104
162
|
|
|
105
163
|
.status-bar {
|
|
106
|
-
background-color:
|
|
164
|
+
background-color: transparent;
|
|
107
165
|
height: v-bind(status_bar_height_style);
|
|
108
166
|
width: 750rpx;
|
|
109
167
|
position: relative;
|
|
110
168
|
|
|
111
169
|
.within {
|
|
112
170
|
position: absolute;
|
|
171
|
+
left: 0;
|
|
172
|
+
top: 0;
|
|
113
173
|
width: 750rpx;
|
|
114
|
-
height: v-bind(status_bar_height_style);
|
|
115
|
-
background-color: var(--bg-color);
|
|
116
|
-
border-top-left-radius: var(--status-bar-border);
|
|
117
|
-
border-top-right-radius: var(--status-bar-border);
|
|
174
|
+
height: calc(v-bind(status_bar_height_style) + 2rpx);
|
|
175
|
+
background-color: var(--bg-color, var(--bg-page, #f8f8f8));
|
|
176
|
+
border-top-left-radius: var(--status-bar-border, var(--card-radius, 32rpx));
|
|
177
|
+
border-top-right-radius: var(--status-bar-border, var(--card-radius, 32rpx));
|
|
118
178
|
}
|
|
119
179
|
}
|
|
120
180
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view :class="theme" style="padding-bottom: 100rpx">
|
|
2
|
+
<view :class="[theme, fontSizeClass, fontFamilyClass]" style="padding-bottom: 100rpx">
|
|
3
3
|
<hlw-nav-bar :is-back="props.isBack" :title="title" :is-bar="props.isBar"></hlw-nav-bar>
|
|
4
4
|
<slot></slot>
|
|
5
5
|
</view>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { useTheme } from "@/core";
|
|
10
10
|
import { onLoad, onShow } from "@dcloudio/uni-app";
|
|
11
11
|
import { ref } from "vue";
|
|
12
|
-
const { theme } = useTheme();
|
|
12
|
+
const { theme, fontSizeClass, fontFamilyClass } = useTheme();
|
|
13
13
|
|
|
14
14
|
const props = defineProps({
|
|
15
15
|
isBar: {
|
|
@@ -29,4 +29,70 @@ const props = defineProps({
|
|
|
29
29
|
const title = ref(props.title);
|
|
30
30
|
</script>
|
|
31
31
|
|
|
32
|
-
<style
|
|
32
|
+
<style lang="scss">
|
|
33
|
+
/* 全局系统字体大小缩放配置 */
|
|
34
|
+
.font-size-small {
|
|
35
|
+
--font-xs: 18rpx;
|
|
36
|
+
--font-sm: 22rpx;
|
|
37
|
+
--font-base: 24rpx;
|
|
38
|
+
--font-md: 28rpx;
|
|
39
|
+
--font-lg: 32rpx;
|
|
40
|
+
--font-xl: 36rpx;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.font-size-standard {
|
|
44
|
+
--font-xs: 20rpx;
|
|
45
|
+
--font-sm: 24rpx;
|
|
46
|
+
--font-base: 28rpx;
|
|
47
|
+
--font-md: 32rpx;
|
|
48
|
+
--font-lg: 36rpx;
|
|
49
|
+
--font-xl: 40rpx;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.font-size-large {
|
|
53
|
+
--font-xs: 22rpx;
|
|
54
|
+
--font-sm: 28rpx;
|
|
55
|
+
--font-base: 32rpx;
|
|
56
|
+
--font-md: 36rpx;
|
|
57
|
+
--font-lg: 40rpx;
|
|
58
|
+
--font-xl: 44rpx;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.font-size-extra-large {
|
|
62
|
+
--font-xs: 24rpx;
|
|
63
|
+
--font-sm: 32rpx;
|
|
64
|
+
--font-base: 36rpx;
|
|
65
|
+
--font-md: 40rpx;
|
|
66
|
+
--font-lg: 44rpx;
|
|
67
|
+
--font-xl: 48rpx;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* 全局字体样式配置 */
|
|
71
|
+
.font-family-system {
|
|
72
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
|
|
73
|
+
view, text, button, input, textarea {
|
|
74
|
+
font-family: inherit !important;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.font-family-sans {
|
|
79
|
+
font-family: "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif !important;
|
|
80
|
+
view, text, button, input, textarea {
|
|
81
|
+
font-family: inherit !important;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.font-family-serif {
|
|
86
|
+
font-family: "Songti SC", "STSong", "SimSun", "Georgia", serif !important;
|
|
87
|
+
view, text, button, input, textarea {
|
|
88
|
+
font-family: inherit !important;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.font-family-kaiti {
|
|
93
|
+
font-family: "Kaiti SC", "STKaiti", "KaiTi", "SimKai", serif !important;
|
|
94
|
+
view, text, button, input, textarea {
|
|
95
|
+
font-family: inherit !important;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</style>
|
package/src/core/theme.ts
CHANGED
|
@@ -1,12 +1,62 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
2
|
import type { ComputedRef } from "vue";
|
|
3
|
+
import {
|
|
4
|
+
useThemeStore,
|
|
5
|
+
themePresets,
|
|
6
|
+
fontSizePresets,
|
|
7
|
+
fontFamilyPresets
|
|
8
|
+
} from "../stores/theme";
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
themePresets,
|
|
12
|
+
type ThemePreset,
|
|
13
|
+
fontSizePresets,
|
|
14
|
+
type FontSizePreset,
|
|
15
|
+
fontFamilyPresets,
|
|
16
|
+
type FontFamilyPreset
|
|
17
|
+
} from "../stores/theme";
|
|
18
|
+
|
|
19
|
+
// ==========================================
|
|
20
|
+
// 统一个性化外观配置 Hook (useTheme)
|
|
21
|
+
// ==========================================
|
|
3
22
|
|
|
4
23
|
export function useTheme() {
|
|
5
|
-
const
|
|
24
|
+
const store = useThemeStore();
|
|
25
|
+
|
|
26
|
+
// 主题
|
|
27
|
+
const theme: ComputedRef<string> = computed(() => store.theme);
|
|
28
|
+
|
|
29
|
+
// 字体大小
|
|
30
|
+
const fontSize: ComputedRef<string> = computed(() => store.fontSize);
|
|
31
|
+
const fontSizeClass: ComputedRef<string> = computed(() => {
|
|
32
|
+
const found = fontSizePresets.find((p) => p.id === store.fontSize);
|
|
33
|
+
return found ? found.class : "font-size-standard";
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// 字体样式
|
|
37
|
+
const fontFamily: ComputedRef<string> = computed(() => store.fontFamily);
|
|
38
|
+
const fontFamilyClass: ComputedRef<string> = computed(() => {
|
|
39
|
+
const found = fontFamilyPresets.find((p) => p.id === store.fontFamily);
|
|
40
|
+
return found ? found.class : "font-family-system";
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// 动作方法
|
|
44
|
+
function setFontSize(size: string): void {
|
|
45
|
+
store.setFontSize(size);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function setFontFamily(font: string): void {
|
|
49
|
+
store.setFontFamily(font);
|
|
50
|
+
}
|
|
51
|
+
|
|
6
52
|
return {
|
|
7
53
|
theme,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
54
|
+
fontSize,
|
|
55
|
+
fontSizeClass,
|
|
56
|
+
setFontSize,
|
|
57
|
+
fontFamily,
|
|
58
|
+
fontFamilyClass,
|
|
59
|
+
setFontFamily,
|
|
60
|
+
store,
|
|
11
61
|
};
|
|
12
62
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,20 +3,27 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 2.0 起合并了原 @hlw-uni/mp-core 全部内容。
|
|
5
5
|
* 业务方一处 import,无需再分包:
|
|
6
|
-
* import { useMsg,
|
|
6
|
+
* import { useMsg, useTheme, ... } from "@hlw-uni/mp-vue";
|
|
7
7
|
*
|
|
8
8
|
* UI 组件(hlw-page / hlw-button / hlw-ad 等)走 easycom 自动注册,不在这里 export。
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
// Composables / 工具 / Theme
|
|
12
12
|
export * from "./composables";
|
|
13
|
+
export {
|
|
14
|
+
useTheme,
|
|
15
|
+
themePresets,
|
|
16
|
+
type ThemePreset,
|
|
17
|
+
fontFamilyPresets,
|
|
18
|
+
type FontFamilyPreset,
|
|
19
|
+
fontSizePresets,
|
|
20
|
+
type FontSizePreset
|
|
21
|
+
} from "./core/theme";
|
|
13
22
|
|
|
14
23
|
// 类型
|
|
15
24
|
export type { HlwMenuItem } from "./components/hlw-menu/types";
|
|
16
25
|
export type { HlwPagingRef, HlwPagingInstance } from "./components/hlw-paging/types";
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
|
|
20
27
|
// App 根上下文
|
|
21
28
|
export { useApp } from "./app";
|
|
22
29
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./theme";
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { defineStore } from "pinia";
|
|
2
|
+
|
|
3
|
+
// ==========================================
|
|
4
|
+
// 1. 主题 (Theme) 预设与类型
|
|
5
|
+
// ==========================================
|
|
6
|
+
|
|
7
|
+
export interface ThemePreset {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
color: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const themePresets: ThemePreset[] = [
|
|
14
|
+
{
|
|
15
|
+
id: "white-theme",
|
|
16
|
+
name: "白色主题",
|
|
17
|
+
color: "#ffffff",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "light-theme",
|
|
21
|
+
name: "简洁主题",
|
|
22
|
+
color: "var(--bg-page, #f8f8f8)",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "mono-theme",
|
|
26
|
+
name: "单色主题",
|
|
27
|
+
color: "var(--primary-color, #3b82f6)",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "color-theme",
|
|
31
|
+
name: "颜色主题",
|
|
32
|
+
color: "var(--primary-color, #3b82f6)",
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
// ==========================================
|
|
37
|
+
// 2. 字体大小 (FontSize) 预设与类型
|
|
38
|
+
// ==========================================
|
|
39
|
+
|
|
40
|
+
export interface FontSizePreset {
|
|
41
|
+
id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
class: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const fontSizePresets: FontSizePreset[] = [
|
|
47
|
+
{
|
|
48
|
+
id: "small",
|
|
49
|
+
name: "较小",
|
|
50
|
+
class: "font-size-small",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: "standard",
|
|
54
|
+
name: "标准",
|
|
55
|
+
class: "font-size-standard",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "large",
|
|
59
|
+
name: "较大",
|
|
60
|
+
class: "font-size-large",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "extra-large",
|
|
64
|
+
name: "超大",
|
|
65
|
+
class: "font-size-extra-large",
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
// ==========================================
|
|
70
|
+
// 3. 字体样式 (FontFamily) 预设与类型
|
|
71
|
+
// ==========================================
|
|
72
|
+
|
|
73
|
+
export interface FontFamilyPreset {
|
|
74
|
+
id: string;
|
|
75
|
+
name: string;
|
|
76
|
+
class: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const fontFamilyPresets: FontFamilyPreset[] = [
|
|
80
|
+
{
|
|
81
|
+
id: "system",
|
|
82
|
+
name: "系统默认",
|
|
83
|
+
class: "font-family-system",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "sans",
|
|
87
|
+
name: "现代黑体",
|
|
88
|
+
class: "font-family-sans",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "serif",
|
|
92
|
+
name: "经典宋体",
|
|
93
|
+
class: "font-family-serif",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: "kaiti",
|
|
97
|
+
name: "优雅楷体",
|
|
98
|
+
class: "font-family-kaiti",
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
// ==========================================
|
|
103
|
+
// 4. 统一个性化配置 Store (Theme / Font)
|
|
104
|
+
// ==========================================
|
|
105
|
+
|
|
106
|
+
export const useThemeStore = defineStore("theme", {
|
|
107
|
+
state: () => ({
|
|
108
|
+
theme: "white-theme",
|
|
109
|
+
fontSize: "standard",
|
|
110
|
+
fontFamily: "system",
|
|
111
|
+
}),
|
|
112
|
+
getters: {},
|
|
113
|
+
actions: {
|
|
114
|
+
setFontSize(size: string) {
|
|
115
|
+
if (["small", "standard", "large", "extra-large"].includes(size)) {
|
|
116
|
+
this.fontSize = size;
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
setFontFamily(font: string) {
|
|
120
|
+
if (["system", "sans", "serif", "kaiti"].includes(font)) {
|
|
121
|
+
this.fontFamily = font;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
unistorage: true,
|
|
126
|
+
});
|