wui-components-v2 1.1.69 → 1.1.71

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 (117) hide show
  1. package/api/core/index.ts +74 -74
  2. package/api/feishu.ts +20 -20
  3. package/api/index.ts +4 -4
  4. package/api/login.ts +51 -51
  5. package/api/menu.ts +45 -45
  6. package/api/page.ts +114 -114
  7. package/api/sys.ts +12 -12
  8. package/api/tree.ts +28 -28
  9. package/components/action-popup/action-popup.vue +116 -116
  10. package/components/add-address-list/add-address-list.vue +187 -187
  11. package/components/add-address-page/add-address-page.vue +77 -77
  12. package/components/add-address-page/config.ts +297 -297
  13. package/components/audio-play/audio-play.vue +220 -220
  14. package/components/batch-upload-file/batch-upload-file.vue +75 -75
  15. package/components/card-botom-buttons/card-botom-buttons.vue +279 -279
  16. package/components/custom-date-picker/custom-date-picker.vue +106 -106
  17. package/components/custom-select-picker/custom-select-picker.vue +95 -95
  18. package/components/demo-block/demo-block.vue +63 -63
  19. package/components/demo-card/demo-card.vue +44 -44
  20. package/components/detail-popup/detail-popup.vue +99 -99
  21. package/components/evaluation-page/evaluation-page.vue +196 -196
  22. package/components/fold-card/fold-card.vue +171 -171
  23. package/components/form-control/form-control.vue +661 -661
  24. package/components/global-loading/GlobalLoading.md +366 -366
  25. package/components/global-loading/global-loading.vue +55 -55
  26. package/components/global-message/GlobalMessage.md +570 -570
  27. package/components/global-message/global-message.vue +68 -68
  28. package/components/global-toast/GlobalToast.md +261 -261
  29. package/components/global-toast/global-toast.vue +56 -56
  30. package/components/label-value/label-value.vue +144 -144
  31. package/components/label-value/open-value-more.vue +56 -56
  32. package/components/list-top-buttons/list-top-buttons.vue +19 -19
  33. package/components/loading/loading.vue +5 -5
  34. package/components/login-form/login-form.vue +126 -126
  35. package/components/login-form-box/login-form-box.vue +65 -65
  36. package/components/mulselect-picker/mulselect-picker.vue +86 -86
  37. package/components/phone-login-form/phone-login-form.vue +204 -204
  38. package/components/privacy-popup/privacy-popup.vue +191 -191
  39. package/components/product-card/product-card.vue +201 -201
  40. package/components/scan-input/scan-input.vue +406 -406
  41. package/components/search/search.vue +128 -128
  42. package/components/select-col-picker/select-col-picker.vue +168 -168
  43. package/components/tab-search/tab-search.vue +73 -73
  44. package/components/tree-select/components/TreeNode.vue +200 -200
  45. package/components/tree-select/components/index.vue +471 -471
  46. package/components/tree-select/components/tree-select.vue +56 -56
  47. package/components/tree-select/index.vue +93 -93
  48. package/components/user-choose/user-choose.vue +169 -151
  49. package/components/video-play/video-play.vue +56 -56
  50. package/components/wui-auto-update-component/wui-auto-update-component.vue +132 -132
  51. package/components/wui-default/wui-default.vue +49 -49
  52. package/components/wui-details-page/wui-details-page.vue +147 -147
  53. package/components/wui-edit-page/wui-edit-page-copy.vue +757 -757
  54. package/components/wui-edit-page/wui-edit-page.vue +793 -793
  55. package/components/wui-enume-select-control/wui-enume-select-control.vue +92 -92
  56. package/components/wui-list/wui-list.vue +235 -235
  57. package/components/wui-login/wui-login.vue +43 -43
  58. package/components/wui-login1/wui-login.vue +41 -41
  59. package/components/wui-menus/wui-menus-top.vue +137 -137
  60. package/components/wui-menus/wui-menus-top1.vue +8 -8
  61. package/components/wui-menus/wui-menus.vue +247 -247
  62. package/components/wui-menus1/components/banner-carousel.vue +320 -320
  63. package/components/wui-menus1/components/navbar.vue +43 -43
  64. package/components/wui-menus1/components/quick-panel.vue +55 -55
  65. package/components/wui-menus1/components/search-bar.vue +49 -49
  66. package/components/wui-menus1/components/section-menus.vue +208 -208
  67. package/components/wui-menus1/wui-menus-top.vue +718 -718
  68. package/components/wui-menus1/wui-menus-top1.vue +398 -398
  69. package/components/wui-menus1/wui-menus.vue +564 -564
  70. package/components/wui-notify-info/notify-handle.vue +53 -53
  71. package/components/wui-notify-info/wui-notify-info.vue +280 -280
  72. package/components/wui-scan-binding-sensor/wui-scan-binding-sensor.vue +75 -75
  73. package/components/wui-search-history-babbar/components/SearchBar.vue +70 -70
  74. package/components/wui-search-history-babbar/wui-search-history-babbar.vue +204 -204
  75. package/components/wui-select-list/wui-select-list.vue +310 -310
  76. package/components/wui-select-popup/wui-select-popup.vue +613 -612
  77. package/components/wui-system-settings/wui-system-settings.vue +144 -144
  78. package/components/wui-tabbar/wui-tabbar.vue +106 -106
  79. package/components/wui-tree-page/components/tree-item.vue +238 -238
  80. package/components/wui-tree-page/wui-tree-page.vue +297 -297
  81. package/components/wui-update-component/wui-update-component.vue +221 -221
  82. package/components/wui-user/wui-user.vue +202 -202
  83. package/composables/types/theme.ts +65 -65
  84. package/composables/types/user.ts +5 -5
  85. package/composables/useColorGenerator.ts +221 -221
  86. package/composables/useCompanyFieldFilter.ts +91 -91
  87. package/composables/useEnumes.ts +43 -43
  88. package/composables/useEventBus.ts +37 -37
  89. package/composables/useGlobalLoading.ts +47 -47
  90. package/composables/useGlobalMessage.ts +53 -53
  91. package/composables/useGlobalToast.ts +63 -63
  92. package/composables/useLocale.ts +54 -54
  93. package/composables/useManualTheme.ts +179 -179
  94. package/composables/useMenus.ts +193 -193
  95. package/composables/useSectionMenus.ts +120 -120
  96. package/composables/useTabbar.ts +50 -50
  97. package/composables/useTheme.ts +74 -74
  98. package/composables/useUser.ts +24 -24
  99. package/index.d.ts +90 -90
  100. package/index.ts +83 -83
  101. package/package.json +24 -24
  102. package/static/iconfont/iconfont.css +63 -63
  103. package/store/language.ts +151 -151
  104. package/store/manualThemeStore.ts +143 -143
  105. package/store/persist.ts +41 -41
  106. package/store/themeStore.ts +74 -74
  107. package/store/userStore.ts +22 -22
  108. package/styles/dark-mode.css +523 -523
  109. package/styles/dark-mode.min.css +1 -1
  110. package/styles/dark-mode.scss +498 -498
  111. package/type.ts +154 -154
  112. package/utils/control-tree.ts +353 -353
  113. package/utils/control-type-supportor.ts +148 -148
  114. package/utils/eventBus.ts +36 -36
  115. package/utils/idata-scan.ts +99 -99
  116. package/utils/index.ts +979 -979
  117. package/utils/rsaEncrypt.ts +10 -10
@@ -1,564 +1,564 @@
1
- <script setup lang="ts">
2
- import type { PropType } from 'vue'
3
- import { defineOptions, defineProps, ref } from 'vue'
4
- import DemoCard from '../demo-card/demo-card.vue'
5
- import { useMenus } from '../../composables/useMenus'
6
- import type { Icon } from '../../composables/useMenus'
7
- import wuiNotifyInfo from '../wui-notify-info/wui-notify-info.vue'
8
- import { useLanguageStore } from '../../store/language'
9
- import sectionMenus from './components/section-menus.vue'
10
- import navbar from './components/navbar.vue'
11
- import quickPanel from './components/quick-panel.vue'
12
- import bannerCarousel from './components/banner-carousel.vue'
13
- import searchBar from './components/search-bar.vue'
14
- import '../../static/iconfont/iconfont.css'
15
- import { getThemeConfig } from '../../api/sys'
16
- import { onMounted } from 'vue'
17
-
18
- defineOptions({
19
- name: 'WuiMenus1',
20
- })
21
- const props = defineProps({
22
- icons: {
23
- type: Array as PropType<Icon[]>,
24
- default: () => [],
25
- },
26
- load: {
27
- type: Function as PropType<() => void>,
28
- default: () => {},
29
- },
30
- menuTopType: {
31
- type: String,
32
- default: '',
33
- },
34
- })
35
- const languageStore = useLanguageStore()
36
- const themeConfig = ref<any>({})
37
- const pagingRef = ref(null)
38
- const {
39
- queryList,
40
- menuList,
41
- currentThemeColor,
42
- filtermenu,
43
- gotoPage,
44
- sheetShow,
45
- actions,
46
- title,
47
- sheetGotoPage,
48
- navTitle,
49
- } = useMenus(props, pagingRef)
50
- onMounted(() => {
51
- getThemeConfig().then(res => {
52
- if (res.status == 'success') {
53
- themeConfig.value = res.themeConfig
54
- }
55
- })
56
- })
57
- </script>
58
-
59
- <template>
60
- <z-paging
61
- ref="pagingRef"
62
- v-model="menuList"
63
- :loading-more-enabled="false"
64
- @query="queryList"
65
- @on-refresh="props?.load"
66
- >
67
- <template #top>
68
- <navbar :nav-title="navTitle" />
69
- <slot name="top" :style="{ background: currentThemeColor.primary }" />
70
- <view v-if="props.menuTopType === '自定义'" class="p-2" />
71
- </template>
72
- <view class="px-3 pb-4">
73
- <!-- 菜单搜索 -->
74
- <searchBar v-if="themeConfig.showHomePage" />
75
- <!-- 轮播图 -->
76
- <bannerCarousel v-if="themeConfig.showHomePage" />
77
- <!-- 快捷菜单 -->
78
- <sectionMenus v-if="themeConfig.showHomePage" />
79
- <!-- 统计 -->
80
- <quickPanel v-if="themeConfig.showHomePage" />
81
- <!-- 消息 -->
82
- <!-- <wuiNotifyInfo /> -->
83
-
84
- <!-- 菜单卡片列表 -->
85
- <view class="menu-section">
86
- <view class="section-header" v-if="themeConfig.showHomePage">
87
- <view class="section-title-wrapper">
88
- <!-- <view class="section-icon primary">
89
- <text class="i-carbon:apps text-sm" />
90
- </view> -->
91
- <text class="section-title dark:text-white text-gray-800">
92
- {{ languageStore.t('全部功能') }}
93
- </text>
94
- </view>
95
- <view class="section-tag">
96
- <text class="tag-text">{{ filtermenu.length }} {{ languageStore.t('个分类') }}</text>
97
- </view>
98
- </view>
99
- <view v-else class="py-3"></view>
100
-
101
- <DemoCard
102
- v-for="(item, index) in filtermenu"
103
- :key="index"
104
- :title="languageStore.t(item.title)"
105
- class="menu-card"
106
- :style="{ animationDelay: `${(index as number) * 0.1}s` }"
107
- >
108
- <template #content>
109
- <view class="menu-grid-container">
110
- <wd-grid :column="4" clickable class="menu-grid">
111
- <wd-grid-item
112
- v-for="(subItem, subIndex) in item.items"
113
- :key="subIndex"
114
- use-text-slot
115
- use-icon-slot
116
- class="menu-grid-item"
117
- @click="gotoPage(subItem)"
118
- >
119
- <template #icon>
120
- <view
121
- class="menu-icon-wrapper flex items-center justify-center"
122
- :style="{ background: subItem.color }"
123
- >
124
- <text class="menu-icon !text-xl iconfont" :class="[subItem.appIcon || 'i-carbon:grid']" />
125
- <view class="icon-shine" />
126
- </view>
127
- </template>
128
- <template #text>
129
- <view class="menu-text-wrapper">
130
- <view class="menu-title text-ellipsis dark:text-white text-gray-800">
131
- {{ languageStore.t(subItem.title) }}
132
- </view>
133
- <!-- <view class="menu-badge" v-if="subIndex === 0">
134
- <text class="badge-dot" />
135
- </view> -->
136
- </view>
137
- </template>
138
- </wd-grid-item>
139
- </wd-grid>
140
- </view>
141
- </template>
142
- </DemoCard>
143
- </view>
144
-
145
- <!-- 底部信息 -->
146
- <view class="footer-section">
147
- <view class="footer-line" />
148
- <text class="footer-text">已经到底了</text>
149
- <view class="footer-line" />
150
- </view>
151
-
152
- <slot name="listBottom" />
153
- </view>
154
-
155
- <template #bottom>
156
- <slot name="bottom" />
157
- </template>
158
- </z-paging>
159
- <wd-action-sheet
160
- v-model="sheetShow"
161
- :z-index="9999"
162
- :actions="actions"
163
- :title="title"
164
- @select="
165
- ({ item }) => {
166
- sheetGotoPage(item)
167
- }
168
- "
169
- />
170
- </template>
171
-
172
- <style scoped lang="scss">
173
- // 菜单区域
174
- .section-header {
175
- display: flex;
176
- align-items: center;
177
- justify-content: space-between;
178
- margin-bottom: 20rpx;
179
- padding: 0 8rpx;
180
- }
181
- .section-title-wrapper {
182
- display: flex;
183
- align-items: center;
184
- gap: 12rpx;
185
- }
186
- .section-title {
187
- font-size: 30rpx;
188
- font-weight: 700;
189
- letter-spacing: 0.02em;
190
- }
191
- .tag-text {
192
- font-size: 20rpx;
193
- color: #16a34a;
194
- font-weight: 600;
195
- }
196
- .section-tag {
197
- display: flex;
198
- align-items: center;
199
- padding: 6rpx 14rpx;
200
- background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
201
- border-radius: 20rpx;
202
- border: 1rpx solid rgba(34, 197, 94, 0.2);
203
- }
204
- .menu-section {
205
- animation: fadeInUp 0.5s ease-out 0.2s backwards;
206
- }
207
- .section-icon {
208
- width: 44rpx;
209
- height: 44rpx;
210
- border-radius: 12rpx;
211
- background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
212
- display: flex;
213
- align-items: center;
214
- justify-content: center;
215
- color: #6b7280;
216
-
217
- &.primary {
218
- background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
219
- color: #3b82f6;
220
- }
221
- }
222
-
223
- // 菜单卡片容器
224
- .menu-card {
225
- animation: slideUp 0.5s ease-out backwards;
226
- margin: 0 !important;
227
- margin-bottom: 20rpx !important;
228
- :deep(.wd-card) {
229
- border-radius: 28rpx;
230
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, rgba(255, 255, 255, 1) 100%);
231
- box-shadow:
232
- 0 8rpx 32rpx rgba(0, 0, 0, 0.06),
233
- 0 2rpx 8rpx rgba(0, 0, 0, 0.04),
234
- inset 0 1rpx 0 rgba(255, 255, 255, 1);
235
- border: 1rpx solid rgba(0, 0, 0, 0.04);
236
- overflow: hidden;
237
- transition: all 0.3s ease;
238
- &:active {
239
- transform: translateY(-2rpx);
240
- box-shadow:
241
- 0 12rpx 40rpx rgba(0, 0, 0, 0.08),
242
- 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
243
- }
244
- }
245
-
246
- :deep(.wd-card__title) {
247
- // padding: 28rpx 28rpx 20rpx;
248
- font-weight: 700;
249
- font-size: 30rpx;
250
- // color: #1f2937;
251
- display: flex;
252
- align-items: center;
253
- gap: 12rpx;
254
- }
255
-
256
- :deep(.wd-card__content) {
257
- padding: 12rpx 16rpx 28rpx;
258
- }
259
- }
260
-
261
- // 网格容器样式
262
- .menu-grid-container {
263
- // background: rgba(249, 250, 251, 0.5);
264
- border-radius: 20rpx;
265
- // padding: 20rpx 12rpx;
266
- transition: all 0.3s ease;
267
- }
268
-
269
- // 网格项样式
270
- .menu-grid {
271
- // grid-auto-rows: 100px !important;
272
- :deep(.wd-grid-item) {
273
- transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
274
-
275
- &:active {
276
- transform: scale(0.95);
277
- }
278
- }
279
-
280
- :deep(.wd-grid-item__wrapper) {
281
- padding: 20rpx 10rpx !important;
282
- display: flex;
283
- flex-direction: column;
284
- align-items: center;
285
- justify-content: center;
286
- }
287
- }
288
-
289
- // 图标容器
290
- .menu-icon-wrapper {
291
- width: 100rpx;
292
- height: 100rpx;
293
- border-radius: 28rpx;
294
- // box-shadow:
295
- // 0 8rpx 24rpx rgba(0, 0, 0, 0.12),
296
- // 0 2rpx 8rpx rgba(0, 0, 0, 0.06),
297
- // inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
298
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
299
- position: relative;
300
- overflow: hidden;
301
-
302
- &::before {
303
- content: '';
304
- position: absolute;
305
- top: 0;
306
- left: 0;
307
- right: 0;
308
- height: 50%;
309
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.35) 0%, transparent 100%);
310
- border-radius: 28rpx 28rpx 0 0;
311
- }
312
-
313
- &:active {
314
- transform: scale(0.92);
315
- box-shadow:
316
- 0 4rpx 16rpx rgba(0, 0, 0, 0.1),
317
- 0 1rpx 4rpx rgba(0, 0, 0, 0.05);
318
- }
319
- }
320
-
321
- // 图标光泽效果
322
- .icon-shine {
323
- position: absolute;
324
- top: -50%;
325
- left: -50%;
326
- width: 200%;
327
- height: 200%;
328
- background: linear-gradient(45deg, transparent 40%, rgba(255, 255, 255, 0.15) 50%, transparent 60%);
329
- animation: shine 15s ease-in-out infinite;
330
- pointer-events: none;
331
- }
332
-
333
- // 图标样式
334
- .menu-icon {
335
- color: rgba(255, 255, 255, 0.95);
336
- filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.2));
337
- z-index: 1;
338
- }
339
-
340
- // 文本容器
341
- .menu-text-wrapper {
342
- padding-top: 16rpx;
343
- text-align: center;
344
- display: flex;
345
- flex-direction: column;
346
- align-items: center;
347
- gap: 6rpx;
348
- }
349
-
350
- // 菜单标题
351
- .menu-title {
352
- font-size: 24rpx;
353
- font-weight: 600;
354
- // color: #374151;
355
- line-height: 1.3;
356
- letter-spacing: 0.02em;
357
- width: 100%;
358
- text-overflow: ellipsis;
359
- white-space: nowrap;
360
- overflow: hidden;
361
- }
362
-
363
- // 菜单徽章
364
- .menu-badge {
365
- display: flex;
366
- align-items: center;
367
- justify-content: center;
368
- }
369
-
370
- .badge-dot {
371
- width: 16rpx;
372
- height: 16rpx;
373
- background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
374
- border-radius: 50%;
375
- box-shadow: 0 2rpx 6rpx rgba(239, 68, 68, 0.4);
376
- animation: pulseDot 2s ease-in-out infinite;
377
- }
378
-
379
- // 底部信息
380
- .footer-section {
381
- display: flex;
382
- align-items: center;
383
- justify-content: center;
384
- gap: 20rpx;
385
- padding: 40rpx 0;
386
- animation: fadeIn 0.5s ease-out 0.5s backwards;
387
- }
388
-
389
- .footer-line {
390
- flex: 1;
391
- height: 1rpx;
392
- background: linear-gradient(90deg, transparent, rgba(0, 0, 0, 0.1), transparent);
393
- max-width: 120rpx;
394
- }
395
-
396
- .footer-text {
397
- font-size: 22rpx;
398
- color: #9ca3af;
399
- font-weight: 500;
400
- }
401
-
402
- // 动画定义
403
- @keyframes fadeInUp {
404
- from {
405
- opacity: 0;
406
- transform: translateY(20rpx);
407
- }
408
- to {
409
- opacity: 1;
410
- transform: translateY(0);
411
- }
412
- }
413
-
414
- @keyframes fadeInScale {
415
- from {
416
- opacity: 0;
417
- transform: scale(0.9);
418
- }
419
- to {
420
- opacity: 1;
421
- transform: scale(1);
422
- }
423
- }
424
-
425
- @keyframes slideUp {
426
- from {
427
- opacity: 0;
428
- transform: translateY(30rpx);
429
- }
430
- to {
431
- opacity: 1;
432
- transform: translateY(0);
433
- }
434
- }
435
-
436
- @keyframes fadeIn {
437
- from {
438
- opacity: 0;
439
- }
440
- to {
441
- opacity: 1;
442
- }
443
- }
444
-
445
- @keyframes shine {
446
- 0%,
447
- 100% {
448
- transform: translateX(-100%) rotate(45deg);
449
- }
450
- 50% {
451
- transform: translateX(100%) rotate(45deg);
452
- }
453
- }
454
-
455
- @keyframes pulseDot {
456
- 0%,
457
- 100% {
458
- transform: scale(1);
459
- opacity: 1;
460
- }
461
- 50% {
462
- transform: scale(1.1);
463
- opacity: 0.8;
464
- }
465
- }
466
-
467
- // 暗黑模式适配
468
- :global(.wot-theme-dark) {
469
- .section-title {
470
- color: #f9fafb;
471
- }
472
-
473
- .section-icon {
474
- background: linear-gradient(135deg, #374151 0%, #1f2937 100%);
475
- color: #9ca3af;
476
-
477
- &.primary {
478
- background: linear-gradient(135deg, rgba(59, 130, 246, 0.2) 0%, rgba(37, 99, 235, 0.15) 100%);
479
- color: #60a5fa;
480
- }
481
- }
482
-
483
- .section-tag {
484
- background: linear-gradient(135deg, rgba(34, 197, 94, 0.15) 0%, rgba(22, 163, 74, 0.1) 100%);
485
- border-color: rgba(34, 197, 94, 0.3);
486
- }
487
-
488
- .tag-text {
489
- color: #4ade80;
490
- }
491
-
492
- .more-text {
493
- color: #9ca3af;
494
- }
495
-
496
- .section-more {
497
- background: rgba(255, 255, 255, 0.05);
498
-
499
- &:active {
500
- background: rgba(255, 255, 255, 0.08);
501
- }
502
- }
503
-
504
- .recent-label {
505
- color: #d1d5db;
506
- }
507
-
508
- .menu-card {
509
- :deep(.wd-card) {
510
- background: linear-gradient(180deg, rgba(30, 30, 35, 0.98) 0%, rgba(25, 25, 30, 1) 100%);
511
- box-shadow:
512
- 0 8rpx 32rpx rgba(0, 0, 0, 0.25),
513
- 0 2rpx 8rpx rgba(0, 0, 0, 0.15),
514
- inset 0 1rpx 0 rgba(255, 255, 255, 0.05);
515
- border-color: rgba(255, 255, 255, 0.06);
516
- }
517
-
518
- :deep(.wd-card__title) {
519
- color: #f9fafb;
520
- }
521
- }
522
-
523
- .menu-grid-container {
524
- background: rgba(30, 30, 35, 0.5);
525
- }
526
-
527
- .menu-title {
528
- color: #e5e7eb;
529
- }
530
-
531
- .footer-line {
532
- background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
533
- }
534
-
535
- .footer-text {
536
- color: #6b7280;
537
- }
538
-
539
- .recent-icon {
540
- &-1 {
541
- background: linear-gradient(135deg, rgba(59, 130, 246, 0.2) 0%, rgba(37, 99, 235, 0.15) 100%);
542
- box-shadow: 0 4rpx 16rpx rgba(59, 130, 246, 0.2);
543
- }
544
-
545
- &-2 {
546
- background: linear-gradient(135deg, rgba(245, 158, 11, 0.2) 0%, rgba(217, 119, 6, 0.15) 100%);
547
- box-shadow: 0 4rpx 16rpx rgba(245, 158, 11, 0.2);
548
- }
549
-
550
- &-3 {
551
- background: linear-gradient(135deg, rgba(34, 197, 94, 0.2) 0%, rgba(22, 163, 74, 0.15) 100%);
552
- box-shadow: 0 4rpx 16rpx rgba(34, 197, 94, 0.2);
553
- }
554
-
555
- &-4 {
556
- background: linear-gradient(135deg, rgba(236, 72, 153, 0.2) 0%, rgba(219, 39, 119, 0.15) 100%);
557
- box-shadow: 0 4rpx 16rpx rgba(236, 72, 153, 0.2);
558
- }
559
- }
560
- }
561
- .menu-grid-container :deep(.wd-grid-item__content) {
562
- align-items: normal;
563
- }
564
- </style>
1
+ <script setup lang="ts">
2
+ import type { PropType } from 'vue'
3
+ import { defineOptions, defineProps, ref } from 'vue'
4
+ import DemoCard from '../demo-card/demo-card.vue'
5
+ import { useMenus } from '../../composables/useMenus'
6
+ import type { Icon } from '../../composables/useMenus'
7
+ import wuiNotifyInfo from '../wui-notify-info/wui-notify-info.vue'
8
+ import { useLanguageStore } from '../../store/language'
9
+ import sectionMenus from './components/section-menus.vue'
10
+ import navbar from './components/navbar.vue'
11
+ import quickPanel from './components/quick-panel.vue'
12
+ import bannerCarousel from './components/banner-carousel.vue'
13
+ import searchBar from './components/search-bar.vue'
14
+ import '../../static/iconfont/iconfont.css'
15
+ import { getThemeConfig } from '../../api/sys'
16
+ import { onMounted } from 'vue'
17
+
18
+ defineOptions({
19
+ name: 'WuiMenus1',
20
+ })
21
+ const props = defineProps({
22
+ icons: {
23
+ type: Array as PropType<Icon[]>,
24
+ default: () => [],
25
+ },
26
+ load: {
27
+ type: Function as PropType<() => void>,
28
+ default: () => {},
29
+ },
30
+ menuTopType: {
31
+ type: String,
32
+ default: '',
33
+ },
34
+ })
35
+ const languageStore = useLanguageStore()
36
+ const themeConfig = ref<any>({})
37
+ const pagingRef = ref(null)
38
+ const {
39
+ queryList,
40
+ menuList,
41
+ currentThemeColor,
42
+ filtermenu,
43
+ gotoPage,
44
+ sheetShow,
45
+ actions,
46
+ title,
47
+ sheetGotoPage,
48
+ navTitle,
49
+ } = useMenus(props, pagingRef)
50
+ onMounted(() => {
51
+ getThemeConfig().then(res => {
52
+ if (res.status == 'success') {
53
+ themeConfig.value = res.themeConfig
54
+ }
55
+ })
56
+ })
57
+ </script>
58
+
59
+ <template>
60
+ <z-paging
61
+ ref="pagingRef"
62
+ v-model="menuList"
63
+ :loading-more-enabled="false"
64
+ @query="queryList"
65
+ @on-refresh="props?.load"
66
+ >
67
+ <template #top>
68
+ <navbar :nav-title="navTitle" />
69
+ <slot name="top" :style="{ background: currentThemeColor.primary }" />
70
+ <view v-if="props.menuTopType === '自定义'" class="p-2" />
71
+ </template>
72
+ <view class="px-3 pb-4">
73
+ <!-- 菜单搜索 -->
74
+ <searchBar v-if="themeConfig.showHomePage" />
75
+ <!-- 轮播图 -->
76
+ <bannerCarousel v-if="themeConfig.showHomePage" />
77
+ <!-- 快捷菜单 -->
78
+ <sectionMenus v-if="themeConfig.showHomePage" />
79
+ <!-- 统计 -->
80
+ <quickPanel v-if="themeConfig.showHomePage" />
81
+ <!-- 消息 -->
82
+ <!-- <wuiNotifyInfo /> -->
83
+
84
+ <!-- 菜单卡片列表 -->
85
+ <view class="menu-section">
86
+ <view class="section-header" v-if="themeConfig.showHomePage">
87
+ <view class="section-title-wrapper">
88
+ <!-- <view class="section-icon primary">
89
+ <text class="i-carbon:apps text-sm" />
90
+ </view> -->
91
+ <text class="section-title dark:text-white text-gray-800">
92
+ {{ languageStore.t('全部功能') }}
93
+ </text>
94
+ </view>
95
+ <view class="section-tag">
96
+ <text class="tag-text">{{ filtermenu.length }} {{ languageStore.t('个分类') }}</text>
97
+ </view>
98
+ </view>
99
+ <view v-else class="py-3"></view>
100
+
101
+ <DemoCard
102
+ v-for="(item, index) in filtermenu"
103
+ :key="index"
104
+ :title="languageStore.t(item.title)"
105
+ class="menu-card"
106
+ :style="{ animationDelay: `${(index as number) * 0.1}s` }"
107
+ >
108
+ <template #content>
109
+ <view class="menu-grid-container">
110
+ <wd-grid :column="4" clickable class="menu-grid">
111
+ <wd-grid-item
112
+ v-for="(subItem, subIndex) in item.items"
113
+ :key="subIndex"
114
+ use-text-slot
115
+ use-icon-slot
116
+ class="menu-grid-item"
117
+ @click="gotoPage(subItem)"
118
+ >
119
+ <template #icon>
120
+ <view
121
+ class="menu-icon-wrapper flex items-center justify-center"
122
+ :style="{ background: subItem.color }"
123
+ >
124
+ <text class="menu-icon !text-xl iconfont" :class="[subItem.appIcon || 'i-carbon:grid']" />
125
+ <view class="icon-shine" />
126
+ </view>
127
+ </template>
128
+ <template #text>
129
+ <view class="menu-text-wrapper">
130
+ <view class="menu-title text-ellipsis dark:text-white text-gray-800">
131
+ {{ languageStore.t(subItem.title) }}
132
+ </view>
133
+ <!-- <view class="menu-badge" v-if="subIndex === 0">
134
+ <text class="badge-dot" />
135
+ </view> -->
136
+ </view>
137
+ </template>
138
+ </wd-grid-item>
139
+ </wd-grid>
140
+ </view>
141
+ </template>
142
+ </DemoCard>
143
+ </view>
144
+
145
+ <!-- 底部信息 -->
146
+ <view class="footer-section">
147
+ <view class="footer-line" />
148
+ <text class="footer-text">已经到底了</text>
149
+ <view class="footer-line" />
150
+ </view>
151
+
152
+ <slot name="listBottom" />
153
+ </view>
154
+
155
+ <template #bottom>
156
+ <slot name="bottom" />
157
+ </template>
158
+ </z-paging>
159
+ <wd-action-sheet
160
+ v-model="sheetShow"
161
+ :z-index="9999"
162
+ :actions="actions"
163
+ :title="title"
164
+ @select="
165
+ ({ item }) => {
166
+ sheetGotoPage(item)
167
+ }
168
+ "
169
+ />
170
+ </template>
171
+
172
+ <style scoped lang="scss">
173
+ // 菜单区域
174
+ .section-header {
175
+ display: flex;
176
+ align-items: center;
177
+ justify-content: space-between;
178
+ margin-bottom: 20rpx;
179
+ padding: 0 8rpx;
180
+ }
181
+ .section-title-wrapper {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: 12rpx;
185
+ }
186
+ .section-title {
187
+ font-size: 30rpx;
188
+ font-weight: 700;
189
+ letter-spacing: 0.02em;
190
+ }
191
+ .tag-text {
192
+ font-size: 20rpx;
193
+ color: #16a34a;
194
+ font-weight: 600;
195
+ }
196
+ .section-tag {
197
+ display: flex;
198
+ align-items: center;
199
+ padding: 6rpx 14rpx;
200
+ background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
201
+ border-radius: 20rpx;
202
+ border: 1rpx solid rgba(34, 197, 94, 0.2);
203
+ }
204
+ .menu-section {
205
+ animation: fadeInUp 0.5s ease-out 0.2s backwards;
206
+ }
207
+ .section-icon {
208
+ width: 44rpx;
209
+ height: 44rpx;
210
+ border-radius: 12rpx;
211
+ background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
212
+ display: flex;
213
+ align-items: center;
214
+ justify-content: center;
215
+ color: #6b7280;
216
+
217
+ &.primary {
218
+ background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
219
+ color: #3b82f6;
220
+ }
221
+ }
222
+
223
+ // 菜单卡片容器
224
+ .menu-card {
225
+ animation: slideUp 0.5s ease-out backwards;
226
+ margin: 0 !important;
227
+ margin-bottom: 20rpx !important;
228
+ :deep(.wd-card) {
229
+ border-radius: 28rpx;
230
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, rgba(255, 255, 255, 1) 100%);
231
+ box-shadow:
232
+ 0 8rpx 32rpx rgba(0, 0, 0, 0.06),
233
+ 0 2rpx 8rpx rgba(0, 0, 0, 0.04),
234
+ inset 0 1rpx 0 rgba(255, 255, 255, 1);
235
+ border: 1rpx solid rgba(0, 0, 0, 0.04);
236
+ overflow: hidden;
237
+ transition: all 0.3s ease;
238
+ &:active {
239
+ transform: translateY(-2rpx);
240
+ box-shadow:
241
+ 0 12rpx 40rpx rgba(0, 0, 0, 0.08),
242
+ 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
243
+ }
244
+ }
245
+
246
+ :deep(.wd-card__title) {
247
+ // padding: 28rpx 28rpx 20rpx;
248
+ font-weight: 700;
249
+ font-size: 30rpx;
250
+ // color: #1f2937;
251
+ display: flex;
252
+ align-items: center;
253
+ gap: 12rpx;
254
+ }
255
+
256
+ :deep(.wd-card__content) {
257
+ padding: 12rpx 16rpx 28rpx;
258
+ }
259
+ }
260
+
261
+ // 网格容器样式
262
+ .menu-grid-container {
263
+ // background: rgba(249, 250, 251, 0.5);
264
+ border-radius: 20rpx;
265
+ // padding: 20rpx 12rpx;
266
+ transition: all 0.3s ease;
267
+ }
268
+
269
+ // 网格项样式
270
+ .menu-grid {
271
+ // grid-auto-rows: 100px !important;
272
+ :deep(.wd-grid-item) {
273
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
274
+
275
+ &:active {
276
+ transform: scale(0.95);
277
+ }
278
+ }
279
+
280
+ :deep(.wd-grid-item__wrapper) {
281
+ padding: 20rpx 10rpx !important;
282
+ display: flex;
283
+ flex-direction: column;
284
+ align-items: center;
285
+ justify-content: center;
286
+ }
287
+ }
288
+
289
+ // 图标容器
290
+ .menu-icon-wrapper {
291
+ width: 100rpx;
292
+ height: 100rpx;
293
+ border-radius: 28rpx;
294
+ // box-shadow:
295
+ // 0 8rpx 24rpx rgba(0, 0, 0, 0.12),
296
+ // 0 2rpx 8rpx rgba(0, 0, 0, 0.06),
297
+ // inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
298
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
299
+ position: relative;
300
+ overflow: hidden;
301
+
302
+ &::before {
303
+ content: '';
304
+ position: absolute;
305
+ top: 0;
306
+ left: 0;
307
+ right: 0;
308
+ height: 50%;
309
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.35) 0%, transparent 100%);
310
+ border-radius: 28rpx 28rpx 0 0;
311
+ }
312
+
313
+ &:active {
314
+ transform: scale(0.92);
315
+ box-shadow:
316
+ 0 4rpx 16rpx rgba(0, 0, 0, 0.1),
317
+ 0 1rpx 4rpx rgba(0, 0, 0, 0.05);
318
+ }
319
+ }
320
+
321
+ // 图标光泽效果
322
+ .icon-shine {
323
+ position: absolute;
324
+ top: -50%;
325
+ left: -50%;
326
+ width: 200%;
327
+ height: 200%;
328
+ background: linear-gradient(45deg, transparent 40%, rgba(255, 255, 255, 0.15) 50%, transparent 60%);
329
+ animation: shine 15s ease-in-out infinite;
330
+ pointer-events: none;
331
+ }
332
+
333
+ // 图标样式
334
+ .menu-icon {
335
+ color: rgba(255, 255, 255, 0.95);
336
+ filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.2));
337
+ z-index: 1;
338
+ }
339
+
340
+ // 文本容器
341
+ .menu-text-wrapper {
342
+ padding-top: 16rpx;
343
+ text-align: center;
344
+ display: flex;
345
+ flex-direction: column;
346
+ align-items: center;
347
+ gap: 6rpx;
348
+ }
349
+
350
+ // 菜单标题
351
+ .menu-title {
352
+ font-size: 24rpx;
353
+ font-weight: 600;
354
+ // color: #374151;
355
+ line-height: 1.3;
356
+ letter-spacing: 0.02em;
357
+ width: 100%;
358
+ text-overflow: ellipsis;
359
+ white-space: nowrap;
360
+ overflow: hidden;
361
+ }
362
+
363
+ // 菜单徽章
364
+ .menu-badge {
365
+ display: flex;
366
+ align-items: center;
367
+ justify-content: center;
368
+ }
369
+
370
+ .badge-dot {
371
+ width: 16rpx;
372
+ height: 16rpx;
373
+ background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
374
+ border-radius: 50%;
375
+ box-shadow: 0 2rpx 6rpx rgba(239, 68, 68, 0.4);
376
+ animation: pulseDot 2s ease-in-out infinite;
377
+ }
378
+
379
+ // 底部信息
380
+ .footer-section {
381
+ display: flex;
382
+ align-items: center;
383
+ justify-content: center;
384
+ gap: 20rpx;
385
+ padding: 40rpx 0;
386
+ animation: fadeIn 0.5s ease-out 0.5s backwards;
387
+ }
388
+
389
+ .footer-line {
390
+ flex: 1;
391
+ height: 1rpx;
392
+ background: linear-gradient(90deg, transparent, rgba(0, 0, 0, 0.1), transparent);
393
+ max-width: 120rpx;
394
+ }
395
+
396
+ .footer-text {
397
+ font-size: 22rpx;
398
+ color: #9ca3af;
399
+ font-weight: 500;
400
+ }
401
+
402
+ // 动画定义
403
+ @keyframes fadeInUp {
404
+ from {
405
+ opacity: 0;
406
+ transform: translateY(20rpx);
407
+ }
408
+ to {
409
+ opacity: 1;
410
+ transform: translateY(0);
411
+ }
412
+ }
413
+
414
+ @keyframes fadeInScale {
415
+ from {
416
+ opacity: 0;
417
+ transform: scale(0.9);
418
+ }
419
+ to {
420
+ opacity: 1;
421
+ transform: scale(1);
422
+ }
423
+ }
424
+
425
+ @keyframes slideUp {
426
+ from {
427
+ opacity: 0;
428
+ transform: translateY(30rpx);
429
+ }
430
+ to {
431
+ opacity: 1;
432
+ transform: translateY(0);
433
+ }
434
+ }
435
+
436
+ @keyframes fadeIn {
437
+ from {
438
+ opacity: 0;
439
+ }
440
+ to {
441
+ opacity: 1;
442
+ }
443
+ }
444
+
445
+ @keyframes shine {
446
+ 0%,
447
+ 100% {
448
+ transform: translateX(-100%) rotate(45deg);
449
+ }
450
+ 50% {
451
+ transform: translateX(100%) rotate(45deg);
452
+ }
453
+ }
454
+
455
+ @keyframes pulseDot {
456
+ 0%,
457
+ 100% {
458
+ transform: scale(1);
459
+ opacity: 1;
460
+ }
461
+ 50% {
462
+ transform: scale(1.1);
463
+ opacity: 0.8;
464
+ }
465
+ }
466
+
467
+ // 暗黑模式适配
468
+ :global(.wot-theme-dark) {
469
+ .section-title {
470
+ color: #f9fafb;
471
+ }
472
+
473
+ .section-icon {
474
+ background: linear-gradient(135deg, #374151 0%, #1f2937 100%);
475
+ color: #9ca3af;
476
+
477
+ &.primary {
478
+ background: linear-gradient(135deg, rgba(59, 130, 246, 0.2) 0%, rgba(37, 99, 235, 0.15) 100%);
479
+ color: #60a5fa;
480
+ }
481
+ }
482
+
483
+ .section-tag {
484
+ background: linear-gradient(135deg, rgba(34, 197, 94, 0.15) 0%, rgba(22, 163, 74, 0.1) 100%);
485
+ border-color: rgba(34, 197, 94, 0.3);
486
+ }
487
+
488
+ .tag-text {
489
+ color: #4ade80;
490
+ }
491
+
492
+ .more-text {
493
+ color: #9ca3af;
494
+ }
495
+
496
+ .section-more {
497
+ background: rgba(255, 255, 255, 0.05);
498
+
499
+ &:active {
500
+ background: rgba(255, 255, 255, 0.08);
501
+ }
502
+ }
503
+
504
+ .recent-label {
505
+ color: #d1d5db;
506
+ }
507
+
508
+ .menu-card {
509
+ :deep(.wd-card) {
510
+ background: linear-gradient(180deg, rgba(30, 30, 35, 0.98) 0%, rgba(25, 25, 30, 1) 100%);
511
+ box-shadow:
512
+ 0 8rpx 32rpx rgba(0, 0, 0, 0.25),
513
+ 0 2rpx 8rpx rgba(0, 0, 0, 0.15),
514
+ inset 0 1rpx 0 rgba(255, 255, 255, 0.05);
515
+ border-color: rgba(255, 255, 255, 0.06);
516
+ }
517
+
518
+ :deep(.wd-card__title) {
519
+ color: #f9fafb;
520
+ }
521
+ }
522
+
523
+ .menu-grid-container {
524
+ background: rgba(30, 30, 35, 0.5);
525
+ }
526
+
527
+ .menu-title {
528
+ color: #e5e7eb;
529
+ }
530
+
531
+ .footer-line {
532
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
533
+ }
534
+
535
+ .footer-text {
536
+ color: #6b7280;
537
+ }
538
+
539
+ .recent-icon {
540
+ &-1 {
541
+ background: linear-gradient(135deg, rgba(59, 130, 246, 0.2) 0%, rgba(37, 99, 235, 0.15) 100%);
542
+ box-shadow: 0 4rpx 16rpx rgba(59, 130, 246, 0.2);
543
+ }
544
+
545
+ &-2 {
546
+ background: linear-gradient(135deg, rgba(245, 158, 11, 0.2) 0%, rgba(217, 119, 6, 0.15) 100%);
547
+ box-shadow: 0 4rpx 16rpx rgba(245, 158, 11, 0.2);
548
+ }
549
+
550
+ &-3 {
551
+ background: linear-gradient(135deg, rgba(34, 197, 94, 0.2) 0%, rgba(22, 163, 74, 0.15) 100%);
552
+ box-shadow: 0 4rpx 16rpx rgba(34, 197, 94, 0.2);
553
+ }
554
+
555
+ &-4 {
556
+ background: linear-gradient(135deg, rgba(236, 72, 153, 0.2) 0%, rgba(219, 39, 119, 0.15) 100%);
557
+ box-shadow: 0 4rpx 16rpx rgba(236, 72, 153, 0.2);
558
+ }
559
+ }
560
+ }
561
+ .menu-grid-container :deep(.wd-grid-item__content) {
562
+ align-items: normal;
563
+ }
564
+ </style>