♻️(component): 初步完成 select 组件重构
This commit is contained in:
parent
ff335e56df
commit
f52ff6207b
@ -42,6 +42,8 @@ const matchModule: string[] = [
|
||||
"empty",
|
||||
"dropdownMenu",
|
||||
"dropdownMenuItem",
|
||||
"tag",
|
||||
"tagInput"
|
||||
];
|
||||
|
||||
export default (): UserConfigExport => {
|
||||
|
@ -1,173 +1,12 @@
|
||||
@import "../badge/index.less";
|
||||
@import "../checkbox/index.less";
|
||||
@import "../input/index.less";
|
||||
|
||||
@select-lg: 44px;
|
||||
@select-md: 38px;
|
||||
@select-sm: 32px;
|
||||
@select-xs: 26px;
|
||||
@select-lg-badge:32px;
|
||||
@select-md-badge:26px;
|
||||
@select-sm-badge:20px;
|
||||
@select-xs-badge:14px;
|
||||
@select-lg-width: 260px;
|
||||
@select-md-width: 220px;
|
||||
@select-sm-width: 180px;
|
||||
@select-xs-width: 140px;
|
||||
|
||||
.set-size(@size,@badge-size,@width) {
|
||||
& {
|
||||
width: @width;
|
||||
height: @size;
|
||||
.layui-input {
|
||||
height: @size;
|
||||
line-height: @size;
|
||||
}
|
||||
.layui-badge{
|
||||
height: @badge-size;
|
||||
line-height: @badge-size;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dl.layui-anim-upbit > dd input[type="checkbox"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
dl.layui-anim-upbit > dd .layui-form-checkbox,
|
||||
.layui-form-item dl.layui-anim-upbit > dd .layui-form-checkbox[lay-skin] {
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
.layui-multiple-select-row {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 34px;
|
||||
padding: 5px 0 5px 6px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
overflow-x: scroll;
|
||||
cursor: pointer;
|
||||
.layui-multiple-select-badge {
|
||||
width: ms-max-content;
|
||||
width: max-content;
|
||||
.layui-badge {
|
||||
margin-left: 5px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
border:1px solid #f0f0f0;
|
||||
&:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
.layui-icon {
|
||||
font-size: 12px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
height: 50px;
|
||||
background-color: whitesmoke;
|
||||
border-radius: 6px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
height: 50px;
|
||||
background-color: whitesmoke;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.layui-select {
|
||||
height: 38px;
|
||||
line-height: 1.3;
|
||||
line-height: 38px\9;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
background-color: #fff;
|
||||
border-color: #eee;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
border-radius: 2px;
|
||||
padding: 0 10px;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.layui-select::-webkit-input-placeholder {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.layui-form-select {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layui-select-title{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.layui-select-title .layui-input {
|
||||
padding-right: 36px;
|
||||
padding-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layui-form-select .layui-edge {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
margin-top: -3px;
|
||||
cursor: pointer;
|
||||
border-width: 6px;
|
||||
border-top-color: var(--global-neutral-color-8);
|
||||
border-top-style: solid;
|
||||
transition: all 0.3s;
|
||||
-webkit-transition: all 0.3s;
|
||||
}
|
||||
|
||||
.layui-input-icon-area{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
.layui-icon-close-fill{
|
||||
margin-left: 10px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
}
|
||||
|
||||
.layui-form-select .layui-icon-triangle-d {
|
||||
display: inline-block;
|
||||
transition: all 0.3s;
|
||||
-webkit-transition: all 0.3s;
|
||||
color:var(--global-neutral-color-8);
|
||||
}
|
||||
|
||||
.layui-form-select dl {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 42px;
|
||||
.layui-select-options {
|
||||
padding: 5px 0;
|
||||
z-index: 899;
|
||||
min-width: 100%;
|
||||
border: 1px solid var(--global-neutral-color-3);
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
background-color: #fff;
|
||||
border-radius: var(--global-border-radius);
|
||||
box-sizing: border-box;
|
||||
box-shadow: 1px 1px 4px rgb(0 0 0 / 8%);
|
||||
}
|
||||
|
||||
.layui-form-select dl dd,
|
||||
.layui-form-select dl dt {
|
||||
.layui-select-options .layui-select-option {
|
||||
padding: 0 10px;
|
||||
line-height: 36px;
|
||||
white-space: nowrap;
|
||||
@ -175,66 +14,7 @@ dl.layui-anim-upbit > dd .layui-form-checkbox,
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.layui-form-select dl dt {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.layui-form-select dl dd {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layui-form-select dl dd:hover {
|
||||
background-color: var(--global-neutral-color-2);
|
||||
-webkit-transition: 0.5s all;
|
||||
transition: 0.5s all;
|
||||
}
|
||||
|
||||
.layui-form-select .layui-select-group dd {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.layui-form-select dl dd.layui-select-tips {
|
||||
padding-left: 10px !important;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.layui-form-select dl dd.layui-this {
|
||||
.layui-select-options .layui-select-option.layui-this {
|
||||
background-color: var(--global-neutral-color-2);
|
||||
color: var(--global-checked-color);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.layui-form-checkbox,
|
||||
.layui-form-select dl dd.layui-disabled {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.layui-form-selected dl {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.layui-multiple-select-input {
|
||||
margin-bottom: 5px;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
|
||||
.layui-input {
|
||||
height: 30px !important;
|
||||
line-height: 30px !important;
|
||||
}
|
||||
}
|
||||
.layui-form-select{
|
||||
&[size="lg"] {
|
||||
.set-size(@select-lg, @select-lg-badge, @select-lg-width);
|
||||
}
|
||||
&[size="md"] {
|
||||
.set-size(@select-md, @select-md-badge, @select-md-width);
|
||||
}
|
||||
&[size="sm"] {
|
||||
.set-size(@select-sm, @select-sm-badge, @select-sm-width);
|
||||
}
|
||||
&[size="xs"] {
|
||||
.set-size(@select-xs, @select-xs-badge, @select-xs-width);
|
||||
}
|
||||
}
|
@ -6,286 +6,72 @@ export default {
|
||||
|
||||
<script setup lang="ts">
|
||||
import "./index.less";
|
||||
import LaySelectOption from "../selectOption/index.vue";
|
||||
import { provide, ref, watch, computed, Ref, nextTick, shallowRef } from "vue";
|
||||
import LayBadge from "../badge/index.vue";
|
||||
import { provide, computed, WritableComputedRef } from "vue";
|
||||
import LayInput from "../input/index.vue";
|
||||
import LayScroll from "../scroll/index.vue";
|
||||
import { onClickOutside } from "@vueuse/core";
|
||||
import { SelectItem } from "../../types";
|
||||
import LayTagInput from "../tagInput/index.vue";
|
||||
import LayDropdown from "../dropdown/index.vue";
|
||||
import LaySelectOption, { LaySelectOptionProps } from "../selectOption/index.vue";
|
||||
|
||||
export interface LaySelectProps {
|
||||
name?: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
showEmpty?: boolean;
|
||||
emptyMessage?: string;
|
||||
modelValue?: any;
|
||||
multiple?: boolean;
|
||||
create?: boolean;
|
||||
items?: {
|
||||
label: string;
|
||||
value: any;
|
||||
key: string;
|
||||
disabled: boolean;
|
||||
keyword: string;
|
||||
}[];
|
||||
items?: LaySelectOptionProps[];
|
||||
size?: "lg" | "md" | "sm" | "xs";
|
||||
allowClear?: boolean;
|
||||
}
|
||||
|
||||
const selectRef = shallowRef<undefined | HTMLElement>(undefined);
|
||||
const multipleSearchInputRef = shallowRef<HTMLElement | undefined>(undefined);
|
||||
|
||||
onClickOutside(selectRef, (event: Event) => {
|
||||
openState.value = false;
|
||||
});
|
||||
export interface SelectEmits {
|
||||
(e: "update:modelValue", value: string): void;
|
||||
(e: "change", value: string): void;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<LaySelectProps>(), {
|
||||
modelValue: null,
|
||||
placeholder: "请选择",
|
||||
disabled: false,
|
||||
showEmpty: true,
|
||||
multiple: false,
|
||||
create: false,
|
||||
size: "md",
|
||||
allowClear: false,
|
||||
});
|
||||
|
||||
const openState = ref(false);
|
||||
const emits = defineEmits<SelectEmits>();
|
||||
|
||||
const open = function () {
|
||||
if (props.disabled) {
|
||||
openState.value = false;
|
||||
return;
|
||||
}
|
||||
openState.value = !openState.value;
|
||||
nextTick(() => {
|
||||
multipleSearchInputRef.value?.querySelector("input")?.focus();
|
||||
});
|
||||
};
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "change", "search", "create"]);
|
||||
|
||||
const selectItem = ref<SelectItem>({
|
||||
value: !props.multiple
|
||||
? props.modelValue
|
||||
: props.modelValue
|
||||
? ([] as any[]).concat(props.modelValue)
|
||||
: [],
|
||||
label: props.multiple ? [] : null,
|
||||
multiple: props.multiple,
|
||||
} as SelectItem);
|
||||
|
||||
watch(
|
||||
() => selectItem.value.value,
|
||||
(val) => {
|
||||
emit("update:modelValue", val);
|
||||
emit("change", val);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(props, () => {
|
||||
let value = props.modelValue;
|
||||
if (props.multiple) {
|
||||
if (Array.isArray(value)) {
|
||||
selectItem.value.value = value;
|
||||
selectItem.value.label = value.map((o) => ItemsMap.value[o]);
|
||||
} else {
|
||||
console.error("多选时请传入数组值");
|
||||
}
|
||||
} else {
|
||||
selectItem.value.value = value;
|
||||
selectItem.value.label = ItemsMap.value[value] || "";
|
||||
}
|
||||
});
|
||||
|
||||
const txt = ref("");
|
||||
const disabledItemMap: { [key: string | number]: boolean } = {};
|
||||
const input = ref(false);
|
||||
const value = computed({
|
||||
set(v: any) {
|
||||
txt.value = v;
|
||||
emit("search", v);
|
||||
},
|
||||
const selectedValue = computed({
|
||||
get() {
|
||||
if (input.value) {
|
||||
return txt.value;
|
||||
}
|
||||
return !selectItem.value.multiple && selectItem.value.value !== null
|
||||
? selectItem.value.label
|
||||
: null;
|
||||
return props.modelValue;
|
||||
},
|
||||
});
|
||||
set(val) {
|
||||
emits('update:modelValue', val);
|
||||
emits('change', val);
|
||||
}
|
||||
})
|
||||
|
||||
const selectItemHandle = async function (
|
||||
_selectItem: SelectItem,
|
||||
isChecked?: boolean
|
||||
) {
|
||||
if (!props.multiple) {
|
||||
openState.value = false;
|
||||
}
|
||||
txt.value = "";
|
||||
disabledItemMap[_selectItem.value as string | number] =
|
||||
_selectItem.disabled as boolean;
|
||||
if (typeof isChecked !== "boolean") {
|
||||
props.multiple
|
||||
? (selectItem.value.label as any[]).push(_selectItem.label)
|
||||
: (selectItem.value.label = _selectItem.label);
|
||||
return;
|
||||
}
|
||||
let values = selectItem.value.value;
|
||||
if (props.multiple && Array.isArray(values)) {
|
||||
const _values = values as any[];
|
||||
const _labels = selectItem.value.label as any[];
|
||||
if (isChecked) {
|
||||
_values.push(_selectItem.value);
|
||||
_labels.push(_selectItem.label);
|
||||
} else {
|
||||
_values.splice(_values.indexOf(_selectItem.value), 1);
|
||||
_labels.splice(_labels.indexOf(_selectItem.label), 1);
|
||||
}
|
||||
selectItem.value.value = _values;
|
||||
selectItem.value.label = _labels;
|
||||
} else {
|
||||
selectItem.value.value = _selectItem.value;
|
||||
selectItem.value.label = _selectItem.label;
|
||||
}
|
||||
};
|
||||
const multiple = computed(() => {
|
||||
return props.multiple;
|
||||
})
|
||||
|
||||
const removeItemHandle = function (e: MouseEvent, _selectItem: SelectItem) {
|
||||
e.stopPropagation();
|
||||
selectItemHandle(_selectItem, false);
|
||||
};
|
||||
const ItemsMap: Ref<{ [index: string]: string }> = ref({});
|
||||
const selectItemPush = function (p: SelectItem) {
|
||||
if (p.value !== null) {
|
||||
//@ts-ignore
|
||||
ItemsMap.value[p.value] = p.label;
|
||||
}
|
||||
};
|
||||
|
||||
const clear = () => {
|
||||
emit("update:modelValue", props.multiple ? [] : "");
|
||||
};
|
||||
|
||||
provide("selectItemHandle", selectItemHandle);
|
||||
provide("selectItemPush", selectItemPush);
|
||||
provide("selectItem", selectItem);
|
||||
provide("keyword", txt);
|
||||
provide('selectedValue', selectedValue);
|
||||
provide('multiple', multiple);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="selectRef"
|
||||
class="layui-unselect layui-form-select"
|
||||
:class="{
|
||||
'layui-form-selected': openState,
|
||||
'layui-form-select-multiple': multiple,
|
||||
}"
|
||||
:size="size"
|
||||
>
|
||||
<div class="layui-select-title" @click="open">
|
||||
<input
|
||||
type="text"
|
||||
:placeholder="
|
||||
selectItem.value !== null &&
|
||||
Array.isArray(selectItem.value) &&
|
||||
selectItem.value.length > 0
|
||||
? ''
|
||||
: emptyMessage ?? placeholder
|
||||
"
|
||||
:disabled="disabled"
|
||||
v-model="value"
|
||||
@input="input = true"
|
||||
@blur="input = false"
|
||||
:name="name"
|
||||
:class="[
|
||||
'layui-input',
|
||||
'layui-unselect',
|
||||
{ 'layui-disabled': disabled },
|
||||
]"
|
||||
/>
|
||||
<span class="layui-input-icon-area">
|
||||
<i
|
||||
:class="[
|
||||
'layui-icon layui-icon-triangle-d',
|
||||
{ 'layui-disabled': disabled },
|
||||
]"
|
||||
:style="{ transform: `rotate(${openState ? 180 : 0}deg)` }"
|
||||
></i>
|
||||
<i
|
||||
class="layui-icon layui-icon-close-fill"
|
||||
v-if="(value || selectItem.label?.length) && allowClear"
|
||||
@click.stop="clear"
|
||||
></i>
|
||||
</span>
|
||||
<!-- 多选 -->
|
||||
<div
|
||||
v-if="selectItem.multiple && Array.isArray(selectItem.label)"
|
||||
class="layui-multiple-select-row"
|
||||
>
|
||||
<div class="layui-multiple-select-badge">
|
||||
<template v-for="(item, index) in selectItem.label" :key="index">
|
||||
<lay-badge theme="gray">
|
||||
<span>{{ item }}</span>
|
||||
<i
|
||||
:class="['layui-icon', { 'layui-icon-close': true }]"
|
||||
v-if="
|
||||
!disabled &&
|
||||
!(
|
||||
Array.isArray(selectItem.value) &&
|
||||
selectItem.value.length > 0 &&
|
||||
disabledItemMap[selectItem.value[index]]
|
||||
)
|
||||
"
|
||||
@click="
|
||||
removeItemHandle($event, {
|
||||
label: item,
|
||||
value: Array.isArray(selectItem.value)
|
||||
? selectItem.value[index]
|
||||
: null,
|
||||
})
|
||||
"
|
||||
></i>
|
||||
</lay-badge>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 下拉内容 -->
|
||||
<dl class="layui-anim layui-anim-upbit">
|
||||
<div ref="multipleSearchInputRef" class="layui-multiple-select-input">
|
||||
<lay-input
|
||||
v-if="multiple"
|
||||
v-model="value"
|
||||
@input="input = true"
|
||||
@blur="input = false"
|
||||
:placeholder="placeholder"
|
||||
prefix-icon="layui-icon-search"
|
||||
allow-clear
|
||||
>
|
||||
</lay-input>
|
||||
</div>
|
||||
<template v-if="!multiple && showEmpty && !props.create">
|
||||
<lay-select-option value="-1" :label="emptyMessage ?? placeholder" />
|
||||
</template>
|
||||
<template v-if="props.create">
|
||||
<dd @click="emit('create', txt)">{{ txt }}</dd>
|
||||
</template>
|
||||
<template v-if="props.items">
|
||||
<lay-select-option
|
||||
v-for="(v, k) in props.items"
|
||||
:key="k"
|
||||
:value="v.value"
|
||||
:label="v.label"
|
||||
:disabled="v.disabled"
|
||||
:keyword="v.keyword"
|
||||
></lay-select-option>
|
||||
<div class="layui-select">
|
||||
<lay-dropdown update-at-scroll>
|
||||
<lay-tag-input v-if="multiple" v-model="selectedValue"></lay-tag-input>
|
||||
<lay-input v-else :placeholder="placeholder" v-model="selectedValue"></lay-input>
|
||||
<template #content>
|
||||
<dl class="layui-select-options">
|
||||
<template v-if="items">
|
||||
<lay-select-option v-for="(item, index) in items" v-bind="item" :key="index"></lay-select-option>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</dl>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -6,11 +6,10 @@ export default {
|
||||
|
||||
<script setup lang="ts">
|
||||
import LayCheckbox from "../checkbox/index.vue";
|
||||
import { SelectItem, SelectItemHandle, SelectItemPush } from "../../types";
|
||||
import { computed, inject, onMounted, Ref, ref } from "vue";
|
||||
import { computed, ComputedRef, inject, WritableComputedRef } from "vue";
|
||||
|
||||
export interface LaySelectOptionProps {
|
||||
value: string | null | undefined | number;
|
||||
value: string | object;
|
||||
label: string;
|
||||
keyword?: string;
|
||||
disabled?: boolean;
|
||||
@ -22,67 +21,33 @@ const props = withDefaults(defineProps<LaySelectOptionProps>(), {
|
||||
label: "",
|
||||
});
|
||||
|
||||
const selectItemHandle = inject("selectItemHandle") as SelectItemHandle;
|
||||
const selectItem = inject("selectItem") as Ref<SelectItem>;
|
||||
const selectItemPush = inject("selectItemPush") as Ref<SelectItemPush>;
|
||||
const keyword = inject("keyword") as Ref<string>;
|
||||
const selectedValue: WritableComputedRef<any> = inject("selectedValue") as WritableComputedRef<any>;
|
||||
const multiple: ComputedRef = inject("multiple") as ComputedRef;
|
||||
|
||||
const selectHandle = function () {
|
||||
!props.disabled && callSelectItemHandle(!selected.value);
|
||||
};
|
||||
const callSelectItemHandle = function (isChecked?: boolean) {
|
||||
// console.log("callSelectItemHandle");
|
||||
selectItemHandle(
|
||||
{
|
||||
value: props.value,
|
||||
label: props.label,
|
||||
disabled: props.disabled,
|
||||
},
|
||||
isChecked
|
||||
);
|
||||
};
|
||||
const selected = computed({
|
||||
get() {
|
||||
const selectValues = selectItem.value.value;
|
||||
if (Array.isArray(selectValues)) {
|
||||
return (selectValues as any[]).indexOf(props.value) > -1;
|
||||
const handleSelect = () => {
|
||||
if(!multiple.value) {
|
||||
selectedValue.value = props.value;
|
||||
}
|
||||
}
|
||||
|
||||
const isSelected = computed(() => {
|
||||
if (multiple.value) {
|
||||
return selectedValue.value.indexOf(props.value) != -1;
|
||||
} else {
|
||||
return selectedValue.value === props.value;
|
||||
}
|
||||
return selectItem.value.value === props.value;
|
||||
},
|
||||
set(val) {},
|
||||
});
|
||||
const callSelectItemPush = function () {
|
||||
let item = {
|
||||
value: props.value,
|
||||
label: props.label,
|
||||
disabled: props.disabled,
|
||||
};
|
||||
// @ts-ignore
|
||||
selectItemPush(item);
|
||||
};
|
||||
const search = ref("");
|
||||
onMounted(() => {
|
||||
search.value = props.keyword || props.label;
|
||||
callSelectItemPush();
|
||||
selected.value && callSelectItemHandle();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<dd
|
||||
v-show="keyword ? search.includes(keyword) : true"
|
||||
:value="value"
|
||||
:class="[{ 'layui-this': selected }, { 'layui-disabled': disabled }]"
|
||||
@click="selectHandle"
|
||||
<dd class="layui-select-option" :class="{ 'layui-this': isSelected && !multiple }" @click="handleSelect">
|
||||
<template v-if="multiple">
|
||||
<lay-checkbox v-model="selectedValue" :value="value" skin="primary"
|
||||
><slot>{{ label }}</slot></lay-checkbox
|
||||
>
|
||||
<template v-if="selectItem.multiple">
|
||||
<lay-checkbox
|
||||
skin="primary"
|
||||
v-model="selected"
|
||||
@change="selectHandle"
|
||||
:value="props.value"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<slot>{{ label }}</slot>
|
||||
</template>
|
||||
</dd>
|
||||
</template>
|
||||
|
@ -8,7 +8,7 @@ import "./index.less";
|
||||
import { LayIcon } from "@layui/icons-vue";
|
||||
import { computed, ref } from "vue";
|
||||
import { TinyColor } from "@ctrl/tinycolor";
|
||||
import { TAG_COLORS, tagType } from "./interface";
|
||||
import { tagType } from "./interface";
|
||||
|
||||
export interface LayTagProps {
|
||||
type?: tagType;
|
||||
|
@ -182,6 +182,12 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
const moreCount = computed(() => {
|
||||
if(tagData.value && computedTagData.value) {
|
||||
return tagData.value.length - computedTagData.value.length
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
handleResize();
|
||||
});
|
||||
@ -216,7 +222,7 @@ defineExpose({
|
||||
<template v-if="computedTagData?.length != tagData?.length">
|
||||
<LayToopTip :isDark="false" trigger="click" popperStyle="padding:6px">
|
||||
<LayTag v-bind="tagProps" key="more" :closable="false" :size="size">
|
||||
+{{tagData!.length - computedTagData!.length }}...
|
||||
+{{ moreCount }}...
|
||||
</LayTag>
|
||||
<template #content>
|
||||
<div class="layui-tag-input-collapsed-panel">
|
||||
|
3
package/component/src/utils/arrayUtil.ts
Normal file
3
package/component/src/utils/arrayUtil.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const check = (arr: any[], value: any) => {
|
||||
return arr.indexOf(value) > -1;
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
export * from "./domUtil";
|
||||
export * from "./DomUtil";
|
||||
export * from "./withInstall";
|
||||
export * from "./arrayUtil";
|
@ -19,6 +19,7 @@
|
||||
<li>[新增] tag-input 标签输入框组件。</li>
|
||||
<li>[新增] table 组件 header 插槽, 用于在工具栏与表格之间插入元素。</li>
|
||||
<li>[新增] tabitem 组件 icon 属性, 用于自定义 tab-item 图标。</li>
|
||||
<li>[修复] layout 组件只引入了 footer 时, layui-layout-vertical样式不生效。</li>
|
||||
<li>[修复] cascader 外部清空modelValue, 内部displayValue不清空问题。</li>
|
||||
<li>[修复] tolltip 组件 content 自动定位。</li>
|
||||
<li>[修复] breadcrumb-item 组件无法正确传递 attrs 的问题。</li>
|
||||
|
Loading…
Reference in New Issue
Block a user