mirror of
				https://github.com/pure-admin/vue-pure-admin.git
				synced 2025-11-03 13:44:47 +08:00 
			
		
		
		
	feat: ReSegmented分段控制器新增size属性,以便适配不同的场景 (#1016)
				
					
				
			* feat: `ReSegmented`分段控制器新增`size`属性,以便适配不同的场景
This commit is contained in:
		
							parent
							
								
									4f44f72a2c
								
							
						
					
					
						commit
						f486ba60a0
					
				@ -1,11 +1,20 @@
 | 
			
		||||
.pure-segmented {
 | 
			
		||||
  --pure-control-padding-horizontal: 12px;
 | 
			
		||||
  --pure-control-padding-horizontal-sm: 8px;
 | 
			
		||||
  --pure-segmented-track-padding: 2px;
 | 
			
		||||
  --pure-segmented-line-width: 1px;
 | 
			
		||||
 | 
			
		||||
  --pure-segmented-border-radius-small: 4px;
 | 
			
		||||
  --pure-segmented-border-radius-base: 6px;
 | 
			
		||||
  --pure-segmented-border-radius-large: 8px;
 | 
			
		||||
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  padding: 2px;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  padding: var(--pure-segmented-track-padding);
 | 
			
		||||
  font-size: var(--el-font-size-base);
 | 
			
		||||
  color: rgba(0, 0, 0, 0.65);
 | 
			
		||||
  background-color: rgb(0 0 0 / 4%);
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
  border-radius: var(--pure-segmented-border-radius-base);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pure-segmented-block {
 | 
			
		||||
@ -23,6 +32,75 @@
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* small */
 | 
			
		||||
.pure-segmented.pure-segmented--small {
 | 
			
		||||
  border-radius: var(--pure-segmented-border-radius-small);
 | 
			
		||||
}
 | 
			
		||||
.pure-segmented.pure-segmented--small .pure-segmented-item {
 | 
			
		||||
  border-radius: var(--el-border-radius-small);
 | 
			
		||||
}
 | 
			
		||||
.pure-segmented.pure-segmented--small .pure-segmented-item > div {
 | 
			
		||||
  min-height: calc(
 | 
			
		||||
    var(--el-component-size-small) - var(--pure-segmented-track-padding) * 2
 | 
			
		||||
  );
 | 
			
		||||
  line-height: calc(
 | 
			
		||||
    var(--el-component-size-small) - var(--pure-segmented-track-padding) * 2
 | 
			
		||||
  );
 | 
			
		||||
  padding: 0
 | 
			
		||||
    calc(
 | 
			
		||||
      var(--pure-control-padding-horizontal-sm) -
 | 
			
		||||
        var(--pure-segmented-line-width)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* large */
 | 
			
		||||
.pure-segmented.pure-segmented--large {
 | 
			
		||||
  border-radius: var(--pure-segmented-border-radius-large);
 | 
			
		||||
}
 | 
			
		||||
.pure-segmented.pure-segmented--large .pure-segmented-item {
 | 
			
		||||
  border-radius: calc(
 | 
			
		||||
    var(--el-border-radius-base) + var(--el-border-radius-small)
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
.pure-segmented.pure-segmented--large .pure-segmented-item > div {
 | 
			
		||||
  min-height: calc(
 | 
			
		||||
    var(--el-component-size-large) - var(--pure-segmented-track-padding) * 2
 | 
			
		||||
  );
 | 
			
		||||
  line-height: calc(
 | 
			
		||||
    var(--el-component-size-large) - var(--pure-segmented-track-padding) * 2
 | 
			
		||||
  );
 | 
			
		||||
  padding: 0
 | 
			
		||||
    calc(
 | 
			
		||||
      var(--pure-control-padding-horizontal) - var(--pure-segmented-line-width)
 | 
			
		||||
    );
 | 
			
		||||
  font-size: var(--el-font-size-medium);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* default */
 | 
			
		||||
.pure-segmented-item {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  border-radius: var(--el-border-radius-base);
 | 
			
		||||
  transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
}
 | 
			
		||||
.pure-segmented .pure-segmented-item > div {
 | 
			
		||||
  min-height: calc(
 | 
			
		||||
    var(--el-component-size) - var(--pure-segmented-track-padding) * 2
 | 
			
		||||
  );
 | 
			
		||||
  line-height: calc(
 | 
			
		||||
    var(--el-component-size) - var(--pure-segmented-track-padding) * 2
 | 
			
		||||
  );
 | 
			
		||||
  padding: 0
 | 
			
		||||
    calc(
 | 
			
		||||
      var(--pure-control-padding-horizontal) - var(--pure-segmented-line-width)
 | 
			
		||||
    );
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  transition: 0.1s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pure-segmented-group {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  display: flex;
 | 
			
		||||
@ -52,23 +130,6 @@
 | 
			
		||||
  will-change: transform, width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pure-segmented-item {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
  transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pure-segmented-item > div {
 | 
			
		||||
  min-height: 28px;
 | 
			
		||||
  line-height: 28px;
 | 
			
		||||
  padding: 0 11px;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pure-segmented-item > input {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  inset-block-start: 0;
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,14 @@
 | 
			
		||||
import "./index.css";
 | 
			
		||||
import type { OptionsType } from "./type";
 | 
			
		||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
			
		||||
import {
 | 
			
		||||
  useDark,
 | 
			
		||||
  isNumber,
 | 
			
		||||
  isFunction,
 | 
			
		||||
  useResizeObserver
 | 
			
		||||
} from "@pureadmin/utils";
 | 
			
		||||
import {
 | 
			
		||||
  type PropType,
 | 
			
		||||
  h,
 | 
			
		||||
  ref,
 | 
			
		||||
  toRef,
 | 
			
		||||
@ -8,14 +17,6 @@ import {
 | 
			
		||||
  defineComponent,
 | 
			
		||||
  getCurrentInstance
 | 
			
		||||
} from "vue";
 | 
			
		||||
import type { OptionsType } from "./type";
 | 
			
		||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
			
		||||
import {
 | 
			
		||||
  isFunction,
 | 
			
		||||
  isNumber,
 | 
			
		||||
  useDark,
 | 
			
		||||
  useResizeObserver
 | 
			
		||||
} from "@pureadmin/utils";
 | 
			
		||||
 | 
			
		||||
const props = {
 | 
			
		||||
  options: {
 | 
			
		||||
@ -32,6 +33,10 @@ const props = {
 | 
			
		||||
  block: {
 | 
			
		||||
    type: Boolean,
 | 
			
		||||
    default: false
 | 
			
		||||
  },
 | 
			
		||||
  /** 控件尺寸	 */
 | 
			
		||||
  size: {
 | 
			
		||||
    type: String as PropType<"small" | "default" | "large">
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -81,13 +86,14 @@ export default defineComponent({
 | 
			
		||||
    function handleInit(index = curIndex.value) {
 | 
			
		||||
      nextTick(() => {
 | 
			
		||||
        const curLabelRef = instance?.proxy?.$refs[`labelRef${index}`] as ElRef;
 | 
			
		||||
        if (!curLabelRef) return;
 | 
			
		||||
        width.value = curLabelRef.clientWidth;
 | 
			
		||||
        translateX.value = curLabelRef.offsetLeft;
 | 
			
		||||
        initStatus.value = true;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (props.block) {
 | 
			
		||||
    function handleResizeInit() {
 | 
			
		||||
      useResizeObserver(".pure-segmented", () => {
 | 
			
		||||
        nextTick(() => {
 | 
			
		||||
          handleInit(curIndex.value);
 | 
			
		||||
@ -95,6 +101,8 @@ export default defineComponent({
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    props.block && handleResizeInit();
 | 
			
		||||
 | 
			
		||||
    watch(
 | 
			
		||||
      () => curIndex.value,
 | 
			
		||||
      index => {
 | 
			
		||||
@ -103,11 +111,12 @@ export default defineComponent({
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        deep: true,
 | 
			
		||||
        immediate: true
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    watch(() => props.size, handleResizeInit);
 | 
			
		||||
 | 
			
		||||
    const rendLabel = () => {
 | 
			
		||||
      return props.options.map((option, index) => {
 | 
			
		||||
        return (
 | 
			
		||||
@ -167,7 +176,12 @@ export default defineComponent({
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
      <div
 | 
			
		||||
        class={["pure-segmented", props.block ? "pure-segmented-block" : ""]}
 | 
			
		||||
        class={{
 | 
			
		||||
          "pure-segmented": true,
 | 
			
		||||
          "pure-segmented-block": props.block,
 | 
			
		||||
          "pure-segmented--large": props.size === "large",
 | 
			
		||||
          "pure-segmented--small": props.size === "small"
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <div class="pure-segmented-group">
 | 
			
		||||
          <div
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
<script setup lang="tsx">
 | 
			
		||||
import { h, ref } from "vue";
 | 
			
		||||
import { h, ref, watch } from "vue";
 | 
			
		||||
import { message } from "@/utils/message";
 | 
			
		||||
import HomeFilled from "@iconify-icons/ep/home-filled";
 | 
			
		||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
			
		||||
@ -11,6 +11,8 @@ defineOptions({
 | 
			
		||||
 | 
			
		||||
/** 基础用法 */
 | 
			
		||||
const value = ref(4); // 必须为number类型
 | 
			
		||||
const size = ref("default");
 | 
			
		||||
const dynamicSize = ref();
 | 
			
		||||
 | 
			
		||||
const optionsBasis: Array<OptionsType> = [
 | 
			
		||||
  {
 | 
			
		||||
@ -192,13 +194,22 @@ function onChange({ index, option }) {
 | 
			
		||||
    type: "success"
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
watch(size, val => (dynamicSize.value = size.value));
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <el-card shadow="never">
 | 
			
		||||
    <template #header>
 | 
			
		||||
      <div class="card-header">
 | 
			
		||||
        <span class="font-medium">分段控制器</span>
 | 
			
		||||
        <el-space wrap :size="40">
 | 
			
		||||
          <span style="font-size: 16px; font-weight: 800"> 分段控制器 </span>
 | 
			
		||||
          <el-radio-group v-model="size" size="small">
 | 
			
		||||
            <el-radio value="large">大尺寸</el-radio>
 | 
			
		||||
            <el-radio value="default">默认尺寸</el-radio>
 | 
			
		||||
            <el-radio value="small">小尺寸</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-space>
 | 
			
		||||
      </div>
 | 
			
		||||
    </template>
 | 
			
		||||
    <el-scrollbar>
 | 
			
		||||
@ -207,28 +218,32 @@ function onChange({ index, option }) {
 | 
			
		||||
          {{ optionsBasis[value].label }}
 | 
			
		||||
        </span>
 | 
			
		||||
      </p>
 | 
			
		||||
      <Segmented v-model="value" :options="optionsBasis" />
 | 
			
		||||
      <Segmented v-model="value" :options="optionsBasis" :size="dynamicSize" />
 | 
			
		||||
      <el-divider />
 | 
			
		||||
      <p class="mb-2">tooltip 提示</p>
 | 
			
		||||
      <Segmented :options="optionsTooltip" />
 | 
			
		||||
      <Segmented :options="optionsTooltip" :size="dynamicSize" />
 | 
			
		||||
      <el-divider />
 | 
			
		||||
      <p class="mb-2">change 事件</p>
 | 
			
		||||
      <Segmented :options="optionsChange" @change="onChange" />
 | 
			
		||||
      <Segmented
 | 
			
		||||
        :options="optionsChange"
 | 
			
		||||
        :size="dynamicSize"
 | 
			
		||||
        @change="onChange"
 | 
			
		||||
      />
 | 
			
		||||
      <el-divider />
 | 
			
		||||
      <p class="mb-2">禁用</p>
 | 
			
		||||
      <Segmented :options="optionsDisabled" />
 | 
			
		||||
      <Segmented :options="optionsDisabled" :size="dynamicSize" />
 | 
			
		||||
      <el-divider />
 | 
			
		||||
      <p class="mb-2">block 属性(将宽度调整为父元素宽度)</p>
 | 
			
		||||
      <Segmented :options="optionsBlock" block />
 | 
			
		||||
      <Segmented :options="optionsBlock" block :size="dynamicSize" />
 | 
			
		||||
      <el-divider />
 | 
			
		||||
      <p class="mb-2">可设置图标</p>
 | 
			
		||||
      <Segmented :options="optionsIcon" />
 | 
			
		||||
      <Segmented :options="optionsIcon" :size="dynamicSize" />
 | 
			
		||||
      <el-divider />
 | 
			
		||||
      <p class="mb-2">只设置图标</p>
 | 
			
		||||
      <Segmented :options="optionsOnlyIcon" />
 | 
			
		||||
      <Segmented :options="optionsOnlyIcon" :size="dynamicSize" />
 | 
			
		||||
      <el-divider />
 | 
			
		||||
      <p class="mb-2">自定义渲染</p>
 | 
			
		||||
      <Segmented :options="optionsLabel" />
 | 
			
		||||
      <Segmented :options="optionsLabel" :size="dynamicSize" />
 | 
			
		||||
    </el-scrollbar>
 | 
			
		||||
  </el-card>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user