✨(component): [Tag}新增 Tag 组件
This commit is contained in:
		
							parent
							
								
									48cacb8d91
								
							
						
					
					
						commit
						24b2cbd143
					
				
							
								
								
									
										88
									
								
								package/component/src/component/tag/index.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								package/component/src/component/tag/index.less
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
			
		||||
@tag-size-default: 24px;
 | 
			
		||||
@tag-size-default-font-size: 12px;
 | 
			
		||||
@tag-size-lg: @tag-size-default + 2px;
 | 
			
		||||
@tag-size-md: @tag-size-default;
 | 
			
		||||
@tag-size-sm: @tag-size-default - 2px;
 | 
			
		||||
@tag-size-xs: @tag-size-default - 2px * 2;
 | 
			
		||||
@tag-size-lg-font-size: @tag-size-default-font-size + 2px;
 | 
			
		||||
@tag-size-md-font-size: @tag-size-default-font-size;
 | 
			
		||||
@tag-size-sm-font-size: @tag-size-default-font-size - 2px;
 | 
			
		||||
@tag-size-xs-font-size: @tag-size-default-font-size - 2px * 2;
 | 
			
		||||
@tag-border-width: 1px;
 | 
			
		||||
 | 
			
		||||
.layui-tag {
 | 
			
		||||
  display: inline-flex;
 | 
			
		||||
  align-items: baseline;
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  height: @tag-size-md;
 | 
			
		||||
  line-height: @tag-size-md - @tag-border-width * 2;
 | 
			
		||||
  padding: 0 6px;
 | 
			
		||||
  font-size: @tag-size-md-font-size;
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
  color: currentColor;
 | 
			
		||||
  border-width: @tag-border-width;
 | 
			
		||||
  border-style: solid;
 | 
			
		||||
  border-color: transparent;
 | 
			
		||||
  border-radius: var(--global-border-radius);
 | 
			
		||||
 | 
			
		||||
  &-icon {
 | 
			
		||||
    margin-right: 4px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-bordered {
 | 
			
		||||
    border-color: var(--global-neutral-color-5);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-size-lg {
 | 
			
		||||
    height: @tag-size-lg;
 | 
			
		||||
    font-size: @tag-size-lg-font-size;
 | 
			
		||||
    line-height: @tag-size-lg - @tag-border-width * 2;
 | 
			
		||||
 | 
			
		||||
    .layui-icon {
 | 
			
		||||
      font-size: @tag-size-lg-font-size - 2px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-size-md {
 | 
			
		||||
    height: @tag-size-md;
 | 
			
		||||
    font-size: @tag-size-md-font-size;
 | 
			
		||||
    line-height: @tag-size-md - @tag-border-width * 2;
 | 
			
		||||
 | 
			
		||||
    .layui-icon {
 | 
			
		||||
      font-size: @tag-size-md-font-size - 2px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-size-sm {
 | 
			
		||||
    height: @tag-size-sm;
 | 
			
		||||
    font-size: @tag-size-sm-font-size;
 | 
			
		||||
    line-height: @tag-size-sm - @tag-border-width * 2;
 | 
			
		||||
 | 
			
		||||
    .layui-icon {
 | 
			
		||||
      font-size: @tag-size-sm-font-size - 2px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-size-xs {
 | 
			
		||||
    height: @tag-size-xs;
 | 
			
		||||
    font-size: @tag-size-xs-font-size;
 | 
			
		||||
    line-height: @tag-size-xs - @tag-border-width * 2;
 | 
			
		||||
 | 
			
		||||
    .layui-icon {
 | 
			
		||||
      font-size: @tag-size-xs-font-size - 2px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  & &-close-icon {
 | 
			
		||||
    margin-left: 4px;
 | 
			
		||||
    font-size: @tag-size-default-font-size - 2px;
 | 
			
		||||
 | 
			
		||||
    .layui-icon {
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								package/component/src/component/tag/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								package/component/src/component/tag/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
import { withInstall, WithInstallType } from "../../utils";
 | 
			
		||||
import Component from "./index.vue";
 | 
			
		||||
 | 
			
		||||
const component: WithInstallType<typeof Component> = withInstall(Component);
 | 
			
		||||
export default component;
 | 
			
		||||
							
								
								
									
										71
									
								
								package/component/src/component/tag/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								package/component/src/component/tag/index.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
export default {
 | 
			
		||||
  name: "LayTag",
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import "./index.less";
 | 
			
		||||
import { LayIcon } from "@layui/icons-vue";
 | 
			
		||||
import { computed, ref } from "vue";
 | 
			
		||||
import { TAG_COLORS, TagColor } from "./interface";
 | 
			
		||||
 | 
			
		||||
export interface LayTagProps {
 | 
			
		||||
  color?: TagColor | string;
 | 
			
		||||
  closable?: boolean;
 | 
			
		||||
  size?: string;
 | 
			
		||||
  bordered?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<LayTagProps>(), {
 | 
			
		||||
  color: "green",
 | 
			
		||||
  size: "md",
 | 
			
		||||
  closable: false,
 | 
			
		||||
  bordered: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(["close"]);
 | 
			
		||||
 | 
			
		||||
const isBuiltInColor = computed(
 | 
			
		||||
  () => props.color && TAG_COLORS.includes(props.color as any)
 | 
			
		||||
);
 | 
			
		||||
const isCustomColor = computed(
 | 
			
		||||
  () => props.color && !TAG_COLORS.includes(props.color as any)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const visible = ref(true);
 | 
			
		||||
 | 
			
		||||
const handleClose = (e: MouseEvent) => {
 | 
			
		||||
  //visible.value = false;
 | 
			
		||||
  emit("close", e);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const classTag = computed(() => [
 | 
			
		||||
  "layui-tag",
 | 
			
		||||
  `layui-tag-size-${props.size}`,
 | 
			
		||||
  {
 | 
			
		||||
    [`layui-bg-${props.color}`]: isBuiltInColor,
 | 
			
		||||
    "layui-tag-bordered": props.bordered,
 | 
			
		||||
  },
 | 
			
		||||
]);
 | 
			
		||||
 | 
			
		||||
const styleTag = computed(() => {
 | 
			
		||||
  return isCustomColor.value ? { backgroundColor: props.color } : undefined;
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <span v-if="visible" :class="classTag" :style="styleTag">
 | 
			
		||||
    <span v-if="$slots.icon" class="layui-tag-icon">
 | 
			
		||||
      <slot name="icon" />
 | 
			
		||||
    </span>
 | 
			
		||||
    <slot />
 | 
			
		||||
    <span
 | 
			
		||||
      v-if="closable"
 | 
			
		||||
      class="layui-tag-close-icon"
 | 
			
		||||
      @click.stop="handleClose"
 | 
			
		||||
    >
 | 
			
		||||
      <slot name="close-icon">
 | 
			
		||||
        <lay-icon type="layui-icon-close"></lay-icon>
 | 
			
		||||
      </slot>
 | 
			
		||||
    </span>
 | 
			
		||||
  </span>
 | 
			
		||||
</template>
 | 
			
		||||
							
								
								
									
										11
									
								
								package/component/src/component/tag/interface.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								package/component/src/component/tag/interface.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
export const TAG_COLORS = [
 | 
			
		||||
  "red",
 | 
			
		||||
  "orange",
 | 
			
		||||
  "green",
 | 
			
		||||
  "cyan",
 | 
			
		||||
  "blue",
 | 
			
		||||
  "black",
 | 
			
		||||
  "gray",
 | 
			
		||||
] as const;
 | 
			
		||||
 | 
			
		||||
export type TagColor = typeof TAG_COLORS[number];
 | 
			
		||||
							
								
								
									
										64
									
								
								package/component/src/component/tagInput/Tag.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								package/component/src/component/tagInput/Tag.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
export default {
 | 
			
		||||
  name: "Tag",
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
 | 
			
		||||
export interface LayTagProps {
 | 
			
		||||
  theme?: string;
 | 
			
		||||
  closable?: boolean;
 | 
			
		||||
  size?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<LayTagProps>(), {
 | 
			
		||||
  closable: true,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(["close"]);
 | 
			
		||||
 | 
			
		||||
const visible = ref(true);
 | 
			
		||||
 | 
			
		||||
const handleClose = (e: MouseEvent) => {
 | 
			
		||||
  visible.value = false;
 | 
			
		||||
  emit("close", e);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-badge v-if="visible" theme="green">
 | 
			
		||||
    <template v-if="$slots.default" #default>
 | 
			
		||||
      <slot name="default"></slot>
 | 
			
		||||
      <lay-icon
 | 
			
		||||
        v-if="closable"
 | 
			
		||||
        type="layui-icon-close"
 | 
			
		||||
        @click.stop="handleClose"
 | 
			
		||||
      ></lay-icon>
 | 
			
		||||
    </template>
 | 
			
		||||
  </lay-badge>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<!-- <template v-for="(item, index) in selectItem.label" :key="index">
 | 
			
		||||
            <lay-badge theme="green">
 | 
			
		||||
              <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> -->
 | 
			
		||||
							
								
								
									
										65
									
								
								package/component/src/component/tagInput/index.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								package/component/src/component/tagInput/index.less
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
.layui-input-tag {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  display: block;
 | 
			
		||||
  padding: 0 5px;
 | 
			
		||||
  height: auto;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
 | 
			
		||||
  .layui-input-prefix {
 | 
			
		||||
    display: inline;
 | 
			
		||||
    text-align: left;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    flex: unset;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .layui-input-suffix{
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    right: 3px;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .layui-input {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    padding-left: 0;
 | 
			
		||||
    width: auto;
 | 
			
		||||
    flex: 1;
 | 
			
		||||
    max-width: 100%;
 | 
			
		||||
    min-width: 12px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-input-tag-collapsed-panel,
 | 
			
		||||
.layui-input-tag {
 | 
			
		||||
  .layui-badge {
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
    height: 28px;
 | 
			
		||||
    line-height: 28px;
 | 
			
		||||
    user-select: none;
 | 
			
		||||
    white-space: pre-wrap;
 | 
			
		||||
 | 
			
		||||
    .layui-icon {
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
      padding-left: 3px;
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        color: #ff5722;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-input-tag-collapsed-panel {
 | 
			
		||||
  white-space: normal;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  flex-wrap: wrap;
 | 
			
		||||
  width: fit-content;
 | 
			
		||||
  max-width: 200px;
 | 
			
		||||
  height: auto;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  .layui-badge{
 | 
			
		||||
    margin-bottom: 4px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								package/component/src/component/tagInput/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								package/component/src/component/tagInput/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
import { withInstall, WithInstallType } from "../../utils";
 | 
			
		||||
import Component from "./index.vue";
 | 
			
		||||
 | 
			
		||||
const component: WithInstallType<typeof Component> = withInstall(Component);
 | 
			
		||||
export default component;
 | 
			
		||||
							
								
								
									
										158
									
								
								package/component/src/component/tagInput/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								package/component/src/component/tagInput/index.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,158 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
export default {
 | 
			
		||||
  name: "LayInputTag",
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import "./index.less";
 | 
			
		||||
import Tag from "./Tag.vue";
 | 
			
		||||
import LayToopTip from "../tooltip/index.vue";
 | 
			
		||||
import { onMounted, shallowRef, ref, watch, computed } from "vue";
 | 
			
		||||
 | 
			
		||||
export interface TagData {
 | 
			
		||||
  value?: string | number;
 | 
			
		||||
  label?: string;
 | 
			
		||||
  closable?: boolean;
 | 
			
		||||
  [other: string]: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface LayInputTagProps {
 | 
			
		||||
  modelValue?: TagData[];
 | 
			
		||||
  inputValue?: string;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
  placeholder?: string;
 | 
			
		||||
  readonly?: boolean;
 | 
			
		||||
  allowClear?: boolean;
 | 
			
		||||
  max?: number;
 | 
			
		||||
  minCollapsedNum?: number;
 | 
			
		||||
  collapseTagsTooltip?: boolean;
 | 
			
		||||
  size?: "md" | "sm" | "xs";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<LayInputTagProps>(), {
 | 
			
		||||
  disabled: false,
 | 
			
		||||
  placeholder: "",
 | 
			
		||||
  readonly: false,
 | 
			
		||||
  allowClear: true,
 | 
			
		||||
  minCollapsedNum: 10,
 | 
			
		||||
  //max:3
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(["update:modelValue", "update:inputValue"]);
 | 
			
		||||
 | 
			
		||||
const mirrorRef = shallowRef<HTMLElement | undefined>(undefined);
 | 
			
		||||
const inputRef = shallowRef<HTMLElement | undefined>(undefined);
 | 
			
		||||
 | 
			
		||||
const tagData = ref<TagData[]>(props.modelValue ?? []);
 | 
			
		||||
const inputValue = ref<string>();
 | 
			
		||||
const oldInputValue = ref<string>();
 | 
			
		||||
 | 
			
		||||
const computedTagData = computed(() => {
 | 
			
		||||
  return props.minCollapsedNum
 | 
			
		||||
    ? tagData.value?.slice(0, props.minCollapsedNum)
 | 
			
		||||
    : tagData.value;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const collapsedTagData = computed(() => {
 | 
			
		||||
  return props.minCollapsedNum && tagData.value?.length > props.minCollapsedNum
 | 
			
		||||
    ? tagData.value?.slice(props.minCollapsedNum)
 | 
			
		||||
    : [];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const handleInputEnter = (e: KeyboardEvent) => {
 | 
			
		||||
  e.preventDefault();
 | 
			
		||||
  const valueStr = inputValue.value ? String(inputValue.value).trim() : "";
 | 
			
		||||
  if (!valueStr || !tagData.value) return;
 | 
			
		||||
  const isLimit = props.max && tagData.value?.length >= props.max;
 | 
			
		||||
  if (!isLimit) {
 | 
			
		||||
    tagData.value =
 | 
			
		||||
      tagData.value instanceof Array
 | 
			
		||||
        ? tagData.value.concat(String(valueStr))
 | 
			
		||||
        : [valueStr];
 | 
			
		||||
    inputValue.value = "";
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handlerInputBackspaceKeyUp = (e: KeyboardEvent) => {
 | 
			
		||||
  if (!tagData.value || !tagData.value.length) return;
 | 
			
		||||
  if (!oldInputValue.value && ["Backspace", "Delete"].includes(e.code)) {
 | 
			
		||||
    tagData.value = tagData.value.slice(0, -1);
 | 
			
		||||
  }
 | 
			
		||||
  oldInputValue.value = inputValue.value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handlerClearClick = (e: MouseEvent) => {
 | 
			
		||||
  tagData.value = [];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handlerClose = (index: number) => {
 | 
			
		||||
  if (!tagData.value) return;
 | 
			
		||||
  const arr = [...tagData.value];
 | 
			
		||||
  arr.splice(index, 1);
 | 
			
		||||
  tagData.value = arr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handlerFocus = (e: MouseEvent) => {
 | 
			
		||||
  (
 | 
			
		||||
    (e.target as HTMLElement).querySelector(".layui-input") as HTMLInputElement
 | 
			
		||||
  )?.focus();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
watch(tagData, (val) => {
 | 
			
		||||
  emit("update:modelValue", val);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
watch(inputValue, (val) => {
 | 
			
		||||
  emit("update:inputValue", val);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onMounted(() => {});
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-input
 | 
			
		||||
    class="layui-input-tag"
 | 
			
		||||
    v-model="inputValue"
 | 
			
		||||
    :placeholder="placeholder"
 | 
			
		||||
    :readonly="readonly"
 | 
			
		||||
    @keydown.enter="handleInputEnter"
 | 
			
		||||
    @keyup="handlerInputBackspaceKeyUp"
 | 
			
		||||
    @click="handlerFocus"
 | 
			
		||||
  >
 | 
			
		||||
    <template #prefix>
 | 
			
		||||
      <template
 | 
			
		||||
        v-for="(item, index) of computedTagData"
 | 
			
		||||
        :key="`${item}-${index}`"
 | 
			
		||||
      >
 | 
			
		||||
        <Tag :closable="!readonly" @close="handlerClose(index)">
 | 
			
		||||
          {{ item }}
 | 
			
		||||
        </Tag>
 | 
			
		||||
      </template>
 | 
			
		||||
      <template v-if="computedTagData?.length != tagData?.length">
 | 
			
		||||
        <LayToopTip :isDark="false">
 | 
			
		||||
          <Tag key="more" :closable="false"
 | 
			
		||||
            >+{{ tagData?.length - computedTagData?.length }}...</Tag
 | 
			
		||||
          >
 | 
			
		||||
          <template #content>
 | 
			
		||||
            <div class="layui-input-tag-collapsed-panel">
 | 
			
		||||
              <template
 | 
			
		||||
                v-for="(item, index) of tagData"
 | 
			
		||||
                :key="`${item}-${index}`"
 | 
			
		||||
              >
 | 
			
		||||
                <Tag
 | 
			
		||||
                  v-if="index >= minCollapsedNum"
 | 
			
		||||
                  :closable="!readonly"
 | 
			
		||||
                  @close="handlerClose(index)"
 | 
			
		||||
                >
 | 
			
		||||
                  {{ item }}
 | 
			
		||||
                </Tag>
 | 
			
		||||
              </template>
 | 
			
		||||
            </div>
 | 
			
		||||
          </template>
 | 
			
		||||
        </LayToopTip>
 | 
			
		||||
      </template>
 | 
			
		||||
    </template>
 | 
			
		||||
    <template #suffix v-if="allowClear && tagData?.length">
 | 
			
		||||
      <lay-icon type="layui-icon-close-fill" @click.stop="handlerClearClick" />
 | 
			
		||||
    </template>
 | 
			
		||||
  </lay-input>
 | 
			
		||||
</template>
 | 
			
		||||
@ -88,6 +88,7 @@ import LayNoticeBar from "./component/noticeBar/index";
 | 
			
		||||
import LayPageHeader from "./component/pageHeader/index";
 | 
			
		||||
import LayCascader from "./component/cascader/index";
 | 
			
		||||
import LayAffix from "./component/affix/index";
 | 
			
		||||
import LayTag from "./component/tag/index";
 | 
			
		||||
import LayConfigProvider from "./provider";
 | 
			
		||||
import { InstallOptions } from "./types";
 | 
			
		||||
 | 
			
		||||
@ -174,6 +175,7 @@ const components: Record<string, Plugin> = {
 | 
			
		||||
  LayPageHeader,
 | 
			
		||||
  LayCascader,
 | 
			
		||||
  LayAffix,
 | 
			
		||||
  LayTag,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const install = (app: App, options?: InstallOptions): void => {
 | 
			
		||||
@ -267,6 +269,7 @@ export {
 | 
			
		||||
  LayPageHeader,
 | 
			
		||||
  LayCascader,
 | 
			
		||||
  LayAffix,
 | 
			
		||||
  LayTag,
 | 
			
		||||
  install,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										313
									
								
								package/document-component/src/document/zh-CN/components/tag.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								package/document-component/src/document/zh-CN/components/tag.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,313 @@
 | 
			
		||||
::: anchor
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 基本介绍
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: describe 标签组件。
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 基础使用
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: demo 标签的基本用法。
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-tag>tag</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag bordered color="#FFF">tag</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag closable>tag</lay-tag>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 标签尺寸
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: demo 通过 size 属性控制标签尺寸。
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-tag>default</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="lg">tag lg</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="md">tag md</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="sm">tag sm</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="xs">tag xs</lay-tag>
 | 
			
		||||
  <br><br>
 | 
			
		||||
  <lay-tag><template #icon><lay-icon type="layui-icon-addition" /></template>default</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="lg"><template #icon><lay-icon type="layui-icon-addition" /></template>tag lg</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="md"><template #icon><lay-icon type="layui-icon-addition" /></template>tag md</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="sm"><template #icon><lay-icon type="layui-icon-addition" /></template>tag sm</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="xs"><template #icon><lay-icon type="layui-icon-addition" /></template>tag xs</lay-tag>
 | 
			
		||||
  <br><br>
 | 
			
		||||
  <lay-tag closable>
 | 
			
		||||
    <template #icon><lay-icon type="layui-icon-addition" /></template>
 | 
			
		||||
    default
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
    
 | 
			
		||||
    <lay-tag size="lg" closable>
 | 
			
		||||
    <template #icon><lay-icon type="layui-icon-addition" /></template>
 | 
			
		||||
    tag lg
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
    
 | 
			
		||||
    <lay-tag size="md" closable>
 | 
			
		||||
    <template #icon><lay-icon type="layui-icon-addition" /></template>
 | 
			
		||||
    tag md
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="sm" closable>
 | 
			
		||||
    <template #icon><lay-icon type="layui-icon-addition" /></template>
 | 
			
		||||
    tag sm
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag size="xs" closable>
 | 
			
		||||
    <template #icon><lay-icon type="layui-icon-addition" /></template>
 | 
			
		||||
    tag xs
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
    
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 可关闭
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: demo 通过 closable 属性控制标签是否可关闭
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-tag closable>Tag</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag closable>
 | 
			
		||||
    <template #icon><lay-icon type="layui-icon-addition" /></template>
 | 
			
		||||
    Tag 2
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
      
 | 
			
		||||
  <lay-tag closable>
 | 
			
		||||
    <template #icon><lay-icon type="layui-icon-addition" /></template>
 | 
			
		||||
    自定义关闭图标
 | 
			
		||||
    <template #close-icon><lay-icon type="layui-icon-close-fill" /></template>
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 标签颜色
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: demo 标签颜色,待优化。
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <span v-for="color in TAG_COLORS">
 | 
			
		||||
  <lay-tag :color="color">Tag</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  </span>
 | 
			
		||||
  <br><br>
 | 
			
		||||
  <span v-for="color in TAG_COLORS">
 | 
			
		||||
  <lay-tag :color="color" bordered>Tag</lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  </span>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { ref } from 'vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  setup() {
 | 
			
		||||
 | 
			
		||||
  const TAG_COLORS = [
 | 
			
		||||
  "red",
 | 
			
		||||
  "orange",
 | 
			
		||||
  "green",
 | 
			
		||||
  "cyan",
 | 
			
		||||
  "blue",
 | 
			
		||||
  "black",
 | 
			
		||||
  "gray",
 | 
			
		||||
  "#EEE",
 | 
			
		||||
  "#5FB878",
 | 
			
		||||
  "#FFB800",
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      TAG_COLORS
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 图标插槽
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: demo 标签的基本用法。
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-tag bordered size="lg" color="#FFF">
 | 
			
		||||
    <template #icon>
 | 
			
		||||
      <lay-icon type="layui-icon-vercode" />
 | 
			
		||||
    </template>
 | 
			
		||||
    tag
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag bordered size="lg" color="#FFF">
 | 
			
		||||
    <template #icon>
 | 
			
		||||
      <lay-icon type="layui-icon-login-qq" />
 | 
			
		||||
    </template>
 | 
			
		||||
    tag
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
    
 | 
			
		||||
  <lay-tag bordered size="lg" color="#FFF">
 | 
			
		||||
    <template #icon>
 | 
			
		||||
      <lay-icon type="layui-icon-star-fill" />
 | 
			
		||||
    </template>
 | 
			
		||||
    tag
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
    
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 动态编辑
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: demo 标签的基本用法。
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  {{ tagData }}
 | 
			
		||||
  <br><br>
 | 
			
		||||
  <template v-for="(tag, index) of tagData" :key="`tag-${index}`">
 | 
			
		||||
  <lay-tag 
 | 
			
		||||
    closable
 | 
			
		||||
    @close="handleClose(index)"
 | 
			
		||||
    color="#EEE"
 | 
			
		||||
    style="margin-right: 5px;"
 | 
			
		||||
    >
 | 
			
		||||
    {{tag}}
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
  </template>
 | 
			
		||||
  <span id="tagDemo" @click="handlerFocus">
 | 
			
		||||
    <lay-input 
 | 
			
		||||
    v-if="showInput"   
 | 
			
		||||
    ref="inputRef"      
 | 
			
		||||
    v-model.trim="inputVal"
 | 
			
		||||
    autofocus
 | 
			
		||||
    style="width:60px; height:24px"
 | 
			
		||||
    @keyup.enter="handleAdd"
 | 
			
		||||
    @blur="handleAdd" />
 | 
			
		||||
  <lay-tag 
 | 
			
		||||
    v-else 
 | 
			
		||||
    color="#EEE" 
 | 
			
		||||
    >
 | 
			
		||||
    <template #icon>
 | 
			
		||||
      <lay-icon type="layui-icon-addition"/>
 | 
			
		||||
    </template>
 | 
			
		||||
    添加
 | 
			
		||||
  </lay-tag>
 | 
			
		||||
  </span>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { ref, nextTick } from 'vue';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  setup() {
 | 
			
		||||
    const tagData = ref(['Tag']);
 | 
			
		||||
    const inputRef = ref(null);
 | 
			
		||||
    const showInput = ref(false);
 | 
			
		||||
    const inputVal = ref('');
 | 
			
		||||
 | 
			
		||||
    const handleAdd = () => {
 | 
			
		||||
      if (inputVal.value) {
 | 
			
		||||
        tagData.value.push(inputVal.value);
 | 
			
		||||
        inputVal.value = '';
 | 
			
		||||
      }
 | 
			
		||||
      showInput.value = false;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const handleClose = (index) => {
 | 
			
		||||
      tagData.value.splice(index, 1);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const handlerFocus = (e) => {
 | 
			
		||||
      showInput.value = true;
 | 
			
		||||
      console.log("FIXME 临时")
 | 
			
		||||
      setTimeout(() => {
 | 
			
		||||
        document.querySelector('#tagDemo input').focus()
 | 
			
		||||
      },200)
 | 
			
		||||
 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      tagData,
 | 
			
		||||
      inputRef,
 | 
			
		||||
      showInput,
 | 
			
		||||
      inputVal,
 | 
			
		||||
      handleAdd,
 | 
			
		||||
      handleClose,
 | 
			
		||||
      handlerFocus,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
::: title Tag 属性
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: table
 | 
			
		||||
 | 
			
		||||
| 属性        | 描述     | 类型    | 默认值    | 可选值                             |
 | 
			
		||||
| ----------- | -------- | ------ | ------ | ------ |
 | 
			
		||||
| size | 标签大小 | string | md | `lg` `md` `sm` `xs`|
 | 
			
		||||
| color | 标签颜色 | string | `green`| `red` `orange` `green` `cyan` `blue` `black` `gray` `string` | 
 | 
			
		||||
| bordered | 是否显示边框 | boolean | false | `true` `false`|
 | 
			
		||||
| closable |  是否可关闭 | boolean | false | `true` `false`|
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::title Tag 插槽
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::table
 | 
			
		||||
| 插槽 | 描述 | 参数 |
 | 
			
		||||
|------ |----------|-----------|
 | 
			
		||||
| default | 默认插槽 | - |
 | 
			
		||||
| icon | 图标 | - |
 | 
			
		||||
| close-icon | 关闭图标 | - |
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::title Tag 事件
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::table
 | 
			
		||||
| 事件 | 描述 | 参数 |
 | 
			
		||||
|------ |----------|-----------|
 | 
			
		||||
| close | 关闭时触发 | e: MouseEvent |
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: contributor tag
 | 
			
		||||
:::  
 | 
			
		||||
 | 
			
		||||
::: previousNext tag
 | 
			
		||||
:::
 | 
			
		||||
@ -419,6 +419,11 @@ const zhCN = [
 | 
			
		||||
            component: () => import("../document/zh-CN/components/photo.md"),
 | 
			
		||||
            meta: { title: "相册" },
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            path: "/zh-CN/components/tag",
 | 
			
		||||
            component: () => import("../document/zh-CN/components/tag.md"),
 | 
			
		||||
            meta: { title: "标签" },
 | 
			
		||||
          },
 | 
			
		||||
        ],
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user