This commit is contained in:
@@ -30,130 +30,130 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElCard } from 'element-plus'
|
||||
import { ElCard } from 'element-plus'
|
||||
|
||||
export interface DetailField {
|
||||
label: string // 字段标签
|
||||
prop?: string // 数据属性路径,支持点号分隔的嵌套路径,如 'one_time_commission_config.enable'
|
||||
formatter?: (value: any, data: any) => string // 自定义格式化函数
|
||||
render?: (data: any) => any // 自定义渲染函数,返回 VNode
|
||||
fullWidth?: boolean // 是否占据整行
|
||||
}
|
||||
|
||||
export interface DetailSection {
|
||||
title: string // 分组标题
|
||||
fields: DetailField[] // 字段列表
|
||||
columns?: 1 | 2 // 列数,默认2列
|
||||
}
|
||||
|
||||
interface Props {
|
||||
sections: DetailSection[] // 详情页分组配置
|
||||
data: any // 详情数据
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
/**
|
||||
* 根据点号分隔的路径获取嵌套对象的值
|
||||
*/
|
||||
const getNestedValue = (obj: any, path: string): any => {
|
||||
if (!path) return obj
|
||||
return path.split('.').reduce((acc, part) => acc?.[part], obj)
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化字段值
|
||||
*/
|
||||
const formatFieldValue = (field: DetailField, data: any): string => {
|
||||
const value = field.prop ? getNestedValue(data, field.prop) : data
|
||||
|
||||
// 如果有自定义格式化函数
|
||||
if (field.formatter) {
|
||||
return field.formatter(value, data)
|
||||
export interface DetailField {
|
||||
label: string // 字段标签
|
||||
prop?: string // 数据属性路径,支持点号分隔的嵌套路径,如 'one_time_commission_config.enable'
|
||||
formatter?: (value: any, data: any) => string // 自定义格式化函数
|
||||
render?: (data: any) => any // 自定义渲染函数,返回 VNode
|
||||
fullWidth?: boolean // 是否占据整行
|
||||
}
|
||||
|
||||
// 默认处理
|
||||
if (value === null || value === undefined || value === '') {
|
||||
return '-'
|
||||
export interface DetailSection {
|
||||
title: string // 分组标题
|
||||
fields: DetailField[] // 字段列表
|
||||
columns?: 1 | 2 // 列数,默认2列
|
||||
}
|
||||
|
||||
return String(value)
|
||||
}
|
||||
interface Props {
|
||||
sections: DetailSection[] // 详情页分组配置
|
||||
data: any // 详情数据
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
/**
|
||||
* 根据点号分隔的路径获取嵌套对象的值
|
||||
*/
|
||||
const getNestedValue = (obj: any, path: string): any => {
|
||||
if (!path) return obj
|
||||
return path.split('.').reduce((acc, part) => acc?.[part], obj)
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化字段值
|
||||
*/
|
||||
const formatFieldValue = (field: DetailField, data: any): string => {
|
||||
const value = field.prop ? getNestedValue(data, field.prop) : data
|
||||
|
||||
// 如果有自定义格式化函数
|
||||
if (field.formatter) {
|
||||
return field.formatter(value, data)
|
||||
}
|
||||
|
||||
// 默认处理
|
||||
if (value === null || value === undefined || value === '') {
|
||||
return '-'
|
||||
}
|
||||
|
||||
return String(value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.detail-container {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
.detail-container {
|
||||
max-height: 70vh;
|
||||
padding: 4px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
.detail-section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.section-fields {
|
||||
display: grid;
|
||||
gap: 16px 24px;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.single-column {
|
||||
grid-template-columns: 1fr;
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
&.double-column {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.field-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
min-height: 32px;
|
||||
|
||||
&.full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
flex-shrink: 0;
|
||||
width: 140px;
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-regular);
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.field-value {
|
||||
flex: 1;
|
||||
color: var(--el-text-color-primary);
|
||||
line-height: 32px;
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.section-fields {
|
||||
&.double-column {
|
||||
display: grid;
|
||||
gap: 16px 24px;
|
||||
|
||||
&.single-column {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
&.double-column {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.field-item {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
min-height: 32px;
|
||||
|
||||
&.full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
width: 100%;
|
||||
margin-bottom: 4px;
|
||||
flex-shrink: 0;
|
||||
width: 140px;
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
|
||||
.field-value {
|
||||
flex: 1;
|
||||
line-height: 32px;
|
||||
color: var(--el-text-color-primary);
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
@media (width <= 768px) {
|
||||
.section-fields {
|
||||
&.double-column {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.field-item {
|
||||
flex-direction: column;
|
||||
|
||||
.field-label {
|
||||
width: 100%;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user