muzhiyu-ui 1.0.0

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.
Files changed (96) hide show
  1. package/README.md +202 -0
  2. package/components/muzhiyu/mu-action-sheet/mu-action-sheet.vue +335 -0
  3. package/components/muzhiyu/mu-alert/mu-alert.vue +220 -0
  4. package/components/muzhiyu/mu-back-top/mu-back-top.vue +161 -0
  5. package/components/muzhiyu/mu-badge/mu-badge.vue +150 -0
  6. package/components/muzhiyu/mu-barcode/mu-barcode.vue +100 -0
  7. package/components/muzhiyu/mu-blank/mu-blank.vue +30 -0
  8. package/components/muzhiyu/mu-bottom-nav/mu-bottom-nav.vue +331 -0
  9. package/components/muzhiyu/mu-bubble/mu-bubble.vue +316 -0
  10. package/components/muzhiyu/mu-button/mu-button.vue +431 -0
  11. package/components/muzhiyu/mu-calendar/mu-calendar.vue +429 -0
  12. package/components/muzhiyu/mu-car-input/mu-car-input.vue +209 -0
  13. package/components/muzhiyu/mu-card/mu-card.vue +317 -0
  14. package/components/muzhiyu/mu-cascader/mu-cascader.vue +336 -0
  15. package/components/muzhiyu/mu-cell/mu-cell.vue +368 -0
  16. package/components/muzhiyu/mu-checkbox/mu-checkbox.vue +116 -0
  17. package/components/muzhiyu/mu-checkbox-group/mu-checkbox-group.vue +40 -0
  18. package/components/muzhiyu/mu-code-input/mu-code-input.vue +264 -0
  19. package/components/muzhiyu/mu-collapse/mu-collapse.vue +316 -0
  20. package/components/muzhiyu/mu-color-picker/mu-color-picker.vue +466 -0
  21. package/components/muzhiyu/mu-config/index.js +34 -0
  22. package/components/muzhiyu/mu-config/mu-config.vue +54 -0
  23. package/components/muzhiyu/mu-countdown/mu-countdown.vue +338 -0
  24. package/components/muzhiyu/mu-cropper/mu-cropper.vue +415 -0
  25. package/components/muzhiyu/mu-date-picker/mu-date-picker.vue +290 -0
  26. package/components/muzhiyu/mu-datetime/mu-datetime.vue +262 -0
  27. package/components/muzhiyu/mu-divider/mu-divider.vue +229 -0
  28. package/components/muzhiyu/mu-drawer/mu-drawer.vue +172 -0
  29. package/components/muzhiyu/mu-dropdown/mu-dropdown.vue +215 -0
  30. package/components/muzhiyu/mu-dropdown-top/mu-dropdown-top.vue +243 -0
  31. package/components/muzhiyu/mu-empty/mu-empty.vue +217 -0
  32. package/components/muzhiyu/mu-fab/mu-fab.vue +324 -0
  33. package/components/muzhiyu/mu-footer/mu-footer.vue +21 -0
  34. package/components/muzhiyu/mu-form/mu-form.vue +170 -0
  35. package/components/muzhiyu/mu-grid/mu-grid.vue +95 -0
  36. package/components/muzhiyu/mu-grid-item/mu-grid-item.vue +247 -0
  37. package/components/muzhiyu/mu-html/mu-html.vue +145 -0
  38. package/components/muzhiyu/mu-icon/mu-icon.vue +822 -0
  39. package/components/muzhiyu/mu-image-grid/mu-image-grid.vue +225 -0
  40. package/components/muzhiyu/mu-image-preview/mu-image-preview.vue +286 -0
  41. package/components/muzhiyu/mu-index-list/mu-index-list.vue +381 -0
  42. package/components/muzhiyu/mu-input/mu-input.vue +570 -0
  43. package/components/muzhiyu/mu-input-number/mu-input-number.vue +193 -0
  44. package/components/muzhiyu/mu-keyboard/mu-keyboard.vue +415 -0
  45. package/components/muzhiyu/mu-list/mu-list.vue +89 -0
  46. package/components/muzhiyu/mu-loading/mu-loading.vue +124 -0
  47. package/components/muzhiyu/mu-loading-page/mu-loading-page.vue +529 -0
  48. package/components/muzhiyu/mu-loadmore/mu-loadmore.vue +26 -0
  49. package/components/muzhiyu/mu-modal/mu-modal.vue +298 -0
  50. package/components/muzhiyu/mu-navbar/mu-navbar.vue +223 -0
  51. package/components/muzhiyu/mu-nomore/mu-nomore.vue +107 -0
  52. package/components/muzhiyu/mu-notice-bar/mu-notice-bar.vue +284 -0
  53. package/components/muzhiyu/mu-notify/mu-notify.vue +202 -0
  54. package/components/muzhiyu/mu-overlay/mu-overlay.vue +94 -0
  55. package/components/muzhiyu/mu-pagination/mu-pagination.vue +330 -0
  56. package/components/muzhiyu/mu-password-input/mu-password-input.vue +119 -0
  57. package/components/muzhiyu/mu-picker/mu-picker.vue +297 -0
  58. package/components/muzhiyu/mu-popup/mu-popup.vue +297 -0
  59. package/components/muzhiyu/mu-progress/mu-progress.vue +156 -0
  60. package/components/muzhiyu/mu-pull-refresh/mu-pull-refresh.vue +54 -0
  61. package/components/muzhiyu/mu-qrcode/mu-qrcode.vue +340 -0
  62. package/components/muzhiyu/mu-qrcode/qrcode.js +2237 -0
  63. package/components/muzhiyu/mu-radio/mu-radio.vue +125 -0
  64. package/components/muzhiyu/mu-radio-group/mu-radio-group.vue +37 -0
  65. package/components/muzhiyu/mu-rate/mu-rate.vue +103 -0
  66. package/components/muzhiyu/mu-search/mu-search.vue +320 -0
  67. package/components/muzhiyu/mu-section/mu-section.vue +206 -0
  68. package/components/muzhiyu/mu-select/mu-select.vue +440 -0
  69. package/components/muzhiyu/mu-share-sheet/mu-share-sheet.vue +269 -0
  70. package/components/muzhiyu/mu-sidebar/mu-sidebar.vue +304 -0
  71. package/components/muzhiyu/mu-signature/mu-signature.vue +449 -0
  72. package/components/muzhiyu/mu-skeleton/mu-skeleton.vue +225 -0
  73. package/components/muzhiyu/mu-slider/mu-slider.vue +228 -0
  74. package/components/muzhiyu/mu-space/mu-space.vue +84 -0
  75. package/components/muzhiyu/mu-steps/mu-steps.vue +311 -0
  76. package/components/muzhiyu/mu-sticky/mu-sticky.vue +57 -0
  77. package/components/muzhiyu/mu-swipe-cell/mu-swipe-cell.vue +281 -0
  78. package/components/muzhiyu/mu-swiper/mu-swiper.vue +107 -0
  79. package/components/muzhiyu/mu-switch/mu-switch.vue +99 -0
  80. package/components/muzhiyu/mu-tabbar/mu-tabbar.vue +382 -0
  81. package/components/muzhiyu/mu-table/mu-table.vue +420 -0
  82. package/components/muzhiyu/mu-tabs/mu-tabs.vue +339 -0
  83. package/components/muzhiyu/mu-tag/mu-tag.vue +65 -0
  84. package/components/muzhiyu/mu-text-ellipsis/mu-text-ellipsis.vue +54 -0
  85. package/components/muzhiyu/mu-timeline/mu-timeline.vue +166 -0
  86. package/components/muzhiyu/mu-tips/mu-tips.vue +36 -0
  87. package/components/muzhiyu/mu-toast/mu-toast.vue +151 -0
  88. package/components/muzhiyu/mu-transfer/mu-transfer.vue +114 -0
  89. package/components/muzhiyu/mu-tree/mu-tree.vue +263 -0
  90. package/components/muzhiyu/mu-upload/mu-upload.vue +415 -0
  91. package/components/muzhiyu/mu-waterfall/mu-waterfall.vue +321 -0
  92. package/components/muzhiyu/mu-watermark/mu-watermark.vue +60 -0
  93. package/index.js +83 -0
  94. package/package.json +38 -0
  95. package/utils/index.js +600 -0
  96. package/utils/request.js +265 -0
@@ -0,0 +1,298 @@
1
+ <template>
2
+ <view v-if="visible" class="mu-modal" :class="{ 'mu-modal--visible': visible, 'mu-modal--no-mask': !mask }" @tap="onMaskTap">
3
+ <!-- 全屏半透明模糊遮罩 -->
4
+ <view v-if="mask" class="mu-modal__mask"></view>
5
+
6
+ <!-- 中央对话框容器 -->
7
+ <view class="mu-modal__body" :class="[`mu-modal--${size}`]" @tap.stop>
8
+ <!-- 可选右上角关闭图标 (主要用于无底部按钮弹窗) -->
9
+ <view v-if="closable" class="mu-modal__close-btn mu-touchable-flat" @tap="handleCancel">
10
+ <mu-icon name="close" :size="16" color="currentColor" />
11
+ </view>
12
+
13
+ <view v-if="title" class="mu-modal__header">
14
+ <text class="mu-modal__title">{{ title }}</text>
15
+ </view>
16
+ <view class="mu-modal__content">
17
+ <slot>
18
+ <text class="mu-modal__text">{{ content }}</text>
19
+ </slot>
20
+ </view>
21
+
22
+ <!-- 底部按钮区 (支持双按键、单确定、单取消、无按键) -->
23
+ <view v-if="showFooter && (showCancel || showConfirm)" class="mu-modal__footer">
24
+ <view
25
+ v-if="showCancel"
26
+ class="mu-modal__btn mu-modal__btn--cancel"
27
+ :class="{ 'mu-modal__btn--single': !showConfirm }"
28
+ :style="{ color: cancelColor || '' }"
29
+ @tap="handleCancel"
30
+ >
31
+ <text>{{ cancelText }}</text>
32
+ </view>
33
+ <view
34
+ v-if="showConfirm"
35
+ class="mu-modal__btn mu-modal__btn--confirm"
36
+ :class="{ 'mu-modal__btn--single': !showCancel }"
37
+ :style="{ color: confirmColor || '#171717' }"
38
+ @tap="handleConfirm"
39
+ >
40
+ <text>{{ confirmText }}</text>
41
+ </view>
42
+ </view>
43
+ </view>
44
+ </view>
45
+ </template>
46
+
47
+ <script setup>
48
+ /**
49
+ * mu-modal 对话框
50
+ * @description 弹出式确认/提示对话框组件,支持黑金高定主题、定制按钮颜色与自定义插槽
51
+ * @property {boolean} show - 是否显示对话框
52
+ * @property {string} title - 弹窗标题
53
+ * @property {string} content - 提示内容文本
54
+ * @property {boolean} mask - 是否显示背板遮罩
55
+ * @property {boolean} showCancel - 是否显示取消按钮
56
+ * @property {boolean} showConfirm - 是否显示确认按钮
57
+ * @property {string} cancelText - 取消按钮文字
58
+ * @property {string} confirmText - 确认按钮文字
59
+ * @property {string} cancelColor - 取消按钮颜色
60
+ * @property {string} confirmColor - 确认按钮颜色 (如危险红色 '#F43F5E')
61
+ * @property {boolean} showFooter - 是否显示底部按钮栏
62
+ * @property {boolean} closable - 是否显示右上角关闭图标
63
+ * @property {boolean} maskClosable - 点击遮罩层是否自动关闭
64
+ * @property {string} size - 弹窗尺寸 ('small' | 'medium' | 'large')
65
+ * @event {Function} cancel - 点击取消按钮时触发
66
+ * @event {Function} confirm - 点击确认按钮时触发
67
+ */
68
+ import { ref, watch } from 'vue'
69
+
70
+ const props = defineProps({
71
+ show: { type: Boolean, default: false },
72
+ title: { type: String, default: '' },
73
+ content: { type: String, default: '' },
74
+ mask: { type: Boolean, default: true },
75
+ showCancel: { type: Boolean, default: true },
76
+ showConfirm: { type: Boolean, default: true },
77
+ cancelText: { type: String, default: '取消' },
78
+ confirmText: { type: String, default: '确定' },
79
+ cancelColor: { type: String, default: '' },
80
+ confirmColor: { type: String, default: '' },
81
+ showFooter: { type: Boolean, default: true },
82
+ closable: { type: Boolean, default: false },
83
+ maskClosable: { type: Boolean, default: false },
84
+ size: { type: String, default: 'medium' }
85
+ })
86
+
87
+ const emit = defineEmits(['cancel', 'confirm', 'update:show'])
88
+
89
+ const visible = ref(props.show)
90
+
91
+ watch(() => props.show, (val) => { visible.value = val })
92
+ watch(visible, (val) => { emit('update:show', val) })
93
+
94
+ function handleCancel() { emit('cancel'); visible.value = false }
95
+ function handleConfirm() { emit('confirm'); visible.value = false }
96
+ function onMaskTap() { if (props.mask && props.maskClosable) visible.value = false }
97
+
98
+ defineExpose({
99
+ show: () => { visible.value = true },
100
+ close: () => { visible.value = false }
101
+ })
102
+ </script>
103
+
104
+ <style lang="scss" scoped>
105
+ @import "@/uni.scss";
106
+
107
+ .mu-modal {
108
+ position: fixed;
109
+ top: 0;
110
+ left: 0;
111
+ right: 0;
112
+ bottom: 0;
113
+ width: 100vw;
114
+ height: 100vh;
115
+ z-index: $mu-z-modal;
116
+ display: flex;
117
+ align-items: center;
118
+ justify-content: center;
119
+ opacity: 0;
120
+ visibility: hidden;
121
+ transition: all $mu-duration-slow $mu-ease;
122
+
123
+ &--visible {
124
+ opacity: 1;
125
+ visibility: visible;
126
+ }
127
+
128
+ &--no-mask {
129
+ pointer-events: none;
130
+ }
131
+
132
+ &__mask {
133
+ position: absolute;
134
+ top: 0;
135
+ left: 0;
136
+ right: 0;
137
+ bottom: 0;
138
+ width: 100%;
139
+ height: 100%;
140
+ background: rgba(15, 23, 42, 0.65);
141
+ backdrop-filter: blur(16px);
142
+ }
143
+
144
+ &__body {
145
+ position: relative;
146
+ z-index: 10;
147
+ pointer-events: auto;
148
+ background: #FFFFFF;
149
+ border-radius: $mu-radius-2xl;
150
+ overflow: hidden;
151
+ animation: mu-modal-spring 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275);
152
+ width: 620rpx;
153
+ border: 1rpx solid rgba(255, 255, 255, 0.12);
154
+ box-shadow: 0 32rpx 64rpx -12rpx rgba(15, 23, 42, 0.3);
155
+ backdrop-filter: blur(24px);
156
+
157
+ &.mu-modal--small { width: 500rpx; }
158
+ &.mu-modal--large { width: 720rpx; }
159
+ }
160
+
161
+ &__close-btn {
162
+ position: absolute;
163
+ top: 24rpx;
164
+ right: 24rpx;
165
+ width: 48rpx;
166
+ height: 48rpx;
167
+ border-radius: 50%;
168
+ background: rgba(15, 23, 42, 0.05);
169
+ display: flex;
170
+ align-items: center;
171
+ justify-content: center;
172
+ cursor: pointer;
173
+ z-index: 20;
174
+ color: $mu-text-tertiary;
175
+ }
176
+
177
+ &__header {
178
+ padding: 44rpx 40rpx 16rpx;
179
+ text-align: center;
180
+ }
181
+
182
+ &__title {
183
+ font-size: 34rpx;
184
+ font-weight: 800;
185
+ color: $mu-text-primary;
186
+ letter-spacing: -0.5rpx;
187
+ }
188
+
189
+ &__content {
190
+ padding: 24rpx 40rpx 40rpx;
191
+ min-height: 100rpx;
192
+ text-align: center;
193
+ }
194
+
195
+ &__text {
196
+ font-size: 28rpx;
197
+ color: $mu-text-secondary;
198
+ line-height: 1.6;
199
+ font-weight: 500;
200
+ }
201
+
202
+ &__footer {
203
+ display: flex;
204
+ border-top: 1rpx solid rgba(226, 232, 240, 0.8);
205
+ background: rgba(248, 250, 252, 0.5);
206
+ }
207
+
208
+ &__btn {
209
+ flex: 1;
210
+ height: 96rpx;
211
+ display: flex;
212
+ align-items: center;
213
+ justify-content: center;
214
+ font-size: 30rpx;
215
+ font-weight: 700;
216
+ cursor: pointer;
217
+ transition: background 0.2s ease;
218
+
219
+ &:active {
220
+ background: rgba(241, 245, 249, 0.9);
221
+ }
222
+
223
+ &--cancel {
224
+ color: $mu-text-secondary;
225
+ border-right: 1rpx solid rgba(226, 232, 240, 0.8);
226
+ }
227
+
228
+ &--confirm {
229
+ color: #171717;
230
+ }
231
+
232
+ &--single {
233
+ border-right: none !important;
234
+ }
235
+ }
236
+ }
237
+
238
+ @keyframes mu-modal-spring {
239
+ 0% { opacity: 0; transform: scale(0.88) translateY(20rpx); }
240
+ 100% { opacity: 1; transform: scale(1) translateY(0); }
241
+ }
242
+
243
+ .mu-dark, page.mu-dark {
244
+
245
+ .mu-modal {
246
+ &__body {
247
+ background: rgba(18, 18, 24, 0.92);
248
+ border-color: rgba(255, 255, 255, 0.12);
249
+ box-shadow: 0 32rpx 64rpx rgba(0, 0, 0, 0.5);
250
+ }
251
+ &__close-btn {
252
+ background: rgba(255, 255, 255, 0.1);
253
+ color: $mu-dark-text-secondary;
254
+ }
255
+ &__title { color: $mu-dark-text-primary; }
256
+ &__text { color: $mu-dark-text-secondary; }
257
+ &__footer {
258
+ border-top-color: rgba(255, 255, 255, 0.08);
259
+ background: rgba(255, 255, 255, 0.02);
260
+ }
261
+ &__btn--cancel {
262
+ color: $mu-dark-text-secondary;
263
+ border-right-color: rgba(255, 255, 255, 0.08);
264
+ }
265
+ &__btn--confirm {
266
+ color: #FFFFFF !important;
267
+ }
268
+ }
269
+ }
270
+
271
+ @media (prefers-color-scheme: dark) {
272
+
273
+ .mu-modal {
274
+ &__body {
275
+ background: rgba(18, 18, 24, 0.92);
276
+ border-color: rgba(255, 255, 255, 0.12);
277
+ box-shadow: 0 32rpx 64rpx rgba(0, 0, 0, 0.5);
278
+ }
279
+ &__close-btn {
280
+ background: rgba(255, 255, 255, 0.1);
281
+ color: $mu-dark-text-secondary;
282
+ }
283
+ &__title { color: $mu-dark-text-primary; }
284
+ &__text { color: $mu-dark-text-secondary; }
285
+ &__footer {
286
+ border-top-color: rgba(255, 255, 255, 0.08);
287
+ background: rgba(255, 255, 255, 0.02);
288
+ }
289
+ &__btn--cancel {
290
+ color: $mu-dark-text-secondary;
291
+ border-right-color: rgba(255, 255, 255, 0.08);
292
+ }
293
+ &__btn--confirm {
294
+ color: #FFFFFF !important;
295
+ }
296
+ }
297
+ }
298
+ </style>
@@ -0,0 +1,223 @@
1
+ <template>
2
+ <view class="mu-navbar" :class="{ 'mu-navbar--fixed': fixed, 'mu-navbar--transparent': transparent }" :style="navbarStyle">
3
+ <!-- 1. 系统状态栏动态占位 Height (iPhone 刘海/灵动岛/Android 动态状态栏) -->
4
+ <view class="mu-navbar__status" :style="{ height: statusBarHeight + 'px' }"></view>
5
+
6
+ <!-- 2. 导航栏核心内容 Header Content (微信小程序胶囊自动留白避让) -->
7
+ <view class="mu-navbar__content" :style="contentStyle">
8
+ <!-- 左侧返回按钮或自定义左插槽 -->
9
+ <view v-if="isBack" class="mu-navbar__left" @tap="handleBack">
10
+ <view class="mu-navbar__back-btn mu-touchable-flat">
11
+ <mu-icon name="arrow_left" :size="20" :color="color || defaultIconColor" />
12
+ </view>
13
+ </view>
14
+ <view v-else class="mu-navbar__left">
15
+ <slot name="left"></slot>
16
+ </view>
17
+
18
+ <!-- 中间标题 (绝对中心精确居中) -->
19
+ <view class="mu-navbar__title" :style="titleStyle">
20
+ <text class="mu-navbar__title-text" :style="textStyle">{{ title }}</text>
21
+ </view>
22
+
23
+ <!-- 右侧功能区域与插槽 (自动预留小程序胶囊右侧间距) -->
24
+ <view class="mu-navbar__right">
25
+ <slot name="right"></slot>
26
+ </view>
27
+ </view>
28
+ </view>
29
+
30
+ <!-- 3. 固定模式 (fixed="true") 下的页面内容自适应下占位节点 -->
31
+ <view v-if="fixed && isPlaceholder" :style="{ height: totalHeaderHeight + 'px' }"></view>
32
+
33
+ <!-- 全局封装 Toast 弹窗挂载点 -->
34
+ <mu-toast />
35
+ </template>
36
+
37
+ <script setup>
38
+ import { ref, computed, onMounted } from 'vue'
39
+ import MuToast from '../mu-toast/mu-toast.vue'
40
+
41
+ const props = defineProps({
42
+ title: { type: String, default: '' },
43
+ fixed: { type: Boolean, default: true },
44
+ isBack: { type: Boolean, default: true },
45
+ transparent: { type: Boolean, default: false },
46
+ background: { type: String, default: '' },
47
+ color: { type: String, default: '' },
48
+ isPlaceholder: { type: Boolean, default: true }
49
+ })
50
+
51
+ const emit = defineEmits(['back'])
52
+
53
+ const statusBarHeight = ref(0)
54
+ const navContentHeight = ref(44)
55
+ const menuButtonWidth = ref(0)
56
+ const menuButtonRightGap = ref(12)
57
+
58
+ onMounted(() => {
59
+ try {
60
+ const sysInfo = uni.getWindowInfo ? uni.getWindowInfo() : uni.getSystemInfoSync()
61
+ statusBarHeight.value = sysInfo.statusBarHeight || 0
62
+
63
+ // #ifdef MP
64
+ if (uni.getMenuButtonBoundingClientRect) {
65
+ const menuButton = uni.getMenuButtonBoundingClientRect()
66
+ if (menuButton && menuButton.height > 0) {
67
+ navContentHeight.value = (menuButton.top - statusBarHeight.value) * 2 + menuButton.height
68
+ menuButtonWidth.value = menuButton.width || 87
69
+ const winWidth = sysInfo.windowWidth || 375
70
+ menuButtonRightGap.value = Math.max(10, winWidth - (menuButton.right || winWidth))
71
+ }
72
+ }
73
+ // #endif
74
+ } catch (e) {
75
+ statusBarHeight.value = 0
76
+ navContentHeight.value = 44
77
+ }
78
+ })
79
+
80
+ const totalHeaderHeight = computed(() => statusBarHeight.value + navContentHeight.value)
81
+
82
+ const navbarStyle = computed(() => ({
83
+ background: props.transparent ? 'transparent' : (props.background || '')
84
+ }))
85
+
86
+ const contentStyle = computed(() => {
87
+ const style = {
88
+ height: `${navContentHeight.value}px`
89
+ }
90
+ if (menuButtonWidth.value > 0) {
91
+ style.paddingRight = `${menuButtonWidth.value + menuButtonRightGap.value + 8}px`
92
+ }
93
+ return style
94
+ })
95
+
96
+ const titleStyle = computed(() => {
97
+ if (menuButtonWidth.value > 0) {
98
+ const sideSpace = menuButtonWidth.value + menuButtonRightGap.value + 16
99
+ return {
100
+ left: `${sideSpace}px`,
101
+ right: `${sideSpace}px`
102
+ }
103
+ }
104
+ return {}
105
+ })
106
+
107
+ const defaultIconColor = computed(() => props.color || '#0F172A')
108
+
109
+ const textStyle = computed(() => (props.color ? { color: props.color } : {}))
110
+
111
+ function handleBack() {
112
+ emit('back')
113
+ const pages = getCurrentPages()
114
+ if (pages && pages.length > 1) {
115
+ uni.navigateBack()
116
+ } else {
117
+ uni.switchTab({ url: '/pages/index/index' })
118
+ }
119
+ }
120
+ </script>
121
+
122
+ <style lang="scss" scoped>
123
+ @import "@/uni.scss";
124
+
125
+ .mu-navbar {
126
+ width: 100%;
127
+ z-index: $mu-z-fixed;
128
+ background: #FFFFFF;
129
+ border-bottom: 1rpx solid $mu-border-light;
130
+
131
+ &--fixed {
132
+ position: fixed;
133
+ top: 0;
134
+ left: 0;
135
+ right: 0;
136
+ }
137
+
138
+ &--transparent {
139
+ background: transparent !important;
140
+ backdrop-filter: none !important;
141
+ border-bottom-color: transparent !important;
142
+ }
143
+
144
+ &__content {
145
+ display: flex;
146
+ align-items: center;
147
+ padding: 0 24rpx;
148
+ position: relative;
149
+ box-sizing: border-box;
150
+ }
151
+
152
+ &__left {
153
+ min-width: 80rpx;
154
+ display: flex;
155
+ align-items: center;
156
+ z-index: 10;
157
+ }
158
+
159
+ &__back-btn {
160
+ display: inline-flex;
161
+ align-items: center;
162
+ justify-content: center;
163
+ padding: 8rpx 16rpx 8rpx 0;
164
+ cursor: pointer;
165
+ transition: opacity 0.2s ease;
166
+
167
+ &:active {
168
+ opacity: 0.7;
169
+ }
170
+ }
171
+
172
+ &__title {
173
+ position: absolute;
174
+ left: 100rpx;
175
+ right: 100rpx;
176
+ text-align: center;
177
+ display: flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ pointer-events: none;
181
+
182
+ &-text {
183
+ font-size: 32rpx;
184
+ color: $mu-text-primary;
185
+ font-weight: 800;
186
+ overflow: hidden;
187
+ text-overflow: ellipsis;
188
+ white-space: nowrap;
189
+ }
190
+ }
191
+
192
+ &__right {
193
+ min-width: 80rpx;
194
+ margin-left: auto;
195
+ display: flex;
196
+ align-items: center;
197
+ justify-content: flex-end;
198
+ z-index: 10;
199
+ }
200
+ }
201
+
202
+ .mu-dark, page.mu-dark {
203
+
204
+ .mu-navbar {
205
+ background: #14141E !important;
206
+ border-bottom-color: rgba(255, 255, 255, 0.08);
207
+
208
+ &__title-text { color: #F8FAFC !important; }
209
+ &__back-btn :deep(.mu-icon) { color: #F8FAFC !important; }
210
+ }
211
+ }
212
+
213
+ @media (prefers-color-scheme: dark) {
214
+
215
+ .mu-navbar {
216
+ background: #14141E !important;
217
+ border-bottom-color: rgba(255, 255, 255, 0.08);
218
+
219
+ &__title-text { color: #F8FAFC !important; }
220
+ &__back-btn :deep(.mu-icon) { color: #F8FAFC !important; }
221
+ }
222
+ }
223
+ </style>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <view class="mu-nomore" :class="[`mu-nomore--${type}`]">
3
+ <!-- 左侧分割线或圆点 -->
4
+ <view v-if="type === 'line'" class="mu-nomore__line mu-nomore__line--left"></view>
5
+ <view v-else-if="type === 'dot'" class="mu-nomore__dot"></view>
6
+
7
+ <!-- 提示内容区 -->
8
+ <view class="mu-nomore__content">
9
+ <slot>
10
+ <view class="mu-nomore__inner">
11
+ <mu-icon v-if="icon" :name="icon" :size="14" color="#94A3B8" style="margin-right: 6rpx;" />
12
+ <text class="mu-nomore__text" :style="{ color }">{{ text }}</text>
13
+ </view>
14
+ </slot>
15
+ </view>
16
+
17
+ <!-- 右侧分割线或圆点 -->
18
+ <view v-if="type === 'line'" class="mu-nomore__line mu-nomore__line--right"></view>
19
+ <view v-else-if="type === 'dot'" class="mu-nomore__dot"></view>
20
+ </view>
21
+ </template>
22
+
23
+ <script setup>
24
+ const props = defineProps({
25
+ text: { type: String, default: '没有更多了' },
26
+ type: { type: String, default: 'line' }, // line (细线) | dot (两端圆点) | plain (纯文本)
27
+ color: { type: String, default: '' },
28
+ icon: { type: String, default: '' }
29
+ })
30
+ </script>
31
+
32
+ <style lang="scss" scoped>
33
+ @import "@/uni.scss";
34
+
35
+ .mu-nomore {
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ width: 100%;
40
+ padding: 32rpx 0;
41
+ box-sizing: border-box;
42
+
43
+ &__line {
44
+ flex: 1;
45
+ height: 1rpx;
46
+ background: linear-gradient(to right, transparent, rgba(226, 232, 240, 0.8));
47
+
48
+ &--right {
49
+ background: linear-gradient(to left, transparent, rgba(226, 232, 240, 0.8));
50
+ }
51
+ }
52
+
53
+ &__dot {
54
+ width: 8rpx;
55
+ height: 8rpx;
56
+ border-radius: 50%;
57
+ background: #CBD5E1;
58
+ margin: 0 16rpx;
59
+ }
60
+
61
+ &__content {
62
+ padding: 0 24rpx;
63
+ flex-shrink: 0;
64
+ }
65
+
66
+ &__inner {
67
+ display: inline-flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ }
71
+
72
+ &__text {
73
+ font-size: 22rpx;
74
+ color: #94A3B8;
75
+ font-weight: 500;
76
+ letter-spacing: 1rpx;
77
+ }
78
+ }
79
+
80
+ .mu-dark, page.mu-dark {
81
+
82
+ .mu-nomore {
83
+ &__line {
84
+ background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.12));
85
+ &--right {
86
+ background: linear-gradient(to left, transparent, rgba(255, 255, 255, 0.12));
87
+ }
88
+ }
89
+ &__dot { background: rgba(255, 255, 255, 0.2); }
90
+ &__text { color: $mu-dark-text-secondary; }
91
+ }
92
+ }
93
+
94
+ @media (prefers-color-scheme: dark) {
95
+
96
+ .mu-nomore {
97
+ &__line {
98
+ background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.12));
99
+ &--right {
100
+ background: linear-gradient(to left, transparent, rgba(255, 255, 255, 0.12));
101
+ }
102
+ }
103
+ &__dot { background: rgba(255, 255, 255, 0.2); }
104
+ &__text { color: $mu-dark-text-secondary; }
105
+ }
106
+ }
107
+ </style>