v-uni-app-ui 1.0.2 → 1.0.6

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 (65) hide show
  1. package/README.md +127 -0
  2. package/dist/v-uni-app-ui.css +1 -0
  3. package/dist/v-uni-app-ui.es.js +6569 -0
  4. package/dist/v-uni-app-ui.umd.js +7 -0
  5. package/package.json +28 -8
  6. package/components/config.js +0 -123
  7. package/components/layout/v-card/v-card.vue +0 -108
  8. package/components/layout/v-grid/v-grid.vue +0 -162
  9. package/components/layout/v-icon-grid/v-icon-grid.vue +0 -195
  10. package/components/layout/v-infinite-scroll/v-infinite-scroll.vue +0 -172
  11. package/components/layout/v-list/v-list.vue +0 -43
  12. package/components/layout/v-row/v-row.vue +0 -142
  13. package/components/layout/v-waterfall/v-waterfall.vue +0 -79
  14. package/components/model/compound/v-checkbox-group/v-checkbox-group.vue +0 -96
  15. package/components/model/compound/v-console/v-console.js +0 -20
  16. package/components/model/compound/v-console/v-console.vue +0 -299
  17. package/components/model/compound/v-date-time/v-date-time.vue +0 -261
  18. package/components/model/compound/v-dialog/v-dialog.vue +0 -178
  19. package/components/model/compound/v-drum-select-picker/v-drum-select-picker.vue +0 -83
  20. package/components/model/compound/v-form/v-form.vue +0 -226
  21. package/components/model/compound/v-form-item/v-form-item.vue +0 -255
  22. package/components/model/compound/v-image/v-image.vue +0 -357
  23. package/components/model/compound/v-input-desensitize/v-input-desensitize.vue +0 -101
  24. package/components/model/compound/v-page/v-page.vue +0 -11
  25. package/components/model/compound/v-pages/v-pages.vue +0 -141
  26. package/components/model/compound/v-picker-list/v-picker-list.vue +0 -109
  27. package/components/model/compound/v-popup/v-popup.vue +0 -151
  28. package/components/model/compound/v-radio-group/v-radio-group.vue +0 -86
  29. package/components/model/compound/v-select-picker/v-select-picker.vue +0 -202
  30. package/components/model/compound/v-series-picker-list/v-series-picker-list.vue +0 -221
  31. package/components/model/compound/v-series-select-picker/v-series-select-picker.vue +0 -203
  32. package/components/model/compound/v-switch/v-switch.vue +0 -136
  33. package/components/model/compound/v-tabs-page/v-tabs-page.vue +0 -138
  34. package/components/model/native/v-badge/v-badge.vue +0 -143
  35. package/components/model/native/v-button/v-button.vue +0 -273
  36. package/components/model/native/v-carousel/v-carousel.vue +0 -138
  37. package/components/model/native/v-checkbox/v-checkbox.vue +0 -215
  38. package/components/model/native/v-collapse/v-collapse.vue +0 -190
  39. package/components/model/native/v-header-navigation-bar/v-header-navigation-bar.vue +0 -92
  40. package/components/model/native/v-input/v-input.vue +0 -352
  41. package/components/model/native/v-input-code/v-input-code.vue +0 -146
  42. package/components/model/native/v-loading/v-loading.vue +0 -206
  43. package/components/model/native/v-menu/v-menu.vue +0 -222
  44. package/components/model/native/v-menu-slide/v-menu-slide.vue +0 -364
  45. package/components/model/native/v-min-loading/v-min-loading.vue +0 -80
  46. package/components/model/native/v-null/v-null.vue +0 -97
  47. package/components/model/native/v-overlay/v-overlay.vue +0 -96
  48. package/components/model/native/v-pull-up-refresh/v-pull-up-refresh.vue +0 -157
  49. package/components/model/native/v-radio/v-radio.vue +0 -138
  50. package/components/model/native/v-scroll-list/v-scroll-list.vue +0 -169
  51. package/components/model/native/v-steps/v-steps.vue +0 -253
  52. package/components/model/native/v-table/v-table.vue +0 -203
  53. package/components/model/native/v-tabs/v-tabs.vue +0 -235
  54. package/components/model/native/v-tag/v-tag.vue +0 -206
  55. package/components/model/native/v-text/v-text.vue +0 -187
  56. package/components/model/native/v-text-button/v-text-button.vue +0 -139
  57. package/components/model/native/v-textarea/v-textarea.vue +0 -178
  58. package/components/model/native/v-title/v-title.vue +0 -91
  59. package/components/model/native/v-toast/info.png +0 -0
  60. package/components/model/native/v-toast/success.png +0 -0
  61. package/components/model/native/v-toast/v-toast.vue +0 -198
  62. package/components/model/native/v-toast/warn.png +0 -0
  63. package/components/model/native/v-upload-file-button/v-upload-file-button.vue +0 -296
  64. package/components/model/native/v-video/v-video.vue +0 -175
  65. package/components/model/native/v-window/v-window.vue +0 -158
@@ -1,108 +0,0 @@
1
- <template>
2
- <view class="v-card" :class="{ 'v-card-elevated': elevated }" :style="{ width, padding, borderRadius }">
3
- <view class="v-card-header" v-if="title || $slots.header">
4
- <slot name="header">
5
- <text class="v-card-title">{{ title }}</text>
6
- </slot>
7
- </view>
8
- <view class="v-card-content">
9
- <slot>
10
- <text v-if="content">{{ content }}</text>
11
- </slot>
12
- </view>
13
- <view class="v-card-actions" v-if="$slots.actions">
14
- <slot name="actions"></slot>
15
- </view>
16
- </view>
17
- </template>
18
-
19
- <script lang="ts" setup>
20
- import { computed,inject } from 'vue';
21
-
22
- interface CardItem {
23
- title?: string;
24
- content?: string;
25
- actions?: any;
26
- }
27
-
28
- /**
29
- * v-card
30
- * title 卡片标题
31
- * content 卡片内容
32
- * width 卡片宽度,默认为100%
33
- * padding 内边距,默认为none
34
- * borderRadius 圆角大小,默认为8px
35
- * elevated 是否启用阴影效果,默认为false
36
- */
37
- const props = defineProps({
38
- title: {
39
- type: String,
40
- default: ''
41
- },
42
- content: {
43
- type: String,
44
- default: ''
45
- },
46
- width: {
47
- type: String,
48
- default: '100%'
49
- },
50
- padding: {
51
- type: String,
52
- default: 'none'
53
- },
54
- borderRadius: {
55
- type: String,
56
- default: '8px'
57
- },
58
- elevated: {
59
- type: Boolean,
60
- default: false
61
- }
62
- });
63
-
64
- const config = inject<any>('config');
65
- // 计算样式
66
- const style = computed(() => ({
67
- width: props.width,
68
- padding: props.padding,
69
- borderRadius: props.borderRadius
70
- }));
71
- </script>
72
-
73
- <style lang="scss" scoped>
74
- .v-card {
75
- background-color: v-bind('config.backgroundColor.reversal');
76
- border: 1rpx solid v-bind('config.border.color');
77
- box-sizing: border-box;
78
- overflow: hidden;
79
- transition: box-shadow 0.3s ease;
80
-
81
- &-elevated {
82
- box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
83
- }
84
-
85
- &-header {
86
- padding: 16rpx;
87
- border-bottom: 1rpx solid v-bind('config.border.color');
88
- }
89
-
90
- &-title {
91
- font-size: v-bind('config.fontSize.mediumText');
92
- font-weight: bold;
93
- color: v-bind('config.fontColor.mainText');
94
- }
95
-
96
- &-content {
97
- padding: 16rpx;
98
- color: v-bind('config.fontColor.subTitle');
99
- }
100
-
101
- &-actions {
102
- padding: 16rpx;
103
- border-top: 1rpx solid v-bind('config.border.color');
104
- display: flex;
105
- justify-content: flex-end;
106
- }
107
- }
108
- </style>
@@ -1,162 +0,0 @@
1
- <template>
2
- <view class="v-grid" :style="gridStyle">
3
- <view v-for="(item, index) in items" :key="index" class="grid-item" :style="itemStyle" @click="handleItemClick(item)">
4
- <slot name="item" :item="item" :index="index">
5
- <view class="default-item">
6
- <view class="image-container" v-if="item.image">
7
- <img :src="item.image" :mode="imageMode" :lazy-load="lazyLoad" @error="handleImageError(item)" class="grid-image" :style="imageStyle" />
8
- <view v-if="item.loading">
9
- <slot name="loading">
10
-
11
- </slot>
12
- </view>
13
- </view>
14
- <view class="content">
15
- <slot name="content" :item="item" :index="index"></slot>
16
- </view>
17
- </view>
18
- </slot>
19
- </view>
20
- </view>
21
- </template>
22
-
23
- <script lang="ts" setup>
24
- import { computed, ref,inject } from 'vue';
25
-
26
- interface GridItem {
27
- id?: string | number;
28
- image?: string;
29
- title: string;
30
- desc?: string;
31
- price?: number;
32
- loading?: boolean;
33
- [key: string]: any;
34
- }
35
-
36
- /**
37
- * v-grid
38
- * items 数据
39
- * cols 列数 (支持响应式对象)
40
- * gap 间距 rpx
41
- * imageMode 图片模式
42
- * lazyLoad 是否懒加载
43
- * imageHeight 图片高度 rpx
44
- */
45
- const props = defineProps({
46
- items: {
47
- type: Array as () => GridItem[],
48
- default: () => []
49
- },
50
- cols: {
51
- type: [Number, Object],
52
- default: 3
53
- },
54
- gap: {
55
- type: [Number, String],
56
- default: 20
57
- },
58
- imageMode: {
59
- type: String,
60
- default: 'aspectFill'
61
- },
62
- lazyLoad: Boolean,
63
- imageHeight: {
64
- type: [Number, String],
65
- default: 300
66
- }
67
- });
68
-
69
- const emit = defineEmits(['item-click', 'image-error']);
70
-
71
- const config = inject<any>('config');
72
- const currentCols = ref(3);
73
- const updateColumns = () => {
74
- const screenWidth = uni.getSystemInfoSync().screenWidth;
75
- if (typeof props.cols === 'object') {
76
- currentCols.value =
77
- screenWidth >= 1200
78
- ? props.cols.xl || 4
79
- : screenWidth >= 992
80
- ? props.cols.lg || 3
81
- : screenWidth >= 768
82
- ? props.cols.md || 2
83
- : screenWidth >= 576
84
- ? props.cols.sm || 2
85
- : props.cols.xs || 1;
86
- } else {
87
- currentCols.value = props.cols;
88
- }
89
- };
90
-
91
- updateColumns();
92
- uni.onWindowResize(() => updateColumns());
93
-
94
- const gridStyle = computed(() => {
95
- const gap = uni.upx2px(Number(props.gap));
96
- return {
97
- marginLeft: `-${gap / 2}px`,
98
- marginRight: `-${gap / 2}px`
99
- };
100
- });
101
-
102
- const itemStyle = computed(() => {
103
- const gap = uni.upx2px(Number(props.gap));
104
- const width = `calc(${100 / currentCols.value}% - ${gap}px)`;
105
- return {
106
- width,
107
- marginLeft: `${gap / 2}px`,
108
- marginRight: `${gap / 2}px`,
109
- marginBottom: `${gap}px`
110
- };
111
- });
112
-
113
- const imageStyle = computed(() => ({
114
- height: uni.upx2px(Number(props.imageHeight)) + 'px'
115
- }));
116
-
117
-
118
- const handleItemClick = (item: GridItem) => {
119
- emit('item-click', item);
120
- };
121
-
122
- const handleImageError = (item: GridItem) => {
123
- emit('image-error', item);
124
- item.loading = false;
125
- };
126
- </script>
127
-
128
- <style lang="scss" scoped>
129
- .v-grid {
130
- display: flex;
131
- flex-wrap: wrap;
132
- box-sizing: border-box;
133
-
134
- .grid-item {
135
- box-sizing: border-box;
136
- background: v-bind("config.backgroundColor.reversal");
137
- border-radius: 8rpx;
138
- overflow: hidden;
139
- transition: all 0.3s ease;
140
-
141
- &:active {
142
- transform: scale(0.98);
143
- }
144
-
145
- .default-item {
146
- .image-container {
147
- position: relative;
148
- background-color: v-bind("config.VGrid.backgroundColor");
149
-
150
- .grid-image {
151
- width: 100%;
152
- display: block;
153
- }
154
- }
155
-
156
- .content {
157
- padding: 20rpx;
158
- }
159
- }
160
- }
161
- }
162
- </style>
@@ -1,195 +0,0 @@
1
- <template>
2
- <view class="v-icon-grid">
3
- <scroll-view class="scroll-container" :scroll-x="scrollable" :show-scrollbar="false" :scroll-with-animation="true">
4
- <view class="icon-grid" :style="{ 'grid-template-columns': `repeat(${columns}, 1fr)` }">
5
- <view
6
- v-for="(icon, index) in icons"
7
- :key="index"
8
- class="icon-item"
9
- :class="{ 'icon-item-active': activeIndex === index }"
10
- @click="handleIconClick(index)"
11
- :style="{
12
- width: typeof itemWidth === 'string' ? itemWidth : `${itemWidth}px`,
13
- margin: typeof gutter === 'string' ? `calc(${gutter} / 2)` : `${gutter / 2}px`
14
- }"
15
- >
16
- <view class="icon-wrapper">
17
- <view class="icon" :style="{ 'font-size': fontSize }">
18
- <text v-if="useIcon" :class="icon.icon"></text>
19
- <v-image v-else :src="icon.image" :style="{ width: iconSize, height: iconSize }" />
20
- </view>
21
- </view>
22
- <view
23
- class="icon-text"
24
- :style="{
25
- color: textColor,
26
- ...textStyle
27
- }"
28
- >
29
- {{ icon.title }}
30
- </view>
31
- </view>
32
- </view>
33
- </scroll-view>
34
- </view>
35
- </template>
36
-
37
- <script lang="ts" setup>
38
- import { ref, computed, inject } from 'vue';
39
-
40
- interface IconItem {
41
- title: string;
42
- icon?: string;
43
- image?: string;
44
- }
45
- /**
46
- * v-icon-grid 图标排版
47
- * icons : 图标数组 title标题 icon图标类名 image图片路径
48
- * iconSize 图标大小
49
- * textColor 文本颜色
50
- * activeColor 活动图标颜色
51
- * itemWidth 每个图标项的宽度
52
- * gutter 图标项之间的间距
53
- * scrollable 是否可滚动 默认值:true滚动 可选值:true滚动 false不滚动
54
- * useIcon 图标还是图片 默认值:true图标 可选值:true图标 false图片
55
- * rows 图片排数 默认值:1
56
- */
57
- const props = defineProps({
58
- icons: {
59
- type: Array as () => IconItem[],
60
- default: () => []
61
- },
62
- iconSize: {
63
- type: String,
64
- default: '50rpx'
65
- },
66
- fontSize: {
67
- type: String,
68
- default: '25rpx'
69
- },
70
- textColor: {
71
- type: String,
72
- default: '#333333'
73
- },
74
- activeColor: {
75
- type: String,
76
- default: 'transparent'
77
- },
78
- itemWidth: {
79
- type: [Number, String],
80
- default: 80
81
- },
82
- gutter: {
83
- type: [Number, String],
84
- default: 10
85
- },
86
- scrollable: {
87
- type: Boolean,
88
- default: true
89
- },
90
- useIcon: {
91
- type: Boolean,
92
- default: true
93
- },
94
- rows: {
95
- type: Number,
96
- default: 1
97
- },
98
- iconTextModel: {
99
- type: String as () => 'normal' | 'wrap' | 'ellipsis',
100
- default: 'normal'
101
- }
102
- });
103
-
104
- const emits = defineEmits(['select']);
105
- const config = inject<any>('config');
106
-
107
- const activeIndex = ref(0);
108
- const columns = computed(() => {
109
- const totalIcons = props.icons.length;
110
- const maxIconsPerRow = Math.ceil(totalIcons / props.rows);
111
- return maxIconsPerRow;
112
- });
113
- const textStyle = computed(() => {
114
- switch (props.iconTextModel) {
115
- case 'wrap':
116
- return {
117
- whiteSpace: 'normal',
118
- overflow: 'visible',
119
- textOverflow: 'clip'
120
- };
121
- case 'ellipsis':
122
- return {
123
- whiteSpace: 'nowrap',
124
- overflow: 'hidden',
125
- textOverflow: 'ellipsis'
126
- };
127
- default: // normal
128
- return {
129
- whiteSpace: 'normal',
130
- overflow: 'visible',
131
- textOverflow: 'clip'
132
- };
133
- }
134
- });
135
-
136
- const handleIconClick = (index: number) => {
137
- activeIndex.value = index;
138
- emits('select', index, props.icons[index]);
139
- };
140
- </script>
141
-
142
- <style lang="scss" scoped>
143
- .v-icon-grid {
144
- width: 100%;
145
- position: relative;
146
- }
147
-
148
- .scroll-container {
149
- width: 100%;
150
- white-space: nowrap;
151
- overflow: hidden;
152
- flex: 1;
153
- }
154
-
155
- .icon-grid {
156
- display: grid;
157
- gap: 10rpx;
158
- }
159
-
160
- .icon-item {
161
- display: flex;
162
- flex-direction: column;
163
- align-items: center;
164
- justify-content: center;
165
- border-radius: 10rpx;
166
- transition: all 0.3s ease;
167
- box-sizing: border-box;
168
- }
169
-
170
- .icon-item-active {
171
- background-color: v-bind('props.activeColor');
172
- }
173
-
174
- .icon-wrapper {
175
- display: flex;
176
- justify-content: center;
177
- align-items: center;
178
- width: v-bind('props.iconSize');
179
- height: v-bind('props.iconSize');
180
- margin-bottom: 5rpx;
181
- }
182
-
183
- .icon {
184
- display: flex;
185
- justify-content: center;
186
- align-items: center;
187
- width: 100%;
188
- height: 100%;
189
- }
190
-
191
- .icon-text {
192
- font-size: v-bind('config.fontSize.mediumText');
193
- text-align: center;
194
- }
195
- </style>
@@ -1,172 +0,0 @@
1
- <template>
2
- <scroll-view
3
- class="infinite-scroll-container"
4
- :scroll-y="true"
5
- :style="containerStyle"
6
- @scroll="handleScroll"
7
- :scroll-with-animation="false"
8
- @scrolltolower="handleScrollToLower"
9
- >
10
- <slot />
11
- <!-- 加载状态提示 -->
12
- <template v-if="$slots.loading">
13
- <slot name="loading" />
14
- </template>
15
- <template v-else-if="loading">
16
- <view class="status-text">加载中...</view>
17
- </template>
18
- <template v-if="$slots.null">
19
- <slot name="null" />
20
- </template>
21
- <template v-else-if="noMore">
22
- <view class="status-text">没有更多了</view>
23
- </template>
24
- </scroll-view>
25
- </template>
26
-
27
- <script lang="ts" setup>
28
- import { ref, onMounted, onUnmounted, nextTick,inject } from 'vue';
29
-
30
- const props = defineProps({
31
- load: {
32
- type: Function,
33
- required: true
34
- },
35
- disabled: {
36
- type: Boolean,
37
- default: false
38
- },
39
- immediate: {
40
- type: Boolean,
41
- default: true
42
- },
43
- distance: {
44
- type: Number,
45
- default: 200
46
- },
47
- throttle: {
48
- type: Number,
49
- default: 200
50
- },
51
- containerStyle: {
52
- type: Object,
53
- default: () => ({})
54
- },
55
- noMore: {
56
- type: Boolean,
57
- default: false
58
- },
59
- timeout: {
60
- type: Number,
61
- default: 5000
62
- }
63
- });
64
-
65
- const config = inject('config');
66
- const loading = ref(false);
67
- const lastCall = ref(0);
68
- const isFirstLoad = ref(true);
69
- const lastScrollHeight = ref(0);
70
- let timeoutId: NodeJS.Timeout | null = null;
71
-
72
- // 节流函数
73
- const throttle = (fn: Function, delay: number) => {
74
- let lastTime = 0;
75
- return function (this: any, ...args: any[]) {
76
- const now = Date.now();
77
- if (now - lastTime >= delay) {
78
- fn.apply(this, args);
79
- lastTime = now;
80
- }
81
- };
82
- };
83
-
84
- // 处理滚动事件
85
- const handleScroll = throttle((event: any) => {
86
- const { scrollTop, scrollHeight } = event.detail;
87
- lastScrollHeight.value = scrollHeight;
88
-
89
- // 只有当内容高度变化时才处理
90
- if (scrollHeight !== lastScrollHeight.value) {
91
- checkLoadMore(scrollTop, scrollHeight);
92
- }
93
- }, props.throttle);
94
-
95
- // 处理滚动到底部事件(作为兜底)
96
- const handleScrollToLower = () => {
97
- if (!loading.value && !props.noMore && !props.disabled) {
98
- loadMore();
99
- }
100
- };
101
-
102
- // 检查是否需要加载更多
103
- const checkLoadMore = (scrollTop: number, scrollHeight: number) => {
104
- const now = Date.now();
105
- if (now - lastCall.value < props.throttle) return;
106
- lastCall.value = now;
107
-
108
- // 计算距离底部的距离
109
- const triggerPosition = scrollTop + props.distance >= scrollHeight - props.distance;
110
-
111
- if (triggerPosition) {
112
- loadMore();
113
- }
114
- };
115
-
116
- // 加载更多数据
117
- const loadMore = async () => {
118
- if (props.disabled || loading.value || props.noMore) return;
119
-
120
- loading.value = true;
121
-
122
- try {
123
- await props.load();
124
- // 等待DOM更新
125
- await nextTick();
126
- } catch (e) {
127
- console.error('加载失败:', e);
128
- } finally {
129
- loading.value = false;
130
- isFirstLoad.value = false;
131
- }
132
- };
133
-
134
- // 初始化检查
135
- const checkInitialLoad = () => {
136
- // 不使用节点查询,改为延迟执行首次加载
137
- if (props.immediate && isFirstLoad.value) {
138
- setTimeout(() => {
139
- loadMore();
140
- }, 100);
141
- }
142
- };
143
-
144
- onMounted(() => {
145
- checkInitialLoad();
146
- });
147
-
148
- onUnmounted(() => {
149
- if (timeoutId) {
150
- clearTimeout(timeoutId);
151
- }
152
- });
153
- </script>
154
-
155
- <style lang="scss">
156
- .infinite-scroll-container {
157
- box-sizing: border-box;
158
- height: 100%;
159
- position: relative;
160
-
161
- .status-text {
162
- padding: 20rpx;
163
- text-align: center;
164
- color: v-bind('config.fontColor.mainText');
165
- font-size: v-bind('config.fontSize.mediumText');
166
-
167
- &:last-child {
168
- padding-bottom: 40rpx;
169
- }
170
- }
171
- }
172
- </style>
@@ -1,43 +0,0 @@
1
- <template>
2
- <view :class="['v-list', `v-list--border-${borderMode}`]">
3
- <slot></slot>
4
- </view>
5
- </template>
6
-
7
- <script setup lang="ts">
8
- import { computed,inject } from 'vue';
9
-
10
- const props = defineProps({
11
- borderMode: {
12
- type: String,
13
- default: 'all',
14
- validator: (value: any) => {
15
- return ['all', 'none', 'item'].includes(value);
16
- }
17
- }
18
- });
19
-
20
- const config = inject<any>('config');
21
- </script>
22
-
23
- <style lang="scss" scoped>
24
- .v-list {
25
- width: 100%;
26
- background-color: v-bind("config.backgroundColor.reversal");
27
-
28
- &--border-all {
29
- border: 1rpx solid v-bind("config.border.color");
30
- border-radius: 4rpx;
31
- }
32
-
33
- &--border-none {
34
- border: none;
35
- }
36
-
37
- &--border-item {
38
- ::v-deep .v-list-item:not(:last-child) {
39
- border-bottom: 1px solid v-bind("config.border.color");
40
- }
41
- }
42
- }
43
- </style>