import { ref, computed, watch, nextTick, unref, onMounted, onBeforeUnmount } from 'vue' import { isDefine, toggleClass } from '@/utils/common' import type { Ref, ShallowRef, UnwrapRef } from 'vue' import type { InstanceTable } from 'global-type' import type { MultipleResult } from '@/api/api' import { throttle } from 'lodash-es' import useMainStore from '@/store/main' import bus from '@/utils/bus' import { ElMessage } from 'element-plus' type ArrayObjectType = Array> type MultipleResultType> = MultipleResult type InputDataType = MultipleResultType | ArrayObjectType type TableDataType = Ref | ShallowRef type ArrayData = T extends MultipleResultType ? D : ExtractArrayValue type RowType> = ArrayData> & { index: number } const mainStore = useMainStore() function isMultipleData(data: any): data is MultipleResultType { return isDefine(data?.result) && isDefine(data?.totalCount) } const useTableCheck = >(data: T, auto = true) => { const tableRef = ref() const elTableRef = computed(() => { return tableRef?.value?.tableRef }) const totalCount = ref(null) const pageSize = ref(null) const pageNumber = ref(null) const initPaginationParams = () => { const _data: any = unref(data) if (isMultipleData(_data)) { totalCount.value = _data.totalCount pageSize.value = _data.pageSize pageNumber.value = _data.pageNumber } } initPaginationParams() watch(data, () => { initPaginationParams() }) const tableData = computed(() => { const d = unref(data) // let result: RowType[] = [] let result: any[] = [] if (d) { if (isMultipleData(d)) { result = d?.result?.map((d, index) => ({ ...d, index: d.index ?? index })) } else { result = d?.map((d, index) => ({ ...d, index: d.index ?? index })) } } return result }) // const current = ref>() const current = ref() // const currentView = ref>() const currentView = ref() const visibleHistory = ref(false) watch( tableData, () => { current.value = void 0 currentView.value = void 0 if (tableData?.value?.length && auto) { nextTick(() => { elTableRef?.value?.setCurrentRow(tableData.value[0]) }) } }, { immediate: true } ) /** 表格选中 */ // const onCurrentChange = (row: RowType) => { const onCurrentChange = (row: any) => { current.value = row } /** 表格行双击 */ // const onDbClick = (row: RowType) => { const onDbClick = (row: any) => { currentView.value = row visibleHistory.value = true } /** 下一份 */ const next = () => { // elTableRef?.value?.setCurrentRow(tableData.value[((current.value?.index || 0) + 1) % tableData.value.length]) const rightTableViewDom = document.querySelector('.table-view') if (rightTableViewDom) { toggleClass(rightTableViewDom, 'collapse') } } const nextRow = throttle(() => { console.log('current.value?.index:', current.value?.index) console.log('tableData.value.length:', tableData.value.length) if (current.value?.index == tableData.value.length - 1) { //说明高亮正处于最后一行了,需要提示用户是否需要翻到下一页。 if (totalCount.value !== null && pageSize.value !== null) { // 说明页面只使用了useTableCheck,而未使用useTable。 //注意:这里只处理只使用了useTableCheck而未使用useTable的情况。另外一种情况在useTable里处理。避免重复 //只使用了useTableCheck,而未使用useTable的情况,基本上是pageSize传了99999这种情况,所以一页就是全部的数据,最后一行就是到底了 if (pageNumber.value * pageSize.value + 1 > totalCount.value) { ElMessage.warning('当前页已是最后一页') } else { //该情况应该不可能出现,因为只使用了useTableCheck而未使用useTable的情况,是只有一页的,即pageSize传的999999之类 // mainStore.setRowNextBottomDialogStatus(true) } } else { //在useTable里才能拿到分页相关信息,所以要对useTable进行通信,告诉它到了最后一行了,是否需要弹框诱导到下一页 bus.emit('atBottomRowFromUseTableCheck') } return } const index = (current.value?.index || 0) + 1 elTableRef?.value?.setCurrentRow(tableData.value[index % tableData.value.length]) const tBodyDomWrap: any = elTableRef?.value?.$refs.bodyWrapper if (tBodyDomWrap) { if (index % tableData.value.length == 0) { elTableRef?.value?.scrollTo({ left: 0, top: 0, behavior: 'smooth' }) } else { const wrap = tBodyDomWrap.getElementsByClassName('el-scrollbar__wrap')[0] const oHeight = wrap.offsetHeight const sTop = wrap.scrollTop const sHeight = wrap.scrollHeight const targetRowAsHeight = 36 * ((current.value?.index || 0) + 1) if (sHeight > oHeight && targetRowAsHeight - sTop > oHeight) { const t = sHeight - targetRowAsHeight elTableRef?.value?.scrollTo({ left: 0, top: sTop + 36, behavior: 'smooth' }) } } } // elTableRef?.value?.scrollTo(0, (current.value?.index || 0) * 36) }, 300) const prevRow = throttle(() => { console.log('current.value?.index:', current.value?.index) if (current.value?.index > 0) { const index = current.value?.index elTableRef?.value?.setCurrentRow(tableData.value[index - 1]) const tBodyDomWrap: any = elTableRef?.value?.$refs.bodyWrapper if (tBodyDomWrap) { if (index % tableData.value.length == 0) { elTableRef?.value?.scrollTo({ left: 0, top: 0, behavior: 'smooth' }) } else { const wrap = tBodyDomWrap.getElementsByClassName('el-scrollbar__wrap')[0] const oHeight = wrap.offsetHeight const sTop = wrap.scrollTop const sHeight = wrap.scrollHeight const targetRowAsHeight = 36 * (current.value?.index || 0) if (targetRowAsHeight - 36 < sTop) { elTableRef?.value?.scrollTo({ left: 0, top: targetRowAsHeight - 36, behavior: 'smooth' }) } } } } }, 300) const arrowDownToNextRow = (e: any) => { // if (e.target.tagName === 'INPUT' || (e.target.className || '').includes('contenteditable-ele')) { // return false // } if ((e.target.className || '').includes('contenteditable-ele')) { return false } // e.preventDefault() if (e.key === 'ArrowDown') { e.preventDefault() nextRow() } else if (e.key === 'ArrowUp') { e.preventDefault() prevRow() } } onMounted(() => { document.addEventListener('keydown', arrowDownToNextRow) }) onBeforeUnmount(() => { document.removeEventListener('keydown', arrowDownToNextRow) }) return { tableRef, elTableRef, tableData, current, currentView, visibleHistory, onCurrentChange, onDbClick, next, nextRow, } } export default useTableCheck