@hlw-uni/mp-vue 2.1.70 → 2.1.97
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/README.md +230 -386
- package/dist/app.d.ts +1 -1
- package/dist/core/index.d.ts +3 -0
- package/dist/core/{theme.d.ts → theme/index.d.ts} +6 -1
- package/dist/hlw.d.ts +1 -10
- package/dist/index.d.ts +2 -2
- package/dist/index.js +834 -804
- package/dist/index.mjs +836 -806
- package/dist/utils/ad/index.d.ts +61 -0
- package/dist/{composables/utils → utils/common}/index.d.ts +1 -24
- package/dist/{composables → utils}/device/index.d.ts +7 -8
- package/dist/utils/index.d.ts +5 -0
- package/dist/{composables → utils}/navigator/index.d.ts +14 -30
- package/dist/{composables → utils}/request/client.d.ts +2 -8
- package/dist/{composables → utils}/request/index.d.ts +1 -1
- package/dist/{composables → utils}/request/service.d.ts +2 -2
- package/package.json +1 -1
- package/src/app.ts +2 -2
- package/src/components/hlw-add-mini/README.md +56 -9
- package/src/components/hlw-add-mini/index.vue +12 -9
- package/src/components/hlw-avatar-upload/index.vue +103 -0
- package/src/components/hlw-back-top/index.vue +1 -1
- package/src/components/hlw-button/index.vue +5 -16
- package/src/components/hlw-canvas/index.vue +7 -7
- package/src/components/hlw-cell/index.vue +1 -1
- package/src/components/{hlw-custom/hlw-custom.vue → hlw-custom-service/hlw-custom-service.vue} +27 -15
- package/src/components/hlw-empty/index.vue +14 -0
- package/src/components/hlw-header/index.vue +1 -1
- package/src/components/hlw-menu/index.vue +40 -37
- package/src/components/hlw-nav-bar/index.vue +23 -8
- package/src/components/hlw-nickname/index.vue +185 -0
- package/src/components/hlw-notice-bar/index.vue +23 -0
- package/src/components/hlw-page/index.vue +19 -1
- package/src/components/hlw-paging/index.vue +36 -0
- package/src/components/hlw-popup/index.vue +23 -0
- package/src/components/hlw-reward-ad/index.vue +133 -0
- package/src/components/hlw-search/index.vue +25 -0
- package/src/components/hlw-sheet/index.vue +1 -1
- package/src/components/hlw-status-bar/index.vue +113 -0
- package/src/components/hlw-tag/index.vue +22 -0
- package/src/core/index.ts +3 -0
- package/src/{composables → core}/msg/index.ts +0 -1
- package/src/{composables → core}/refs/index.ts +0 -1
- package/src/core/theme/index.ts +115 -0
- package/src/hlw.ts +1 -21
- package/src/index.ts +3 -11
- package/src/utils/ad/README.md +114 -0
- package/src/utils/ad/index.ts +234 -0
- package/src/{composables/utils → utils/common}/index.ts +1 -27
- package/src/{composables → utils}/device/index.ts +13 -21
- package/src/utils/index.ts +5 -0
- package/src/{composables → utils}/navigator/index.ts +30 -31
- package/src/{composables → utils}/request/client.ts +3 -11
- package/src/{composables → utils}/request/index.ts +1 -1
- package/src/{composables → utils}/request/service.ts +5 -6
- package/src/{composables → utils}/request/types.ts +0 -1
- package/dist/composables/ad/index.d.ts +0 -42
- package/dist/composables/index.d.ts +0 -11
- package/src/composables/ad/README.md +0 -58
- package/src/composables/ad/index.ts +0 -227
- package/src/composables/device/README.md +0 -50
- package/src/composables/index.ts +0 -38
- package/src/composables/msg/README.md +0 -79
- package/src/composables/navigator/README.md +0 -71
- package/src/composables/refs/README.md +0 -40
- package/src/composables/request/README.md +0 -124
- package/src/composables/share/README.md +0 -53
- package/src/composables/utils/README.md +0 -81
- package/src/core/theme.ts +0 -62
- /package/dist/{composables → core}/msg/index.d.ts +0 -0
- /package/dist/{composables → core}/refs/index.d.ts +0 -0
- /package/dist/{composables → core}/share/index.d.ts +0 -0
- /package/dist/{composables → utils}/request/adapters/alist.d.ts +0 -0
- /package/dist/{composables → utils}/request/adapters/base.d.ts +0 -0
- /package/dist/{composables → utils}/request/adapters/cos.d.ts +0 -0
- /package/dist/{composables → utils}/request/adapters/index.d.ts +0 -0
- /package/dist/{composables → utils}/request/adapters/oss.d.ts +0 -0
- /package/dist/{composables → utils}/request/adapters/qiniu.d.ts +0 -0
- /package/dist/{composables → utils}/request/types.d.ts +0 -0
- /package/src/{composables → core}/share/index.ts +0 -0
- /package/src/{composables → utils}/request/adapters/alist.ts +0 -0
- /package/src/{composables → utils}/request/adapters/base.ts +0 -0
- /package/src/{composables → utils}/request/adapters/cos.ts +0 -0
- /package/src/{composables → utils}/request/adapters/index.ts +0 -0
- /package/src/{composables → utils}/request/adapters/oss.ts +0 -0
- /package/src/{composables → utils}/request/adapters/qiniu.ts +0 -0
package/src/components/{hlw-custom/hlw-custom.vue → hlw-custom-service/hlw-custom-service.vue}
RENAMED
|
@@ -4,15 +4,8 @@
|
|
|
4
4
|
<text class="contact-title">{{ title }}</text>
|
|
5
5
|
<text class="contact-desc">{{ desc }}</text>
|
|
6
6
|
</view>
|
|
7
|
-
<button
|
|
8
|
-
class="
|
|
9
|
-
open-type="contact"
|
|
10
|
-
:send-message-title="resolvedContact.title"
|
|
11
|
-
:send-message-path="resolvedContact.path"
|
|
12
|
-
:send-message-img="resolvedContact.img"
|
|
13
|
-
:show-message-card="resolvedContact.show"
|
|
14
|
-
>
|
|
15
|
-
<text class="i-ri-customer-service-line contact-button-icon" />
|
|
7
|
+
<button class="contact-button" open-type="contact" :send-message-title="resolvedContact.title" :send-message-path="resolvedContact.path" :send-message-img="resolvedContact.img" :show-message-card="resolvedContact.show">
|
|
8
|
+
<span class="iconfont icon-service" />
|
|
16
9
|
<text class="contact-button-text">{{ resolvedBtnTitle }}</text>
|
|
17
10
|
</button>
|
|
18
11
|
</view>
|
|
@@ -21,6 +14,30 @@
|
|
|
21
14
|
<script setup lang="ts">
|
|
22
15
|
import { computed } from "vue";
|
|
23
16
|
|
|
17
|
+
/**
|
|
18
|
+
* HlwCustomService — 客服卡片自定义组件
|
|
19
|
+
*
|
|
20
|
+
* 用于引导用户点击联系微信客服,支持配置标题、描述、按钮文案及原生客服卡片参数。
|
|
21
|
+
*
|
|
22
|
+
* @props
|
|
23
|
+
* title - 客服卡片主标题
|
|
24
|
+
* desc - 客服卡片描述/说明文字
|
|
25
|
+
* btn_title - 客服按钮文案,默认 "联系客服"
|
|
26
|
+
* contact - 微信原生客服卡片配置项
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```vue
|
|
30
|
+
* <HlwCustomService
|
|
31
|
+
* title="专属客服"
|
|
32
|
+
* desc="遇到问题?点击咨询您的专属客服"
|
|
33
|
+
* btn_title="去咨询"
|
|
34
|
+
* :contact="{ send_message_title: '咨询标题' }"
|
|
35
|
+
* />
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
defineOptions({ name: "HlwCustomService" });
|
|
40
|
+
|
|
24
41
|
interface ContactConfig {
|
|
25
42
|
send_message_title?: string;
|
|
26
43
|
send_message_path?: string;
|
|
@@ -38,7 +55,7 @@ const props = withDefaults(
|
|
|
38
55
|
{
|
|
39
56
|
btn_title: "",
|
|
40
57
|
contact: () => ({}),
|
|
41
|
-
}
|
|
58
|
+
},
|
|
42
59
|
);
|
|
43
60
|
|
|
44
61
|
const resolvedBtnTitle = computed(() => {
|
|
@@ -106,11 +123,6 @@ const resolvedContact = computed(() => {
|
|
|
106
123
|
line-height: 68rpx;
|
|
107
124
|
}
|
|
108
125
|
|
|
109
|
-
.contact-button-icon {
|
|
110
|
-
width: var(--font-sm);
|
|
111
|
-
height: var(--font-sm);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
126
|
.contact-button-text {
|
|
115
127
|
color: inherit;
|
|
116
128
|
font-size: var(--font-sm);
|
|
@@ -8,6 +8,20 @@
|
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script setup lang="ts">
|
|
11
|
+
/**
|
|
12
|
+
* HlwEmpty — 空状态组件
|
|
13
|
+
*
|
|
14
|
+
* 用于页面或区域无数据时的占位展示,支持自定义提示文本和占位图片。
|
|
15
|
+
*
|
|
16
|
+
* @props
|
|
17
|
+
* text - 占位提示文案,默认 "暂无数据"
|
|
18
|
+
* image - 占位图地址,未提供时默认渲染原生盒子 icon
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```vue
|
|
22
|
+
* <HlwEmpty text="空空如也,快去添加内容吧" />
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
11
25
|
defineProps<{
|
|
12
26
|
text?: string;
|
|
13
27
|
image?: string;
|
|
@@ -9,17 +9,18 @@
|
|
|
9
9
|
<!-- 列表模式 -->
|
|
10
10
|
<template v-if="props.mode === 'list'">
|
|
11
11
|
<template v-for="(item, index) in visibleItems" :key="index">
|
|
12
|
-
<navigator v-if="item.url" :url="item.url" class="hlw-menu-item" hover-class="hlw-menu-item--active">
|
|
12
|
+
<navigator v-if="item.url" :url="item.url" animation-type="none" class="hlw-menu-item" hover-class="hlw-menu-item--active">
|
|
13
13
|
<view class="hlw-menu-left">
|
|
14
14
|
<view class="hlw-menu-icon" :class="`hlw-menu-icon--${item.iconTheme || 'slate'}`">
|
|
15
|
-
<
|
|
15
|
+
<image v-if="isImageIcon(item.icon)" :src="item.icon" class="hlw-menu-icon-img" mode="aspectFit" />
|
|
16
|
+
<span v-else :class="item.icon"></span>
|
|
16
17
|
</view>
|
|
17
18
|
<text class="hlw-menu-label">{{ item.label }}</text>
|
|
18
19
|
</view>
|
|
19
20
|
<view class="hlw-menu-right">
|
|
20
21
|
<text v-if="item.value" class="hlw-menu-value">{{ item.value }}</text>
|
|
21
22
|
<text v-if="item.tag" class="hlw-menu-tag" :class="[`hlw-menu-tag--${item.tagTheme || 'rose'}`, item.tagPulse ? 'hlw-menu-tag-pulse' : '']">{{ item.tag }}</text>
|
|
22
|
-
<
|
|
23
|
+
<span class="i-fa6-solid-chevron-right hlw-menu-arrow"></span>
|
|
23
24
|
</view>
|
|
24
25
|
</navigator>
|
|
25
26
|
|
|
@@ -39,30 +40,32 @@
|
|
|
39
40
|
>
|
|
40
41
|
<view class="hlw-menu-left">
|
|
41
42
|
<view class="hlw-menu-icon" :class="`hlw-menu-icon--${item.iconTheme || 'slate'}`">
|
|
42
|
-
<
|
|
43
|
+
<image v-if="isImageIcon(item.icon)" :src="item.icon" class="hlw-menu-icon-img" mode="aspectFit" />
|
|
44
|
+
<span v-else :class="item.icon"></span>
|
|
43
45
|
</view>
|
|
44
46
|
<text class="hlw-menu-label">{{ item.label }}</text>
|
|
45
47
|
</view>
|
|
46
48
|
<view class="hlw-menu-right">
|
|
47
|
-
<
|
|
49
|
+
<span v-if="item.loading" class="i-fa6-solid-circle-notch hlw-menu-spin hlw-menu-muted"></span>
|
|
48
50
|
<text v-if="item.value" class="hlw-menu-value">{{ item.value }}</text>
|
|
49
51
|
<text v-if="item.tag" class="hlw-menu-tag" :class="[`hlw-menu-tag--${item.tagTheme || 'rose'}`, item.tagPulse ? 'hlw-menu-tag-pulse' : '']">{{ item.tag }}</text>
|
|
50
|
-
<
|
|
52
|
+
<span class="i-fa6-solid-chevron-right hlw-menu-arrow"></span>
|
|
51
53
|
</view>
|
|
52
54
|
</button>
|
|
53
55
|
|
|
54
56
|
<view v-else class="hlw-menu-item" hover-class="hlw-menu-item--active" @click="handleClick(item)">
|
|
55
57
|
<view class="hlw-menu-left">
|
|
56
58
|
<view class="hlw-menu-icon" :class="`hlw-menu-icon--${item.iconTheme || 'slate'}`">
|
|
57
|
-
<
|
|
59
|
+
<image v-if="isImageIcon(item.icon)" :src="item.icon" class="hlw-menu-icon-img" mode="aspectFit" />
|
|
60
|
+
<span v-else :class="item.icon"></span>
|
|
58
61
|
</view>
|
|
59
62
|
<text class="hlw-menu-label">{{ item.label }}</text>
|
|
60
63
|
</view>
|
|
61
64
|
<view class="hlw-menu-right">
|
|
62
|
-
<
|
|
65
|
+
<span v-if="item.loading" class="i-fa6-solid-circle-notch hlw-menu-spin hlw-menu-muted"></span>
|
|
63
66
|
<text v-if="item.value" class="hlw-menu-value">{{ item.value }}</text>
|
|
64
67
|
<text v-if="item.tag" class="hlw-menu-tag" :class="[`hlw-menu-tag--${item.tagTheme || 'rose'}`, item.tagPulse ? 'hlw-menu-tag-pulse' : '']">{{ item.tag }}</text>
|
|
65
|
-
<
|
|
68
|
+
<span class="i-fa6-solid-chevron-right hlw-menu-arrow"></span>
|
|
66
69
|
</view>
|
|
67
70
|
</view>
|
|
68
71
|
|
|
@@ -73,10 +76,11 @@
|
|
|
73
76
|
<!-- 宫格模式 -->
|
|
74
77
|
<view v-else class="hlw-menu-grid" :style="{ gridTemplateColumns: `repeat(${props.columns}, 1fr)` }">
|
|
75
78
|
<template v-for="(item, index) in visibleItems" :key="index">
|
|
76
|
-
<navigator v-if="item.url" :url="item.url" class="hlw-menu-grid-item" hover-class="hlw-menu-grid-item--active">
|
|
79
|
+
<navigator v-if="item.url" :url="item.url" animation-type="none" class="hlw-menu-grid-item" hover-class="hlw-menu-grid-item--active">
|
|
77
80
|
<view class="hlw-menu-grid-icon-wrap">
|
|
78
81
|
<view class="hlw-menu-icon hlw-menu-icon--grid" :class="`hlw-menu-icon--${item.iconTheme || 'slate'}`">
|
|
79
|
-
<
|
|
82
|
+
<image v-if="isImageIcon(item.icon)" :src="item.icon" class="hlw-menu-icon-img" mode="aspectFit" />
|
|
83
|
+
<span v-else :class="item.icon"></span>
|
|
80
84
|
</view>
|
|
81
85
|
<text v-if="item.tag" class="hlw-menu-badge" :class="[`hlw-menu-tag--${item.tagTheme || 'rose'}`, item.tagPulse ? 'hlw-menu-tag-pulse' : '']">{{ item.tag }}</text>
|
|
82
86
|
</view>
|
|
@@ -86,7 +90,8 @@
|
|
|
86
90
|
<view v-else class="hlw-menu-grid-item" hover-class="hlw-menu-grid-item--active" @click="handleClick(item)">
|
|
87
91
|
<view class="hlw-menu-grid-icon-wrap">
|
|
88
92
|
<view class="hlw-menu-icon hlw-menu-icon--grid" :class="`hlw-menu-icon--${item.iconTheme || 'slate'}`">
|
|
89
|
-
<
|
|
93
|
+
<image v-if="isImageIcon(item.icon)" :src="item.icon" class="hlw-menu-icon-img" mode="aspectFit" />
|
|
94
|
+
<span v-else :class="item.icon"></span>
|
|
90
95
|
</view>
|
|
91
96
|
<text v-if="item.tag" class="hlw-menu-badge" :class="[`hlw-menu-tag--${item.tagTheme || 'rose'}`, item.tagPulse ? 'hlw-menu-tag-pulse' : '']">{{ item.tag }}</text>
|
|
92
97
|
</view>
|
|
@@ -179,6 +184,11 @@ const emit = defineEmits<{
|
|
|
179
184
|
getphonenumber: [item: HlwMenuItem, event: unknown];
|
|
180
185
|
}>();
|
|
181
186
|
|
|
187
|
+
const isImageIcon = (icon?: string) => {
|
|
188
|
+
if (!icon) return false;
|
|
189
|
+
return icon.startsWith("http") || icon.startsWith("/") || icon.startsWith(".") || icon.includes("/");
|
|
190
|
+
};
|
|
191
|
+
|
|
182
192
|
const visibleItems = computed(() => props.items.filter((item) => item.visible !== false));
|
|
183
193
|
|
|
184
194
|
const handleClick = (item: HlwMenuItem) => {
|
|
@@ -196,13 +206,13 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
196
206
|
|
|
197
207
|
<style lang="scss" scoped>
|
|
198
208
|
.hlw-menu {
|
|
199
|
-
--hlw-menu-icon-size: var(--font-
|
|
200
|
-
--hlw-menu-icon-box-size:
|
|
201
|
-
--hlw-menu-grid-icon-size: var(--font-
|
|
209
|
+
--hlw-menu-icon-size: var(--font-md, 32rpx);
|
|
210
|
+
--hlw-menu-icon-box-size: var(--hlw-menu-icon-size);
|
|
211
|
+
--hlw-menu-grid-icon-size: var(--font-xl, 40rpx);
|
|
202
212
|
--hlw-menu-grid-icon-box-size: calc(var(--hlw-menu-grid-icon-size) + 52rpx);
|
|
203
213
|
background: var(--surface-card, #ffffff);
|
|
204
214
|
border-radius: var(--radius-lg, 24rpx);
|
|
205
|
-
border: 1rpx solid var(--border-color, #
|
|
215
|
+
border: 1rpx solid var(--border-color-light, #ececec);
|
|
206
216
|
overflow: hidden;
|
|
207
217
|
width: 100%;
|
|
208
218
|
|
|
@@ -224,7 +234,7 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
224
234
|
|
|
225
235
|
.hlw-menu-title-divider {
|
|
226
236
|
height: 0;
|
|
227
|
-
border-bottom: 1rpx dashed var(--border-color, #
|
|
237
|
+
border-bottom: 1rpx dashed var(--border-color-light, #ececec);
|
|
228
238
|
}
|
|
229
239
|
|
|
230
240
|
/* ========== 列表模式 ========== */
|
|
@@ -232,7 +242,7 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
232
242
|
display: flex;
|
|
233
243
|
align-items: center;
|
|
234
244
|
justify-content: space-between;
|
|
235
|
-
padding:
|
|
245
|
+
padding: 32rpx 36rpx;
|
|
236
246
|
|
|
237
247
|
&--active {
|
|
238
248
|
background: var(--surface-card-muted, #f8fafc);
|
|
@@ -246,7 +256,7 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
246
256
|
justify-content: space-between;
|
|
247
257
|
width: 100%;
|
|
248
258
|
margin: 0;
|
|
249
|
-
padding:
|
|
259
|
+
padding: 32rpx 36rpx;
|
|
250
260
|
background: transparent;
|
|
251
261
|
color: inherit;
|
|
252
262
|
font-size: inherit;
|
|
@@ -264,15 +274,15 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
264
274
|
}
|
|
265
275
|
|
|
266
276
|
.hlw-menu-divider {
|
|
267
|
-
margin: 0
|
|
277
|
+
margin: 0 36rpx;
|
|
268
278
|
height: 0;
|
|
269
|
-
border-bottom: 1rpx dashed var(--border-color, #
|
|
279
|
+
border-bottom: 1rpx dashed var(--border-color-light, #ececec);
|
|
270
280
|
}
|
|
271
281
|
|
|
272
282
|
.hlw-menu-left {
|
|
273
283
|
display: flex;
|
|
274
284
|
align-items: center;
|
|
275
|
-
gap:
|
|
285
|
+
gap: 20rpx;
|
|
276
286
|
}
|
|
277
287
|
|
|
278
288
|
.hlw-menu-right {
|
|
@@ -328,13 +338,14 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
328
338
|
.hlw-menu-icon {
|
|
329
339
|
width: var(--hlw-menu-icon-box-size);
|
|
330
340
|
height: var(--hlw-menu-icon-box-size);
|
|
331
|
-
border-radius: var(--radius-md, 16rpx);
|
|
332
341
|
display: flex;
|
|
333
342
|
align-items: center;
|
|
334
343
|
justify-content: center;
|
|
335
344
|
flex-shrink: 0;
|
|
336
345
|
|
|
337
|
-
text
|
|
346
|
+
text,
|
|
347
|
+
span,
|
|
348
|
+
.hlw-menu-icon-img {
|
|
338
349
|
width: var(--hlw-menu-icon-size);
|
|
339
350
|
height: var(--hlw-menu-icon-size);
|
|
340
351
|
font-size: var(--hlw-menu-icon-size);
|
|
@@ -344,8 +355,9 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
344
355
|
&--grid {
|
|
345
356
|
width: var(--hlw-menu-grid-icon-box-size);
|
|
346
357
|
height: var(--hlw-menu-grid-icon-box-size);
|
|
347
|
-
|
|
348
|
-
|
|
358
|
+
text,
|
|
359
|
+
span,
|
|
360
|
+
.hlw-menu-icon-img {
|
|
349
361
|
width: var(--hlw-menu-grid-icon-size);
|
|
350
362
|
height: var(--hlw-menu-grid-icon-size);
|
|
351
363
|
font-size: var(--hlw-menu-grid-icon-size);
|
|
@@ -354,48 +366,39 @@ const handleGetPhoneNumber = (item: HlwMenuItem, event: unknown) => {
|
|
|
354
366
|
}
|
|
355
367
|
|
|
356
368
|
&--orange {
|
|
357
|
-
background: #fff7ed;
|
|
358
369
|
color: #f97316;
|
|
359
370
|
}
|
|
360
371
|
&--purple {
|
|
361
|
-
background: #faf5ff;
|
|
362
372
|
color: #a855f7;
|
|
363
373
|
}
|
|
364
374
|
&--wechat {
|
|
365
|
-
background: #f0fdf4;
|
|
366
375
|
color: #07c160;
|
|
367
376
|
}
|
|
368
377
|
&--cyan {
|
|
369
|
-
background: #ecfeff;
|
|
370
378
|
color: #06b6d4;
|
|
371
379
|
}
|
|
372
380
|
&--emerald {
|
|
373
|
-
background: #ecfdf5;
|
|
374
381
|
color: #10b981;
|
|
375
382
|
}
|
|
376
383
|
&--slate {
|
|
377
|
-
background: #f1f5f9;
|
|
378
384
|
color: #64748b;
|
|
379
385
|
}
|
|
380
386
|
&--rose {
|
|
381
|
-
background: #fff1f2;
|
|
382
387
|
color: #f43f5e;
|
|
383
388
|
}
|
|
384
389
|
&--blue {
|
|
385
|
-
background: var(--primary-light, rgba(76, 68, 239, 0.12));
|
|
386
390
|
color: var(--primary-color, #3b82f6);
|
|
387
391
|
}
|
|
388
392
|
&--red {
|
|
389
|
-
background: #fef2f2;
|
|
390
393
|
color: #ef4444;
|
|
391
394
|
}
|
|
392
395
|
}
|
|
393
396
|
|
|
394
397
|
/* ========== 标签 / 角标 ========== */
|
|
395
398
|
.hlw-menu-label {
|
|
396
|
-
font-size: var(--font-
|
|
397
|
-
font-weight: 500;
|
|
399
|
+
font-size: var(--font-26, 26rpx);
|
|
398
400
|
color: var(--text-secondary, #334155);
|
|
401
|
+
letter-spacing: 1rpx;
|
|
399
402
|
}
|
|
400
403
|
|
|
401
404
|
.hlw-menu-value {
|
|
@@ -3,7 +3,7 @@
|
|
|
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">
|
|
6
|
-
<
|
|
6
|
+
<span class="i-fa6-solid-chevron-left icon-left"></span>
|
|
7
7
|
</view>
|
|
8
8
|
<text class="title">{{ title }}</text>
|
|
9
9
|
</view>
|
|
@@ -15,6 +15,21 @@
|
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
17
|
<script lang="ts" setup>
|
|
18
|
+
/**
|
|
19
|
+
* HlwNavBar — 自定义导航栏组件
|
|
20
|
+
*
|
|
21
|
+
* 自适应状态栏高度与胶囊按钮,完美替代微信小程序原生导航栏。支持不同主题配色、返回按钮及自适应高度。
|
|
22
|
+
*
|
|
23
|
+
* @props
|
|
24
|
+
* title - 导航栏标题文字
|
|
25
|
+
* isBack - 是否显示返回按钮,默认 false;点击自动回退或回到首页
|
|
26
|
+
* isBar - 是否占用状态栏高度,默认 false
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```vue
|
|
30
|
+
* <hlw-nav-bar title="设置中心" is-back />
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
18
33
|
import { computed, ref } from "vue";
|
|
19
34
|
import { useTheme } from "@/core";
|
|
20
35
|
|
|
@@ -82,11 +97,11 @@ function tapBack() {
|
|
|
82
97
|
border-bottom: var(--navbar-border-bottom, 1rpx solid #e7e7e7);
|
|
83
98
|
|
|
84
99
|
.title {
|
|
85
|
-
color: var(--
|
|
100
|
+
color: var(--text-primary, #303048);
|
|
86
101
|
}
|
|
87
102
|
|
|
88
103
|
.icon-left {
|
|
89
|
-
color: var(--
|
|
104
|
+
color: var(--text-primary, #303048);
|
|
90
105
|
}
|
|
91
106
|
}
|
|
92
107
|
|
|
@@ -96,11 +111,11 @@ function tapBack() {
|
|
|
96
111
|
border-bottom: 1rpx solid rgba(226, 232, 240, 0);
|
|
97
112
|
|
|
98
113
|
.title {
|
|
99
|
-
color: var(--
|
|
114
|
+
color: var(--text-primary, #303048);
|
|
100
115
|
}
|
|
101
116
|
|
|
102
117
|
.icon-left {
|
|
103
|
-
color: var(--
|
|
118
|
+
color: var(--text-primary, #303048);
|
|
104
119
|
}
|
|
105
120
|
}
|
|
106
121
|
|
|
@@ -154,9 +169,9 @@ function tapBack() {
|
|
|
154
169
|
}
|
|
155
170
|
|
|
156
171
|
.title {
|
|
157
|
-
font-size: var(--navbar-font-size,
|
|
158
|
-
letter-spacing:
|
|
159
|
-
font-weight:
|
|
172
|
+
font-size: var(--font-md, var(--navbar-font-size, 32rpx));
|
|
173
|
+
letter-spacing: 2rpx;
|
|
174
|
+
font-weight: 500;
|
|
160
175
|
}
|
|
161
176
|
}
|
|
162
177
|
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="hlw-nickname" @tap="openDialog">
|
|
3
|
+
<slot>
|
|
4
|
+
<text class="hlw-nickname__text">{{ props.text || '微信用户' }}</text>
|
|
5
|
+
</slot>
|
|
6
|
+
|
|
7
|
+
<!-- 修改昵称弹窗 -->
|
|
8
|
+
<root-portal v-if="showEditNicknameDialog">
|
|
9
|
+
<view class="nickname-modal" @tap="closeDialog">
|
|
10
|
+
<view class="nickname-dialog" @tap.stop>
|
|
11
|
+
<view class="dialog-title">修改昵称</view>
|
|
12
|
+
<view class="dialog-input-wrapper">
|
|
13
|
+
<input
|
|
14
|
+
class="dialog-input"
|
|
15
|
+
type="nickname"
|
|
16
|
+
v-model="tempNickname"
|
|
17
|
+
placeholder="请输入或获取微信昵称"
|
|
18
|
+
@blur="onNicknameBlur"
|
|
19
|
+
@input="onNicknameInput"
|
|
20
|
+
/>
|
|
21
|
+
</view>
|
|
22
|
+
<view class="dialog-actions">
|
|
23
|
+
<button class="dialog-btn cancel-btn" @tap="closeDialog">取消</button>
|
|
24
|
+
<button class="dialog-btn confirm-btn" @tap="confirmNickname">确定</button>
|
|
25
|
+
</view>
|
|
26
|
+
</view>
|
|
27
|
+
</view>
|
|
28
|
+
</root-portal>
|
|
29
|
+
</view>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script setup lang="ts">
|
|
33
|
+
import { ref } from "vue";
|
|
34
|
+
|
|
35
|
+
defineOptions({ name: "HlwNickname" });
|
|
36
|
+
|
|
37
|
+
interface Props {
|
|
38
|
+
/** 当前展示的昵称 */
|
|
39
|
+
text?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
43
|
+
text: "",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const emit = defineEmits<{
|
|
47
|
+
(e: "onNick", nickname: string): void;
|
|
48
|
+
}>();
|
|
49
|
+
|
|
50
|
+
const showEditNicknameDialog = ref(false);
|
|
51
|
+
const tempNickname = ref("");
|
|
52
|
+
|
|
53
|
+
function openDialog() {
|
|
54
|
+
tempNickname.value = props.text || "";
|
|
55
|
+
showEditNicknameDialog.value = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function closeDialog() {
|
|
59
|
+
showEditNicknameDialog.value = false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function onNicknameInput(e: any) {
|
|
63
|
+
tempNickname.value = e.detail?.value || "";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function onNicknameBlur(e: any) {
|
|
67
|
+
// 微信小程序特有:点击键盘上方微信昵称 suggestion 时,会触发 blur 并带上值
|
|
68
|
+
const value = e.detail?.value || "";
|
|
69
|
+
if (value) {
|
|
70
|
+
tempNickname.value = value;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function confirmNickname() {
|
|
75
|
+
const nickname = tempNickname.value?.trim();
|
|
76
|
+
if (!nickname) {
|
|
77
|
+
hlw.$msg.toast("昵称不能为空");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (nickname.length > 20) {
|
|
81
|
+
hlw.$msg.toast("昵称长度不能超过 20 个字符");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
emit("onNick", nickname);
|
|
85
|
+
closeDialog();
|
|
86
|
+
}
|
|
87
|
+
</script>
|
|
88
|
+
|
|
89
|
+
<style scoped>
|
|
90
|
+
.hlw-nickname {
|
|
91
|
+
display: inline-block;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* 弹窗遮罩 */
|
|
95
|
+
.nickname-modal {
|
|
96
|
+
position: fixed;
|
|
97
|
+
left: 0;
|
|
98
|
+
top: 0;
|
|
99
|
+
right: 0;
|
|
100
|
+
bottom: 0;
|
|
101
|
+
z-index: 10000;
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
justify-content: center;
|
|
105
|
+
background: rgba(0, 0, 0, 0.6);
|
|
106
|
+
backdrop-filter: blur(8rpx);
|
|
107
|
+
animation: fadeIn 0.2s ease-out;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* 弹窗主体 */
|
|
111
|
+
.nickname-dialog {
|
|
112
|
+
width: 600rpx;
|
|
113
|
+
padding: 40rpx;
|
|
114
|
+
border-radius: 24rpx;
|
|
115
|
+
background: #ffffff;
|
|
116
|
+
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.25);
|
|
117
|
+
animation: scaleIn 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.dialog-title {
|
|
121
|
+
margin-bottom: 30rpx;
|
|
122
|
+
color: #1e293b;
|
|
123
|
+
text-align: center;
|
|
124
|
+
font-size: 32rpx;
|
|
125
|
+
font-weight: 600;
|
|
126
|
+
letter-spacing: 1rpx;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.dialog-input-wrapper {
|
|
130
|
+
margin-bottom: 40rpx;
|
|
131
|
+
padding: 20rpx 24rpx;
|
|
132
|
+
border: 2rpx solid #e2e8f0;
|
|
133
|
+
border-radius: 16rpx;
|
|
134
|
+
background: #f8fafc;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.dialog-input {
|
|
138
|
+
width: 100%;
|
|
139
|
+
height: 48rpx;
|
|
140
|
+
color: #1e293b;
|
|
141
|
+
font-size: 28rpx;
|
|
142
|
+
text-align: left;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.dialog-actions {
|
|
146
|
+
display: flex;
|
|
147
|
+
gap: 20rpx;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.dialog-btn {
|
|
151
|
+
flex: 1;
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
justify-content: center;
|
|
155
|
+
height: 80rpx;
|
|
156
|
+
margin: 0;
|
|
157
|
+
font-size: 28rpx;
|
|
158
|
+
font-weight: 500;
|
|
159
|
+
border-radius: 16rpx;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.dialog-btn::after {
|
|
163
|
+
border: 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.cancel-btn {
|
|
167
|
+
background: #f1f5f9;
|
|
168
|
+
color: #64748b;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.confirm-btn {
|
|
172
|
+
background: #3b82f6;
|
|
173
|
+
color: #ffffff;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@keyframes fadeIn {
|
|
177
|
+
from { opacity: 0; }
|
|
178
|
+
to { opacity: 1; }
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@keyframes scaleIn {
|
|
182
|
+
from { transform: scale(0.9); opacity: 0; }
|
|
183
|
+
to { transform: scale(1); opacity: 1; }
|
|
184
|
+
}
|
|
185
|
+
</style>
|
|
@@ -13,6 +13,29 @@
|
|
|
13
13
|
</template>
|
|
14
14
|
|
|
15
15
|
<script setup lang="ts">
|
|
16
|
+
/**
|
|
17
|
+
* HlwNoticeBar — 滚动通告栏
|
|
18
|
+
*
|
|
19
|
+
* 用于显示重要广播、紧急通告或系统消息。支持横向无缝滚动播放、可关闭状态及自定义图标/色彩。
|
|
20
|
+
*
|
|
21
|
+
* @props
|
|
22
|
+
* text - 通告文本内容
|
|
23
|
+
* scrollable - 是否开启滚动播放,默认 true
|
|
24
|
+
* closable - 是否显示关闭按钮,默认 false
|
|
25
|
+
* color - 文字颜色,默认 "#ed6a0c"
|
|
26
|
+
* background - 背景颜色,默认 "#fffbe8"
|
|
27
|
+
* speed - 滚动速度(每秒像素数),默认 60
|
|
28
|
+
* leftIcon - 左侧自定义图标 class,默认喇叭图标
|
|
29
|
+
*
|
|
30
|
+
* @events
|
|
31
|
+
* close - 点击关闭按钮时触发
|
|
32
|
+
* click - 点击通告内容区时触发
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```vue
|
|
36
|
+
* <HlwNoticeBar text="系统将于今晚24点停机维护,给您带来的不便敬请谅解!" closable />
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
16
39
|
import { computed, ref } from "vue";
|
|
17
40
|
|
|
18
41
|
interface Props {
|
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view :class="[theme, fontSizeClass, fontFamilyClass]">
|
|
3
|
-
<hlw-nav-bar v-if="isBar" :is-back="props.isBack" :title="title" :is-bar="props.isBar"></hlw-nav-bar>
|
|
3
|
+
<hlw-nav-bar v-if="props.isBar" :is-back="props.isBack" :title="title" :is-bar="props.isBar"></hlw-nav-bar>
|
|
4
4
|
<slot></slot>
|
|
5
5
|
</view>
|
|
6
6
|
</template>
|
|
7
7
|
|
|
8
8
|
<script lang="ts" setup>
|
|
9
|
+
/**
|
|
10
|
+
* HlwPage — 页面核心容器组件
|
|
11
|
+
*
|
|
12
|
+
* 所有小程序页面的主框架容器。自动适配全局主题、字体大小和字体样式。
|
|
13
|
+
* 可以快捷集成自定义导航栏(HlwNavBar),保持整个页面结构的一致性。
|
|
14
|
+
*
|
|
15
|
+
* @props
|
|
16
|
+
* isBar - 是否显示并使用自定义导航栏,默认 false
|
|
17
|
+
* title - 自定义导航栏标题文字(在 isBar 为 true 时生效)
|
|
18
|
+
* isBack - 是否显示自定义导航栏的返回键(在 isBar 为 true 时生效),默认 false
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```vue
|
|
22
|
+
* <hlw-page is-bar is-back title="个人中心">
|
|
23
|
+
* <view>页面内容...</view>
|
|
24
|
+
* </hlw-page>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
9
27
|
import { useTheme } from "@/core";
|
|
10
28
|
import { onLoad, onShow } from "@dcloudio/uni-app";
|
|
11
29
|
import { ref } from "vue";
|