232 lines
7.4 KiB
Vue
232 lines
7.4 KiB
Vue
<template>
|
||
<!-- 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"
|
||
:model-value="fieldValue.toString()"
|
||
:loading="row.loading"
|
||
active-value="1"
|
||
inactive-value="0"
|
||
/>
|
||
|
||
<!-- 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="fullUrl(fieldValue)"
|
||
></el-image>
|
||
</div>
|
||
|
||
<!-- tag -->
|
||
<div v-if="field.render == 'tag' && fieldValue !== ''">
|
||
<el-tag :type="getTagType(fieldValue, field.custom)" effect="dark">
|
||
{{ 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"
|
||
/>
|
||
|
||
<!-- 按钮组 -->
|
||
<!-- 只对默认的编辑、删除、排序按钮进行鉴权,其他按钮请通过 display 属性控制按钮是否显示 -->
|
||
<div v-if="field.render == 'buttons' && field.buttons">
|
||
<template v-for="(btn, idx) in field.buttons" :key="idx">
|
||
<!-- 常规按钮 -->
|
||
<el-button
|
||
v-if="btn.render == 'basicButton'"
|
||
@click="onButtonClick(btn)"
|
||
:class="btn.class"
|
||
class="table-operate"
|
||
:type="btn.type"
|
||
:disabled="btn.disabled && btn.disabled(row, field)"
|
||
v-bind="btn.attr"
|
||
>
|
||
<Icon :name="btn.icon" />
|
||
<div v-if="btn.text" class="table-operate-text">{{ btn.text }}</div>
|
||
</el-button>
|
||
|
||
<!-- 带提示信息的按钮 -->
|
||
<el-tooltip
|
||
v-if="btn.render == 'tipButton'"
|
||
:disabled="btn.title && !btn.disabledTip ? false : true"
|
||
:content="btn.title"
|
||
placement="top"
|
||
>
|
||
<el-button
|
||
@click="onButtonClick(btn)"
|
||
:class="btn.class"
|
||
class="table-operate"
|
||
:type="btn.type"
|
||
:disabled="btn.disabled && btn.disabled(row, field)"
|
||
v-bind="btn.attr"
|
||
>
|
||
<Icon :name="btn.icon" />
|
||
<div v-if="btn.text" class="table-operate-text">{{ btn.text }}</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 class="ml-6">
|
||
<el-tooltip :disabled="btn.title ? false : true" :content="btn.title" placement="top">
|
||
<el-button
|
||
:class="btn.class"
|
||
class="table-operate"
|
||
:type="btn.type"
|
||
:disabled="btn.disabled && btn.disabled(row, field)"
|
||
v-bind="btn.attr"
|
||
>
|
||
<Icon :name="btn.icon" />
|
||
<div v-if="btn.text" class="table-operate-text">{{ btn.text }}</div>
|
||
</el-button>
|
||
</el-tooltip>
|
||
</div>
|
||
</template>
|
||
</el-popconfirm>
|
||
|
||
<!-- 带提示的可拖拽按钮 -->
|
||
<el-tooltip
|
||
v-if="btn.render == 'moveButton' && btn.name == 'weigh-sort'"
|
||
:disabled="btn.title && !btn.disabledTip ? false : true"
|
||
:content="btn.title"
|
||
placement="top"
|
||
>
|
||
<el-button
|
||
:class="btn.class"
|
||
class="table-operate move-button"
|
||
:type="btn.type"
|
||
:disabled="btn.disabled && btn.disabled(row, field)"
|
||
v-bind="btn.attr"
|
||
>
|
||
<Icon :name="btn.icon" />
|
||
<div v-if="btn.text" class="table-operate-text">{{ btn.text }}</div>
|
||
</el-button>
|
||
</el-tooltip>
|
||
</template>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, inject } from 'vue'
|
||
import 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 = (value: any) => {
|
||
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] : ''
|
||
}
|
||
</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;
|
||
}
|
||
.table-operate {
|
||
padding: 4px 5px;
|
||
height: auto;
|
||
}
|
||
.table-operate .icon {
|
||
font-size: 14px !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%;
|
||
}
|
||
</style>
|