@hbdlzy/ui-core 0.1.0 → 0.1.2
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/README.md +61 -3
- package/components.manifest.json +239 -24
- package/dist/index.cjs +1 -1
- package/dist/index.js +3005 -13
- package/dist/style.css +1 -0
- package/package.json +5 -3
- package/src/components/BaseCard/BaseCard.types.ts +38 -0
- package/src/components/BaseCard/BaseCard.vue +250 -0
- package/src/components/BaseCard/README.md +164 -0
- package/src/components/BaseCard/index.ts +5 -0
- package/src/components/BaseEChart/BaseEChart.types.ts +35 -0
- package/src/components/BaseEChart/BaseEChart.vue +327 -0
- package/src/components/BaseEChart/README.md +136 -0
- package/src/components/BaseEChart/index.ts +5 -0
- package/src/components/BaseExportButton/BaseExportButton.vue +1 -1
- package/src/components/BaseExportButton/README.md +104 -8
- package/src/components/BaseTable/BaseTable.types.ts +174 -0
- package/src/components/BaseTable/BaseTable.vue +809 -0
- package/src/components/BaseTable/README.md +398 -0
- package/src/components/BaseTable/index.ts +25 -0
- package/src/components/OutlinedCascader/OutlinedCascader.types.ts +28 -0
- package/src/components/OutlinedCascader/OutlinedCascader.vue +250 -0
- package/src/components/OutlinedCascader/README.md +91 -0
- package/src/components/OutlinedCascader/index.ts +10 -0
- package/src/components/OutlinedDatePicker/OutlinedDatePicker.types.ts +40 -0
- package/src/components/OutlinedDatePicker/OutlinedDatePicker.vue +365 -0
- package/src/components/OutlinedDatePicker/README.md +137 -0
- package/src/components/OutlinedDatePicker/index.ts +11 -0
- package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.types.ts +34 -0
- package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.vue +421 -0
- package/src/components/OutlinedDateTimePicker/README.md +88 -0
- package/src/components/OutlinedDateTimePicker/index.ts +11 -0
- package/src/components/OutlinedInput/OutlinedInput.types.ts +32 -0
- package/src/components/OutlinedInput/OutlinedInput.vue +307 -0
- package/src/components/OutlinedInput/README.md +154 -0
- package/src/components/OutlinedInput/index.ts +10 -0
- package/src/components/OutlinedSelect/OutlinedSelect.types.ts +48 -0
- package/src/components/OutlinedSelect/OutlinedSelect.vue +359 -0
- package/src/components/OutlinedSelect/README.md +166 -0
- package/src/components/OutlinedSelect/index.ts +12 -0
- package/src/components/OutlinedTimePicker/OutlinedTimePicker.types.ts +36 -0
- package/src/components/OutlinedTimePicker/OutlinedTimePicker.vue +303 -0
- package/src/components/OutlinedTimePicker/README.md +93 -0
- package/src/components/OutlinedTimePicker/index.ts +10 -0
- package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.types.ts +56 -0
- package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.vue +354 -0
- package/src/components/OutlinedTreeSelect/README.md +107 -0
- package/src/components/OutlinedTreeSelect/index.ts +12 -0
- package/src/echarts/index.ts +12 -0
- package/src/excel/exportExcel.ts +36 -10
- package/src/index.ts +29 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="outlined-select"
|
|
4
|
+
:class="[containerClasses, rootClass]"
|
|
5
|
+
:style="[containerStyle, rootStyle]"
|
|
6
|
+
>
|
|
7
|
+
<el-select
|
|
8
|
+
ref="selectRef"
|
|
9
|
+
v-bind="selectAttrs"
|
|
10
|
+
class="outlined-select__control"
|
|
11
|
+
:model-value="selectValue"
|
|
12
|
+
:placeholder="placeholder"
|
|
13
|
+
:disabled="disabled"
|
|
14
|
+
:multiple="multiple"
|
|
15
|
+
:filterable="filterable"
|
|
16
|
+
:clearable="clearable"
|
|
17
|
+
:collapse-tags="collapseTags"
|
|
18
|
+
:collapse-tags-tooltip="collapseTagsTooltip"
|
|
19
|
+
:max-collapse-tags="maxCollapseTags"
|
|
20
|
+
:style="selectStyle"
|
|
21
|
+
@update:model-value="handleModelValueUpdate"
|
|
22
|
+
@focus="handleFocus"
|
|
23
|
+
@blur="handleBlur"
|
|
24
|
+
@change="handleChange"
|
|
25
|
+
@visible-change="handleVisibleChange"
|
|
26
|
+
@clear="handleClear"
|
|
27
|
+
>
|
|
28
|
+
<slot v-if="hasCustomOptionsSlot" />
|
|
29
|
+
|
|
30
|
+
<template v-else>
|
|
31
|
+
<el-option
|
|
32
|
+
v-for="(item, index) in options"
|
|
33
|
+
:key="createOptionKey(item, index)"
|
|
34
|
+
:label="resolveOptionLabel(item)"
|
|
35
|
+
:value="resolveOptionValue(item)"
|
|
36
|
+
:disabled="Boolean(item.disabled)"
|
|
37
|
+
/>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<template #empty>
|
|
41
|
+
<slot name="empty" />
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<template #header>
|
|
45
|
+
<slot name="header" />
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<template #footer>
|
|
49
|
+
<slot name="footer" />
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<template #tag="slotProps">
|
|
53
|
+
<slot
|
|
54
|
+
name="tag"
|
|
55
|
+
v-bind="slotProps"
|
|
56
|
+
/>
|
|
57
|
+
</template>
|
|
58
|
+
</el-select>
|
|
59
|
+
|
|
60
|
+
<div
|
|
61
|
+
v-if="floatingLabel"
|
|
62
|
+
class="outlined-select__label"
|
|
63
|
+
:class="labelClasses"
|
|
64
|
+
>
|
|
65
|
+
{{ floatingLabel }}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<script setup lang="ts">
|
|
71
|
+
import { computed, ref, useAttrs, useSlots, watch } from 'vue'
|
|
72
|
+
import type {
|
|
73
|
+
OutlinedSelectCssValue,
|
|
74
|
+
OutlinedSelectExpose,
|
|
75
|
+
OutlinedSelectOption,
|
|
76
|
+
OutlinedSelectOptionValue,
|
|
77
|
+
OutlinedSelectProps,
|
|
78
|
+
OutlinedSelectValue
|
|
79
|
+
} from './OutlinedSelect.types'
|
|
80
|
+
|
|
81
|
+
defineOptions({
|
|
82
|
+
name: 'OutlinedSelect',
|
|
83
|
+
inheritAttrs: false
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const props = withDefaults(defineProps<OutlinedSelectProps>(), {
|
|
87
|
+
value: undefined,
|
|
88
|
+
options: () => [],
|
|
89
|
+
placeholder: '',
|
|
90
|
+
label: '',
|
|
91
|
+
disabled: false,
|
|
92
|
+
typeInput: '',
|
|
93
|
+
showPassword: false,
|
|
94
|
+
collapseTags: false,
|
|
95
|
+
collapseTagsTooltip: true,
|
|
96
|
+
filterable: true,
|
|
97
|
+
clearable: true,
|
|
98
|
+
multiple: false,
|
|
99
|
+
inputHeight: 40,
|
|
100
|
+
isBorder: false,
|
|
101
|
+
keyValue: 'value',
|
|
102
|
+
labelValue: 'label',
|
|
103
|
+
noCheck: false,
|
|
104
|
+
maxCollapseTags: 5,
|
|
105
|
+
marginBottom: 20,
|
|
106
|
+
paddingTop: 20
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
const emit = defineEmits<{
|
|
110
|
+
(event: 'input', value: OutlinedSelectValue | ''): void
|
|
111
|
+
(event: 'update:value', value: OutlinedSelectValue | ''): void
|
|
112
|
+
(event: 'change', value: OutlinedSelectValue | ''): void
|
|
113
|
+
(event: 'focus', value: FocusEvent): void
|
|
114
|
+
(event: 'blur', value: FocusEvent): void
|
|
115
|
+
(event: 'visible-change', value: boolean): void
|
|
116
|
+
(event: 'clear'): void
|
|
117
|
+
}>()
|
|
118
|
+
|
|
119
|
+
const attrs = useAttrs()
|
|
120
|
+
const slots = useSlots()
|
|
121
|
+
const selectRef = ref<any>(null)
|
|
122
|
+
const selectValue = ref<OutlinedSelectValue | ''>(normalizeSelectValue(props.value, props.multiple))
|
|
123
|
+
const focused = ref(false)
|
|
124
|
+
const blurred = ref(false)
|
|
125
|
+
const visible = ref(false)
|
|
126
|
+
|
|
127
|
+
watch(
|
|
128
|
+
() => [props.value, props.multiple] as const,
|
|
129
|
+
([value, multiple]) => {
|
|
130
|
+
selectValue.value = normalizeSelectValue(value, multiple)
|
|
131
|
+
},
|
|
132
|
+
{ immediate: true }
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
const rootClass = computed(() => attrs.class)
|
|
136
|
+
const rootStyle = computed(() => attrs.style)
|
|
137
|
+
|
|
138
|
+
const selectAttrs = computed(() => {
|
|
139
|
+
const { class: _class, style: _style, ...rest } = attrs
|
|
140
|
+
return rest
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const containerClasses = computed(() => ({
|
|
144
|
+
'outlined-select--bordered': props.isBorder
|
|
145
|
+
}))
|
|
146
|
+
|
|
147
|
+
const containerStyle = computed(() => ({
|
|
148
|
+
marginBottom: toCssValue(props.marginBottom),
|
|
149
|
+
paddingTop: toCssValue(props.paddingTop)
|
|
150
|
+
}))
|
|
151
|
+
|
|
152
|
+
const selectStyle = computed(() => ({
|
|
153
|
+
minHeight: `${props.inputHeight}px`,
|
|
154
|
+
height: props.multiple ? 'auto' : `${props.inputHeight}px`
|
|
155
|
+
}))
|
|
156
|
+
|
|
157
|
+
const floatingLabel = computed(() => props.label || props.placeholder || '')
|
|
158
|
+
const hasCustomOptionsSlot = computed(() => Boolean(slots.default))
|
|
159
|
+
|
|
160
|
+
const hasContent = computed(() => {
|
|
161
|
+
if (props.multiple) {
|
|
162
|
+
return Array.isArray(selectValue.value) && selectValue.value.length > 0
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return hasFilledValue(selectValue.value)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
const shouldFloat = computed(() => (props.noCheck ? focused.value : focused.value || hasContent.value))
|
|
169
|
+
|
|
170
|
+
const labelClasses = computed(() => ({
|
|
171
|
+
'outlined-select__label--floating': shouldFloat.value,
|
|
172
|
+
'outlined-select__label--placeholder': !shouldFloat.value,
|
|
173
|
+
'outlined-select__label--filled': !props.noCheck && hasContent.value && !focused.value
|
|
174
|
+
}))
|
|
175
|
+
|
|
176
|
+
function handleModelValueUpdate(value: OutlinedSelectValue) {
|
|
177
|
+
const normalizedValue = normalizeSelectValue(value, props.multiple)
|
|
178
|
+
selectValue.value = normalizedValue
|
|
179
|
+
emitModelValue(normalizedValue)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function handleChange(value: OutlinedSelectValue) {
|
|
183
|
+
const normalizedValue = normalizeSelectValue(value, props.multiple)
|
|
184
|
+
selectValue.value = normalizedValue
|
|
185
|
+
emit('change', normalizedValue)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function handleFocus(event: FocusEvent) {
|
|
189
|
+
blurred.value = false
|
|
190
|
+
focused.value = true
|
|
191
|
+
emit('focus', event)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function handleBlur(event: FocusEvent) {
|
|
195
|
+
blurred.value = true
|
|
196
|
+
|
|
197
|
+
if (!visible.value) {
|
|
198
|
+
focused.value = false
|
|
199
|
+
emitModelValue(selectValue.value)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
emit('blur', event)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function handleVisibleChange(nextVisible: boolean) {
|
|
206
|
+
visible.value = nextVisible
|
|
207
|
+
|
|
208
|
+
if (!nextVisible && blurred.value) {
|
|
209
|
+
focused.value = false
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
emit('visible-change', nextVisible)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function handleClear() {
|
|
216
|
+
emit('clear')
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function emitModelValue(value: OutlinedSelectValue | '') {
|
|
220
|
+
emit('input', value)
|
|
221
|
+
emit('update:value', value)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function normalizeSelectValue(value: OutlinedSelectValue | undefined, multiple: boolean): OutlinedSelectValue | '' {
|
|
225
|
+
if (multiple) {
|
|
226
|
+
if (Array.isArray(value)) {
|
|
227
|
+
return value
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (value === undefined || value === null || value === '') {
|
|
231
|
+
return []
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return [value]
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return value ?? ''
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function resolveOptionLabel(option: OutlinedSelectOption) {
|
|
241
|
+
const label = option[props.labelValue]
|
|
242
|
+
return label === undefined || label === null ? '' : String(label)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function resolveOptionValue(option: OutlinedSelectOption): OutlinedSelectOptionValue {
|
|
246
|
+
return (option[props.keyValue] as OutlinedSelectOptionValue) ?? null
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function createOptionKey(option: OutlinedSelectOption, index: number) {
|
|
250
|
+
const value = resolveOptionValue(option)
|
|
251
|
+
return `${index}-${typeof value === 'object' ? JSON.stringify(value) : String(value)}`
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function hasFilledValue(value: unknown) {
|
|
255
|
+
return value !== undefined && value !== null && String(value) !== ''
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function toCssValue(value: OutlinedSelectCssValue | undefined) {
|
|
259
|
+
if (typeof value === 'number') {
|
|
260
|
+
return `${value}px`
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return value
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
defineExpose<OutlinedSelectExpose>({
|
|
267
|
+
focus: () => {
|
|
268
|
+
selectRef.value?.focus?.()
|
|
269
|
+
},
|
|
270
|
+
blur: () => {
|
|
271
|
+
selectRef.value?.blur?.()
|
|
272
|
+
},
|
|
273
|
+
clear: () => {
|
|
274
|
+
selectRef.value?.blur?.()
|
|
275
|
+
|
|
276
|
+
if (props.multiple) {
|
|
277
|
+
selectValue.value = []
|
|
278
|
+
emitModelValue([])
|
|
279
|
+
emit('change', [])
|
|
280
|
+
emit('clear')
|
|
281
|
+
return
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
selectValue.value = ''
|
|
285
|
+
emitModelValue('')
|
|
286
|
+
emit('change', '')
|
|
287
|
+
emit('clear')
|
|
288
|
+
},
|
|
289
|
+
toggleMenu: () => {
|
|
290
|
+
selectRef.value?.toggleMenu?.()
|
|
291
|
+
},
|
|
292
|
+
getSelectRef: () => selectRef.value
|
|
293
|
+
})
|
|
294
|
+
</script>
|
|
295
|
+
|
|
296
|
+
<style scoped>
|
|
297
|
+
.outlined-select {
|
|
298
|
+
position: relative;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.outlined-select__label {
|
|
302
|
+
position: absolute;
|
|
303
|
+
left: -2px;
|
|
304
|
+
padding: 2px 5px;
|
|
305
|
+
border-radius: 2px;
|
|
306
|
+
background-color: #ffffff;
|
|
307
|
+
font-size: 12px;
|
|
308
|
+
line-height: 1;
|
|
309
|
+
transition: color 200ms cubic-bezier(0, 0, 0.2, 1), transform 200ms cubic-bezier(0, 0, 0.2, 1);
|
|
310
|
+
pointer-events: none;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.outlined-select__label--floating {
|
|
314
|
+
top: 18px;
|
|
315
|
+
z-index: 1;
|
|
316
|
+
opacity: 1;
|
|
317
|
+
transform: translate(14px, -6px) scale(1);
|
|
318
|
+
color: var(--el-color-primary);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.outlined-select__label--placeholder {
|
|
322
|
+
top: 50%;
|
|
323
|
+
left: 1px;
|
|
324
|
+
z-index: -1;
|
|
325
|
+
opacity: 0;
|
|
326
|
+
transform: translate(14px, 6px) scale(1);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.outlined-select__label--filled {
|
|
330
|
+
color: var(--el-text-color-regular);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
:deep(.outlined-select__control.el-select) {
|
|
334
|
+
width: 100%;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
:deep(.outlined-select__control .el-select__wrapper) {
|
|
338
|
+
min-height: inherit;
|
|
339
|
+
height: inherit;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
:deep(.outlined-select__control .el-select__tags) {
|
|
343
|
+
padding-top: 4px;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
:deep(.outlined-select__control .el-select__selection) {
|
|
347
|
+
min-height: inherit;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
:deep(.outlined-select--bordered .el-select__wrapper) {
|
|
351
|
+
box-shadow: none;
|
|
352
|
+
border-radius: 0;
|
|
353
|
+
border-bottom: 1px solid #cccccc;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
:deep(.outlined-select--bordered .el-select__wrapper.is-focused) {
|
|
357
|
+
border-bottom-color: var(--el-color-primary);
|
|
358
|
+
}
|
|
359
|
+
</style>
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# OutlinedSelect
|
|
2
|
+
|
|
3
|
+
`OutlinedSelect` 用来统一项目里带浮动标签样式的下拉选择框,避免页面层重复写下拉框高度、标签悬浮、值映射和焦点控制逻辑。
|
|
4
|
+
|
|
5
|
+
## 解决的问题
|
|
6
|
+
|
|
7
|
+
- 统一浮动标签下拉框样式
|
|
8
|
+
- 统一 `v-model:value`、`input`、`update:value` 和 `change` 事件约定
|
|
9
|
+
- 统一 `options / keyValue / labelValue` 配置式下拉渲染
|
|
10
|
+
- 自动处理弹层展开时的焦点态和浮动标签状态
|
|
11
|
+
- 通过组件实例直接调用 `focus`、`blur`、`clear`、`toggleMenu`
|
|
12
|
+
|
|
13
|
+
## 适用场景
|
|
14
|
+
|
|
15
|
+
- 页面需要和 `OutlinedInput / OutlinedDatePicker` 保持一致视觉语言
|
|
16
|
+
- 表单页里有大量重复的基础下拉框
|
|
17
|
+
- 希望页面只传 `options` 和映射字段,不想再重复写 `el-option`
|
|
18
|
+
- 需要兼容旧项目里 `key-value / label-value / noCheck` 这类写法
|
|
19
|
+
|
|
20
|
+
## 不适用场景
|
|
21
|
+
|
|
22
|
+
- 页面需要完全自定义选择器结构
|
|
23
|
+
- 单页中需要强业务联动的复杂远程搜索选择器
|
|
24
|
+
- 不是浮动标签风格的下拉框
|
|
25
|
+
|
|
26
|
+
## 基础用法
|
|
27
|
+
|
|
28
|
+
```vue
|
|
29
|
+
<template>
|
|
30
|
+
<OutlinedSelect
|
|
31
|
+
v-model:value="form.mode"
|
|
32
|
+
placeholder="参与方式"
|
|
33
|
+
:is-border="true"
|
|
34
|
+
:options="modeOptions"
|
|
35
|
+
/>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<script setup lang="ts">
|
|
39
|
+
import { reactive } from 'vue'
|
|
40
|
+
import { OutlinedSelect } from '@hbdlzy/ui-core'
|
|
41
|
+
|
|
42
|
+
const form = reactive({
|
|
43
|
+
mode: ''
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const modeOptions = [
|
|
47
|
+
{ label: '现货', value: 'spot' },
|
|
48
|
+
{ label: '调频', value: 'fm' }
|
|
49
|
+
]
|
|
50
|
+
</script>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 自定义字段映射示例
|
|
54
|
+
|
|
55
|
+
```vue
|
|
56
|
+
<template>
|
|
57
|
+
<OutlinedSelect
|
|
58
|
+
v-model:value="form.nodeName"
|
|
59
|
+
placeholder="所属节点"
|
|
60
|
+
:options="nodeOptions"
|
|
61
|
+
key-value="nodeName"
|
|
62
|
+
label-value="nodeName"
|
|
63
|
+
:is-border="true"
|
|
64
|
+
/>
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<script setup lang="ts">
|
|
68
|
+
import { reactive } from 'vue'
|
|
69
|
+
import { OutlinedSelect } from '@hbdlzy/ui-core'
|
|
70
|
+
|
|
71
|
+
const form = reactive({
|
|
72
|
+
nodeName: ''
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const nodeOptions = [
|
|
76
|
+
{ nodeName: '华北节点' },
|
|
77
|
+
{ nodeName: '华东节点' }
|
|
78
|
+
]
|
|
79
|
+
</script>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 多选示例
|
|
83
|
+
|
|
84
|
+
```vue
|
|
85
|
+
<template>
|
|
86
|
+
<OutlinedSelect
|
|
87
|
+
v-model:value="selectedTags"
|
|
88
|
+
placeholder="标签"
|
|
89
|
+
:options="tagOptions"
|
|
90
|
+
multiple
|
|
91
|
+
collapse-tags
|
|
92
|
+
:is-border="true"
|
|
93
|
+
/>
|
|
94
|
+
</template>
|
|
95
|
+
|
|
96
|
+
<script setup lang="ts">
|
|
97
|
+
import { ref } from 'vue'
|
|
98
|
+
import { OutlinedSelect } from '@hbdlzy/ui-core'
|
|
99
|
+
|
|
100
|
+
const selectedTags = ref<string[]>([])
|
|
101
|
+
|
|
102
|
+
const tagOptions = [
|
|
103
|
+
{ label: '削峰填谷', value: 'peak' },
|
|
104
|
+
{ label: '调频服务', value: 'fm' },
|
|
105
|
+
{ label: '收益分析', value: 'income' }
|
|
106
|
+
]
|
|
107
|
+
</script>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Props
|
|
111
|
+
|
|
112
|
+
- `value`: 当前值,推荐通过 `v-model:value` 使用
|
|
113
|
+
- `options`: 配置式选项列表,默认 `[]`
|
|
114
|
+
- `placeholder`: 占位文案,同时默认作为浮动标签文案
|
|
115
|
+
- `label`: 自定义浮动标签文案,未传时回退到 `placeholder`
|
|
116
|
+
- `disabled`: 是否禁用
|
|
117
|
+
- `collapseTags`: 多选时是否折叠标签
|
|
118
|
+
- `collapseTagsTooltip`: 折叠标签时是否显示 tooltip
|
|
119
|
+
- `filterable`: 是否可搜索,默认 `true`
|
|
120
|
+
- `clearable`: 是否可清空,默认 `true`
|
|
121
|
+
- `multiple`: 是否多选
|
|
122
|
+
- `inputHeight`: 控件高度基准,默认 `40`
|
|
123
|
+
- `isBorder`: 是否启用底部边框样式
|
|
124
|
+
- `keyValue`: 选项值字段名,默认 `value`
|
|
125
|
+
- `labelValue`: 选项显示字段名,默认 `label`
|
|
126
|
+
- `noCheck`: 是否只根据焦点控制浮动标签
|
|
127
|
+
- `maxCollapseTags`: 折叠标签时最大显示数量,默认 `5`
|
|
128
|
+
- `marginBottom`: 外层容器底部间距,默认 `20`
|
|
129
|
+
- `paddingTop`: 外层容器顶部留白,默认 `20`
|
|
130
|
+
|
|
131
|
+
## Events
|
|
132
|
+
|
|
133
|
+
- `input`: 值变化时触发
|
|
134
|
+
- `update:value`: `v-model:value` 对应更新事件
|
|
135
|
+
- `change`: 用户确认变更时触发
|
|
136
|
+
- `focus`: 聚焦时触发
|
|
137
|
+
- `blur`: 失焦时触发
|
|
138
|
+
- `visible-change`: 下拉面板展开状态变化时触发
|
|
139
|
+
- `clear`: 点击清空按钮时触发
|
|
140
|
+
|
|
141
|
+
## Slots
|
|
142
|
+
|
|
143
|
+
- `default`: 完全自定义选项内容
|
|
144
|
+
- `empty`: 空状态插槽
|
|
145
|
+
- `header`: 下拉头部插槽
|
|
146
|
+
- `footer`: 下拉底部插槽
|
|
147
|
+
- `tag`: 多选标签插槽
|
|
148
|
+
|
|
149
|
+
## Expose
|
|
150
|
+
|
|
151
|
+
- `focus`: 手动聚焦选择器
|
|
152
|
+
- `blur`: 手动失焦选择器
|
|
153
|
+
- `clear`: 手动清空当前值
|
|
154
|
+
- `toggleMenu`: 手动展开或关闭下拉面板
|
|
155
|
+
- `getSelectRef`: 获取底层 `el-select` 实例
|
|
156
|
+
|
|
157
|
+
## 透传规则
|
|
158
|
+
|
|
159
|
+
- 未被组件显式声明的属性,会自动透传给内部 `el-select`
|
|
160
|
+
- 适合继续传 `teleported`、`remote`、`remote-method`、`reserve-keyword` 等 Element Plus 原生能力
|
|
161
|
+
|
|
162
|
+
## 推荐约定
|
|
163
|
+
|
|
164
|
+
- 新页面优先使用 `v-model:value`
|
|
165
|
+
- 常规下拉优先传 `options`
|
|
166
|
+
- 只有需要复杂远程搜索或强定制选项时,才考虑使用 `default` 插槽完全接管
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import OutlinedSelect from './OutlinedSelect.vue'
|
|
2
|
+
|
|
3
|
+
export default OutlinedSelect
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
OutlinedSelectCssValue,
|
|
7
|
+
OutlinedSelectExpose,
|
|
8
|
+
OutlinedSelectOption,
|
|
9
|
+
OutlinedSelectOptionValue,
|
|
10
|
+
OutlinedSelectProps,
|
|
11
|
+
OutlinedSelectValue
|
|
12
|
+
} from './OutlinedSelect.types'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type OutlinedTimePickerCssValue = string | number
|
|
2
|
+
|
|
3
|
+
export type OutlinedTimePickerValue =
|
|
4
|
+
| string
|
|
5
|
+
| number
|
|
6
|
+
| Date
|
|
7
|
+
| Array<string | number | Date>
|
|
8
|
+
| null
|
|
9
|
+
|
|
10
|
+
export interface OutlinedTimePickerProps {
|
|
11
|
+
value?: OutlinedTimePickerValue
|
|
12
|
+
placeholder?: string
|
|
13
|
+
label?: string
|
|
14
|
+
disabled?: boolean
|
|
15
|
+
clearable?: boolean
|
|
16
|
+
isRange?: boolean
|
|
17
|
+
startPlaceholder?: string
|
|
18
|
+
endPlaceholder?: string
|
|
19
|
+
rangeSeparator?: string
|
|
20
|
+
format?: string
|
|
21
|
+
valueFormat?: string
|
|
22
|
+
arrowControl?: boolean
|
|
23
|
+
inputHeight?: number
|
|
24
|
+
isBorder?: boolean
|
|
25
|
+
marginBottom?: OutlinedTimePickerCssValue
|
|
26
|
+
paddingTop?: OutlinedTimePickerCssValue
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface OutlinedTimePickerExpose {
|
|
30
|
+
focus: () => void
|
|
31
|
+
blur: () => void
|
|
32
|
+
handleOpen: () => void
|
|
33
|
+
handleClose: () => void
|
|
34
|
+
clear: () => void
|
|
35
|
+
getPickerRef: () => unknown | null
|
|
36
|
+
}
|