a
This commit is contained in:
149
src/components/StatusTag/README.md
Normal file
149
src/components/StatusTag/README.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# StatusTag 组件
|
||||
|
||||
状态标签组件,用于显示状态值对应的标签文本,支持自定义样式和颜色。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ 支持标签样式和纯文本样式两种显示模式
|
||||
- ✅ 支持自定义类型映射(typeMap)和颜色映射(colorMap)
|
||||
- ✅ 内置默认样式('1' → warning/dark,'0' → primary/light)
|
||||
- ✅ 外部传入优先,支持覆盖默认样式
|
||||
|
||||
## Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 必填 |
|
||||
|------|------|------|--------|------|
|
||||
| value | 当前状态值 | `string \| number` | `''` | 是 |
|
||||
| options | 选项列表,格式:`[{label: '是', value: '1'}, {label: '否', value: '0'}]` | `Option[]` | `[]` | 是 |
|
||||
| showTag | 是否显示标签样式(有边框和背景),`false` 为纯文本样式 | `boolean` | `true` | 否 |
|
||||
| typeMap | 自定义类型映射,用于标签模式,如:`{'1': {type: 'warning', effect: 'dark'}}` | `Record<string \| number, { type: string; effect?: string }>` | `{}` | 否 |
|
||||
| colorMap | 自定义颜色映射,用于纯文本模式,如:`{'1': '#E6A23C'}` | `Record<string \| number, string>` | `{}` | 否 |
|
||||
|
||||
### Option 接口
|
||||
|
||||
```typescript
|
||||
interface Option {
|
||||
label: string // 显示文本
|
||||
value: string | number // 选项值
|
||||
}
|
||||
```
|
||||
|
||||
## 默认样式
|
||||
|
||||
组件内置了默认的样式映射,无需传入 `typeMap` 或 `colorMap` 即可使用:
|
||||
|
||||
- **值 '1' 或 1**:
|
||||
- 标签模式:`warning` 类型 + `dark` 效果(橙色深色)
|
||||
- 纯文本模式:`var(--el-color-warning)`(橙色)
|
||||
|
||||
- **值 '0' 或 0**:
|
||||
- 标签模式:`primary` 类型 + `light` 效果(蓝色浅色)
|
||||
- 纯文本模式:`var(--el-color-primary)`(蓝色)
|
||||
|
||||
- **其他值**:
|
||||
- 标签模式:`info` 类型 + `light` 效果(灰色)
|
||||
- 纯文本模式:默认文本颜色
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基础用法
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<StatusTag
|
||||
:value="scope.row.tied"
|
||||
:options="YES_OR_NO"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import StatusTag from '/@/components/StatusTag/index.vue'
|
||||
|
||||
const YES_OR_NO = [
|
||||
{ label: '是', value: '1' },
|
||||
{ label: '否', value: '0' }
|
||||
]
|
||||
</script>
|
||||
```
|
||||
|
||||
### 纯文本模式(无边框和背景)
|
||||
|
||||
```vue
|
||||
<StatusTag
|
||||
:value="scope.row.tied"
|
||||
:options="YES_OR_NO"
|
||||
:show-tag="false"
|
||||
/>
|
||||
```
|
||||
|
||||
### 自定义类型映射
|
||||
|
||||
```vue
|
||||
<StatusTag
|
||||
:value="scope.row.status"
|
||||
:options="statusOptions"
|
||||
:type-map="{
|
||||
'1': { type: 'success', effect: 'dark' },
|
||||
'0': { type: 'danger', effect: 'light' }
|
||||
}"
|
||||
/>
|
||||
```
|
||||
|
||||
### 自定义颜色映射(纯文本模式)
|
||||
|
||||
```vue
|
||||
<StatusTag
|
||||
:value="scope.row.status"
|
||||
:options="statusOptions"
|
||||
:show-tag="false"
|
||||
:color-map="{
|
||||
'1': '#67C23A',
|
||||
'0': '#F56C6C'
|
||||
}"
|
||||
/>
|
||||
```
|
||||
|
||||
### 完整示例
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<el-table :data="tableData">
|
||||
<el-table-column label="是否退休" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<StatusTag
|
||||
:value="scope.row.tied"
|
||||
:options="YES_OR_NO"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import global from '/@/components/tools/commondict.vue'
|
||||
|
||||
const StatusTag = defineAsyncComponent(() => import('/@/components/StatusTag/index.vue'))
|
||||
const YES_OR_NO = global.YES_OR_NO
|
||||
</script>
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **必须传入 `options`**:组件不提供默认选项,必须通过 `options` prop 传入选项列表
|
||||
2. **值匹配**:组件会自动匹配字符串和数字类型的值(如 `'1'` 和 `1` 会被视为相同)
|
||||
3. **样式优先级**:外部传入的 `typeMap` 和 `colorMap` 会覆盖默认样式
|
||||
4. **未匹配值**:如果 `value` 在 `options` 中找不到对应项,会显示 `'-'`
|
||||
|
||||
## 样式说明
|
||||
|
||||
### 标签模式(showTag: true)
|
||||
|
||||
使用 Element Plus 的 `el-tag` 组件,支持所有 `el-tag` 的类型和效果:
|
||||
- `type`: `success` | `info` | `warning` | `danger` | `primary`
|
||||
- `effect`: `dark` | `light` | `plain`
|
||||
|
||||
### 纯文本模式(showTag: false)
|
||||
|
||||
使用纯文本显示,通过 CSS 颜色控制样式,支持任何颜色值(CSS 变量、十六进制、RGB 等)。
|
||||
|
||||
140
src/components/StatusTag/index.vue
Normal file
140
src/components/StatusTag/index.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<el-tag
|
||||
v-if="showTag"
|
||||
:type="tagType"
|
||||
:effect="tagEffect"
|
||||
>
|
||||
{{ label }}
|
||||
</el-tag>
|
||||
<span v-else class="status-tag" :class="statusClass" :style="statusStyle">
|
||||
{{ label }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
interface Option {
|
||||
label: string
|
||||
value: string | number
|
||||
}
|
||||
|
||||
interface Props {
|
||||
value?: string | number // 当前值
|
||||
options?: Option[] // 选项列表,格式:[{label: '是', value: '1'}, {label: '否', value: '0'}]
|
||||
showTag?: boolean // 是否显示标签样式(有边框和背景),默认为 true
|
||||
typeMap?: Record<string | number, { type: string; effect?: string }> // 自定义类型映射,如 {'1': {type: 'warning', effect: 'dark'}}
|
||||
colorMap?: Record<string | number, string> // 纯文本模式下的颜色映射,如 {'1': '#E6A23C'}
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
value: '',
|
||||
options: () => [],
|
||||
showTag: true,
|
||||
typeMap: () => ({}),
|
||||
colorMap: () => ({})
|
||||
})
|
||||
|
||||
// 默认的类型映射(只使用字符串键)
|
||||
const defaultTypeMap: Record<string, { type: string; effect: string }> = {
|
||||
'1': { type: 'warning', effect: 'dark' },
|
||||
'0': { type: 'primary', effect: 'light' }
|
||||
}
|
||||
|
||||
// 默认的颜色映射(只使用字符串键)
|
||||
const defaultColorMap: Record<string, string> = {
|
||||
'1': 'var(--el-color-warning)',
|
||||
'0': 'var(--el-color-primary)'
|
||||
}
|
||||
|
||||
// 获取值的字符串形式(用于查找映射)
|
||||
const getValueKey = (value: string | number): string => {
|
||||
return String(value)
|
||||
}
|
||||
|
||||
// 合并后的类型映射(外部传入优先,否则使用默认)
|
||||
const mergedTypeMap = computed(() => {
|
||||
// 将外部传入的 typeMap 也转换为字符串键
|
||||
const externalTypeMap: Record<string, { type: string; effect?: string }> = {}
|
||||
Object.keys(props.typeMap).forEach(key => {
|
||||
externalTypeMap[String(key)] = props.typeMap[key]
|
||||
})
|
||||
return { ...defaultTypeMap, ...externalTypeMap }
|
||||
})
|
||||
|
||||
// 合并后的颜色映射(外部传入优先,否则使用默认)
|
||||
const mergedColorMap = computed(() => {
|
||||
// 将外部传入的 colorMap 也转换为字符串键
|
||||
const externalColorMap: Record<string, string> = {}
|
||||
Object.keys(props.colorMap).forEach(key => {
|
||||
externalColorMap[String(key)] = props.colorMap[key]
|
||||
})
|
||||
return { ...defaultColorMap, ...externalColorMap }
|
||||
})
|
||||
|
||||
// 合并后的选项列表(必须通过外部传入 options)
|
||||
const mergedOptions = computed(() => {
|
||||
// 必须传入 options,否则返回空数组
|
||||
return props.options && props.options.length > 0 ? props.options : []
|
||||
})
|
||||
|
||||
// 根据值找到对应的选项
|
||||
const currentOption = computed(() => {
|
||||
return mergedOptions.value.find((opt: Option) => {
|
||||
const optValue = String(opt.value)
|
||||
const propValue = String(props.value)
|
||||
return optValue === propValue || Number(opt.value) === Number(props.value)
|
||||
})
|
||||
})
|
||||
|
||||
// 显示标签
|
||||
const label = computed(() => {
|
||||
return currentOption.value?.label || '-'
|
||||
})
|
||||
|
||||
// 标签类型(showTag 为 true 时使用)
|
||||
const tagType = computed(() => {
|
||||
const valueKey = getValueKey(props.value)
|
||||
if (mergedTypeMap.value[valueKey]) {
|
||||
return mergedTypeMap.value[valueKey].type
|
||||
}
|
||||
return 'info'
|
||||
})
|
||||
|
||||
// 标签效果(showTag 为 true 时使用)
|
||||
const tagEffect = computed(() => {
|
||||
const valueKey = getValueKey(props.value)
|
||||
if (mergedTypeMap.value[valueKey]?.effect) {
|
||||
return mergedTypeMap.value[valueKey].effect
|
||||
}
|
||||
return 'light'
|
||||
})
|
||||
|
||||
// 纯文本模式下的样式类
|
||||
const statusClass = computed(() => {
|
||||
if (props.colorMap[props.value]) {
|
||||
return ''
|
||||
}
|
||||
return 'status-default'
|
||||
})
|
||||
|
||||
// 纯文本模式下的内联样式
|
||||
const statusStyle = computed(() => {
|
||||
const valueKey = getValueKey(props.value)
|
||||
if (mergedColorMap.value[valueKey]) {
|
||||
return { color: mergedColorMap.value[valueKey] }
|
||||
}
|
||||
return {}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.status-tag {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.status-default {
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user