fix(select): [select] Adapt to multiple+disabled+showOnly scenarios with different themes (#1835)

This commit is contained in:
MomoPoppy 2024-08-07 09:28:56 +08:00 committed by GitHub
parent b32a7007f1
commit e694210a1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 133 additions and 29 deletions

View File

@ -1,14 +1,20 @@
<template>
<div>
<br />
<div>场景1多选</div>
<br />
<tiny-select v-model="value1" multiple searchable>
<tiny-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value"> </tiny-option>
<tiny-option
v-for="item in options1"
:key="item.value"
:label="item.label"
:value="item.value"
:disabled="item.disabled"
:required="item.required"
>
</tiny-option>
</tiny-select>
<br />
<br />
<br />
<div>场景2必选</div>
<br />
<tiny-select v-model="value2" multiple>
@ -17,25 +23,21 @@
:key="item.value"
:label="item.label"
:value="item.value"
:disabled="item.disabled"
:required="item.required"
>
</tiny-option>
</tiny-select>
<br />
<br />
<br />
<div>场景3配置式必选</div>
<br />
<tiny-select v-model="value3" multiple :options="options2"> </tiny-select>
<br />
<br />
<br />
<div>场景4多选个数限制</div>
<br />
<tiny-select v-model="value4" multiple :multiple-limit="2" show-limit-text>
<tiny-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value"> </tiny-option>
</tiny-select>
<br />
<tiny-select v-model="value4" :options="options1" multiple :multiple-limit="2" show-limit-text> </tiny-select>
<br />
<br />
<div>场景5自定义图标 + 自定义样式</div>
@ -43,12 +45,45 @@
<tiny-select
v-model="value4"
multiple
:options="options1"
:dropdown-icon="iconPopup"
:drop-style="{ width: '200px', 'min-width': '200px' }"
>
<tiny-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value"> </tiny-option>
</tiny-select>
<br />
<br />
<div>场景6禁用</div>
<br />
<tiny-select v-model="value5" multiple :options="options1" disabled> </tiny-select>
<br />
<br />
<div>场景7只展示</div>
<br />
<tiny-select v-model="value5" multiple :options="options1" display-only> </tiny-select>
<br />
<br />
<div>场景8显示全选文本</div>
<br />
<tiny-select v-model="value5" multiple :options="options1" show-all-text-tag> </tiny-select>
<br />
<br />
<tiny-select v-model="value5" multiple :options="options1" show-all-text-tag disabled> </tiny-select>
<br />
<br />
<div>场景9折叠tag + 必选项 + 禁用项</div>
<br />
<tiny-select v-model="value5" multiple :options="options1" collapse-tags> </tiny-select>
<br />
<br />
<div>场景10悬浮展开 + 必选项 + 禁用项</div>
<br />
<tiny-select v-model="value5" multiple :options="options1" hover-expand> </tiny-select>
<br />
<br />
<br />
<div>场景11点击展开 + 必选项 + 禁用项</div>
<br />
<tiny-select v-model="value5" multiple :options="options1" click-expand> </tiny-select>
</div>
</template>
@ -64,8 +99,8 @@ export default {
data() {
return {
options1: [
{ value: '选项1', label: '北京' },
{ value: '选项2', label: '上海' },
{ value: '选项1', label: '北京(禁用)', disabled: true }, //
{ value: '选项2', label: '上海(必选)', required: true }, //
{ value: '选项3', label: '天津' },
{ value: '选项4', label: '重庆' },
{ value: '选项5', label: '深圳' },
@ -77,7 +112,7 @@ export default {
{ value: '选项2', label: '上海' },
{ value: '选项3', label: '天津' },
{ value: '选项4', label: '重庆' },
{ value: '选项5', label: '深圳', required: true },
{ value: '选项5', label: '深圳(必选)', required: true },
{ value: '选项6', label: '南京' },
{ value: '选项7', label: '成都' }
],
@ -85,6 +120,7 @@ export default {
value2: ['选项1', '选项2'],
value3: ['选项1', '选项2'],
value4: [],
value5: ['选项1', '选项2', '选项3', '选项4', '选项5', '选项6', '选项7'],
iconPopup: iconPopup()
}
}

View File

@ -94,6 +94,14 @@ export default {
state.isSilentBlur = true
api.updateModelValue(value)
api.directEmitChange(value)
},
// aurora 禁用和只展示的时候都是tagText默认主题是 isDisplayOnly 才显示tagText
computedShowTagText: () => {
return state.isDisabled || state.isDisplayOnly
},
// aurora 禁用已选项无效果,必选不显示关闭图标
isTagClosable: (item) => {
return !item.required
}
}
}

View File

@ -2262,9 +2262,9 @@ export const computedDisabledTooltipContent =
}
export const computedSelectDisabled =
({ props, parent }) =>
({ state }) =>
() =>
props.disabled || (parent.form || {}).disabled || props.displayOnly || (parent.form || {}).displayOnly
state.isDisabled || state.isDisplayOnly
export const computedIsExpand =
({ props, state }) =>
@ -2340,6 +2340,23 @@ export const watchShowClose =
}
// 以下为tiny 新增功能
/**
*
* default smb displayOnly tagText, tag
* aurora displayOnly||disabled tagText, tag
*/
export const computedShowTagText =
({ state }) =>
() =>
state.isDisplayOnly
/**
* tag disabled required
* default required目前和aurora保持一致不显示
* aurora required
*/
export const isTagClosable = () => (item) => !item.required
export const computedGetIcon =
({ designConfig, props }) =>
() => {
@ -2359,6 +2376,7 @@ export const computedGetTagType =
}
return props.tagType
}
export const clearSearchText =
({ state, api }) =>
() => {
@ -2366,6 +2384,7 @@ export const clearSearchText =
state.previousQuery = undefined
api.handleQueryChange(state.query)
}
export const clearNoMatchValue =
({ props, emit }) =>
(newModelValue) => {

View File

@ -106,7 +106,9 @@ import {
clearNoMatchValue,
handleDebouncedQueryChange,
onClickCollapseTag,
computedIsExpand
computedIsExpand,
computedShowTagText,
isTagClosable
} from './index'
import debounce from '../common/deps/debounce'
import { isNumber } from '../common/type'
@ -170,7 +172,9 @@ export const api = [
'loadTreeData',
'updateModelValue',
'clearSearchText',
'onClickCollapseTag'
'onClickCollapseTag',
'computedShowTagText',
'isTagClosable'
]
const initState = ({ reactive, computed, props, api, emitter, parent, constants, useBreakpoint, vm, designConfig }) => {
@ -287,6 +291,8 @@ const initStateAdd = ({ computed, props, api, parent }) => {
formItemSize: computed(() => (parent.formItem || { state: {} }).state.formItemSize),
selectDisabled: computed(() => api.computedSelectDisabled()),
isDisplayOnly: computed(() => props.displayOnly || (parent.form || {}).displayOnly),
isDisabled: computed(() => props.disabled || (parent.form || {}).disabled),
isShowTagText: computed(() => api.computedShowTagText()),
gridCheckedData: computed(() => api.getcheckedData()),
isExpandAll: computed(() => api.computedIsExpandAll()),
searchSingleCopy: computed(() => props.allowCopy && !props.multiple && (props.filterable || props.searchable)),
@ -381,7 +387,7 @@ const initApi = ({
computedOptionsAllDisabled: computedOptionsAllDisabled(state),
computedDisabledTooltipContent: computedDisabledTooltipContent({ props, state }),
computedSelectDisabled: computedSelectDisabled({ props, parent }),
computedSelectDisabled: computedSelectDisabled({ state }),
computedIsExpand: computedIsExpand({ props, state }),
computedIsExpandAll: computedIsExpandAll(props),
watchInitValue: watchInitValue({ props, emit }),
@ -390,7 +396,9 @@ const initApi = ({
computedGetIcon: computedGetIcon({ designConfig, props }),
computedGetTagType: computedGetTagType({ designConfig, props }),
clearSearchText: clearSearchText({ state, api }),
clearNoMatchValue: clearNoMatchValue({ props, emit })
clearNoMatchValue: clearNoMatchValue({ props, emit }),
computedShowTagText: computedShowTagText({ state }),
isTagClosable: isTagClosable()
})
addApi({ api, props, state, emit, constants, parent, nextTick, dispatch, vm, isMobileFirstMode, designConfig })

View File

@ -1,5 +1,6 @@
export const tinyInputAuroraTheme = {
'ti-input-border-color': '#d9d9d9',
'ti-input-hover-border-color': '#1890ff',
'ti-input-icon-close-text-color': '#bfbfbf'
'ti-input-icon-close-text-color': '#bfbfbf',
'ti-input-display-content-line-height': 'var(--ti-common-space-6x)'
}

View File

@ -303,6 +303,7 @@
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
line-height: var(--ti-input-display-content-line-height);
}
&__mask {

View File

@ -89,4 +89,6 @@
--ti-input-suffix-icon-height: 1em;
// 输入框placeholder颜色
--ti-input-placeholder-color: var(--ti-common-color-placeholder, #adb0b8);
// displayOnly 时文本行高
--ti-input-display-content-line-height: var(--ti-common-line-height-number);
}

View File

@ -6,6 +6,7 @@ export const tinySelectAuroraTheme = {
'ti-select-tags-margin-bottom': '2px',
'ti-select-tags-margin-left': 'var(--ti-common-space-0)',
'ti-select-tags-wrap-padding-left': '8px',
'ti-select-tags-padding-right-disabled': 'var(--ti-common-space-4x)',
'ti-select-input-icon-close-margin-right': 'var(--ti-common-space-2x)',
'ti-select-tags-height': '28px',
'ti-select-input-icon-top': '50%',

View File

@ -122,6 +122,13 @@
> span {
font-size: 0;
.tiny-tag.is-required {
cursor: not-allowed;
> svg {
cursor: not-allowed;
}
}
}
}
@ -192,7 +199,7 @@
display: inline-flex;
> span {
color: red;
color: var(--ti-select-tags-text-color-disabled);
font-size: var(--ti-tag-font-size);
margin: var(--ti-select-tags-margin-top) var(--ti-select-tags-margin-right)
var(--ti-select-tags-margin-bottom) var(--ti-select-tags-margin-left);
@ -318,7 +325,8 @@
}
}
&.is-disabled {
&.is-disabled,
&.is-display-only {
cursor: not-allowed;
.@{input-prefix-cls} {
@ -334,6 +342,10 @@
.@{select-prefix-cls}__tags {
padding-right: 16px;
}
.@{select-prefix-cls}__tags.is-show-tag {
padding-right: var(--ti-select-tags-padding-right-disabled);
}
}
&-tip &-tipcontent {

View File

@ -13,6 +13,7 @@ export const tinySelectSmbTheme = {
'ti-select-tags-margin-top': 'var(--ti-common-space-2)',
'ti-select-tags-margin-bottom': 'var(--ti-common-space-2)',
'ti-select-tags-max-height': 'none',
'ti-select-tags-padding-right-disabled': 'var(--ti-common-space-8x)',
'ti-select-collapse-button-text-icon-color': 'var(--ti-common-color-text-link)',
'ti-select-input-icon-top-mini': 'var(--ti-common-space-4x)'
}

View File

@ -65,6 +65,10 @@
--ti-select-tags-height: calc(var(--ti-common-size-base) * 7);
// 选择器多选标签最大高度
--ti-select-tags-max-height: var(--ti-common-size-24x, 96px);
// 多选禁用时右侧内边距
--ti-select-tags-padding-right-disabled: var(--ti-common-size-7x, 28px);
// 多选禁用文本色
--ti-select-tags-text-color-disabled: var(--ti-common-color-text-disabled, #adb0b8);
// 选择器后缀图标显示状态
--ti-select-suffix-display: 'inline-block';
// 选择器右侧图标间距

View File

@ -25,7 +25,7 @@
hoverExpand ? 'is-hover-expand' : '',
clickExpand ? 'is-click-expand' : '',
state.showCollapseTag ? 'collapse-tag-clicked' : '',
state.selectDisabled ? 'is-disabled' : '',
state.isDisabled ? 'is-disabled' : '',
inputBoxType === 'underline' ? 'tiny-select__underline' : ''
]"
@mouseleave.self="
@ -69,18 +69,24 @@
</tiny-filter-box>
<div
ref="tags"
:class="['tiny-select__tags', { 'is-showicon': slots.prefix, 'not-selected': !state.selected.length }]"
:class="[
'tiny-select__tags',
{ 'is-showicon': slots.prefix, 'not-selected': !state.selected.length },
{ 'is-show-tag': !state.isShowTagText }
]"
v-if="multiple && !state.isDisplayOnly && !shape"
:style="state.tagsStyle"
>
<span v-if="!state.selectDisabled">
<span v-if="!state.isShowTagText">
<span v-if="collapseTags && state.selected.length">
<!-- 显示第1个标签 + 数字 -->
<tiny-tag
:closable="!state.selectDisabled"
:class="{ 'is-required': state.selected[0].required }"
:closable="isTagClosable(state.selected[0])"
:size="state.collapseTagSize"
:hit="state.selected[0].state ? state.selected[0].state.hitState : state.selected[0].hitState"
:key="state.key"
:disabled="state.selected[0].disabled"
:type="state.getTagType"
@close="deleteTag($event, state.selected[0])"
disable-transitions
@ -128,6 +134,7 @@
:type="state.getTagType"
key="tags-all-text-tag"
data-tag="tags-all-text-tag"
:disabled="state.isDisabled"
:closable="true"
:size="state.collapseTagSize"
@close="toggleCheckAll(false)"
@ -152,8 +159,12 @@
<tiny-tag
v-for="(item, index) in state.selected"
:key="getValueKey(item)"
:class="{ 'not-visible': state.toHideIndex <= index && !state.isExpand }"
:closable="!item.disabled && !item.required"
:class="{
'not-visible': state.toHideIndex <= index && !state.isExpand,
'is-required': item.required
}"
:closable="isTagClosable(item)"
:disabled="state.isDisabled || item.disabled"
:size="state.collapseTagSize"
:hit="item.state ? item.state.hitState : item.hitState"
:type="state.getTagType"
@ -200,7 +211,7 @@
</span>
</span>
<span v-else class="tiny-select__tags-text is-disabled">
<span v-else :class="['tiny-select__tags-text', 'is-display-only', { 'is-disabled': state.isDisabled }]">
<tiny-tooltip
:effect="tooltipConfig.effect || 'light'"
:placement="tooltipConfig.placement || 'top'"