@ruixinkeji/prism-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 (48) hide show
  1. package/README.md +141 -0
  2. package/components/PrismAIAssist/PrismAIAssist.vue +98 -0
  3. package/components/PrismAddressInput/PrismAddressInput.vue +597 -0
  4. package/components/PrismCityCascadeSelect/PrismCityCascadeSelect.vue +793 -0
  5. package/components/PrismCityPicker/PrismCityPicker.vue +1008 -0
  6. package/components/PrismCitySelect/PrismCitySelect.vue +435 -0
  7. package/components/PrismCode/PrismCode.vue +749 -0
  8. package/components/PrismCodeInput/PrismCodeInput.vue +156 -0
  9. package/components/PrismDateTimePicker/PrismDateTimePicker.vue +953 -0
  10. package/components/PrismDropdown/PrismDropdown.vue +77 -0
  11. package/components/PrismGroupSticky/PrismGroupSticky.vue +352 -0
  12. package/components/PrismIdCardInput/PrismIdCardInput.vue +253 -0
  13. package/components/PrismImagePicker/PrismImagePicker.vue +457 -0
  14. package/components/PrismIndexBar/PrismIndexBar.vue +243 -0
  15. package/components/PrismLicensePlateInput/PrismLicensePlateInput.vue +1100 -0
  16. package/components/PrismMusicPlayer/PrismMusicPlayer.vue +530 -0
  17. package/components/PrismNavBar/PrismNavBar.vue +199 -0
  18. package/components/PrismSecureInput/PrismSecureInput.vue +360 -0
  19. package/components/PrismSticky/PrismSticky.vue +173 -0
  20. package/components/PrismSwiper/PrismSwiper.vue +339 -0
  21. package/components/PrismSwitch/PrismSwitch.vue +202 -0
  22. package/components/PrismTabBar/PrismTabBar.vue +147 -0
  23. package/components/PrismTabs/PrismTabs.vue +49 -0
  24. package/components/PrismVoiceInput/PrismVoiceInput.vue +529 -0
  25. package/index.d.ts +24 -0
  26. package/index.esm.js +25 -0
  27. package/index.js +25 -0
  28. package/package.json +89 -0
  29. package/styles/base.scss +227 -0
  30. package/styles/button.scss +120 -0
  31. package/styles/card.scss +306 -0
  32. package/styles/colors.scss +877 -0
  33. package/styles/data.scss +1229 -0
  34. package/styles/effects.scss +407 -0
  35. package/styles/feedback.scss +698 -0
  36. package/styles/form.scss +1574 -0
  37. package/styles/index.scss +46 -0
  38. package/styles/list.scss +184 -0
  39. package/styles/navigation.scss +554 -0
  40. package/styles/overlay.scss +182 -0
  41. package/styles/utilities.scss +134 -0
  42. package/styles/variables.scss +138 -0
  43. package/theme/blue.scss +36 -0
  44. package/theme/cyan.scss +32 -0
  45. package/theme/green.scss +32 -0
  46. package/theme/orange.scss +32 -0
  47. package/theme/purple.scss +32 -0
  48. package/theme/red.scss +32 -0
@@ -0,0 +1,457 @@
1
+ <template>
2
+ <view class="prism-image-picker" :class="{ 'dark-mode': appStore.isDarkMode }">
3
+ <!-- 主图片区域 -->
4
+ <view class="picker-main">
5
+ <!-- 已选图片预览 -->
6
+ <view class="image-preview" v-if="modelValue" @click="handleMainClick">
7
+ <image class="preview-img" :src="modelValue" :mode="imageMode"></image>
8
+ <view class="image-remove" @click.stop="removeImage" v-if="!disabled">
9
+ <text class="fa fa-times"></text>
10
+ </view>
11
+ <view class="image-edit" v-if="!disabled">
12
+ <text class="fa fa-camera"></text>
13
+ </view>
14
+ </view>
15
+ <!-- 上传按钮 -->
16
+ <view class="upload-btn" v-else @click="handleUpload" :class="{ 'disabled': disabled }">
17
+ <text class="fa" :class="uploadIcon"></text>
18
+ <text class="upload-text">{{ uploadText }}</text>
19
+ </view>
20
+ </view>
21
+
22
+ <!-- 默认图片选择区域 -->
23
+ <view class="default-images" v-if="defaultImages.length && showDefaults">
24
+ <view class="default-title" v-if="defaultTitle">{{ defaultTitle }}</view>
25
+ <scroll-view class="default-scroll" scroll-x>
26
+ <view class="default-list">
27
+ <view
28
+ v-for="(img, index) in defaultImages"
29
+ :key="index"
30
+ class="default-item"
31
+ :class="{ 'active': modelValue === img }"
32
+ @click="selectDefault(img)"
33
+ >
34
+ <image :src="img" mode="aspectFill"></image>
35
+ <view class="check-icon" v-if="modelValue === img">
36
+ <text class="fa fa-check"></text>
37
+ </view>
38
+ </view>
39
+ </view>
40
+ </scroll-view>
41
+ </view>
42
+
43
+ <!-- 来源选择弹窗 -->
44
+ <view class="source-popup" v-if="showSourcePopup" @click="showSourcePopup = false">
45
+ <view class="source-content" @click.stop>
46
+ <view class="source-title">选择图片</view>
47
+ <view class="source-options">
48
+ <view class="source-option" @click="chooseFromCamera">
49
+ <view class="option-icon">
50
+ <text class="fa fa-camera"></text>
51
+ </view>
52
+ <text>拍照</text>
53
+ </view>
54
+ <view class="source-option" @click="chooseFromAlbum">
55
+ <view class="option-icon">
56
+ <text class="fa fa-images"></text>
57
+ </view>
58
+ <text>相册</text>
59
+ </view>
60
+ </view>
61
+ <view class="source-cancel" @click="showSourcePopup = false">取消</view>
62
+ </view>
63
+ </view>
64
+ </view>
65
+ </template>
66
+
67
+ <script setup>
68
+ import { ref } from 'vue';
69
+ import { useAppStore } from '@/store/app';
70
+
71
+ const props = defineProps({
72
+ modelValue: {
73
+ type: String,
74
+ default: ''
75
+ },
76
+ // 默认图片列表
77
+ defaultImages: {
78
+ type: Array,
79
+ default: () => []
80
+ },
81
+ // 是否显示默认图片
82
+ showDefaults: {
83
+ type: Boolean,
84
+ default: true
85
+ },
86
+ // 默认图片区域标题
87
+ defaultTitle: {
88
+ type: String,
89
+ default: ''
90
+ },
91
+ // 上传按钮图标
92
+ uploadIcon: {
93
+ type: String,
94
+ default: 'fa-camera'
95
+ },
96
+ // 上传按钮文字
97
+ uploadText: {
98
+ type: String,
99
+ default: '添加图片'
100
+ },
101
+ // 图片显示模式
102
+ imageMode: {
103
+ type: String,
104
+ default: 'aspectFill'
105
+ },
106
+ // 是否显示来源选择弹窗
107
+ showSourceSelect: {
108
+ type: Boolean,
109
+ default: false
110
+ },
111
+ // 图片来源:album/camera/both
112
+ sourceType: {
113
+ type: String,
114
+ default: 'both',
115
+ validator: (val) => ['album', 'camera', 'both'].includes(val)
116
+ },
117
+ // 是否压缩
118
+ compressed: {
119
+ type: Boolean,
120
+ default: true
121
+ },
122
+ // 禁用状态
123
+ disabled: {
124
+ type: Boolean,
125
+ default: false
126
+ }
127
+ });
128
+
129
+ const emit = defineEmits(['update:modelValue', 'change', 'upload', 'remove']);
130
+
131
+ const appStore = useAppStore();
132
+ const showSourcePopup = ref(false);
133
+
134
+ // 处理上传
135
+ function handleUpload() {
136
+ if (props.disabled) return;
137
+
138
+ if (props.showSourceSelect && props.sourceType === 'both') {
139
+ showSourcePopup.value = true;
140
+ } else if (props.sourceType === 'camera') {
141
+ chooseFromCamera();
142
+ } else {
143
+ chooseFromAlbum();
144
+ }
145
+ }
146
+
147
+ // 点击主图片
148
+ function handleMainClick() {
149
+ if (props.disabled) return;
150
+ handleUpload();
151
+ }
152
+
153
+ // 从相机选择
154
+ function chooseFromCamera() {
155
+ showSourcePopup.value = false;
156
+ chooseImage(['camera']);
157
+ }
158
+
159
+ // 从相册选择
160
+ function chooseFromAlbum() {
161
+ showSourcePopup.value = false;
162
+ chooseImage(['album']);
163
+ }
164
+
165
+ // 选择图片
166
+ function chooseImage(sourceType) {
167
+ uni.chooseImage({
168
+ count: 1,
169
+ sizeType: props.compressed ? ['compressed'] : ['original'],
170
+ sourceType: sourceType,
171
+ success: (res) => {
172
+ const tempFilePath = res.tempFilePaths[0];
173
+ emit('update:modelValue', tempFilePath);
174
+ emit('change', tempFilePath);
175
+ emit('upload', {
176
+ tempFilePath,
177
+ tempFile: res.tempFiles[0]
178
+ });
179
+ },
180
+ fail: (err) => {
181
+ console.log('选择图片失败', err);
182
+ }
183
+ });
184
+ }
185
+
186
+ // 选择默认图片
187
+ function selectDefault(img) {
188
+ if (props.disabled) return;
189
+ emit('update:modelValue', img);
190
+ emit('change', img);
191
+ }
192
+
193
+ // 移除图片
194
+ function removeImage() {
195
+ emit('update:modelValue', '');
196
+ emit('change', '');
197
+ emit('remove');
198
+ }
199
+ </script>
200
+
201
+ <style lang="scss">
202
+ .prism-image-picker {
203
+ .picker-main {
204
+ display: inline-block;
205
+ }
206
+
207
+ .image-preview {
208
+ position: relative;
209
+ width: 160rpx;
210
+ height: 160rpx;
211
+ border-radius: 16rpx;
212
+ overflow: hidden;
213
+ }
214
+
215
+ .preview-img {
216
+ width: 100%;
217
+ height: 100%;
218
+ }
219
+
220
+ .image-remove {
221
+ position: absolute;
222
+ top: 8rpx;
223
+ right: 8rpx;
224
+ width: 40rpx;
225
+ height: 40rpx;
226
+ background: rgba(0, 0, 0, 0.5);
227
+ border-radius: 50%;
228
+ display: flex;
229
+ align-items: center;
230
+ justify-content: center;
231
+
232
+ .fa {
233
+ font-size: 20rpx;
234
+ color: #FFFFFF;
235
+ }
236
+ }
237
+
238
+ .image-edit {
239
+ position: absolute;
240
+ bottom: 0;
241
+ left: 0;
242
+ right: 0;
243
+ height: 48rpx;
244
+ background: rgba(0, 0, 0, 0.5);
245
+ display: flex;
246
+ align-items: center;
247
+ justify-content: center;
248
+
249
+ .fa {
250
+ font-size: 24rpx;
251
+ color: #FFFFFF;
252
+ }
253
+ }
254
+
255
+ .upload-btn {
256
+ width: 160rpx;
257
+ height: 160rpx;
258
+ background: var(--prism-bg-color-container, #F7F8FA);
259
+ border: 2rpx dashed var(--prism-border-color-light, #E5E6EB);
260
+ border-radius: 16rpx;
261
+ display: flex;
262
+ flex-direction: column;
263
+ align-items: center;
264
+ justify-content: center;
265
+ gap: 12rpx;
266
+ transition: all 0.2s;
267
+
268
+ .fa {
269
+ font-size: 48rpx;
270
+ color: var(--prism-text-placeholder, #C9CDD4);
271
+ }
272
+
273
+ .upload-text {
274
+ font-size: 24rpx;
275
+ color: var(--prism-text-secondary, #86909C);
276
+ }
277
+
278
+ &:active {
279
+ background: var(--prism-primary-light, rgba(52, 120, 246, 0.08));
280
+ border-color: var(--prism-primary-color, #3478F6);
281
+
282
+ .fa {
283
+ color: var(--prism-primary-color, #3478F6);
284
+ }
285
+ }
286
+
287
+ &.disabled {
288
+ opacity: 0.5;
289
+ pointer-events: none;
290
+ }
291
+ }
292
+
293
+ // 默认图片区域
294
+ .default-images {
295
+ margin-top: 24rpx;
296
+ }
297
+
298
+ .default-title {
299
+ font-size: 26rpx;
300
+ color: var(--prism-text-secondary, #86909C);
301
+ margin-bottom: 16rpx;
302
+ }
303
+
304
+ .default-scroll {
305
+ white-space: nowrap;
306
+
307
+ &::-webkit-scrollbar {
308
+ display: none;
309
+ }
310
+ }
311
+
312
+ .default-list {
313
+ display: inline-flex;
314
+ gap: 16rpx;
315
+ }
316
+
317
+ .default-item {
318
+ position: relative;
319
+ width: 96rpx;
320
+ height: 96rpx;
321
+ border-radius: 12rpx;
322
+ overflow: hidden;
323
+ border: 2rpx solid transparent;
324
+ flex-shrink: 0;
325
+ transition: all 0.2s;
326
+
327
+ image {
328
+ width: 100%;
329
+ height: 100%;
330
+ }
331
+
332
+ &.active {
333
+ border-color: var(--prism-primary-color, #3478F6);
334
+ }
335
+
336
+ .check-icon {
337
+ position: absolute;
338
+ bottom: 0;
339
+ right: 0;
340
+ width: 32rpx;
341
+ height: 32rpx;
342
+ background: var(--prism-primary-color, #3478F6);
343
+ border-radius: 8rpx 0 0 0;
344
+ display: flex;
345
+ align-items: center;
346
+ justify-content: center;
347
+
348
+ .fa {
349
+ font-size: 18rpx;
350
+ color: #FFFFFF;
351
+ }
352
+ }
353
+ }
354
+
355
+ // 来源选择弹窗
356
+ .source-popup {
357
+ position: fixed;
358
+ top: 0;
359
+ left: 0;
360
+ right: 0;
361
+ bottom: 0;
362
+ background: var(--prism-mask-bg, rgba(0, 0, 0, 0.5));
363
+ display: flex;
364
+ align-items: flex-end;
365
+ justify-content: center;
366
+ z-index: 9999;
367
+ }
368
+
369
+ .source-content {
370
+ width: 100%;
371
+ background: var(--prism-bg-color-card, #FFFFFF);
372
+ border-radius: 24rpx 24rpx 0 0;
373
+ padding: 32rpx;
374
+ padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
375
+ }
376
+
377
+ .source-title {
378
+ font-size: 32rpx;
379
+ font-weight: 600;
380
+ color: var(--prism-text-primary, #1D2129);
381
+ text-align: center;
382
+ margin-bottom: 32rpx;
383
+ }
384
+
385
+ .source-options {
386
+ display: flex;
387
+ gap: 24rpx;
388
+ }
389
+
390
+ .source-option {
391
+ flex: 1;
392
+ height: 160rpx;
393
+ background: var(--prism-bg-color-container, #F7F8FA);
394
+ border-radius: 16rpx;
395
+ display: flex;
396
+ flex-direction: column;
397
+ align-items: center;
398
+ justify-content: center;
399
+ gap: 16rpx;
400
+ transition: all 0.2s;
401
+
402
+ .option-icon {
403
+ width: 64rpx;
404
+ height: 64rpx;
405
+ background: var(--prism-primary-light, rgba(52, 120, 246, 0.1));
406
+ border-radius: 50%;
407
+ display: flex;
408
+ align-items: center;
409
+ justify-content: center;
410
+
411
+ .fa {
412
+ font-size: 32rpx;
413
+ color: var(--prism-primary-color, #3478F6);
414
+ }
415
+ }
416
+
417
+ text:last-child {
418
+ font-size: 28rpx;
419
+ color: var(--prism-text-primary, #1D2129);
420
+ }
421
+
422
+ &:active {
423
+ background: var(--prism-primary-light, rgba(52, 120, 246, 0.1));
424
+ }
425
+ }
426
+
427
+ .source-cancel {
428
+ margin-top: 24rpx;
429
+ height: 88rpx;
430
+ display: flex;
431
+ align-items: center;
432
+ justify-content: center;
433
+ font-size: 32rpx;
434
+ color: var(--prism-text-secondary, #86909C);
435
+ }
436
+ }
437
+
438
+ // 深色模式
439
+ .dark-mode.prism-image-picker {
440
+ .upload-btn {
441
+ background: var(--prism-bg-color-container, #2A2A2A);
442
+ border-color: rgba(255, 255, 255, 0.15);
443
+ }
444
+
445
+ .source-content {
446
+ background: var(--prism-bg-color-card, #1A1A1A);
447
+ }
448
+
449
+ .source-option {
450
+ background: var(--prism-bg-color-container, #2A2A2A);
451
+
452
+ &:active {
453
+ background: rgba(52, 120, 246, 0.15);
454
+ }
455
+ }
456
+ }
457
+ </style>
@@ -0,0 +1,243 @@
1
+ <template>
2
+ <view>
3
+ <!-- 右侧索引条 -->
4
+ <view
5
+ class="prism-index-bar"
6
+ :class="{ 'dark-mode': isDarkMode }"
7
+ @touchstart="onIndexTouchStart"
8
+ @touchmove.stop.prevent="onIndexTouchMove"
9
+ @touchend="onIndexTouchEnd"
10
+ >
11
+ <view
12
+ v-for="item in items"
13
+ :key="item.value"
14
+ class="prism-index-item"
15
+ :class="{ 'active': currentIndex === item.value }"
16
+ :style="{ background: item.background }"
17
+ >
18
+ </view>
19
+ </view>
20
+
21
+ <!-- 气泡提示 -->
22
+ <view
23
+ v-if="showIndicator && currentIndex"
24
+ class="prism-index-indicator"
25
+ :class="{ 'dark-mode': isDarkMode }"
26
+ :style="{
27
+ top: indicatorTop + 'px',
28
+ background: currentItemBackground
29
+ }"
30
+ >
31
+ {{ currentItemLabel }}
32
+ <!-- 箭头 -->
33
+ <view
34
+ class="prism-index-indicator-arrow"
35
+ :style="{ borderLeftColor: currentItemBackground }"
36
+ ></view>
37
+ </view>
38
+ </view>
39
+ </template>
40
+
41
+ <script setup>
42
+ import { ref, computed, getCurrentInstance } from 'vue';
43
+
44
+ const props = defineProps({
45
+ // 索引项列表 [{ value: 'key', label: '显示文字', background: '#fff' 或 'linear-gradient(...)' }]
46
+ items: {
47
+ type: Array,
48
+ default: () => []
49
+ },
50
+ // 是否深色模式
51
+ isDarkMode: {
52
+ type: Boolean,
53
+ default: false
54
+ },
55
+ // 当前选中的索引值(支持 v-model)
56
+ modelValue: {
57
+ type: String,
58
+ default: ''
59
+ }
60
+ });
61
+
62
+ const emit = defineEmits(['update:modelValue', 'change']);
63
+
64
+ const instance = getCurrentInstance();
65
+
66
+ // 当前选中的索引
67
+ const currentIndex = ref(props.modelValue);
68
+ // 是否显示气泡
69
+ const showIndicator = ref(false);
70
+ // 气泡位置
71
+ const indicatorTop = ref(0);
72
+ // 索引条位置信息
73
+ let indexBarRect = null;
74
+
75
+ // 当前选中项的标签
76
+ const currentItemLabel = computed(() => {
77
+ const item = props.items.find(i => i.value === currentIndex.value);
78
+ return item ? item.label : '';
79
+ });
80
+
81
+ // 当前选中项的背景
82
+ const currentItemBackground = computed(() => {
83
+ const item = props.items.find(i => i.value === currentIndex.value);
84
+ return item ? item.background : 'rgba(0, 0, 0, 0.85)';
85
+ });
86
+
87
+ // 根据触摸位置计算当前索引
88
+ const getItemByTouch = (touchY) => {
89
+ if (!indexBarRect || !props.items.length) return null;
90
+ const itemHeight = indexBarRect.height / props.items.length;
91
+ const relativeY = touchY - indexBarRect.top;
92
+ const index = Math.floor(relativeY / itemHeight);
93
+ if (index < 0) return props.items[0];
94
+ if (index >= props.items.length) return props.items[props.items.length - 1];
95
+ return props.items[index];
96
+ };
97
+
98
+ // 更新选中索引
99
+ const updateIndex = (touchY) => {
100
+ // 更新气泡位置
101
+ indicatorTop.value = touchY;
102
+
103
+ const item = getItemByTouch(touchY);
104
+ if (item && item.value !== currentIndex.value) {
105
+ currentIndex.value = item.value;
106
+ emit('update:modelValue', item.value);
107
+ emit('change', item.value);
108
+ }
109
+ };
110
+
111
+ // 触摸开始
112
+ const onIndexTouchStart = (e) => {
113
+ showIndicator.value = true;
114
+ const touchY = e.touches[0].clientY;
115
+ indicatorTop.value = touchY;
116
+
117
+ // 获取索引条位置并更新索引
118
+ uni.createSelectorQuery()
119
+ .in(instance)
120
+ .select('.prism-index-bar')
121
+ .boundingClientRect((rect) => {
122
+ if (rect) {
123
+ indexBarRect = rect;
124
+ const item = getItemByTouch(touchY);
125
+ if (item) {
126
+ currentIndex.value = item.value;
127
+ emit('update:modelValue', item.value);
128
+ emit('change', item.value);
129
+ }
130
+ }
131
+ })
132
+ .exec();
133
+ };
134
+
135
+ // 触摸移动
136
+ const onIndexTouchMove = (e) => {
137
+ const touchY = e.touches[0].clientY;
138
+ if (indexBarRect) {
139
+ updateIndex(touchY);
140
+ }
141
+ };
142
+
143
+ // 触摸结束
144
+ const onIndexTouchEnd = () => {
145
+ showIndicator.value = false;
146
+ };
147
+ </script>
148
+
149
+ <style lang="scss" scoped>
150
+ /* 右侧索引条 */
151
+ .prism-index-bar {
152
+ position: fixed;
153
+ right: 8rpx;
154
+ top: 50%;
155
+ transform: translateY(-50%);
156
+ display: flex;
157
+ flex-direction: column;
158
+ align-items: center;
159
+ gap: 12rpx;
160
+ z-index: 999;
161
+ padding: 16rpx 12rpx;
162
+ background: rgba(255, 255, 255, 0.1);
163
+ border-radius: 24rpx;
164
+ backdrop-filter: blur(10px);
165
+ -webkit-backdrop-filter: blur(10px);
166
+ }
167
+
168
+ .prism-index-item {
169
+ width: 40rpx;
170
+ height: 40rpx;
171
+ border-radius: 50%;
172
+ border: 3rpx solid rgba(255, 255, 255, 0.8);
173
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
174
+ transition: all 0.3s ease;
175
+ position: relative;
176
+ flex-shrink: 0;
177
+
178
+ &:active {
179
+ transform: scale(1.15);
180
+ }
181
+
182
+ &.active {
183
+ width: 48rpx;
184
+ height: 48rpx;
185
+ border-width: 4rpx;
186
+ border-color: #FFFFFF;
187
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.3);
188
+ }
189
+ }
190
+
191
+ /* 气泡提示 */
192
+ .prism-index-indicator {
193
+ position: fixed;
194
+ right: 80rpx;
195
+ padding: 12rpx 20rpx;
196
+ color: #FFFFFF;
197
+ border-radius: 8rpx;
198
+ font-size: 24rpx;
199
+ white-space: nowrap;
200
+ backdrop-filter: blur(10px);
201
+ -webkit-backdrop-filter: blur(10px);
202
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.3);
203
+ animation: fadeIn 0.2s ease;
204
+ z-index: 1000;
205
+ transform: translateY(-50%);
206
+ pointer-events: none;
207
+ }
208
+
209
+ /* 气泡箭头 */
210
+ .prism-index-indicator-arrow {
211
+ position: absolute;
212
+ right: -8rpx;
213
+ top: 50%;
214
+ transform: translateY(-50%);
215
+ width: 0;
216
+ height: 0;
217
+ border-left: 8rpx solid;
218
+ border-top: 8rpx solid transparent;
219
+ border-bottom: 8rpx solid transparent;
220
+ }
221
+
222
+ @keyframes fadeIn {
223
+ from {
224
+ opacity: 0;
225
+ }
226
+ to {
227
+ opacity: 1;
228
+ }
229
+ }
230
+
231
+ /* 深色模式适配 */
232
+ .dark-mode.prism-index-bar {
233
+ .prism-index-item {
234
+ border-color: rgba(0, 0, 0, 0.5);
235
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.4);
236
+
237
+ &.active {
238
+ border-color: rgba(255, 255, 255, 0.9);
239
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.6);
240
+ }
241
+ }
242
+ }
243
+ </style>