Files
admin_core/src/components/tables/fieldRenderer.vue
张成 46e654aace 1
2025-11-20 11:27:30 +08:00

267 lines
6.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div style="width: 100%;">
<!-- 使用组件映射表来简化条件渲染 -->
<component
:is="getComponentName(col.com)"
:value="col.com === 'Radio' ? radioValue : value"
v-bind="getComponentProps(col)"
:disabled="disabled"
:class="getComponentClass(col.com)"
:style="getComponentStyle(col.com)"
@input="handleInput"
@on-change="handleChange"
>
<!-- Select 组件的选项 -->
<template v-if="col.com === 'Select'">
<Option
:value="item.key"
:key="item.key"
v-for="item in col.source"
>
{{ item.value }}
</Option>
</template>
<!-- Radio 组件的选项 -->
<template v-else-if="col.com === 'Radio'">
<Radio
:label="getRadioValue(item)"
:key="getRadioKey(item)"
v-for="item in getRadioSource(col)"
>
{{ getRadioLabel(item) }}
</Radio>
</template>
<!-- SelectIcon 组件的选项 -->
<template v-else-if="col.com === 'SelectIcon'">
<Option
v-for="(icon, index) in icons"
:value="icon"
:key="index"
>
<Icon size="20" :type="icon" />
{{ icon }}
</Option>
</template>
<!-- 自定义渲染 -->
<template v-else-if="col.editRender">
<templateRender
:value="value"
:render="col.editRender"
/>
</template>
</component>
</div>
</template>
<script>
import templateRender from './templateRender'
// 导入框架中的图标配置
let icons = []
try {
icons = require('../../config/icons.json') || []
} catch (e) {
console.warn('未找到图标配置文件,图标选择功能将不可用', e)
icons = []
}
export default {
name: 'FieldRenderer',
components: {
templateRender
},
props: {
col: {
type: Object,
required: true
},
value: {
type: [String, Number, Boolean, Array, Object, Date],
default: ''
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
icons: []
}
},
computed: {
// 直接返回原始值,不进行类型转换
radioValue() {
return this.value
}
},
mounted() {
// 安全处理图标数据
if (Array.isArray(icons)) {
this.icons = icons.map((item) => item.trim ? item.trim() : item)
} else {
this.icons = []
}
},
methods: {
// 组件映射表 - 统一管理组件类型
getComponentName(componentType) {
const componentMap = {
'Select': 'Select',
'Radio': 'RadioGroup',
'SelectIcon': 'AutoComplete',
'UploadSingle': 'UploadSingle',
'TextArea': 'TextArea',
'Input': 'Input',
'DatePicker': 'DatePicker',
'TimePicker': 'TimePicker',
'Switch': 'Switch',
'Checkbox': 'Checkbox',
'Slider': 'Slider',
'Rate': 'Rate',
'Cascader': 'Cascader',
'TreeSelect': 'TreeSelect',
'Transfer': 'Transfer',
'Upload': 'Upload',
'ColorPicker': 'ColorPicker',
'InputNumber': 'InputNumber'
}
// 如果没有指定组件类型,默认为 Input
return componentMap[componentType] || 'Input'
},
// 获取组件属性
getComponentProps(col) {
const baseProps = { ...col }
// 移除不需要传递给组件的属性
delete baseProps.com
delete baseProps.source
delete baseProps.options
delete baseProps.editRender
delete baseProps.inLine
delete baseProps.display
delete baseProps.disabled
delete baseProps.disabledOnAdd
delete baseProps.required
delete baseProps.data_type
delete baseProps.type
delete baseProps.rowStyle
// 根据组件类型添加特定属性
if (col.com === 'Select') {
baseProps.filterable = true
baseProps.clearable = true
} else if (col.com === 'SelectIcon') {
baseProps.icon = 'ios-search'
} else if (col.com === 'TextArea') {
baseProps.rows = 4
baseProps.placeholder = '请输入内容'
} else if (col.com === 'Input' || !col.com) {
baseProps.placeholder = col.placeholder || '请输入' + col.title
baseProps.clearable = true
}
return baseProps
},
// 获取 Radio 数据源(支持 source 和 options 两种格式)
getRadioSource(col) {
return col.source || col.options || []
},
// 获取 Radio 选项的值(支持多种数据格式)
getRadioValue(item) {
// 支持 { key: value, value: label } 格式
if (item.key !== undefined) {
return item.key
}
// 支持 { value: value, label: label } 格式
if (item.value !== undefined) {
return item.value
}
// 支持字符串数组
if (typeof item === 'string' || typeof item === 'number') {
return item
}
return item
},
// 获取 Radio 选项的 key用于 v-for
getRadioKey(item) {
if (item.key !== undefined) {
return item.key
}
if (item.value !== undefined) {
return item.value
}
if (typeof item === 'string' || typeof item === 'number') {
return item
}
return JSON.stringify(item)
},
// 获取 Radio 选项的显示文本
getRadioLabel(item) {
// 支持 { key: value, value: label } 格式
if (item.value !== undefined && typeof item.value === 'string') {
return item.value
}
// 支持 { value: value, label: label } 格式
if (item.label !== undefined) {
return item.label
}
// 支持字符串数组
if (typeof item === 'string' || typeof item === 'number') {
return item
}
return item.value || item.key || item
},
// 获取组件样式类
getComponentClass(componentType) {
const classMap = {
'Select': 'text-left',
'SelectIcon': 'text-left'
}
return classMap[componentType] || ''
},
// 获取组件样式
getComponentStyle(componentType) {
const styleMap = {
'Input': 'width:100%;',
'TextArea': 'width:100%;',
'DatePicker': 'width:100%;',
'TimePicker': 'width:100%;'
}
return styleMap[componentType] || ''
},
// 处理输入事件
handleInput(value) {
// 如果接收到的是事件对象,提取值
if (value && typeof value === 'object' && value.target) {
value = value.target.value
}
// 直接传递值,不进行类型转换
this.$emit('input', value)
},
// 处理变化事件
handleChange(value) {
// 如果接收到的是事件对象,提取值
if (value && typeof value === 'object' && value.target) {
value = value.target.value
}
// 直接传递值,不进行类型转换
this.$emit('change', value)
}
}
}
</script>