@hbdlzy/ui-core 0.1.5 → 0.1.7
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 +4 -0
- package/components.manifest.json +37 -1
- package/dist/components/BaseTable/BaseTable.types.d.ts +17 -2
- package/dist/components/BaseTable/BaseTable.vue.d.ts +4 -4
- package/dist/components/BaseTable/index.d.ts +1 -1
- package/dist/components/OutlinedCascader/OutlinedCascader.types.d.ts +3 -0
- package/dist/components/OutlinedCascader/OutlinedCascader.vue.d.ts +9 -0
- package/dist/components/OutlinedDatePicker/OutlinedDatePicker.types.d.ts +3 -0
- package/dist/components/OutlinedDatePicker/OutlinedDatePicker.vue.d.ts +9 -0
- package/dist/components/OutlinedDateTimePicker/OutlinedDateTimePicker.types.d.ts +3 -0
- package/dist/components/OutlinedDateTimePicker/OutlinedDateTimePicker.vue.d.ts +9 -0
- package/dist/components/OutlinedInput/OutlinedInput.types.d.ts +3 -0
- package/dist/components/OutlinedInput/OutlinedInput.vue.d.ts +9 -0
- package/dist/components/OutlinedSelect/OutlinedSelect.types.d.ts +3 -0
- package/dist/components/OutlinedSelect/OutlinedSelect.vue.d.ts +9 -0
- package/dist/components/OutlinedTimePicker/OutlinedTimePicker.types.d.ts +3 -0
- package/dist/components/OutlinedTimePicker/OutlinedTimePicker.vue.d.ts +9 -0
- package/dist/components/OutlinedTreeSelect/OutlinedTreeSelect.types.d.ts +3 -0
- package/dist/components/OutlinedTreeSelect/OutlinedTreeSelect.vue.d.ts +9 -0
- package/dist/components/SvgIcon/SvgIcon.types.d.ts +6 -0
- package/dist/components/SvgIcon/SvgIcon.vue.d.ts +32 -0
- package/dist/components/SvgIcon/index.d.ts +3 -0
- package/dist/index.cjs +5 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1114 -241
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/BaseTable/BaseTable.types.ts +19 -2
- package/src/components/BaseTable/BaseTable.vue +1089 -105
- package/src/components/BaseTable/README.md +88 -5
- package/src/components/BaseTable/index.ts +5 -0
- package/src/components/OutlinedCascader/OutlinedCascader.types.ts +3 -0
- package/src/components/OutlinedCascader/OutlinedCascader.vue +71 -6
- package/src/components/OutlinedCascader/README.md +3 -0
- package/src/components/OutlinedDatePicker/OutlinedDatePicker.types.ts +3 -0
- package/src/components/OutlinedDatePicker/OutlinedDatePicker.vue +71 -6
- package/src/components/OutlinedDatePicker/README.md +3 -0
- package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.types.ts +3 -0
- package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.vue +144 -64
- package/src/components/OutlinedDateTimePicker/README.md +3 -0
- package/src/components/OutlinedInput/OutlinedInput.types.ts +3 -0
- package/src/components/OutlinedInput/OutlinedInput.vue +87 -8
- package/src/components/OutlinedInput/README.md +3 -0
- package/src/components/OutlinedSelect/OutlinedSelect.types.ts +3 -0
- package/src/components/OutlinedSelect/OutlinedSelect.vue +72 -6
- package/src/components/OutlinedSelect/README.md +3 -0
- package/src/components/OutlinedTimePicker/OutlinedTimePicker.types.ts +3 -0
- package/src/components/OutlinedTimePicker/OutlinedTimePicker.vue +75 -8
- package/src/components/OutlinedTimePicker/README.md +3 -0
- package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.types.ts +3 -0
- package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.vue +72 -6
- package/src/components/OutlinedTreeSelect/README.md +3 -0
- package/src/components/SvgIcon/README.md +53 -0
- package/src/components/SvgIcon/SvgIcon.types.ts +6 -0
- package/src/components/SvgIcon/SvgIcon.vue +68 -0
- package/src/components/SvgIcon/index.ts +5 -0
- package/src/index.ts +2 -0
|
@@ -199,9 +199,9 @@ const resultAdapter = (result: any) => {
|
|
|
199
199
|
|
|
200
200
|
如果接口参数结构更特殊,可以改用 `sortMapper`。
|
|
201
201
|
|
|
202
|
-
## 表头列搜索
|
|
202
|
+
## 表头列搜索 / 筛选
|
|
203
203
|
|
|
204
|
-
`BaseTable`
|
|
204
|
+
`BaseTable` 现在支持列头输入搜索、下拉筛选、多选下拉和级联筛选能力,用法和旧 `TableComponent.vue` 里的 `isSearch` 很接近,但配置方式更收敛。
|
|
205
205
|
|
|
206
206
|
### 基础写法
|
|
207
207
|
|
|
@@ -217,7 +217,7 @@ const columns = [
|
|
|
217
217
|
|
|
218
218
|
开启后,这一列的表头会出现搜索图标,点击后会弹出输入框,并提供“搜索 / 重置”操作。
|
|
219
219
|
|
|
220
|
-
###
|
|
220
|
+
### 输入框高级写法
|
|
221
221
|
|
|
222
222
|
```ts
|
|
223
223
|
const columns = [
|
|
@@ -235,13 +235,94 @@ const columns = [
|
|
|
235
235
|
]
|
|
236
236
|
```
|
|
237
237
|
|
|
238
|
+
### 下拉筛选写法
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
const columns = [
|
|
242
|
+
{
|
|
243
|
+
label: '状态',
|
|
244
|
+
prop: 'status',
|
|
245
|
+
kind: 'tag',
|
|
246
|
+
options: [
|
|
247
|
+
{ label: '启用', value: 'enabled', tagType: 'success' },
|
|
248
|
+
{ label: '停用', value: 'disabled', tagType: 'info' }
|
|
249
|
+
],
|
|
250
|
+
headerSearch: {
|
|
251
|
+
type: 'select',
|
|
252
|
+
placeholder: '请选择状态',
|
|
253
|
+
width: 220,
|
|
254
|
+
searchText: '筛选'
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
下拉筛选默认复用当前列的 `options`,也可以在 `headerSearch.options` 中单独传入选项。需要多选时可以配置 `multiple: true`,请求参数会以数组形式传出。
|
|
261
|
+
|
|
262
|
+
### 多选下拉筛选写法
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
const columns = [
|
|
266
|
+
{
|
|
267
|
+
label: '资讯分类',
|
|
268
|
+
prop: 'categories',
|
|
269
|
+
kind: 'tag',
|
|
270
|
+
options: [
|
|
271
|
+
{ label: '市场资讯', value: 'market', tagType: 'primary' },
|
|
272
|
+
{ label: '运行日报', value: 'operation', tagType: 'success' }
|
|
273
|
+
],
|
|
274
|
+
headerSearch: {
|
|
275
|
+
type: 'select',
|
|
276
|
+
multiple: true,
|
|
277
|
+
placeholder: '请选择分类',
|
|
278
|
+
searchText: '筛选'
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
多选下拉会在面板里保留展开状态,方便连续选择多个选项;点击“筛选”后请求参数形如 `{ categories: ['market', 'operation'] }`。
|
|
285
|
+
|
|
286
|
+
### 级联下拉筛选写法
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
const columns = [
|
|
290
|
+
{
|
|
291
|
+
label: '所在区域',
|
|
292
|
+
prop: 'regionPath',
|
|
293
|
+
headerSearch: {
|
|
294
|
+
type: 'cascader',
|
|
295
|
+
placeholder: '请选择区域',
|
|
296
|
+
width: 420,
|
|
297
|
+
options: [
|
|
298
|
+
{
|
|
299
|
+
label: '华北',
|
|
300
|
+
value: 'north',
|
|
301
|
+
children: [
|
|
302
|
+
{
|
|
303
|
+
label: '北京',
|
|
304
|
+
value: 'beijing',
|
|
305
|
+
children: [
|
|
306
|
+
{ label: '朝阳区', value: 'chaoyang' }
|
|
307
|
+
]
|
|
308
|
+
}
|
|
309
|
+
]
|
|
310
|
+
}
|
|
311
|
+
]
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
]
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
级联筛选默认使用 `children` 作为子级字段,可以通过 `optionChildrenKey` 改写;请求参数会以完整路径数组传出,例如 `{ regionPath: ['north', 'beijing', 'chaoyang'] }`。
|
|
318
|
+
|
|
238
319
|
### 行为说明
|
|
239
320
|
|
|
240
321
|
- 远程模式下,列头搜索值会自动合并到 `request(params)` 的参数里
|
|
241
322
|
- 触发搜索或重置时,会自动把页码重置到第一页
|
|
242
323
|
- 如果配置了 `paramKey`,请求参数会优先使用它
|
|
243
324
|
- 如果没有配置 `paramKey`,默认使用当前列的 `prop`
|
|
244
|
-
-
|
|
325
|
+
- 本地数据模式下,输入搜索会对当前 `data` 做简单文本包含过滤,下拉筛选会按选项值精确匹配,级联筛选会按路径前缀匹配
|
|
245
326
|
- 多个开启搜索的列会按“同时满足”处理
|
|
246
327
|
|
|
247
328
|
示例请求参数:
|
|
@@ -250,7 +331,8 @@ const columns = [
|
|
|
250
331
|
{
|
|
251
332
|
currentPage: 1,
|
|
252
333
|
pageSize: 20,
|
|
253
|
-
owner: '张三'
|
|
334
|
+
owner: '张三',
|
|
335
|
+
status: 'enabled'
|
|
254
336
|
}
|
|
255
337
|
```
|
|
256
338
|
|
|
@@ -362,6 +444,7 @@ const columns = [
|
|
|
362
444
|
|
|
363
445
|
```ts
|
|
364
446
|
tableRef.value?.setHeaderSearchValue('owner', '张三')
|
|
447
|
+
tableRef.value?.setHeaderSearchValue('status', 'enabled')
|
|
365
448
|
tableRef.value?.resetHeaderSearch()
|
|
366
449
|
```
|
|
367
450
|
|
|
@@ -10,6 +10,11 @@ export type {
|
|
|
10
10
|
BaseTableColumnKind,
|
|
11
11
|
BaseTableCssValue,
|
|
12
12
|
BaseTableExpose,
|
|
13
|
+
BaseTableHeaderSearchConfig,
|
|
14
|
+
BaseTableHeaderSearchPathValue,
|
|
15
|
+
BaseTableHeaderSearchPrimitiveValue,
|
|
16
|
+
BaseTableHeaderSearchType,
|
|
17
|
+
BaseTableHeaderSearchValue,
|
|
13
18
|
BaseTableLoadedPayload,
|
|
14
19
|
BaseTableNormalizedResult,
|
|
15
20
|
BaseTableOption,
|
|
@@ -17,6 +17,9 @@ export interface OutlinedCascaderProps {
|
|
|
17
17
|
levels?: boolean
|
|
18
18
|
marginBottom?: OutlinedCascaderCssValue
|
|
19
19
|
paddingTop?: OutlinedCascaderCssValue
|
|
20
|
+
required?: boolean
|
|
21
|
+
error?: boolean
|
|
22
|
+
errorMessage?: string
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
export interface OutlinedCascaderExpose {
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
:options="options"
|
|
13
13
|
:props="propsValue"
|
|
14
14
|
:clearable="clearable"
|
|
15
|
-
:placeholder="
|
|
15
|
+
:placeholder="controlPlaceholder"
|
|
16
16
|
:filterable="filterable"
|
|
17
17
|
:show-all-levels="levels"
|
|
18
18
|
:disabled="disabled"
|
|
19
19
|
:popper-class="popperClass"
|
|
20
20
|
:style="cascaderStyle"
|
|
21
|
+
:aria-invalid="hasError ? 'true' : undefined"
|
|
21
22
|
@update:model-value="handleModelValueUpdate"
|
|
22
23
|
@focus="handleFocus"
|
|
23
24
|
@blur="handleBlur"
|
|
@@ -30,8 +31,19 @@
|
|
|
30
31
|
class="outlined-cascader__label"
|
|
31
32
|
:class="labelClasses"
|
|
32
33
|
>
|
|
33
|
-
|
|
34
|
+
<span
|
|
35
|
+
v-if="required"
|
|
36
|
+
class="outlined-cascader__required"
|
|
37
|
+
>*</span>
|
|
38
|
+
<span>{{ floatingLabel }}</span>
|
|
34
39
|
</div>
|
|
40
|
+
|
|
41
|
+
<p
|
|
42
|
+
v-if="hasError"
|
|
43
|
+
class="outlined-cascader__error"
|
|
44
|
+
>
|
|
45
|
+
{{ resolvedErrorMessage }}
|
|
46
|
+
</p>
|
|
35
47
|
</div>
|
|
36
48
|
</template>
|
|
37
49
|
|
|
@@ -63,7 +75,10 @@ const props = withDefaults(defineProps<OutlinedCascaderProps>(), {
|
|
|
63
75
|
filterable: true,
|
|
64
76
|
levels: true,
|
|
65
77
|
marginBottom: 20,
|
|
66
|
-
paddingTop: 20
|
|
78
|
+
paddingTop: 20,
|
|
79
|
+
required: false,
|
|
80
|
+
error: false,
|
|
81
|
+
errorMessage: ''
|
|
67
82
|
})
|
|
68
83
|
|
|
69
84
|
const emit = defineEmits<{
|
|
@@ -99,7 +114,8 @@ const cascaderAttrs = computed(() => {
|
|
|
99
114
|
})
|
|
100
115
|
|
|
101
116
|
const containerClasses = computed(() => ({
|
|
102
|
-
'outlined-cascader--bordered': props.isBorder
|
|
117
|
+
'outlined-cascader--bordered': props.isBorder,
|
|
118
|
+
'outlined-cascader--error': hasError.value
|
|
103
119
|
}))
|
|
104
120
|
|
|
105
121
|
const containerStyle = computed(() => ({
|
|
@@ -113,6 +129,9 @@ const cascaderStyle = computed(() => ({
|
|
|
113
129
|
}))
|
|
114
130
|
|
|
115
131
|
const floatingLabel = computed(() => props.label || props.placeholder || '')
|
|
132
|
+
const controlPlaceholder = computed(() => addRequiredMark(props.placeholder))
|
|
133
|
+
const hasError = computed(() => Boolean(props.error))
|
|
134
|
+
const resolvedErrorMessage = computed(() => props.errorMessage || createRequiredMessage(floatingLabel.value))
|
|
116
135
|
|
|
117
136
|
const hasContent = computed(() => cascaderValue.value.length > 0)
|
|
118
137
|
|
|
@@ -178,6 +197,18 @@ function toCssValue(value: OutlinedCascaderCssValue | undefined) {
|
|
|
178
197
|
return value
|
|
179
198
|
}
|
|
180
199
|
|
|
200
|
+
function addRequiredMark(value: string) {
|
|
201
|
+
if (!props.required || !value || value.startsWith('*')) {
|
|
202
|
+
return value
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return `*${value}`
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function createRequiredMessage(label: string) {
|
|
209
|
+
return label ? `${label}为必填项` : '该项为必填项'
|
|
210
|
+
}
|
|
211
|
+
|
|
181
212
|
defineExpose<OutlinedCascaderExpose>({
|
|
182
213
|
focus: () => {
|
|
183
214
|
cascaderRef.value?.togglePopperVisible?.(true)
|
|
@@ -205,6 +236,9 @@ defineExpose<OutlinedCascaderExpose>({
|
|
|
205
236
|
.outlined-cascader__label {
|
|
206
237
|
position: absolute;
|
|
207
238
|
left: -2px;
|
|
239
|
+
display: inline-flex;
|
|
240
|
+
align-items: center;
|
|
241
|
+
gap: 2px;
|
|
208
242
|
padding: 2px 5px;
|
|
209
243
|
border-radius: 2px;
|
|
210
244
|
background-color: #ffffff;
|
|
@@ -234,17 +268,48 @@ defineExpose<OutlinedCascaderExpose>({
|
|
|
234
268
|
color: var(--el-text-color-regular);
|
|
235
269
|
}
|
|
236
270
|
|
|
271
|
+
.outlined-cascader--error {
|
|
272
|
+
--el-input-focus-border-color: var(--el-color-danger);
|
|
273
|
+
--el-input-hover-border-color: var(--el-color-danger);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.outlined-cascader__required,
|
|
277
|
+
.outlined-cascader--error .outlined-cascader__label,
|
|
278
|
+
.outlined-cascader__error {
|
|
279
|
+
color: var(--el-color-danger);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.outlined-cascader__error {
|
|
283
|
+
margin: 6px 0 0;
|
|
284
|
+
font-size: 12px;
|
|
285
|
+
line-height: 1.2;
|
|
286
|
+
}
|
|
287
|
+
|
|
237
288
|
:deep(.outlined-cascader__control .el-input) {
|
|
238
289
|
height: 100%;
|
|
239
290
|
}
|
|
240
291
|
|
|
241
|
-
|
|
292
|
+
.outlined-cascader--bordered :deep(.el-input__wrapper) {
|
|
242
293
|
box-shadow: none;
|
|
243
294
|
border-radius: 0;
|
|
244
295
|
border-bottom: 1px solid #cccccc;
|
|
245
296
|
}
|
|
246
297
|
|
|
247
|
-
|
|
298
|
+
.outlined-cascader--bordered :deep(.el-input__wrapper.is-focus) {
|
|
248
299
|
border-bottom-color: var(--el-color-primary);
|
|
249
300
|
}
|
|
301
|
+
|
|
302
|
+
.outlined-cascader--error :deep(.el-input__wrapper) {
|
|
303
|
+
box-shadow: 0 0 0 1px var(--el-color-danger) inset;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.outlined-cascader--error :deep(.el-input.is-focus .el-input__wrapper),
|
|
307
|
+
.outlined-cascader--error :deep(.el-input__wrapper:hover) {
|
|
308
|
+
box-shadow: 0 0 0 1px var(--el-color-danger) inset;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.outlined-cascader--error.outlined-cascader--bordered :deep(.el-input__wrapper) {
|
|
312
|
+
box-shadow: 0 0 0 1px var(--el-color-danger) inset;
|
|
313
|
+
border-bottom-color: transparent;
|
|
314
|
+
}
|
|
250
315
|
</style>
|
|
@@ -54,6 +54,9 @@ const areaOptions = [
|
|
|
54
54
|
| `propsValue` | `Record<string, unknown>` | `undefined` | 透传给 `el-cascader` 的 `props` |
|
|
55
55
|
| `placeholder` | `string` | `''` | 占位文案,也会作为浮动标签文案 |
|
|
56
56
|
| `label` | `string` | `''` | 自定义浮动标签文案,优先级高于 `placeholder` |
|
|
57
|
+
| `required` | `boolean` | `false` | 是否显示必填星号 |
|
|
58
|
+
| `error` | `boolean` | `false` | 是否显示错误态,开启后级联框变红并展示错误文案 |
|
|
59
|
+
| `errorMessage` | `string` | `''` | 错误文案,未传时默认使用“字段名为必填项” |
|
|
57
60
|
| `popperClass` | `string` | `''` | 自定义弹层类名 |
|
|
58
61
|
| `disabled` | `boolean` | `false` | 是否禁用 |
|
|
59
62
|
| `inputHeight` | `number` | `40` | 输入框高度 |
|
|
@@ -29,6 +29,9 @@ export interface OutlinedDatePickerProps {
|
|
|
29
29
|
disabledDate?: OutlinedDatePickerDisabledDate
|
|
30
30
|
marginBottom?: OutlinedDatePickerCssValue
|
|
31
31
|
paddingTop?: OutlinedDatePickerCssValue
|
|
32
|
+
required?: boolean
|
|
33
|
+
error?: boolean
|
|
34
|
+
errorMessage?: string
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
export interface OutlinedDatePickerExpose {
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
:type="typeDate"
|
|
13
13
|
:format="format"
|
|
14
14
|
:value-format="resolvedValueFormat"
|
|
15
|
-
:placeholder="
|
|
15
|
+
:placeholder="controlPlaceholder"
|
|
16
16
|
:disabled="disabled"
|
|
17
17
|
:style="pickerStyle"
|
|
18
|
+
:aria-invalid="hasError ? 'true' : undefined"
|
|
18
19
|
@update:model-value="handleModelValueUpdate"
|
|
19
20
|
@focus="handleFocus"
|
|
20
21
|
@blur="handleBlur"
|
|
@@ -27,8 +28,19 @@
|
|
|
27
28
|
class="outlined-date-picker__label"
|
|
28
29
|
:class="labelClasses"
|
|
29
30
|
>
|
|
30
|
-
|
|
31
|
+
<span
|
|
32
|
+
v-if="required"
|
|
33
|
+
class="outlined-date-picker__required"
|
|
34
|
+
>*</span>
|
|
35
|
+
<span>{{ floatingLabel }}</span>
|
|
31
36
|
</div>
|
|
37
|
+
|
|
38
|
+
<p
|
|
39
|
+
v-if="hasError"
|
|
40
|
+
class="outlined-date-picker__error"
|
|
41
|
+
>
|
|
42
|
+
{{ resolvedErrorMessage }}
|
|
43
|
+
</p>
|
|
32
44
|
</div>
|
|
33
45
|
</template>
|
|
34
46
|
|
|
@@ -62,7 +74,10 @@ const props = withDefaults(defineProps<OutlinedDatePickerProps>(), {
|
|
|
62
74
|
isBorder: false,
|
|
63
75
|
disabledDate: undefined,
|
|
64
76
|
marginBottom: 20,
|
|
65
|
-
paddingTop: 20
|
|
77
|
+
paddingTop: 20,
|
|
78
|
+
required: false,
|
|
79
|
+
error: false,
|
|
80
|
+
errorMessage: ''
|
|
66
81
|
})
|
|
67
82
|
|
|
68
83
|
const emit = defineEmits<{
|
|
@@ -159,7 +174,8 @@ const pickerAttrs = computed(() => {
|
|
|
159
174
|
})
|
|
160
175
|
|
|
161
176
|
const containerClasses = computed(() => ({
|
|
162
|
-
'outlined-date-picker--bordered': props.isBorder
|
|
177
|
+
'outlined-date-picker--bordered': props.isBorder,
|
|
178
|
+
'outlined-date-picker--error': hasError.value
|
|
163
179
|
}))
|
|
164
180
|
|
|
165
181
|
const containerStyle = computed(() => ({
|
|
@@ -172,6 +188,9 @@ const pickerStyle = computed(() => ({
|
|
|
172
188
|
}))
|
|
173
189
|
|
|
174
190
|
const floatingLabel = computed(() => props.label || props.placeholder || '')
|
|
191
|
+
const controlPlaceholder = computed(() => addRequiredMark(props.placeholder))
|
|
192
|
+
const hasError = computed(() => Boolean(props.error))
|
|
193
|
+
const resolvedErrorMessage = computed(() => props.errorMessage || createRequiredMessage(floatingLabel.value))
|
|
175
194
|
|
|
176
195
|
const hasContent = computed(() => hasFilledValue(pickerValue.value))
|
|
177
196
|
|
|
@@ -279,6 +298,18 @@ function toCssValue(value: OutlinedDatePickerCssValue | undefined) {
|
|
|
279
298
|
return value
|
|
280
299
|
}
|
|
281
300
|
|
|
301
|
+
function addRequiredMark(value: string) {
|
|
302
|
+
if (!props.required || !value || value.startsWith('*')) {
|
|
303
|
+
return value
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return `*${value}`
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function createRequiredMessage(label: string) {
|
|
310
|
+
return label ? `${label}为必填项` : '该项为必填项'
|
|
311
|
+
}
|
|
312
|
+
|
|
282
313
|
defineExpose<OutlinedDatePickerExpose>({
|
|
283
314
|
focus: () => {
|
|
284
315
|
pickerRef.value?.focus?.()
|
|
@@ -304,6 +335,9 @@ defineExpose<OutlinedDatePickerExpose>({
|
|
|
304
335
|
.outlined-date-picker__label {
|
|
305
336
|
position: absolute;
|
|
306
337
|
left: -2px;
|
|
338
|
+
display: inline-flex;
|
|
339
|
+
align-items: center;
|
|
340
|
+
gap: 2px;
|
|
307
341
|
padding: 2px 5px;
|
|
308
342
|
border-radius: 2px;
|
|
309
343
|
background-color: #ffffff;
|
|
@@ -333,6 +367,23 @@ defineExpose<OutlinedDatePickerExpose>({
|
|
|
333
367
|
color: var(--el-text-color-regular);
|
|
334
368
|
}
|
|
335
369
|
|
|
370
|
+
.outlined-date-picker--error {
|
|
371
|
+
--el-input-focus-border-color: var(--el-color-danger);
|
|
372
|
+
--el-input-hover-border-color: var(--el-color-danger);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.outlined-date-picker__required,
|
|
376
|
+
.outlined-date-picker--error .outlined-date-picker__label,
|
|
377
|
+
.outlined-date-picker__error {
|
|
378
|
+
color: var(--el-color-danger);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.outlined-date-picker__error {
|
|
382
|
+
margin: 6px 0 0;
|
|
383
|
+
font-size: 12px;
|
|
384
|
+
line-height: 1.2;
|
|
385
|
+
}
|
|
386
|
+
|
|
336
387
|
:deep(.outlined-date-picker__control.el-date-editor) {
|
|
337
388
|
width: 100%;
|
|
338
389
|
}
|
|
@@ -353,13 +404,27 @@ defineExpose<OutlinedDatePickerExpose>({
|
|
|
353
404
|
right: 30px;
|
|
354
405
|
}
|
|
355
406
|
|
|
356
|
-
|
|
407
|
+
.outlined-date-picker--bordered :deep(.el-input__wrapper) {
|
|
357
408
|
box-shadow: none;
|
|
358
409
|
border-radius: 0;
|
|
359
410
|
border-bottom: 1px solid #cccccc;
|
|
360
411
|
}
|
|
361
412
|
|
|
362
|
-
|
|
413
|
+
.outlined-date-picker--bordered :deep(.el-input__wrapper.is-focus) {
|
|
363
414
|
border-bottom-color: var(--el-color-primary);
|
|
364
415
|
}
|
|
416
|
+
|
|
417
|
+
.outlined-date-picker--error :deep(.el-input__wrapper) {
|
|
418
|
+
box-shadow: 0 0 0 1px var(--el-color-danger) inset;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.outlined-date-picker--error :deep(.el-input__wrapper.is-focus),
|
|
422
|
+
.outlined-date-picker--error :deep(.el-input__wrapper:hover) {
|
|
423
|
+
box-shadow: 0 0 0 1px var(--el-color-danger) inset;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.outlined-date-picker--error.outlined-date-picker--bordered :deep(.el-input__wrapper) {
|
|
427
|
+
box-shadow: 0 0 0 1px var(--el-color-danger) inset;
|
|
428
|
+
border-bottom-color: transparent;
|
|
429
|
+
}
|
|
365
430
|
</style>
|
|
@@ -97,6 +97,9 @@ const form = reactive({
|
|
|
97
97
|
- `value`: 当前值,推荐通过 `v-model:value` 使用
|
|
98
98
|
- `placeholder`: 占位文案,同时默认作为浮动标签文案
|
|
99
99
|
- `label`: 自定义浮动标签文案,未传时回退到 `placeholder`
|
|
100
|
+
- `required`: 是否显示必填星号,默认 `false`
|
|
101
|
+
- `error`: 是否显示错误态,开启后日期框变红并展示错误文案
|
|
102
|
+
- `errorMessage`: 错误文案,未传时默认使用“字段名为必填项”
|
|
100
103
|
- `disabled`: 是否禁用
|
|
101
104
|
- `timeValue`: 是否按带时间场景处理默认时间
|
|
102
105
|
- `typeDate`: 日期控件类型,默认 `date`
|
|
@@ -20,6 +20,9 @@ export interface OutlinedDateTimePickerProps {
|
|
|
20
20
|
clearable?: boolean
|
|
21
21
|
marginBottom?: OutlinedDateTimePickerCssValue
|
|
22
22
|
paddingTop?: OutlinedDateTimePickerCssValue
|
|
23
|
+
required?: boolean
|
|
24
|
+
error?: boolean
|
|
25
|
+
errorMessage?: string
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
export interface OutlinedDateTimePickerExpose {
|