252 lines
8.5 KiB
Vue
252 lines
8.5 KiB
Vue
<template>
|
|
<!-- text -->
|
|
<div v-if="field.render == 'renderFormatter'">
|
|
{{ fieldValue }}
|
|
</div>
|
|
<!-- Icon -->
|
|
<Icon class="ba-icon-dark" v-if="field.render == 'icon'" :name="fieldValue ? fieldValue : field.default ?? ''" />
|
|
|
|
<!-- switch -->
|
|
<el-switch v-if="field.render == 'switch'" @change="onChangeField(field, $event)"
|
|
:model-value="fieldValue.toString()" :loading="row.loading" inline-prompt :active-value="field.activeValue"
|
|
:active-text="field.activeText" :inactive-value="field.inactiveValue" :inactive-text="field.inactiveText" />
|
|
|
|
<!-- image -->
|
|
<div v-if="field.render == 'image' && fieldValue" class="ba-render-image">
|
|
<el-image :hide-on-click-modal="true" :preview-teleported="true" :preview-src-list="[fullUrl(fieldValue)]"
|
|
:src="fieldValue.length > 100 ? fieldValue : fullUrl(fieldValue)"></el-image>
|
|
</div>
|
|
|
|
<!-- tag -->
|
|
<div v-if="field.render == 'tag' && fieldValue !== ''">
|
|
<el-tag :type="getTagType(fieldValue, field.custom) || 'primary'" :effect="field.effect ||'light'" size="small">
|
|
{{ field.replaceValue ? field.replaceValue[fieldValue] : fieldValue }}
|
|
</el-tag>
|
|
</div>
|
|
|
|
<!-- datetime -->
|
|
<div v-if="field.render == 'datetime'">
|
|
{{ !fieldValue ? '/' : timeFormat(fieldValue, field.timeFormat ?? undefined) }}
|
|
</div>
|
|
|
|
<!-- color -->
|
|
<div v-if="field.render == 'color'">
|
|
<div :style="{ background: fieldValue }" class="ba-render-color"></div>
|
|
</div>
|
|
|
|
<!-- customTemplate 自定义模板 -->
|
|
<div v-if="field.render == 'customTemplate'"
|
|
v-html="field.customTemplate ? field.customTemplate(row, field, fieldValue, column, index) : ''"></div>
|
|
|
|
<!-- 自定义组件/函数渲染 -->
|
|
<component v-if="field.render == 'customRender'" :is="field.customRender" :renderRow="row" :renderField="field"
|
|
:renderValue="fieldValue" :renderColumn="column" :renderIndex="index" />
|
|
|
|
<!-- 按钮组 -->
|
|
<div v-if="field.render == 'buttons' && buttons" class="cn-render-buttons">
|
|
<template v-for="(btn, idx) in buttons" :key="idx">
|
|
<!-- 常规按钮 -->
|
|
<el-button link v-if="btn.render == 'basicButton'" @click="onButtonClick(btn)" :class="btn.class"
|
|
class="table-operate" :type="btn.type" :disabled="btn.showDisabled && btn.showDisabled(row, field)"
|
|
:loading="props.row.loading || false" v-bind="btn.attr">
|
|
<div v-if="btn.text || btn.title" class="table-operate-text">{{ btn.text || btn.title }}</div>
|
|
</el-button>
|
|
|
|
<!-- 带提示信息的按钮 -->
|
|
<el-tooltip v-if="btn.render == 'tipButton'" :disabled="btn.title && !btn.disabledTip ? false : true"
|
|
:content="btn.title" placement="top">
|
|
<el-button link @click="onButtonClick(btn)" :class="btn.class" class="table-operate" :type="btn.type"
|
|
v-bind="btn.attr">
|
|
<div v-if="btn.text || btn.title" class="table-operate-text">
|
|
{{ btn.text || btn.title }}
|
|
</div>
|
|
</el-button>
|
|
</el-tooltip>
|
|
|
|
<!-- 带确认框的按钮 -->
|
|
<el-popconfirm v-if="btn.render == 'confirmButton'" :disabled="btn.disabled && btn.disabled(row, field)"
|
|
v-bind="btn.popconfirm" @confirm="onButtonClick(btn)">
|
|
<template #reference>
|
|
<div style="display: inline-block">
|
|
<el-button link :class="btn.class" class="table-operate" :type="btn.type" v-bind="btn.attr">
|
|
<div v-if="btn.text || btn.title" class="table-operate-text">
|
|
{{ btn.text || btn.title }}
|
|
</div>
|
|
</el-button>
|
|
</div>
|
|
</template>
|
|
</el-popconfirm>
|
|
|
|
<el-dropdown v-if="btn.render == 'dropdown'" trigger="click" @command="handlerCommand">
|
|
<el-button link type="primary" class="table-operate">
|
|
<div class="table-operate-text">更多</div>
|
|
</el-button>
|
|
<template #dropdown>
|
|
<el-dropdown-menu>
|
|
<el-dropdown-item v-for="item in btn.buttons" :key="item.text" :command="item"
|
|
:disabled="item.showDisabled && item.showDisabled(row, field)" :style="{
|
|
color: item.type === 'primary' ? 'var(--el-color-primary)' : 'var(--el-color-danger)'
|
|
}">
|
|
{{ item.text }}
|
|
</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</template>
|
|
</el-dropdown>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, inject } from 'vue'
|
|
import { ElMessageBox, type TagProps } from 'element-plus'
|
|
import type TableStoreClass from '@/utils/tableStore'
|
|
import { fullUrl, timeFormat } from '@/utils/common'
|
|
import type { VxeColumnProps } from 'vxe-table'
|
|
|
|
const TableStore = inject('tableStore') as TableStoreClass
|
|
|
|
interface Props {
|
|
row: TableRow
|
|
field: TableColumn
|
|
column: VxeColumnProps
|
|
index: number
|
|
}
|
|
const props = defineProps<Props>()
|
|
|
|
// 字段值(单元格值)
|
|
const fieldName = ref(props.field.field)
|
|
const fieldValue = ref(fieldName.value ? props.row[fieldName.value] : '')
|
|
if (fieldName.value && fieldName.value.indexOf('.') > -1) {
|
|
let fieldNameArr = fieldName.value.split('.')
|
|
let val: any = ref(props.row[fieldNameArr[0]])
|
|
for (let index = 1; index < fieldNameArr.length; index++) {
|
|
val.value = val.value ? val.value[fieldNameArr[index]] ?? '' : ''
|
|
}
|
|
fieldValue.value = val.value
|
|
}
|
|
|
|
if (props.field.renderFormatter && typeof props.field.renderFormatter == 'function') {
|
|
fieldValue.value = props.field.renderFormatter(props.row, props.field, fieldValue.value, props.column, props.index)
|
|
}
|
|
|
|
const onChangeField = (row: any, value: any) => {
|
|
row.onChangeField && row.onChangeField(props.row, value)
|
|
|
|
// TableStore.onTableAction('field-change', { value: value, ...props })
|
|
}
|
|
|
|
const onButtonClick = (btn: OptButton) => {
|
|
btn.click && btn.click(props.row, props.field)
|
|
}
|
|
|
|
const getTagType = (value: string, custom: any): TagProps['type'] => {
|
|
return custom && custom[value] ? custom[value] : ''
|
|
}
|
|
|
|
// 按钮组处理 最多显示三个按钮 多余的显示为下拉
|
|
const buttonsFilter = props.field.buttons?.filter(btn => !(btn.disabled && btn.disabled(props.row, props.field))) || []
|
|
const buttons = ref<any[]>([])
|
|
if (buttonsFilter.length > 3) {
|
|
buttonsFilter?.forEach((btn, index) => {
|
|
btn.text = btn.text || btn.title
|
|
if (index < 2) {
|
|
buttons.value.push(btn)
|
|
} else {
|
|
if (buttons.value.length > 2) {
|
|
buttons.value[buttons.value.length - 1].buttons.push(btn)
|
|
} else {
|
|
buttons.value.push({
|
|
render: 'dropdown',
|
|
buttons: [btn]
|
|
})
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
buttons.value = buttonsFilter
|
|
}
|
|
const handlerCommand = (item: OptButton) => {
|
|
switch (item.render) {
|
|
case 'basicButton':
|
|
onButtonClick(item)
|
|
break
|
|
case 'confirmButton':
|
|
ElMessageBox.confirm(item.popconfirm?.title || '提示', {
|
|
confirmButtonText: item.popconfirm?.confirmButtonText || '确认',
|
|
cancelButtonText: item.popconfirm?.cancelButtonText || '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
onButtonClick(item)
|
|
})
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.m-10 {
|
|
margin: 4px;
|
|
}
|
|
|
|
.ba-render-image {
|
|
text-align: center;
|
|
}
|
|
|
|
.images-item {
|
|
width: 50px;
|
|
margin: 0 5px;
|
|
}
|
|
|
|
.el-image {
|
|
height: 36px;
|
|
// width: 36px;
|
|
}
|
|
|
|
.table-operate-text {
|
|
padding-left: 5px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.table-operate {
|
|
padding: 4px 5px;
|
|
height: auto;
|
|
}
|
|
|
|
.cn-render-buttons {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.icon {
|
|
font-size: 12px !important;
|
|
// color: var(--ba-bg-color-overlay) !important;
|
|
}
|
|
}
|
|
|
|
.move-button {
|
|
cursor: move;
|
|
}
|
|
|
|
.ml-6 {
|
|
display: inline-flex;
|
|
vertical-align: middle;
|
|
margin-left: 6px;
|
|
}
|
|
|
|
.ml-6+.el-button {
|
|
margin-left: 6px;
|
|
}
|
|
|
|
.ba-render-color {
|
|
height: 25px;
|
|
width: 100%;
|
|
}
|
|
|
|
.cn-render-buttons {
|
|
:deep(.el-button) {
|
|
margin-left: 0;
|
|
}
|
|
}
|
|
</style>
|