a
This commit is contained in:
168
src/components/IconText/index.vue
Normal file
168
src/components/IconText/index.vue
Normal file
@@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<div class="icon-text" :style="containerStyle">
|
||||
<el-icon
|
||||
v-if="icon"
|
||||
class="icon-text-icon"
|
||||
:style="iconStyle">
|
||||
<component :is="icon" />
|
||||
</el-icon>
|
||||
<span
|
||||
v-if="text"
|
||||
class="icon-text-text"
|
||||
:style="textStyle">
|
||||
{{ text }}
|
||||
</span>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { Component } from 'vue'
|
||||
|
||||
// 尺寸配置映射(参考 el-tag 的尺寸)
|
||||
const sizeConfig = {
|
||||
small: {
|
||||
iconSize: 14,
|
||||
textSize: 12,
|
||||
gap: 4
|
||||
},
|
||||
medium: {
|
||||
iconSize: 16,
|
||||
textSize: 14,
|
||||
gap: 4
|
||||
},
|
||||
large: {
|
||||
iconSize: 20,
|
||||
textSize: 16,
|
||||
gap: 5
|
||||
}
|
||||
}
|
||||
|
||||
// 类型颜色映射(与 el-tag 保持一致,提高可读性)
|
||||
const typeColorMap: Record<string, string> = {
|
||||
success: '#67c23a', // 成功 - 绿色
|
||||
danger: '#f56c6c', // 危险 - 红色
|
||||
warning: '#e6a23c', // 警告 - 橙色
|
||||
info: '#909399', // 信息 - 灰色
|
||||
primary: '#409eff' // 主要 - 蓝色
|
||||
}
|
||||
|
||||
interface Props {
|
||||
// 图标组件(Element Plus 图标)
|
||||
icon?: Component | string
|
||||
// 文字内容
|
||||
text?: string
|
||||
// 类型(类似 el-tag 的 type):success、danger、warning、info、primary
|
||||
type?: 'success' | 'danger' | 'warning' | 'info' | 'primary'
|
||||
// 尺寸(类似 el-tag 的 size):small、medium、large
|
||||
size?: 'small' | 'medium' | 'large'
|
||||
// 图标颜色(优先级高于 type)
|
||||
iconColor?: string
|
||||
// 文字颜色(优先级高于 type)
|
||||
textColor?: string
|
||||
// 图标尺寸(单位:px,优先级高于 size)
|
||||
iconSize?: number | string
|
||||
// 文字尺寸(单位:px,优先级高于 size)
|
||||
textSize?: number | string
|
||||
// 图标和文字之间的间距(单位:px,优先级高于 size)
|
||||
gap?: number | string
|
||||
// 对齐方式
|
||||
align?: 'left' | 'center' | 'right'
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
icon: undefined,
|
||||
text: '',
|
||||
type: undefined,
|
||||
size: 'medium',
|
||||
iconColor: '',
|
||||
textColor: '',
|
||||
iconSize: undefined,
|
||||
textSize: undefined,
|
||||
gap: undefined,
|
||||
align: 'left'
|
||||
})
|
||||
|
||||
// 获取实际尺寸配置
|
||||
const actualSizeConfig = computed(() => {
|
||||
const config = sizeConfig[props.size]
|
||||
return {
|
||||
iconSize: props.iconSize ?? config.iconSize,
|
||||
textSize: props.textSize ?? config.textSize,
|
||||
gap: props.gap ?? config.gap
|
||||
}
|
||||
})
|
||||
|
||||
// 获取实际颜色
|
||||
const actualIconColor = computed(() => {
|
||||
if (props.iconColor) return props.iconColor
|
||||
if (props.type && typeColorMap[props.type]) return typeColorMap[props.type]
|
||||
return ''
|
||||
})
|
||||
|
||||
const actualTextColor = computed(() => {
|
||||
if (props.textColor) return props.textColor
|
||||
if (props.type && typeColorMap[props.type]) return typeColorMap[props.type]
|
||||
return ''
|
||||
})
|
||||
|
||||
// 容器样式
|
||||
const containerStyle = computed(() => {
|
||||
const styles: Record<string, string> = {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: `${actualSizeConfig.value.gap}px`
|
||||
}
|
||||
|
||||
if (props.align === 'center') {
|
||||
styles.justifyContent = 'center'
|
||||
} else if (props.align === 'right') {
|
||||
styles.justifyContent = 'flex-end'
|
||||
}
|
||||
|
||||
return styles
|
||||
})
|
||||
|
||||
// 图标样式
|
||||
const iconStyle = computed(() => {
|
||||
const styles: Record<string, string> = {
|
||||
fontSize: `${actualSizeConfig.value.iconSize}px`,
|
||||
verticalAlign: 'middle'
|
||||
}
|
||||
|
||||
if (actualIconColor.value) {
|
||||
styles.color = actualIconColor.value
|
||||
}
|
||||
|
||||
return styles
|
||||
})
|
||||
|
||||
// 文字样式
|
||||
const textStyle = computed(() => {
|
||||
const styles: Record<string, string> = {
|
||||
fontSize: `${actualSizeConfig.value.textSize}px`,
|
||||
verticalAlign: 'middle'
|
||||
}
|
||||
|
||||
if (actualTextColor.value) {
|
||||
styles.color = actualTextColor.value
|
||||
}
|
||||
|
||||
return styles
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.icon-text {
|
||||
line-height: 1;
|
||||
|
||||
.icon-text-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.icon-text-text {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -16,6 +16,7 @@ import Sign from '/@/components/Sign/index.vue';
|
||||
import ChinaArea from '/@/components/ChinaArea/index.vue';
|
||||
import OrgSelector from '/@/components/OrgSelector/index.vue';
|
||||
import AiEditor from '/@/components/AiEditor/index.vue';
|
||||
import IconText from '/@/components/IconText/index.vue';
|
||||
|
||||
// 第三方组件
|
||||
import ElementPlus from 'element-plus';
|
||||
@@ -56,6 +57,7 @@ export default {
|
||||
app.component('ChinaArea', ChinaArea);
|
||||
app.component('OrgSelector', OrgSelector);
|
||||
app.component('Sign', Sign);
|
||||
app.component('IconText', IconText);
|
||||
|
||||
// 导入全部的elmenet-plus的图标
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
|
||||
Reference in New Issue
Block a user