<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 { initTableRow, isMerge, mergeTableRow, useMergeTableRow } from '@/commonMethods/useMergeTableRow' // import { } 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 = (value1: any, value: any, index: number, text: string, type: string, list: any[], title: string) => { // console.log(value, 'value') // // console.log(value, 'valuevaluevalue') emit('changeLoadSituationa', value1, index, text, type, list, title) } // 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) { if (Array.isArray(newValue) && newValue?.length) { const data = newValue[newValue.length - 1] if (isMerge(data)) { console.log('isMerge') return } } console.log('要合并了') useMergeTableRow(newValue, props.needMergeCells) } }, { deep: true, immediate: true, }) defineExpose({ clearMulti, initColumnsState, }) onBeforeMount(() => { initColumnsState() changeColumns() }) const inputBlur = (value: any, index: number, attribute: string) => { if (!String(value)) { props.data[index][attribute] = '0' } } </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;align-items: center;text-align: center;justify-content: center;"> <!-- 输入框/选择器等 前面插槽 --> <slot name="pre-content" :scope="scope.row" :column="item" :index="scope.$index" /> <!-- 自定义内容 --> <slot v-if="item.customContent" name="custom-content" :scope="scope.row" :column="item" :index="scope.$index" /> <template v-if="!item.customContent"> <!-- 文本内容 --> <span v-if="item.type === 'text'" style="text-align: center;"> {{ scope.row[item.value] }} </span> <!-- 输入框 --> <el-input v-if="item.type === 'input'" 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)" /> <!-- 数字输入框 --> <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)" :precision="item.precision" :value-on-clear="0" @change="(value) => changeLoadSituationa(value, scope.$index, item.text, 'change', props.data, props.title)" /> <!-- <el-input v-if="item.type === 'number'" v-model="scope.row[item.value]" type="number" :placeholder="`${item.text}`" style="width: 100%;" controls-position="right" :disabled="disabled(scope, item)" :precision="item.precision" :value-on-clear="0" @change="(value) => changeLoadSituationa(value, scope.$index, item.text, 'change', props.data, props.title)" @blur="inputBlur(scope.row[item.value], scope.$index, item.value)" /> --> <!-- 下拉框 --> <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 radio" @change="(value) => changeLoadSituationa(value, scope.$index, item.text, 'change', props.data, props.title)" > <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="(val) => { getDictValue(scope.row[item.value], val, scope.$index, item.text, 'change', props.data, props.title) }" /> </template> <!-- 输入框/选择器等 后面插槽 --> <slot name="next-content" :scope="scope.row" :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: block !important; } } </style> <!-- <style lang="scss"> .normal-table { .el-radio__label { display: none !important; } } </style> -->