<script lang="ts" setup name="NonthTemplateTable">
import type { Ref } from 'vue'
import { ElTable } from 'element-plus'
import { defineExpose, ref } from 'vue'
import type { TableColumn } from '@/components/NormalTable/table_interface'
import { getDictByCode } from '@/api/system/dict'
import type { dictType } from '@/global'
// import { useMergeCells } from '@/commonMethods/useMergeCells'
import { mergeTableRow, useMergeTableRow } from '@/commonMethods/useMergeTableRow'
// ------------------定义props、 emit-------------------
const props = defineProps({
pageType: {
type: String,
default: 'detail',
},
// 数据
data: {
type: Array,
default() {
return []
},
},
// 表格高度
height: {
type: Number,
default() {
return null
},
},
// 数据列配置
columns: {
type: Array<TableColumn>,
default() {
return () => []
},
},
// 表格大小
size: {
type: String,
default: 'default',
}, // 表格大小,默认,small,mini等,与el-table条件相同
// 标题
title: {
type: String,
default: '',
},
// 排序
index: {
type: String,
default: '',
},
// 按钮展示
showBtn: {
type: Boolean,
default: false,
},
// 计算机结果按钮
calcBtn: {
type: Boolean,
default: false,
},
// 自定义内容
customContent: {
type: Boolean,
default: false,
},
// 下拉框内容
selectAllList: {
type: Object,
default: () => ({}),
},
// 是否展示多选列
isMulti: {
type: Boolean,
default: true,
},
// 标题
showTitle: {
type: Boolean,
default: false,
},
// 需要合并的列
needMergeCells: {
type: Array,
default: () => ([]),
},
// 自定义下拉框内容
customSelect: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['change', 'selectionChange', 'rowClick', 'rowDbClick', 'multiSelect', 'filterChange', 'addRow', 'delRow', 'changeLoadSituationa', 'calculateResult', 'disabled', 'disabledItem', 'customSelect'])
// ------------------------------------------字典----------------------------------------------
// -------定义数据--------------
interface columnsCheckInfo {
text: string
show: boolean
}
const columnsChecked: Ref<columnsCheckInfo[]> = ref([])
const table = ref<InstanceType<typeof ElTable>>()
const singleChecked = ref('') // 单选选中id
// 初始化列显示状态
function initColumnsState() {
columnsChecked.value = []
for (const column of props.columns) {
columnsChecked.value.push({ text: column.text, show: !!column.show })
}
}
// 最终展示列
const columnsFiltered: Ref<TableColumn[]> = ref([])
// 切换列
function changeColumns() {
columnsFiltered.value = []
for (const i in props.columns) {
if (columnsChecked.value[i].show === true) {
columnsFiltered.value.push(props.columns[i])
}
}
}
// 刷新
function refresh() {
emit('change')
}
// 多选选中结果
function selectionChange(selection: []) {
emit('selectionChange', selection)
}
// 点击行
function rowClick(row: object, column?: any, event?: any) {
emit('rowClick', row)
}
// 双击行
function rowDbClick(row: object, column?: any, event?: any) {
emit('rowDbClick', row)
}
// 监听columns
watch(props.columns, (val) => {
initColumnsState()
changeColumns()
})
// 多选选中
const selectList = ref<any[]>([])
// 多选
const handleSelectionChange = (val: any) => {
selectList.value = val
emit('selectionChange', val)
}
// 清除多选选中
const clearMulti = () => {
console.log('清理选中')
table.value!.clearSelection()
singleChecked.value = ''
}
// 删除行
const delRow = (selectList: any[], list: any[], title: string) => {
emit('delRow', selectList, list, title)
}
// 添加行
const addRow = (list: any[], title: string, index: string) => {
emit('addRow', list, title, index)
}
// 下拉框
const getAnySelect = (text: string, title: string, scope: any, column: any) => {
let result = [] as any
if (props.customSelect) {
emit('customSelect', { text, title, scope, column }, (value: any) => {
result = value
})
return result
}
return props.selectAllList[text]
}
// 下拉框禁用情况
const disabled = (scope: any, column: any) => {
let result = false
emit('disabled', { scope, column }, (value: boolean) => {
result = value
})
return result
}
// 下拉框某一项禁用情况
// citem 当前下拉框选项
// const disabledItem = (scope: any, column: any, citem: any) => {
// let result = false
// emit('disabledItem', { scope, column, citem }, (value: boolean) => {
// result = value
// })
// return result
// }
// 下拉框获取焦点 或者 下拉框的值发生变化
const changeLoadSituationa = (value: any, index: number, text: string, type: string, list: any[], title: string) => {
emit('changeLoadSituationa', value, index, text, type, list, title)
}
// 计算结果
const calculateResult = (title: string, index: string) => {
emit('calculateResult', title, index)
}
// 获取字典value
const getDictValue = (value: string) => {
console.log(value, 'value')
}
// function spanMethod({ rowIndex, columnIndex }: { rowIndex: number; columnIndex: number }) {
// if (!props.needMergeCells.length) { return }
// return useMergeCells(props.data, props.needMergeCells, rowIndex, columnIndex)
// }
watch(() => props.data, (newValue, old) => {
if (!props.needMergeCells.length) {
return
}
if (newValue) {
useMergeTableRow(newValue, props.needMergeCells)
}
}, {
deep: true,
immediate: true,
})
defineExpose({
clearMulti, initColumnsState,
})
onBeforeMount(() => {
initColumnsState()
changeColumns()
})
</script>
<template>
<detail-block title="">
<div style="display: flex;justify-content: space-between;">
<span v-if="props.showTitle" style="padding: 0 10px;">{{ props.title }}</span>
<!-- 是否可选等一些条件 -->
<slot name="custom-check" />
<div style="padding: 0 10px;padding-bottom: 10px;display: flex;">
<!-- 是否可选等一些条件 -->
<slot name="custom-right" />
<el-button v-if="props.showBtn" type="primary" @click="addRow(props.data, props.title, props.index)">
增加行
</el-button>
<el-button v-if="props.showBtn" type="info" @click="delRow(selectList, props.data, props.title)">
删除行
</el-button>
<el-button v-if="props.calcBtn" type="primary" @click="calculateResult(props.title, props.index)">
计算结果
</el-button>
<!-- 自定义按钮 -->
<slot name="custom-btn" />
</div>
</div>
<el-table
id="print"
ref="table"
:data="data"
:height="height"
border
stripe
:span-method="mergeTableRow"
:size="size"
style="width: 100%;"
@selection-change="handleSelectionChange"
@row-click="rowClick"
@row-dblclick="rowDbClick"
>
<el-table-column v-if="props.isMulti " type="selection" width="38" />
<el-table-column align="center" label="序号" width="80" type="index" />
<el-table-column
v-for="item in columns"
:key="item.value"
:prop="item.value"
:label="item.text"
:width="item.width"
align="center"
>
<template #header>
<span v-show="item.required" style="color: red;">*</span><span>{{ item.text }}</span>
</template>
<template #default="scope">
<div style="display: flex;text-align: center;">
<!-- 输入框/选择器等 前面插槽 -->
<slot name="pre-content" :scope="scope" :column="item" />
<!-- 自定义内容 -->
<slot v-if="props.customContent" name="custom-content" :scope="scope" :column="item" />
<template v-if="!props.customContent">
<!-- 文本内容 -->
<div v-if="item.type === 'text'" style="text-align: center;width: 100%;line-height: 30px;">
{{ scope.row[item.value] }}
</div>
<!-- 输入框 -->
<el-input
v-if="item.type === 'input'" v-model="scope.row[item.value]"
:placeholder="`${item.text}`" style="width: 100%;"
:disabled="disabled(scope, item)"
/>
<!-- 数字输入框 -->
<el-input-number
v-if="item.type === 'number'" v-model="scope.row[item.value]"
:placeholder="`${item.text}`" style="width: 100%;" controls-position="right"
:disabled="disabled(scope, item)"
/>
<!-- 下拉框 -->
<el-select
v-if="item.type === 'select'" v-model="scope.row[item.value]"
:placeholder="`${item.text}`" style="width: 100%;"
:disabled="disabled(scope, item)"
@change="(value) => changeLoadSituationa(value, scope.$index, item.text, 'change', props.data, props.title)"
@focus="(value) => changeLoadSituationa(value, scope.$index, item.text, 'focus', props.data, props.title)"
>
<el-option
v-for="citem in getAnySelect(item.text, title, scope, item)"
:key="citem.id"
:label="citem.name"
:disabled="citem.disabled"
:value="citem[item.bind ? item.bind : 'name']"
/>
</el-select>
<!-- 下拉框-多选 -->
<el-select
v-if="item.type === 'select-multi'" v-model="scope.row[item.value]"
multiple
:placeholder="`${item.text}`" style="width: 100%;"
:disabled="disabled(scope, item)"
@change="(value) => changeLoadSituationa(value, scope.$index, item.text, 'change', props.data, props.title)"
@focus="(value) => changeLoadSituationa(value, scope.$index, item.text, 'focus', props.data, props.title)"
>
<el-option
v-for="citem in getAnySelect(item.text, title, scope, item)"
:key="citem.id"
:label="citem.name"
:disabled="citem.disabled"
:value="citem[item.bind ? item.bind : 'name']"
/>
</el-select>
<!-- 单选 -->
<el-radio-group v-if="item.type === 'radio'" v-model="scope.row[item.value]" :disabled="disabled(scope, item)" style="width: 100%;" class="ml-4 raioo">
<el-radio label="1" size="large">
是
</el-radio>
<el-radio label="0" size="large">
否
</el-radio>
</el-radio-group>
<!-- 输入下拉框(与字典联动) -->
<select-by-dict
v-if="item.type === 'select-dict'"
v-model="scope.row[item.value]"
:placeholder="`${item.text}`"
style="width: 100%;"
:disabled="disabled(scope, item)"
:dict-code="item.code"
@get-dict-value="getDictValue"
/>
</template>
<!-- 输入框/选择器等 后面插槽 -->
<slot name="next-content" :scope="scope" :column="item" />
</div>
</template>
</el-table-column>
<!-- <slot name="custom-column" /> -->
</el-table>
</detail-block>
</template>
<style lang="scss" scoped>
.single-table {
width: 100%;
:deep(.el-table th.el-table__cell:nth-child(1) .cell) {
visibility: hidden;
}
}
.radio {
:deep(.el-radio__label) {
display: none !important;
}
}
</style>
<style lang="scss">
.normal-table {
.el-radio__label {
display: none !important;
}
}
</style>