You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
6.5 KiB
228 lines
6.5 KiB
<script lang="ts" setup>
|
|
import { PropType } from 'vue'
|
|
import dayjs from 'dayjs'
|
|
import { useDesign } from '@/hooks/web/useDesign'
|
|
import { propTypes } from '@/utils/propTypes'
|
|
import { useAppStore } from '@/store/modules/app'
|
|
import { DescriptionsSchema } from '@/types/descriptions'
|
|
const { t } = useI18n() // 国际化
|
|
|
|
defineOptions({ name: 'Descriptions' })
|
|
|
|
const appStore = useAppStore()
|
|
|
|
const mobile = computed(() => appStore.getMobile)
|
|
|
|
const attrs = useAttrs()
|
|
|
|
const slots = useSlots()
|
|
const height = ref('auto')
|
|
const isShow = ref(true)
|
|
|
|
|
|
const props = defineProps({
|
|
title: propTypes.string.def(''),
|
|
message: propTypes.string.def(''),
|
|
collapse: propTypes.bool.def(true),
|
|
columns: propTypes.number.def(1),
|
|
width: propTypes.string.def('50px'),
|
|
labelAlign: propTypes.string.def('right'),
|
|
labelClassName: propTypes.string.def(''),
|
|
valueClassName: propTypes.string.def(''),
|
|
schema: {
|
|
type: Array as PropType<DescriptionsSchema[]>,
|
|
default: () => []
|
|
},
|
|
data: {
|
|
type: Object as PropType<any>,
|
|
default: () => ({})
|
|
}
|
|
})
|
|
const schema = ref(props.schema)
|
|
|
|
const { getPrefixCls } = useDesign()
|
|
|
|
const prefixCls = getPrefixCls('descriptions')
|
|
|
|
const getBindValue = computed(() => {
|
|
const delArr: string[] = ['title', 'message', 'collapse', 'schema', 'data', 'class']
|
|
const obj = { ...attrs, ...props }
|
|
for (const key in obj) {
|
|
if (delArr.indexOf(key) !== -1) {
|
|
delete obj[key]
|
|
}
|
|
}
|
|
return obj
|
|
})
|
|
|
|
const getBindItemValue = (item: DescriptionsSchema) => {
|
|
const delArr: string[] = ['field']
|
|
const obj = { ...item }
|
|
for (const key in obj) {
|
|
if (delArr.indexOf(key) !== -1) {
|
|
delete obj[key]
|
|
}
|
|
}
|
|
return obj
|
|
}
|
|
|
|
// 折叠
|
|
const show = ref(true)
|
|
|
|
const toggleClick = () => {
|
|
if (props.collapse) {
|
|
show.value = !unref(show)
|
|
}
|
|
}
|
|
const showAll = () =>{
|
|
if(isShow.value){
|
|
height.value ='200px'
|
|
}else{
|
|
height.value ='auto'
|
|
}
|
|
isShow.value = !isShow.value
|
|
|
|
}
|
|
|
|
// 默认排序
|
|
const updateSort = (val) => {
|
|
console.log(999,val)
|
|
val.forEach(item=>{
|
|
if(!item.sortDetailDefault){
|
|
item.sortDetailDefault = 999 // 默认999
|
|
}
|
|
})
|
|
val.sort((column1,column2)=>{
|
|
return column1.sortDetailDefault - column2.sortDetailDefault
|
|
})
|
|
}
|
|
updateSort(schema.value)
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
:class="[
|
|
prefixCls,
|
|
'bg-[var(--el-color-white)] dark:bg-[var(--el-bg-color)] dark:border-[var(--el-border-color)] dark:border-1px'
|
|
]"
|
|
>
|
|
<div
|
|
v-if="title"
|
|
:class="[
|
|
`${prefixCls}-header`,
|
|
'h-50px flex justify-between items-center b-b-1 border-solid border-[var(--el-border-color)] px-10px cursor-pointer dark:border-[var(--el-border-color)]'
|
|
]"
|
|
@click="toggleClick"
|
|
>
|
|
<div :class="[`${prefixCls}-header__title`, 'relative font-18px font-bold ml-10px']">
|
|
<div class="flex items-center">
|
|
{{ t(`ts.${title}`).replace('ts.', '') }}
|
|
<ElTooltip v-if="message" :content="message" placement="right">
|
|
<Icon class="ml-5px" icon="ep:warning" />
|
|
</ElTooltip>
|
|
</div>
|
|
</div>
|
|
<Icon v-if="collapse" :icon="show ? 'ep:arrow-down' : 'ep:arrow-up'" />
|
|
</div>
|
|
|
|
<ElCollapseTransition :style="{height: height,overflow: 'hidden'}">
|
|
<div v-show="show" :class="[`${prefixCls}-content`]">
|
|
<ElDescriptions
|
|
:column="props.columns"
|
|
:direction="mobile ? 'vertical' : 'horizontal'"
|
|
border
|
|
v-bind="getBindValue"
|
|
>
|
|
<template v-if="slots['extra']" #extra>
|
|
<slot name="extra"></slot>
|
|
</template>
|
|
<ElDescriptionsItem
|
|
v-for="item in schema"
|
|
:key="item.field"
|
|
v-bind="getBindItemValue(item)"
|
|
:label-align="labelAlign"
|
|
:label-class-name="item.labelClassName||labelClassName"
|
|
:class-name="valueClassName || item.labelClassName"
|
|
:width="width"
|
|
:span="item.span"
|
|
>
|
|
<template #label>
|
|
<slot
|
|
:name="`${item.field}-label`"
|
|
:row="{
|
|
label: item.label
|
|
}"
|
|
>{{ t(`ts.${item.label}`).replace('ts.', '') }}
|
|
</slot>
|
|
</template>
|
|
|
|
<template #default>
|
|
<slot v-if="item.dateFormat">
|
|
{{
|
|
data[item.field] !== null ? dayjs(data[item.field]).format(item.dateFormat) : ''
|
|
}}
|
|
</slot>
|
|
|
|
<slot v-else-if="item.formatter">
|
|
<span>{{
|
|
item.formatter(data[item.field])
|
|
}}</span>
|
|
</slot>
|
|
<slot v-else-if="item.valueFilter">
|
|
<el-tag v-if="item.dictType" :type="item.dictType">{{ item.valueFilter(data[item.field]) }}</el-tag>
|
|
<span v-else>{{
|
|
item.valueFilter(data[item.field])
|
|
}}</span>
|
|
</slot>
|
|
<slot v-else-if="item.slotFilter" :name="'Descriptions_'+item.field" :row="data">{{ data[item.field] }}</slot>
|
|
<slot v-else-if="item.dictType">
|
|
<div v-if="data[item.field]&&Array.isArray(data[item.field])" >
|
|
<DictTag :type="item.dictType" :value="cur" v-for="(cur,key) in data[item.field]" :key="key" style="margin-right: 6px;margin-bottom: 6px;"/>
|
|
</div>
|
|
<DictTag :type="item.dictType" :value="data[item.field] + ''" v-if="(data[item.field]||data[item.field]==0)&&!Array.isArray(data[item.field])"/>
|
|
</slot>
|
|
<slot v-else :name="item.field" :row="data">{{ data[item.field] }}</slot>
|
|
</template>
|
|
</ElDescriptionsItem>
|
|
</ElDescriptions>
|
|
</div>
|
|
</ElCollapseTransition>
|
|
<!-- <div class="flex align-center justify-center">
|
|
<el-button type="primary" class="mt-20px" @click="showAll">{{!isShow?'展开':'收起'}}</el-button>
|
|
</div> -->
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
$prefix-cls: #{$namespace}-descriptions;
|
|
|
|
.#{$prefix-cls}-header {
|
|
&__title {
|
|
&::after {
|
|
position: absolute;
|
|
top: 3px;
|
|
left: -10px;
|
|
width: 4px;
|
|
height: 70%;
|
|
background: var(--el-color-primary);
|
|
content: '';
|
|
}
|
|
}
|
|
}
|
|
|
|
.#{$prefix-cls}-content {
|
|
:deep(.#{$elNamespace}-descriptions__cell) {
|
|
width: 0;
|
|
}
|
|
}
|
|
:deep(.text-red) {
|
|
color:red!important;
|
|
// background: #fff3f3;
|
|
}
|
|
:deep(.text-red .el-tag) {
|
|
background:#fef0f0!important;
|
|
color:red!important;
|
|
border-color:#fde2e2!important;
|
|
// background: #fff3f3;
|
|
}
|
|
</style>
|
|
|