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-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;
 | 
					  box-sizing: border-box;
 | 
				
			||||||
  display: inline-block;
 | 
					  display: inline-block;
 | 
				
			||||||
  padding: 2px;
 | 
					  padding: var(--pure-segmented-track-padding);
 | 
				
			||||||
  font-size: 14px;
 | 
					  font-size: var(--el-font-size-base);
 | 
				
			||||||
  color: rgba(0, 0, 0, 0.65);
 | 
					  color: rgba(0, 0, 0, 0.65);
 | 
				
			||||||
  background-color: rgb(0 0 0 / 4%);
 | 
					  background-color: rgb(0 0 0 / 4%);
 | 
				
			||||||
  border-radius: 2px;
 | 
					  border-radius: var(--pure-segmented-border-radius-base);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.pure-segmented-block {
 | 
					.pure-segmented-block {
 | 
				
			||||||
@ -23,6 +32,75 @@
 | 
				
			|||||||
  text-overflow: ellipsis;
 | 
					  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 {
 | 
					.pure-segmented-group {
 | 
				
			||||||
  position: relative;
 | 
					  position: relative;
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
@ -52,23 +130,6 @@
 | 
				
			|||||||
  will-change: transform, width;
 | 
					  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 {
 | 
					.pure-segmented-item > input {
 | 
				
			||||||
  position: absolute;
 | 
					  position: absolute;
 | 
				
			||||||
  inset-block-start: 0;
 | 
					  inset-block-start: 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,14 @@
 | 
				
			|||||||
import "./index.css";
 | 
					import "./index.css";
 | 
				
			||||||
 | 
					import type { OptionsType } from "./type";
 | 
				
			||||||
 | 
					import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
 | 
					  useDark,
 | 
				
			||||||
 | 
					  isNumber,
 | 
				
			||||||
 | 
					  isFunction,
 | 
				
			||||||
 | 
					  useResizeObserver
 | 
				
			||||||
 | 
					} from "@pureadmin/utils";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  type PropType,
 | 
				
			||||||
  h,
 | 
					  h,
 | 
				
			||||||
  ref,
 | 
					  ref,
 | 
				
			||||||
  toRef,
 | 
					  toRef,
 | 
				
			||||||
@ -8,14 +17,6 @@ import {
 | 
				
			|||||||
  defineComponent,
 | 
					  defineComponent,
 | 
				
			||||||
  getCurrentInstance
 | 
					  getCurrentInstance
 | 
				
			||||||
} from "vue";
 | 
					} from "vue";
 | 
				
			||||||
import type { OptionsType } from "./type";
 | 
					 | 
				
			||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
					 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  isFunction,
 | 
					 | 
				
			||||||
  isNumber,
 | 
					 | 
				
			||||||
  useDark,
 | 
					 | 
				
			||||||
  useResizeObserver
 | 
					 | 
				
			||||||
} from "@pureadmin/utils";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = {
 | 
					const props = {
 | 
				
			||||||
  options: {
 | 
					  options: {
 | 
				
			||||||
@ -32,6 +33,10 @@ const props = {
 | 
				
			|||||||
  block: {
 | 
					  block: {
 | 
				
			||||||
    type: Boolean,
 | 
					    type: Boolean,
 | 
				
			||||||
    default: false
 | 
					    default: false
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  /** 控件尺寸	 */
 | 
				
			||||||
 | 
					  size: {
 | 
				
			||||||
 | 
					    type: String as PropType<"small" | "default" | "large">
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -81,13 +86,14 @@ export default defineComponent({
 | 
				
			|||||||
    function handleInit(index = curIndex.value) {
 | 
					    function handleInit(index = curIndex.value) {
 | 
				
			||||||
      nextTick(() => {
 | 
					      nextTick(() => {
 | 
				
			||||||
        const curLabelRef = instance?.proxy?.$refs[`labelRef${index}`] as ElRef;
 | 
					        const curLabelRef = instance?.proxy?.$refs[`labelRef${index}`] as ElRef;
 | 
				
			||||||
 | 
					        if (!curLabelRef) return;
 | 
				
			||||||
        width.value = curLabelRef.clientWidth;
 | 
					        width.value = curLabelRef.clientWidth;
 | 
				
			||||||
        translateX.value = curLabelRef.offsetLeft;
 | 
					        translateX.value = curLabelRef.offsetLeft;
 | 
				
			||||||
        initStatus.value = true;
 | 
					        initStatus.value = true;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (props.block) {
 | 
					    function handleResizeInit() {
 | 
				
			||||||
      useResizeObserver(".pure-segmented", () => {
 | 
					      useResizeObserver(".pure-segmented", () => {
 | 
				
			||||||
        nextTick(() => {
 | 
					        nextTick(() => {
 | 
				
			||||||
          handleInit(curIndex.value);
 | 
					          handleInit(curIndex.value);
 | 
				
			||||||
@ -95,6 +101,8 @@ export default defineComponent({
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    props.block && handleResizeInit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    watch(
 | 
					    watch(
 | 
				
			||||||
      () => curIndex.value,
 | 
					      () => curIndex.value,
 | 
				
			||||||
      index => {
 | 
					      index => {
 | 
				
			||||||
@ -103,11 +111,12 @@ export default defineComponent({
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        deep: true,
 | 
					 | 
				
			||||||
        immediate: true
 | 
					        immediate: true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watch(() => props.size, handleResizeInit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const rendLabel = () => {
 | 
					    const rendLabel = () => {
 | 
				
			||||||
      return props.options.map((option, index) => {
 | 
					      return props.options.map((option, index) => {
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
@ -167,7 +176,12 @@ export default defineComponent({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return () => (
 | 
					    return () => (
 | 
				
			||||||
      <div
 | 
					      <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 class="pure-segmented-group">
 | 
				
			||||||
          <div
 | 
					          <div
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
<script setup lang="tsx">
 | 
					<script setup lang="tsx">
 | 
				
			||||||
import { h, ref } from "vue";
 | 
					import { h, ref, watch } from "vue";
 | 
				
			||||||
import { message } from "@/utils/message";
 | 
					import { message } from "@/utils/message";
 | 
				
			||||||
import HomeFilled from "@iconify-icons/ep/home-filled";
 | 
					import HomeFilled from "@iconify-icons/ep/home-filled";
 | 
				
			||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
					import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
				
			||||||
@ -11,6 +11,8 @@ defineOptions({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/** 基础用法 */
 | 
					/** 基础用法 */
 | 
				
			||||||
const value = ref(4); // 必须为number类型
 | 
					const value = ref(4); // 必须为number类型
 | 
				
			||||||
 | 
					const size = ref("default");
 | 
				
			||||||
 | 
					const dynamicSize = ref();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const optionsBasis: Array<OptionsType> = [
 | 
					const optionsBasis: Array<OptionsType> = [
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@ -192,13 +194,22 @@ function onChange({ index, option }) {
 | 
				
			|||||||
    type: "success"
 | 
					    type: "success"
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(size, val => (dynamicSize.value = size.value));
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <el-card shadow="never">
 | 
					  <el-card shadow="never">
 | 
				
			||||||
    <template #header>
 | 
					    <template #header>
 | 
				
			||||||
      <div class="card-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>
 | 
					      </div>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    <el-scrollbar>
 | 
					    <el-scrollbar>
 | 
				
			||||||
@ -207,28 +218,32 @@ function onChange({ index, option }) {
 | 
				
			|||||||
          {{ optionsBasis[value].label }}
 | 
					          {{ optionsBasis[value].label }}
 | 
				
			||||||
        </span>
 | 
					        </span>
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <Segmented v-model="value" :options="optionsBasis" />
 | 
					      <Segmented v-model="value" :options="optionsBasis" :size="dynamicSize" />
 | 
				
			||||||
      <el-divider />
 | 
					      <el-divider />
 | 
				
			||||||
      <p class="mb-2">tooltip 提示</p>
 | 
					      <p class="mb-2">tooltip 提示</p>
 | 
				
			||||||
      <Segmented :options="optionsTooltip" />
 | 
					      <Segmented :options="optionsTooltip" :size="dynamicSize" />
 | 
				
			||||||
      <el-divider />
 | 
					      <el-divider />
 | 
				
			||||||
      <p class="mb-2">change 事件</p>
 | 
					      <p class="mb-2">change 事件</p>
 | 
				
			||||||
      <Segmented :options="optionsChange" @change="onChange" />
 | 
					      <Segmented
 | 
				
			||||||
 | 
					        :options="optionsChange"
 | 
				
			||||||
 | 
					        :size="dynamicSize"
 | 
				
			||||||
 | 
					        @change="onChange"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
      <el-divider />
 | 
					      <el-divider />
 | 
				
			||||||
      <p class="mb-2">禁用</p>
 | 
					      <p class="mb-2">禁用</p>
 | 
				
			||||||
      <Segmented :options="optionsDisabled" />
 | 
					      <Segmented :options="optionsDisabled" :size="dynamicSize" />
 | 
				
			||||||
      <el-divider />
 | 
					      <el-divider />
 | 
				
			||||||
      <p class="mb-2">block 属性(将宽度调整为父元素宽度)</p>
 | 
					      <p class="mb-2">block 属性(将宽度调整为父元素宽度)</p>
 | 
				
			||||||
      <Segmented :options="optionsBlock" block />
 | 
					      <Segmented :options="optionsBlock" block :size="dynamicSize" />
 | 
				
			||||||
      <el-divider />
 | 
					      <el-divider />
 | 
				
			||||||
      <p class="mb-2">可设置图标</p>
 | 
					      <p class="mb-2">可设置图标</p>
 | 
				
			||||||
      <Segmented :options="optionsIcon" />
 | 
					      <Segmented :options="optionsIcon" :size="dynamicSize" />
 | 
				
			||||||
      <el-divider />
 | 
					      <el-divider />
 | 
				
			||||||
      <p class="mb-2">只设置图标</p>
 | 
					      <p class="mb-2">只设置图标</p>
 | 
				
			||||||
      <Segmented :options="optionsOnlyIcon" />
 | 
					      <Segmented :options="optionsOnlyIcon" :size="dynamicSize" />
 | 
				
			||||||
      <el-divider />
 | 
					      <el-divider />
 | 
				
			||||||
      <p class="mb-2">自定义渲染</p>
 | 
					      <p class="mb-2">自定义渲染</p>
 | 
				
			||||||
      <Segmented :options="optionsLabel" />
 | 
					      <Segmented :options="optionsLabel" :size="dynamicSize" />
 | 
				
			||||||
    </el-scrollbar>
 | 
					    </el-scrollbar>
 | 
				
			||||||
  </el-card>
 | 
					  </el-card>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user