import { getCurrentInstance, h, ref, defineComponent } from 'vue' import { ElTable, ElTableColumn, ElRadio } from 'element-plus' import { getFieldValue, isNotEmpty, isEmpty, isArray } from '@cip/utils/util' // import { handleFormConfig, handleTableConfig } from '../helper/d-render' import CipFormItem from '@cip/components/cip-form-item' import CipTableHandler from '@cip/components/cip-table-handler' import './index.less' // import { getViewComponent } from '@cip/components/cip-form-input/util' // import { useFieldValue } from '@cip/components/cip-form-item/form-item-hooks' export default defineComponent({ name: 'CipTable', inheritAttrs: false, props: { offset: Number, height: { type: String }, selectable: { type: Function }, selectRadio: { type: [String, Number] }, selectLabel: { type: String }, selectType: { type: String }, selectColumns: Array, columns: { type: Array, default: () => [] }, fieldKey: String, tableHeaderLabel: String, data: { type: Array, default: () => [] }, dependOnValues: Object, // 作为basic-table组件时对外部的依赖 inForm: Boolean, // 是否为表单的输入或展示 rowKey: [String, Function], treeProps: { type: Object, default: () => ({}) }, handlerWidth: { type: String, default: '120px' }, withTableHandle: Boolean, hideIndex: Boolean, indexFixed: Boolean // 左侧悬浮 }, emits: ['sort', 'update:data', 'update:selectColumns'], setup (props, context) { const instance = getCurrentInstance() const cipTableRef = ref() instance.ctx.cipTableRef = cipTableRef const updateData = (val, index) => { console.log('updateData') const data = props.data data[index] = val context.emit('update:data', data) } const getFormItem = (key, config, row, index) => { return h(CipFormItem, { key: index, model: row, fieldKey: key, config: config, inTable: true, tableDependOnValues: props.dependOnValues, tableData: props.data, 'onUpdate:model': (val) => { row = val updateData(val, index) } }) } const tableColumn = ({ key, config } = {}) => { const headerSlots = ({ column, $index }) => { return {config.required === true && *} {config.label} } const { children, ...tableColumnConfig } = config return h(ElTableColumn, { prop: key, align: config.type === 'number' ? 'right' : '', // 针对数字类型进行居右优化 style: 'display: flex;', ...tableColumnConfig }, { header: headerSlots, default: ({ row, $index, column }) => { // if ($index === -1) return // 如果写上这个代码 children 将失效 // const otherValue = !isEmpty(config.otherKey) ? getFieldValue(row, config.otherKey) : undefined if (isArray(config.children) && config.children.length > 0) { return config.children.map(tableColumn) } else { if ($index < 0) return null const modelValue = getFieldValue(row, key) // const [otherValue] = useFieldValue({ value: config.otherKey }, { value: row }, () => {}) // 同时开放key值插槽及key+'Slot' 的插槽 if (!['default', 'append', 'expand', '_handler'].includes(key) && context.slots[key]) { return context.slots[key]({ row, $index, column }) } // 特殊字段插槽 ['default', 'append'] if (context.slots[`${key}Slot`]) { return context.slots[key]({ row, $index, column }) } const inputConfig = { ...config } // 进行一次浅拷贝 inputConfig.width = '100%' inputConfig.hideLabel = true // config.labelWidth = 0 if (inputConfig.writable === true) { // 将form 输入组件的宽度设为100% config中的width 代表表格宽度 inputConfig.ruleKey = `${props.fieldKey}.${$index}.${key}` return getFormItem(key, inputConfig, row, $index) } if (!inputConfig.writable) { // if ((config.dependOn?.length > 0 || config.outDependOn?.length > 0)) { // 开启响应的效果 开启只读模式 inputConfig.readable = true if (!inputConfig.dynamic) { inputConfig.dependOn = [] } // ERROR: 此处将导致watch 出现错误 return getFormItem(key, inputConfig, row, $index) // } else { // // TODO: 考虑是否合并, 合并后样式是否有异常 // const viewProps = { // modelValue, // model: row, // config: config, // otherValue: otherValue.value // } // // 存在otherKey的时候把otherKey的值赋给otherValue // return h(getViewComponent(config.type), viewProps) // } } else { return modelValue } } } }) } const tableColumns = () => props.columns.map(tableColumn) const tableDefaultSlots = () => { const slots = tableColumns() if (isNotEmpty(props.offset) && props.offset > -1 && !props.hideIndex) { const indexColumn = h(ElTableColumn, { label: '序号', fixed: props.indexFixed ? 'left' : '', width: isEmpty(props.rowKey) ? '55px' : '75px' }, { default: ({ $index }) => `${$index + 1 + props.offset}` }) slots.unshift(indexColumn) } if (props.selectType === 'checkbox') { const option = { type: 'selection', width: '45px', fixed: 'left' } if (isNotEmpty(props.selectable)) { // 选择 option.selectable = (row, index) => props.selectable(row || {}, index) } const selectionColumn = h(ElTableColumn, option) slots.unshift(selectionColumn) } if (props.selectType === 'radio') { const selectionColumn = h(ElTableColumn, { width: '45px', fixed: 'left' }, { default: ({ row }) => h(ElRadio, { label: row[props.selectLabel] ?? row.id, modelValue: props.selectRadio }, { default: () => '' }) }) slots.unshift(selectionColumn) } if (context.slots.expand) { const expendColumn = h(ElTableColumn, { type: 'expand', width: '32px' }, { default: ({ row, index }) => context.slots.expand({ row, index }) }) slots.unshift(expendColumn) } // jsx编译时有时候会去除_handler插槽 if (props.withTableHandle && (context.slots._handler || context.slots.$handler)) { const handlerSlot = context.slots._handler || context.slots.$handler const handlerColumn = h(ElTableColumn, { label: '操作', fixed: 'right', width: props.handlerWidth || '120px' }, { default: ({ row, $index }) => h(CipTableHandler, { limit: 3 }, { default: () => handlerSlot({ row, $index }) }) }) slots.unshift(handlerColumn) // 内部组件必须使用cip-table-button } if (context.slots.default) { slots.push(context.slots.default()) } if (context.slots.prepend) { const prependSlots = context.slots.prepend() if (isArray(prependSlots)) { slots.unshift(...prependSlots) } else { slots.unshift(prependSlots) } } if (context.slots.append) { const appendSlots = context.slots.append() if (isArray(appendSlots)) { slots.push(...appendSlots) } else { slots.push(appendSlots) } } if (props.tableHeaderLabel) return h(ElTableColumn, { label: props.tableHeaderLabel, align: 'center' }, { default: () => slots }) return slots } const onSortChange = ({ prop, order }) => { context.emit('sort', { prop, order }) } return () => h(ElTable, { ...context.attrs, data: props.data, ref: cipTableRef, height: props.height, class: 'cip-table', rowKey: props.rowKey, treeProps: props.treeProps, onSortChange, onSelectionChange: (val) => { context.emit('update:selectColumns', val) } }, { default: tableDefaultSlots }) } })