stellar-ui-plus 1.22.26 → 1.22.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/ste-calendar/ATTRIBUTES.md +1 -0
- package/components/ste-calendar/props.ts +28 -27
- package/components/ste-calendar/ste-calendar.easycom.json +8 -1
- package/components/ste-calendar/ste-calendar.vue +9 -2
- package/components/ste-checkbox/README.md +2 -0
- package/components/ste-checkbox/ste-checkbox.vue +121 -125
- package/components/ste-checkbox-group/ste-checkbox-group.vue +18 -5
- package/components/ste-input/README.md +40 -7
- package/components/ste-input/ste-input.scss +2 -1
- package/components/ste-input/ste-input.vue +2 -0
- package/components/ste-login-info/props.ts +4 -0
- package/components/ste-login-info/ste-login-info.vue +3 -5
- package/components/ste-notice-bar/ste-notice-bar.vue +1 -0
- package/components/ste-radio/README.md +2 -56
- package/components/ste-step/ste-step.scss +5 -1
- package/components/ste-step/ste-step.vue +12 -13
- package/components/ste-steps/ATTRIBUTES.md +2 -1
- package/components/ste-steps/props.ts +13 -12
- package/components/ste-steps/ste-steps.easycom.json +9 -1
- package/components/ste-swiper-item/ste-swiper-item.vue +12 -1
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
| `monthCount` | 渲染的月份个数 | `number` | `12` | - | - |
|
|
26
26
|
| `weekendColor` | 周末颜色,默认跟随主题色 | `string` | `` | - | - |
|
|
27
27
|
| `signs` | 日历标签 | `{[key:string]:SignType}` | `{}` | - | - |
|
|
28
|
+
| `showScrollbar` | 是否显示滚动条 | `boolean` | `true` | - | `1.22.27` |
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
#### Events
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
import type { PropType } from 'vue'
|
|
2
|
-
import type { DateType, SignType } from './date'
|
|
1
|
+
import type { PropType } from 'vue';
|
|
2
|
+
import type { DateType, SignType } from './date';
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
5
|
+
title: { type: String, default: () => '日期选择' },
|
|
6
|
+
showTitle: { type: Boolean, default: () => true },
|
|
7
|
+
list: { type: Array as PropType<DateType[]>, default: () => [] },
|
|
8
|
+
mode: { type: String, default: () => 'single' },
|
|
9
|
+
startText: { type: String, default: () => '开始' },
|
|
10
|
+
endText: { type: String, default: () => '结束' },
|
|
11
|
+
color: { type: String, default: () => '' },
|
|
12
|
+
minDate: { type: [String, Number, Date], default: () => 0 },
|
|
13
|
+
maxDate: { type: [String, Number, Date], default: () => 0 },
|
|
14
|
+
maxCount: { type: [Number, String], default: () => 0 },
|
|
15
|
+
formatter: { type: String, default: () => 'YYYY-MM-DD' },
|
|
16
|
+
showMark: { type: Boolean, default: () => true },
|
|
17
|
+
readonly: { type: Boolean, default: () => false },
|
|
18
|
+
maxRange: { type: Number, default: () => null },
|
|
19
|
+
rangePrompt: { type: String, default: () => null },
|
|
20
|
+
showRangePrompt: { type: Boolean, default: () => true },
|
|
21
|
+
allowSameDay: { type: Boolean, default: () => false },
|
|
22
|
+
showConfirm: { type: Boolean, default: () => true },
|
|
23
|
+
width: { type: [Number, String], default: () => '100%' },
|
|
24
|
+
height: { type: [Number, String], default: () => '100%' },
|
|
25
|
+
signs: { type: Object as PropType<{ [key: string]: SignType }>, default: () => ({}) },
|
|
26
|
+
defaultDate: { type: [String, Number, Date], default: () => 0 },
|
|
27
|
+
monthCount: { type: Number, default: () => 12 },
|
|
28
|
+
weekendColor: { type: String, default: () => '' },
|
|
29
|
+
showScrollbar: { type: Boolean, default: () => true },
|
|
30
|
+
};
|
|
@@ -160,6 +160,13 @@
|
|
|
160
160
|
"type": "{[key:string]:SignType}",
|
|
161
161
|
"default": "{}"
|
|
162
162
|
},
|
|
163
|
+
{
|
|
164
|
+
"name": "showScrollbar",
|
|
165
|
+
"description": "是否显示滚动条",
|
|
166
|
+
"type": "boolean",
|
|
167
|
+
"default": "true",
|
|
168
|
+
"version": "1.22.27"
|
|
169
|
+
},
|
|
163
170
|
{
|
|
164
171
|
"name": "[event]select",
|
|
165
172
|
"description": "选择日期时触发",
|
|
@@ -198,4 +205,4 @@
|
|
|
198
205
|
]
|
|
199
206
|
}
|
|
200
207
|
]
|
|
201
|
-
}
|
|
208
|
+
}
|
|
@@ -215,7 +215,15 @@ const onScroll = (e: any) => {
|
|
|
215
215
|
</view>
|
|
216
216
|
</view>
|
|
217
217
|
</view>
|
|
218
|
-
<scroll-view
|
|
218
|
+
<scroll-view
|
|
219
|
+
class="date-content"
|
|
220
|
+
:class="{ 'show-confirm': cmpShowConfirm, 'show-title': showTitle }"
|
|
221
|
+
scroll-y
|
|
222
|
+
:scroll-top="contentScrollTop"
|
|
223
|
+
@scroll="onScroll"
|
|
224
|
+
:show-scrollbar="showScrollbar"
|
|
225
|
+
enhanced
|
|
226
|
+
>
|
|
219
227
|
<view class="month-item" v-for="m in cmpDates.monthDatas" :key="m.key" :id="`month-${m.key}`">
|
|
220
228
|
<view class="month-bg" v-if="showMark">
|
|
221
229
|
{{ m.month }}
|
|
@@ -304,7 +312,6 @@ const onScroll = (e: any) => {
|
|
|
304
312
|
|
|
305
313
|
.date-content {
|
|
306
314
|
width: 100%;
|
|
307
|
-
overflow-y: auto;
|
|
308
315
|
height: calc(100% - var(--font-size-80, 80rpx));
|
|
309
316
|
padding-bottom: 12rpx;
|
|
310
317
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { useSlots, computed, ref, nextTick,
|
|
2
|
+
import { useSlots, computed, ref, nextTick, onMounted, onUnmounted, type CSSProperties } from 'vue';
|
|
3
3
|
import { useColorStore } from '../../store/color';
|
|
4
4
|
let { getColor } = useColorStore();
|
|
5
5
|
import utils from '../../utils/utils';
|
|
@@ -19,147 +19,150 @@ const props = defineProps(propsData);
|
|
|
19
19
|
const emits = defineEmits<CheckboxEmits>();
|
|
20
20
|
const slots = useSlots();
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const Parent = useInject<{ props: Required<CheckboxGroupProps>; updateValue: (value: any[]) => void }>(CHECKBOX_KEY);
|
|
22
|
+
const Parent = useInject<{
|
|
23
|
+
props: Required<CheckboxGroupProps>;
|
|
24
|
+
updateValue: (value: any[]) => void;
|
|
25
|
+
registerChild: () => number;
|
|
26
|
+
unregisterChild: () => void;
|
|
27
|
+
}>(CHECKBOX_KEY);
|
|
29
28
|
const parentProps = computed(() => Parent?.parent?.props);
|
|
30
29
|
|
|
31
|
-
//
|
|
32
|
-
const
|
|
33
|
-
const cmpShape = computed(() => getDefaultData('shape', 'circle'));
|
|
34
|
-
const cmpIconSize = computed(() => getDefaultData('iconSize', 36));
|
|
35
|
-
const cmpCheckedColor = computed(() => getDefaultData('checkedColor', getColor().steThemeColor));
|
|
36
|
-
const cmpTextPosition = computed(() => getDefaultData('textPosition', 'right'));
|
|
37
|
-
const cmpTextSize = computed(() => getDefaultData('textSize', 28));
|
|
38
|
-
const cmpTextInactiveColor = computed(() => getDefaultData('textInactiveColor', '#000000'));
|
|
39
|
-
const cmpTextActiveColor = computed(() => getDefaultData('textActiveColor', '#000000'));
|
|
40
|
-
const cmpTextDisabled = computed(() => getDefaultData('textDisabled', false));
|
|
41
|
-
const cmpMarginLeft = computed(() => getDefaultData('marginLeft', '0'));
|
|
42
|
-
const cmpMarginRight = computed(() => getDefaultData('marginRight', '0'));
|
|
43
|
-
const cmpColumnGap = computed(() => getDefaultData('columnGap', '16'));
|
|
30
|
+
// 记录当前组件在 group 中的索引
|
|
31
|
+
const childIndex = ref<number>(-1);
|
|
44
32
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
})
|
|
33
|
+
onMounted(() => {
|
|
34
|
+
if (Parent?.parent?.registerChild) {
|
|
35
|
+
childIndex.value = Parent.parent.registerChild();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
50
38
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}));
|
|
39
|
+
onUnmounted(() => {
|
|
40
|
+
if (Parent?.parent?.unregisterChild) {
|
|
41
|
+
Parent.parent.unregisterChild();
|
|
42
|
+
}
|
|
43
|
+
});
|
|
57
44
|
|
|
58
|
-
//
|
|
59
|
-
const
|
|
60
|
-
color: cmpChecked.value ? cmpTextActiveColor.value : cmpTextInactiveColor.value,
|
|
61
|
-
flexDirection: cmpTextPosition.value == 'right' ? 'row' : 'row-reverse',
|
|
62
|
-
}));
|
|
45
|
+
// 🚀 优化: 缓存 themeColor,避免每次调用 getColor()
|
|
46
|
+
const themeColor = getColor().steThemeColor;
|
|
63
47
|
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
const style: CSSProperties = {};
|
|
48
|
+
// 强制更新选中状态
|
|
49
|
+
let num = ref(1);
|
|
67
50
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
} else {
|
|
74
|
-
style['cursor'] = 'pointer';
|
|
75
|
-
}
|
|
76
|
-
// #endif
|
|
51
|
+
// 🚀 优化: 只保留必要的 computed
|
|
52
|
+
const cmpChecked = computed(() => {
|
|
53
|
+
let v = num.value && parentProps.value ? parentProps.value.modelValue.includes(props.name) : props.modelValue;
|
|
54
|
+
return v;
|
|
55
|
+
});
|
|
77
56
|
|
|
78
|
-
|
|
79
|
-
|
|
57
|
+
const cmpDisabled = computed(() => {
|
|
58
|
+
let disabled = getDefaultData('disabled', false);
|
|
59
|
+
// 限制最大可选数
|
|
60
|
+
if (parentProps.value && parentProps.value.max) {
|
|
61
|
+
if (!cmpChecked.value && parentProps.value.modelValue.length >= parentProps.value.max) {
|
|
62
|
+
disabled = true;
|
|
63
|
+
}
|
|
80
64
|
}
|
|
81
|
-
|
|
82
|
-
return style;
|
|
65
|
+
return disabled;
|
|
83
66
|
});
|
|
84
67
|
|
|
85
|
-
//
|
|
86
|
-
const cmpRootStyle = computed(() =>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// 图标样式(相对简单,保持原样)
|
|
93
|
-
const cmpIconStyle = computed(() => ({
|
|
94
|
-
marginRight: utils.formatPx(cmpColumnGap.value),
|
|
95
|
-
}));
|
|
68
|
+
// 🚀 优化: 合并所有样式计算,直接调用 getDefaultData
|
|
69
|
+
const cmpRootStyle = computed(() => {
|
|
70
|
+
const textSize = getDefaultData('textSize', 28);
|
|
71
|
+
const textPosition = getDefaultData('textPosition', 'right');
|
|
72
|
+
const readonly = getDefaultData('readonly', false);
|
|
73
|
+
const textDisabled = getDefaultData('textDisabled', false);
|
|
96
74
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
borderRadius: cmpShape.value == 'circle' ? '50%' : '0',
|
|
100
|
-
width: `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`,
|
|
101
|
-
height: `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`,
|
|
102
|
-
lineHeight: `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`,
|
|
103
|
-
columnGap: slots.default ? undefined : 0,
|
|
104
|
-
}));
|
|
75
|
+
let marginLeft = getDefaultData('marginLeft', '0');
|
|
76
|
+
let marginRight = getDefaultData('marginRight', '0');
|
|
105
77
|
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
background: cmpChecked.value ? cmpCheckedColor.value : '#FFFFFF',
|
|
110
|
-
}));
|
|
78
|
+
// 如果在 checkbox-group 中,并且不是第一个元素,自动应用间距
|
|
79
|
+
if (parentProps.value && childIndex.value > 0 && marginLeft === '0') {
|
|
80
|
+
const direction = parentProps.value.direction || 'column';
|
|
111
81
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
82
|
+
if (direction === 'row') {
|
|
83
|
+
// 横向排列时,设置左间距 16rpx
|
|
84
|
+
marginLeft = '16';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
115
87
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
88
|
+
const style: CSSProperties = {
|
|
89
|
+
fontSize: `var(--font-size-${textSize},${utils.formatPx(textSize)})`,
|
|
90
|
+
color: cmpChecked.value ? getDefaultData('textActiveColor', '#000000') : getDefaultData('textInactiveColor', '#000000'),
|
|
91
|
+
flexDirection: textPosition === 'right' ? 'row' : 'row-reverse',
|
|
92
|
+
marginLeft: utils.formatPx(marginLeft),
|
|
93
|
+
marginRight: utils.formatPx(marginRight),
|
|
119
94
|
};
|
|
120
|
-
});
|
|
121
95
|
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
96
|
+
// 纵向排列时,设置上间距 16rpx
|
|
97
|
+
if (parentProps.value && childIndex.value > 0) {
|
|
98
|
+
const direction = parentProps.value.direction || 'column';
|
|
99
|
+
if (direction === 'column') {
|
|
100
|
+
style.marginTop = '16rpx';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
125
103
|
|
|
126
104
|
// #ifdef H5
|
|
127
|
-
if (cmpDisabled.value ||
|
|
105
|
+
if (cmpDisabled.value || readonly) {
|
|
128
106
|
style['cursor'] = 'not-allowed';
|
|
107
|
+
} else if (textDisabled) {
|
|
108
|
+
style['cursor'] = 'default';
|
|
129
109
|
} else {
|
|
130
110
|
style['cursor'] = 'pointer';
|
|
131
111
|
}
|
|
132
112
|
// #endif
|
|
133
113
|
|
|
114
|
+
if (textDisabled) {
|
|
115
|
+
style['pointerEvents'] = 'none';
|
|
116
|
+
}
|
|
117
|
+
|
|
134
118
|
return style;
|
|
135
119
|
});
|
|
136
120
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
...disabledInputStyle.value,
|
|
142
|
-
...interactiveInputStyle.value,
|
|
143
|
-
}));
|
|
144
|
-
|
|
145
|
-
const cmpChecked = computed(() => {
|
|
146
|
-
let v = num.value && parentProps.value ? parentProps.value.modelValue.includes(props.name) : props.modelValue;
|
|
147
|
-
return v;
|
|
121
|
+
const cmpIconStyle = computed(() => {
|
|
122
|
+
return {
|
|
123
|
+
marginRight: utils.formatPx(getDefaultData('columnGap', '16')),
|
|
124
|
+
} as CSSProperties;
|
|
148
125
|
});
|
|
149
126
|
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
127
|
+
const cmpInputStyle = computed(() => {
|
|
128
|
+
const shape = getDefaultData('shape', 'circle');
|
|
129
|
+
const iconSize = getDefaultData('iconSize', 36);
|
|
130
|
+
const checkedColor = getDefaultData('checkedColor', themeColor);
|
|
131
|
+
const readonly = getDefaultData('readonly', false);
|
|
132
|
+
const checked = cmpChecked.value;
|
|
133
|
+
|
|
134
|
+
const style: CSSProperties = {
|
|
135
|
+
borderRadius: shape === 'circle' ? '50%' : '0',
|
|
136
|
+
border: `${utils.formatPx(2)} solid ${checked ? checkedColor : '#BBBBBB'}`,
|
|
137
|
+
background: checked ? checkedColor : '#FFFFFF',
|
|
138
|
+
width: `var(--font-size-${iconSize},${utils.formatPx(iconSize)})`,
|
|
139
|
+
height: `var(--font-size-${iconSize},${utils.formatPx(iconSize)})`,
|
|
140
|
+
lineHeight: `var(--font-size-${iconSize},${utils.formatPx(iconSize)})`,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// #ifdef H5
|
|
144
|
+
style['cursor'] = cmpDisabled.value || readonly ? 'not-allowed' : 'pointer';
|
|
145
|
+
// #endif
|
|
146
|
+
|
|
147
|
+
if (cmpDisabled.value) {
|
|
148
|
+
style['background'] = '#eeeeee';
|
|
149
|
+
style['borderColor'] = '#bbbbbb';
|
|
157
150
|
}
|
|
158
|
-
|
|
151
|
+
|
|
152
|
+
// 在没有使用插槽内容时去掉边距
|
|
153
|
+
if (!slots.default) {
|
|
154
|
+
style['columnGap'] = '0';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return style;
|
|
159
158
|
});
|
|
160
159
|
|
|
161
|
-
//
|
|
162
|
-
|
|
160
|
+
// 🚀 优化: slotProps 也直接计算
|
|
161
|
+
const cmpSlotProps = computed(() => ({
|
|
162
|
+
checked: cmpChecked.value,
|
|
163
|
+
disabled: cmpDisabled.value,
|
|
164
|
+
readonly: getDefaultData('readonly', false),
|
|
165
|
+
}));
|
|
163
166
|
|
|
164
167
|
// 批处理更新相关
|
|
165
168
|
const isBatchUpdating = ref(false);
|
|
@@ -195,7 +198,9 @@ const batchedUpdate = async (updateFn: () => Promise<void>) => {
|
|
|
195
198
|
|
|
196
199
|
// 实际的点击处理逻辑
|
|
197
200
|
const handleClick = async () => {
|
|
198
|
-
|
|
201
|
+
const readonly = getDefaultData('readonly', false);
|
|
202
|
+
|
|
203
|
+
if (cmpDisabled.value || readonly) {
|
|
199
204
|
return;
|
|
200
205
|
}
|
|
201
206
|
|
|
@@ -240,20 +245,11 @@ const click = () => {
|
|
|
240
245
|
batchedUpdate(handleClick);
|
|
241
246
|
};
|
|
242
247
|
|
|
243
|
-
type
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return props[key];
|
|
249
|
-
} else {
|
|
250
|
-
return value;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
} catch (e) {
|
|
254
|
-
return value;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
248
|
+
type PropsKeyType = keyof typeof props;
|
|
249
|
+
const getDefaultData = <T,>(key: PropsKeyType, defaultValue: T): T => {
|
|
250
|
+
const value = props[key];
|
|
251
|
+
return value !== undefined && value !== '' ? (value as T) : defaultValue;
|
|
252
|
+
};
|
|
257
253
|
</script>
|
|
258
254
|
|
|
259
255
|
<template>
|
|
@@ -261,7 +257,7 @@ function getDefaultData(key: PropsKeyTypee, value: any) {
|
|
|
261
257
|
<view class="icon" :style="[cmpIconStyle]">
|
|
262
258
|
<slot name="icon" :slotProps="cmpSlotProps">
|
|
263
259
|
<view class="input-icon" :style="[cmpInputStyle]">
|
|
264
|
-
<ste-icon v-if="cmpChecked
|
|
260
|
+
<ste-icon v-if="cmpChecked" :size="getDefaultData('iconSize', 36) * 0.8" code="" :color="cmpDisabled ? '#bbbbbb' : '#fff'" bold />
|
|
265
261
|
</view>
|
|
266
262
|
</slot>
|
|
267
263
|
</view>
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { computed, type CSSProperties } from 'vue';
|
|
2
|
+
import { computed, ref, type CSSProperties } from 'vue';
|
|
3
3
|
import propsData, { checkboxGroupEmits } from './props';
|
|
4
4
|
import { useProvide } from '../../utils/mixin';
|
|
5
5
|
import { CHECKBOX_KEY } from '../ste-checkbox/props';
|
|
6
6
|
const props = defineProps(propsData);
|
|
7
7
|
const emits = defineEmits(checkboxGroupEmits);
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const childrenCount = ref(0);
|
|
10
|
+
|
|
11
|
+
// 注册子组件,返回索引
|
|
12
|
+
function registerChild() {
|
|
13
|
+
const index = childrenCount.value;
|
|
14
|
+
childrenCount.value++;
|
|
15
|
+
return index;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 卸载时减少计数
|
|
19
|
+
function unregisterChild() {
|
|
20
|
+
childrenCount.value--;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
useProvide(CHECKBOX_KEY, 'ste-checkbox')({ props, updateValue, registerChild, unregisterChild });
|
|
10
24
|
|
|
11
25
|
const cmpRootStyle = computed(() => {
|
|
12
26
|
return {
|
|
@@ -21,14 +35,13 @@ function updateValue(value: any[]) {
|
|
|
21
35
|
</script>
|
|
22
36
|
|
|
23
37
|
<template>
|
|
24
|
-
<view class="ste-checkbox-group-root" :style="[cmpRootStyle]">
|
|
38
|
+
<view class="ste-checkbox-group-root" :style="[cmpRootStyle]" :class="[direction]">
|
|
25
39
|
<slot></slot>
|
|
26
40
|
</view>
|
|
27
41
|
</template>
|
|
28
42
|
|
|
29
43
|
<style lang="scss" scoped>
|
|
30
44
|
.ste-checkbox-group-root {
|
|
31
|
-
display:
|
|
32
|
-
row-gap: 16rpx;
|
|
45
|
+
display: flex;
|
|
33
46
|
}
|
|
34
47
|
</style>
|
|
@@ -129,17 +129,50 @@
|
|
|
129
129
|
```html
|
|
130
130
|
<template>
|
|
131
131
|
<ste-input placeholder="请输入内容" confirmType="next" rootClass="root-my-input" shape="line">
|
|
132
|
-
<
|
|
133
|
-
<
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
132
|
+
<template v-slot:prefix>
|
|
133
|
+
<view style="margin-right: 28rpx">
|
|
134
|
+
<ste-icon code="" size="28" />
|
|
135
|
+
<text>文本</text>
|
|
136
|
+
</view>
|
|
137
|
+
</template>
|
|
138
|
+
<template v-slot:suffix>
|
|
139
|
+
<view>
|
|
140
|
+
<ste-icon code="" size="28" />
|
|
141
|
+
</view>
|
|
142
|
+
</template>
|
|
139
143
|
</ste-input>
|
|
140
144
|
</template>
|
|
141
145
|
```
|
|
142
146
|
|
|
147
|
+
#### 前后插槽-验证码
|
|
148
|
+
|
|
149
|
+
```html
|
|
150
|
+
<template>
|
|
151
|
+
<ste-input placeholder="请输入验证码" confirmType="next" rootClass="root-my-input" shape="line">
|
|
152
|
+
<template v-slot:suffix>
|
|
153
|
+
<view>
|
|
154
|
+
<ste-button :mode="100" :round="false" @click="getCode" :disabled="count > 0">{{ count <= 0 ? '获取验证码' : count + '秒后获取' }}</ste-button>
|
|
155
|
+
</view>
|
|
156
|
+
</template>
|
|
157
|
+
</ste-input>
|
|
158
|
+
</template>
|
|
159
|
+
<script lang="ts" setup>
|
|
160
|
+
import { ref } from 'vue';
|
|
161
|
+
const count = ref(0);
|
|
162
|
+
let codeTimer: any;
|
|
163
|
+
|
|
164
|
+
function getCode() {
|
|
165
|
+
count.value = 20;
|
|
166
|
+
codeTimer = setInterval(() => {
|
|
167
|
+
if (count.value <= 0) {
|
|
168
|
+
clearInterval(codeTimer);
|
|
169
|
+
}
|
|
170
|
+
count.value--;
|
|
171
|
+
}, 1000);
|
|
172
|
+
}
|
|
173
|
+
</script>
|
|
174
|
+
```
|
|
175
|
+
|
|
143
176
|
#### 前置过滤
|
|
144
177
|
|
|
145
178
|
```html
|
|
@@ -169,6 +169,7 @@ function inputClick() {
|
|
|
169
169
|
:placeholder-class="placeholderClass"
|
|
170
170
|
:confirm-type="confirmType"
|
|
171
171
|
:cursor-spacing="cursorSpacing"
|
|
172
|
+
:maxlength="maxlength"
|
|
172
173
|
@input="onInput"
|
|
173
174
|
@focus="onFocus"
|
|
174
175
|
@blur="onBlur"
|
|
@@ -197,6 +198,7 @@ function inputClick() {
|
|
|
197
198
|
:placeholder-style="placeholderStyle"
|
|
198
199
|
:placeholder-class="placeholderClass"
|
|
199
200
|
:confirm-type="confirmType"
|
|
201
|
+
:maxlength="maxlength"
|
|
200
202
|
@input="onInput"
|
|
201
203
|
@focus="onFocus"
|
|
202
204
|
@blur="onBlur"
|
|
@@ -16,6 +16,10 @@ const loginInfoProps = {
|
|
|
16
16
|
loginSrc: { type: String, default: '' },
|
|
17
17
|
/** 未登录标题 */
|
|
18
18
|
loginTitle: { type: String, default: '' },
|
|
19
|
+
showTitleIcon: {
|
|
20
|
+
type: Boolean as PropType<boolean>,
|
|
21
|
+
default: false,
|
|
22
|
+
},
|
|
19
23
|
};
|
|
20
24
|
|
|
21
25
|
export const loginInfoEmits = {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<text>{{ subTitle }}</text>
|
|
14
14
|
</view>
|
|
15
15
|
</view>
|
|
16
|
-
<view class="user-info user-info-login" @click="loginTitleClick" v-
|
|
16
|
+
<view class="user-info user-info-login" @click="loginTitleClick" v-if="loginStatus == 0 || showTitleIcon">
|
|
17
17
|
<view class="name">
|
|
18
18
|
<text class="name-text">{{ loginTitle }}</text>
|
|
19
19
|
<ste-icon code="" size="28" color="#000" marginLeft="8" :fontFamily="fontFamily" />
|
|
@@ -76,13 +76,11 @@ const loginTitleClick = () => {
|
|
|
76
76
|
margin-right: 24rpx;
|
|
77
77
|
}
|
|
78
78
|
.user-info-login {
|
|
79
|
-
justify-content: center;
|
|
79
|
+
// justify-content: center;
|
|
80
|
+
flex: 0 !important;
|
|
80
81
|
}
|
|
81
82
|
.user-info {
|
|
82
83
|
flex: 1;
|
|
83
|
-
display: flex;
|
|
84
|
-
flex-direction: column;
|
|
85
|
-
justify-content: space-between;
|
|
86
84
|
|
|
87
85
|
.name {
|
|
88
86
|
display: flex;
|
|
@@ -4,63 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
---$
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
后面的演示代码中涉及到的变量和方法都使用该代码
|
|
7
|
+
- 由于性能不如原生组件,若数据量较多时推荐使用虚拟列表的形式渲染或者直接使用原生组件
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
<script lang="ts" setup>
|
|
13
|
-
import { reactive } from 'vue';
|
|
14
|
-
const val = reactive({
|
|
15
|
-
value1: 'a',
|
|
16
|
-
value2: 'a',
|
|
17
|
-
value3: 'a',
|
|
18
|
-
value4: 'a',
|
|
19
|
-
value5: 'a',
|
|
20
|
-
value6: 'a',
|
|
21
|
-
value7: 'a',
|
|
22
|
-
value8: '',
|
|
23
|
-
value9: 'a',
|
|
24
|
-
value10: 'a',
|
|
25
|
-
value11: '',
|
|
26
|
-
value12: '',
|
|
27
|
-
value13: '',
|
|
28
|
-
value14: '',
|
|
29
|
-
value15: '',
|
|
30
|
-
});
|
|
31
|
-
function click1(value: any, suspend: () => void, next: () => void) {
|
|
32
|
-
uni.showToast({
|
|
33
|
-
icon: 'none',
|
|
34
|
-
title: `点击:${value} 复选框的值`,
|
|
35
|
-
});
|
|
36
|
-
suspend(); // 阻止操作
|
|
37
|
-
|
|
38
|
-
setTimeout(() => {
|
|
39
|
-
next(); // 异步操作后,执行操作
|
|
40
|
-
}, 1500);
|
|
41
|
-
}
|
|
42
|
-
function click2(value: any, suspend: () => void, _next: any, stop: () => void) {
|
|
43
|
-
uni.showToast({
|
|
44
|
-
icon: 'none',
|
|
45
|
-
title: `点击:${value} 复选框的值`,
|
|
46
|
-
});
|
|
47
|
-
suspend(); // 阻止操作
|
|
48
|
-
setTimeout(() => {
|
|
49
|
-
// 异步操作后,停止操作
|
|
50
|
-
stop();
|
|
51
|
-
}, 200);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function change(value: any) {
|
|
55
|
-
setTimeout(() => {
|
|
56
|
-
uni.showToast({
|
|
57
|
-
icon: 'none',
|
|
58
|
-
title: `改变:${value} 复选框的值`,
|
|
59
|
-
});
|
|
60
|
-
}, 1000);
|
|
61
|
-
}
|
|
62
|
-
</script>
|
|
63
|
-
```
|
|
9
|
+
### 代码演示
|
|
64
10
|
|
|
65
11
|
#### 基础用法
|
|
66
12
|
|
|
@@ -62,13 +62,17 @@
|
|
|
62
62
|
position: relative;
|
|
63
63
|
|
|
64
64
|
.ste-step-line {
|
|
65
|
-
background: var(---line-color);
|
|
65
|
+
// background: var(---line-color);
|
|
66
66
|
display: inline-block;
|
|
67
67
|
position: absolute;
|
|
68
68
|
height: 2rpx;
|
|
69
69
|
left: 50%;
|
|
70
70
|
right: -50%;
|
|
71
71
|
top: 20rpx;
|
|
72
|
+
border-top-width: 2rpx;
|
|
73
|
+
border-top-color: var(---line-color);
|
|
74
|
+
border-top-style: solid;
|
|
75
|
+
box-sizing: border-box;
|
|
72
76
|
}
|
|
73
77
|
.ste-step-icon.is-icon {
|
|
74
78
|
border-radius: 50%;
|
|
@@ -27,6 +27,7 @@ const stepIndex = ref(0);
|
|
|
27
27
|
const cmpDirection = computed(() => parentProps.direction);
|
|
28
28
|
const cmpDot = computed(() => parentProps.dot);
|
|
29
29
|
const cmpReverse = computed(() => parentProps.reverse);
|
|
30
|
+
const cmpLineStyle = computed(() => parentProps.lineStyle);
|
|
30
31
|
|
|
31
32
|
watch(
|
|
32
33
|
() => parent?.internalChildren,
|
|
@@ -90,18 +91,17 @@ function clickStep() {
|
|
|
90
91
|
<template>
|
|
91
92
|
<view class="ste-step" :class="[`ste-step-${cmpDirection}`, cmpReverse ? 'reverse' : '']" :style="[cmpRootStyle]">
|
|
92
93
|
<view class="ste-step-head" :class="cmpDot ? 'head-is-dot' : ''">
|
|
93
|
-
<view class="ste-step-line" v-if="stepIndex < childrenLen"></view>
|
|
94
|
+
<view class="ste-step-line" v-if="stepIndex < childrenLen" :style="{ borderTopStyle: cmpLineStyle }"></view>
|
|
94
95
|
<view class="ste-step-icon" :class="[!cmpDot ? ($slots.icon || icon ? '' : cmpStatusObj.icon ? 'is-icon' : 'is-text') : 'is-dot']" @click="clickStep">
|
|
95
|
-
<
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
</template>
|
|
96
|
+
<slot name="icon">
|
|
97
|
+
<template v-if="cmpDot"></template>
|
|
98
|
+
<template v-else-if="cmpStatusObj.icon">
|
|
99
|
+
<ste-icon class="ste-step-icon-inner" :code="cmpStatusObj.icon" :size="icon ? 40 : 20" :color="cmpStatusObj.color"></ste-icon>
|
|
100
|
+
</template>
|
|
101
|
+
<template v-else>
|
|
102
|
+
<view class="ste-step-inner">{{ stepIndex }}</view>
|
|
103
|
+
</template>
|
|
104
|
+
</slot>
|
|
105
105
|
</view>
|
|
106
106
|
</view>
|
|
107
107
|
<view class="ste-step-content" :class="[`ste-step-content-${parentProps.direction}`]">
|
|
@@ -112,8 +112,7 @@ function clickStep() {
|
|
|
112
112
|
<slot name="title"></slot>
|
|
113
113
|
</view>
|
|
114
114
|
<view class="ste-step-desc" v-if="description || $slots.description">
|
|
115
|
-
<
|
|
116
|
-
<slot name="description"></slot>
|
|
115
|
+
<slot name="description"><span v-html="description"></span></slot>
|
|
117
116
|
</view>
|
|
118
117
|
</view>
|
|
119
118
|
</view>
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
| `active` | 步骤进度 | `number` | `0` | - | - |
|
|
5
5
|
| `direction` | 步骤条方向 | `boolean` | `row` | `row`:横向<br/>`column`:竖向 | - |
|
|
6
6
|
| `dot` | 点状步骤条 | `boolean` | `false` | - | - |
|
|
7
|
-
| `reverse` | 方向反转 | `boolean` | `false` | - |
|
|
7
|
+
| `reverse` | 方向反转 | `boolean` | `false` | - | `1.22.27` |
|
|
8
|
+
| `lineStyle` | 线条样式(支持border-style全部属性) | `string` | `solid` | - | `1.22.27` |
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
#### Events
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import type { ExtractPropTypes, PropType } from 'vue'
|
|
1
|
+
import type { ExtractPropTypes, PropType } from 'vue';
|
|
2
2
|
|
|
3
|
-
type directionType = 'row' | 'column'
|
|
3
|
+
type directionType = 'row' | 'column';
|
|
4
4
|
|
|
5
|
-
export const STEPS_KEY = Symbol('ste-steps')
|
|
5
|
+
export const STEPS_KEY = Symbol('ste-steps');
|
|
6
6
|
const stepsProps = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
7
|
+
active: { type: Number, default: 0 },
|
|
8
|
+
direction: { type: String as PropType<directionType>, default: 'row' },
|
|
9
|
+
dot: { type: Boolean, default: false },
|
|
10
|
+
reverse: { type: Boolean, default: false },
|
|
11
|
+
lineStyle: { type: String, default: 'solid' },
|
|
12
|
+
};
|
|
12
13
|
|
|
13
|
-
export type StepsProps = ExtractPropTypes<typeof stepsProps
|
|
14
|
+
export type StepsProps = ExtractPropTypes<typeof stepsProps>;
|
|
14
15
|
|
|
15
16
|
export const stepsEmits = {
|
|
16
|
-
|
|
17
|
-
}
|
|
17
|
+
'click-step': (index: number) => typeof index === 'number',
|
|
18
|
+
};
|
|
18
19
|
|
|
19
|
-
export default stepsProps
|
|
20
|
+
export default stepsProps;
|
|
@@ -35,7 +35,15 @@
|
|
|
35
35
|
"name": "reverse",
|
|
36
36
|
"description": "方向反转",
|
|
37
37
|
"type": "boolean",
|
|
38
|
-
"default": "false"
|
|
38
|
+
"default": "false",
|
|
39
|
+
"version": "1.22.27"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "lineStyle",
|
|
43
|
+
"description": "线条样式(支持border-style全部属性)",
|
|
44
|
+
"type": "string",
|
|
45
|
+
"default": "solid",
|
|
46
|
+
"version": "1.22.27"
|
|
39
47
|
},
|
|
40
48
|
{
|
|
41
49
|
"name": "[event]clickStep",
|
|
@@ -42,7 +42,18 @@ useInject(SWIPER_KEY, { setTransform, setLinearScale });
|
|
|
42
42
|
.ste-swiper-item-root {
|
|
43
43
|
width: 100%;
|
|
44
44
|
height: 100%;
|
|
45
|
-
/*
|
|
45
|
+
/* 启用硬件加速优化 */
|
|
46
46
|
will-change: transform;
|
|
47
|
+
/* 隐藏背面,避免翻转时闪烁 */
|
|
48
|
+
backface-visibility: hidden;
|
|
49
|
+
/* CSS containment 优化 */
|
|
50
|
+
contain: layout style paint;
|
|
51
|
+
/* 抗锯齿 */
|
|
52
|
+
-webkit-font-smoothing: antialiased;
|
|
53
|
+
-moz-osx-font-smoothing: grayscale;
|
|
54
|
+
/* 优化图像渲染 */
|
|
55
|
+
image-rendering: -webkit-optimize-contrast;
|
|
56
|
+
/* 确保子元素也使用硬件加速 */
|
|
57
|
+
transform-style: flat;
|
|
47
58
|
}
|
|
48
59
|
</style>
|