|
|
@ -11,6 +11,7 @@ |
|
|
|
:loading-label="$t('tip.dataLoading')" |
|
|
|
v-bind="attrs" |
|
|
|
:separator="table.separator" |
|
|
|
:hide-header="props.hideHeader" |
|
|
|
:selection="selectionComputed" |
|
|
|
:rows="table.rows" |
|
|
|
:columns="columnsComputed" |
|
|
@ -18,7 +19,6 @@ |
|
|
|
:loading="state.loading" |
|
|
|
:class="tableClassComputed" |
|
|
|
:table-style="tableHeightComputed" |
|
|
|
card-container-class="card-container-class3333" |
|
|
|
:row-key="rowKey_" |
|
|
|
:visible-columns="visibleColumnsComputed" |
|
|
|
:hide-bottom="pageable && !props.localMode && !tree ? false : true" |
|
|
@ -95,6 +95,11 @@ |
|
|
|
:request="onRequest" |
|
|
|
></GridPagination> |
|
|
|
</template> |
|
|
|
|
|
|
|
<!-- 隐藏表头且无数据时 --> |
|
|
|
<template v-if="table.rows.length === 0 && props.hideHeader" #top-row> |
|
|
|
<div :style="hideHeaderAndNoDataStyleComputed"><q-icon size="2em" name="info" />{{ $t('tip.noData') }}</div> |
|
|
|
</template> |
|
|
|
</q-table> |
|
|
|
|
|
|
|
<!-- 新增与编辑窗口 --> |
|
|
@ -128,7 +133,7 @@ import GridPagination from './GridPagination.vue'; |
|
|
|
import GridEditor from './GridEditor.vue'; |
|
|
|
import CellEditor from './CellEditor.vue'; |
|
|
|
import GridView from './GridView.vue'; |
|
|
|
import { selectMode as selectMode_, getMergeColumns, sortByProperties, editStatus } from './ts/grid.ts'; |
|
|
|
import { selectMode as selectMode_, sortByProperties, editStatus, groupMode as groupMode_ } from './ts/grid.ts'; |
|
|
|
|
|
|
|
import { columnDefaultProps } from './ts/grid.ts'; |
|
|
|
|
|
|
@ -183,10 +188,13 @@ const props = defineProps({ |
|
|
|
foreignKey: { type: String, default: 'parent' }, // 数据外键(常规表格模式时,该字段暂时无用,将来可用作多个表格的数据关系字段。树形表格模式时,该字段为构建树数据的关系字段) |
|
|
|
refreshData: { type: Boolean, default: false }, // 新增、删除、修改成功后是否刷新数据列表,默认不刷新但是新增修改后台必须返回对应的行数据对象,删除则必须返回删除的记录集primaryKey集合。 |
|
|
|
dbClickOperation: { type: String, default: 'view' }, // 默认的双击操作:可填写内置或自定义按钮name,执行的操作为按钮对应的click,固定值提供:expand(展开双击的行)、none(双击不执行任何动作) |
|
|
|
separator: { type: String, default: 'horizontal' }, |
|
|
|
groupMode: { type: String, default: '' }, |
|
|
|
group: { |
|
|
|
type: Array, |
|
|
|
separator: { type: String, default: 'cell' }, // 表格分割线,支持:horizontal、vertical、cell、none |
|
|
|
hideHeader: { type: Boolean, default: false }, // 隐藏表头 |
|
|
|
groupMode: { type: String, default: undefined }, // 分组模式,支持:alone、merge |
|
|
|
groupStartOpen: { type: [String, Array], default: undefined }, // alone分组模式下默认展开的组,字符串支持:all、first、none,数组可配置多个组名。 |
|
|
|
groupByField: { |
|
|
|
// 分组字段配置,当分组模式为 alone 时若配置的为数组,取数组第一个字段。 |
|
|
|
type: [String, Array], |
|
|
|
default: () => { |
|
|
|
return []; |
|
|
|
}, |
|
|
@ -343,7 +351,6 @@ const tableColumnsMap = ref(arrayToMap('name', rawColumns.value)); |
|
|
|
const rowKey_ = '_rowKey_'; // 行数据中前端附加的UUID字段名 |
|
|
|
const queryFormFieldsMap = arrayToMap('name', props.queryFormFields); |
|
|
|
const tableColumns = ref(columnDefaultProps(rawColumns.value, props.sortNo)); |
|
|
|
const mergeColumns = getMergeColumns(tableColumns.value); |
|
|
|
const url = { |
|
|
|
dataUrl: props.dataUrl, |
|
|
|
fetchDataUrl: props.fetchDataUrl, |
|
|
@ -450,8 +457,12 @@ const denseBottomComputed = computed(() => { |
|
|
|
const visibleColumnsComputed = computed(() => { |
|
|
|
const visibleColumns: string[] = []; |
|
|
|
table.columns.forEach((item) => { |
|
|
|
if (!item.hidden && (!props.tree || (props.tree && item.name !== '_sortNo_'))) { |
|
|
|
visibleColumns.push(item.name); |
|
|
|
if (!props.tree || (props.tree && item.name !== '_sortNo_')) { |
|
|
|
if (Tools.isEmpty(item.showIf)) { |
|
|
|
visibleColumns.push(item.name); |
|
|
|
} else if (typeof item.showIf === 'boolean' && item.showIf) { |
|
|
|
visibleColumns.push(item.name); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
return visibleColumns; |
|
|
@ -472,8 +483,8 @@ const state = reactive({ |
|
|
|
middleScrollWidth: 0, // 表格出现滚动条时的宽度,若无滚动条则与 middleWidth 一致 |
|
|
|
middleHeight: 0, // 表格当前middle区域高度(表格列头及数据行区域) |
|
|
|
columnHeadHeight: 0, // 表格当前列头高度 |
|
|
|
tableTitleWidth: 0, // 当前表格title宽度 |
|
|
|
titleTotalHeight: 0, // 当前表格title排除无数据行的总高度 |
|
|
|
hideHeaderNoDataHeight: 0, // 隐藏表头时无数据提示区域高度 |
|
|
|
}, |
|
|
|
pagination: { |
|
|
|
config: { |
|
|
@ -559,6 +570,14 @@ const noDataTrHeightComputed = computed(() => { |
|
|
|
}; |
|
|
|
return style; |
|
|
|
}); |
|
|
|
const hideHeaderAndNoDataStyleComputed = computed(() => { |
|
|
|
return { |
|
|
|
height: state.refHeightWidth.hideHeaderNoDataHeight + 'px', |
|
|
|
display: 'flex', |
|
|
|
'align-items': 'center', |
|
|
|
'justify-content': 'center', |
|
|
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
const noDataTrColspanComputed = computed(() => { |
|
|
|
let colspan = excludeColumnNum.value; |
|
|
@ -625,6 +644,7 @@ const onResize = () => { |
|
|
|
state.refHeightWidth.middleWidth = tableRef.value.$el.getElementsByClassName('q-table__middle')[0]?.clientWidth; |
|
|
|
state.refHeightWidth.middleScrollWidth = tableRef.value.$el.getElementsByClassName('q-table__middle')[0]?.scrollWidth; |
|
|
|
state.refHeightWidth.columnHeadHeight = tableRef.value.$el.getElementsByTagName('thead')[0]?.clientHeight; |
|
|
|
state.refHeightWidth.hideHeaderNoDataHeight = tableRef.value.$el.getElementsByClassName('q-table__middle')[0]?.clientHeight; |
|
|
|
// 判断是否有数据,没数据修改 middleHeight |
|
|
|
if ((table.rows && table.rows.length > 0) || attrs['hide-bottom']) { |
|
|
|
state.refHeightWidth.middleHeight = tableRef.value.$el.getElementsByClassName('q-table__middle')[0]?.clientHeight; |
|
|
@ -635,12 +655,15 @@ const onResize = () => { |
|
|
|
} |
|
|
|
state.refHeightWidth.middleHeight = state.refHeightWidth.columnHeadHeight + scrollHeight; |
|
|
|
} |
|
|
|
state.refHeightWidth.tableTitleWidth = tableRef.value.$el.getElementsByClassName('_table-title')[0]?.clientWidth; |
|
|
|
let titleTotalHeight = tableRef.value.$el.getElementsByTagName('thead')[0].offsetHeight; |
|
|
|
let titleTotalHeight = tableRef.value.$el.getElementsByTagName('thead')[0]?.offsetHeight; |
|
|
|
// 无数据时列头会增加一行,多表头的top距离计算会出错,需减掉多出来的提示行。 |
|
|
|
if (table.rows.length === 0) { |
|
|
|
const noDataTrHeight = tableRef.value.$el.getElementsByClassName('noDataTr')[0].offsetHeight; |
|
|
|
titleTotalHeight = titleTotalHeight - noDataTrHeight; |
|
|
|
const noDataTrHeight = tableRef.value.$el.getElementsByClassName('noDataTr')[0]?.offsetHeight; |
|
|
|
if (titleTotalHeight && titleTotalHeight > 0) { |
|
|
|
titleTotalHeight = titleTotalHeight - noDataTrHeight; |
|
|
|
} else { |
|
|
|
titleTotalHeight = noDataTrHeight; |
|
|
|
} |
|
|
|
} |
|
|
|
state.refHeightWidth.titleTotalHeight = titleTotalHeight; |
|
|
|
} |
|
|
@ -901,10 +924,10 @@ const initRowDataExtraProperty = (rowData) => { |
|
|
|
* @param rows 数据行集合 |
|
|
|
*/ |
|
|
|
const setRowDataExtraProperty = (rows: []) => { |
|
|
|
if (mergeColumns.length > 0 && !props.tree) { |
|
|
|
if (props.groupMode === groupMode_.merge && !props.tree) { |
|
|
|
// 如果存在需要合并的字段,并且不是树表格,重新对数据进行排序 |
|
|
|
table.mergeRecords = {}; |
|
|
|
sortByProperties(rows, mergeColumns); |
|
|
|
// sortByProperties(rows, mergeColumns); |
|
|
|
} |
|
|
|
if (rows && rows.length > 0) { |
|
|
|
rows.forEach((item: any, index) => { |
|
|
@ -954,20 +977,20 @@ const setOldValue = (rowData) => { |
|
|
|
* desc: { 天安门: [5,1] } |
|
|
|
*/ |
|
|
|
const addMergeRecords = (rowData) => { |
|
|
|
if (mergeColumns.length > 0 && !props.tree) { |
|
|
|
mergeColumns.forEach((columnName) => { |
|
|
|
const tmpArr = [rowData[rowDataExtraPropertyName.rowKey]]; |
|
|
|
if (table.mergeRecords[columnName]) { |
|
|
|
if (table.mergeRecords[columnName][rowData[columnName]]) { |
|
|
|
table.mergeRecords[columnName][rowData[columnName]].push(rowData[rowDataExtraPropertyName.rowKey]); |
|
|
|
} else { |
|
|
|
table.mergeRecords[columnName][rowData[columnName]] = tmpArr; |
|
|
|
} |
|
|
|
} else { |
|
|
|
table.mergeRecords[columnName] = { [rowData[columnName]]: tmpArr }; |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
// if (mergeColumns.length > 0 && !props.tree) { |
|
|
|
// mergeColumns.forEach((columnName) => { |
|
|
|
// const tmpArr = [rowData[rowDataExtraPropertyName.rowKey]]; |
|
|
|
// if (table.mergeRecords[columnName]) { |
|
|
|
// if (table.mergeRecords[columnName][rowData[columnName]]) { |
|
|
|
// table.mergeRecords[columnName][rowData[columnName]].push(rowData[rowDataExtraPropertyName.rowKey]); |
|
|
|
// } else { |
|
|
|
// table.mergeRecords[columnName][rowData[columnName]] = tmpArr; |
|
|
|
// } |
|
|
|
// } else { |
|
|
|
// table.mergeRecords[columnName] = { [rowData[columnName]]: tmpArr }; |
|
|
|
// } |
|
|
|
// }); |
|
|
|
// } |
|
|
|
}; |
|
|
|
|
|
|
|
watchEffect(() => { |
|
|
@ -1004,7 +1027,7 @@ watchEffect(() => { |
|
|
|
}); |
|
|
|
|
|
|
|
const tableClassComputed = computed(() => { |
|
|
|
const classArr = <string[]>['sticky-header-column-table', 'w-grid']; |
|
|
|
const classArr = <string[]>['sticky-header-column-table']; |
|
|
|
if (table.stickyNum && table.stickyNum > 0) { |
|
|
|
if (headerRef.value?.getColumnTitleState()?.columnTitleRowNum > 1) { |
|
|
|
// 存在多行列头 |
|
|
@ -1666,14 +1689,14 @@ const refreshStyle = (time = 500) => { |
|
|
|
if (tableRef.value) { |
|
|
|
state.refHeightWidth.yLocation = tableRef.value.$el.getBoundingClientRect()?.y; |
|
|
|
if (tableRef.value.$el.getElementsByClassName('noDataTr').length > 0) { |
|
|
|
state.refHeightWidth.noDataTrYLocation = tableRef.value.$el.getElementsByClassName('noDataTr')[0].getBoundingClientRect().y; |
|
|
|
state.refHeightWidth.noDataTrYLocation = tableRef.value.$el.getElementsByClassName('noDataTr')[0]?.getBoundingClientRect().y; |
|
|
|
} |
|
|
|
state.refHeightWidth.topHeight = tableRef.value.$el.getElementsByClassName('q-table__top')[0]?.clientHeight; |
|
|
|
state.refHeightWidth.bottomHeight = tableRef.value.$el.getElementsByClassName('q-table__bottom')[0]?.clientHeight; |
|
|
|
state.refHeightWidth.middleWidth = tableRef.value.$el.getElementsByClassName('q-table__middle')[0]?.clientWidth; |
|
|
|
state.refHeightWidth.middleScrollWidth = tableRef.value.$el.getElementsByClassName('q-table__middle')[0]?.scrollWidth; |
|
|
|
state.refHeightWidth.columnHeadHeight = tableRef.value.$el.getElementsByTagName('thead')[0]?.clientHeight; |
|
|
|
state.refHeightWidth.tableTitleWidth = tableRef.value.$el.getElementsByClassName('_table-title')[0]?.clientWidth; |
|
|
|
state.refHeightWidth.hideHeaderNoDataHeight = tableRef.value.$el.getElementsByClassName('q-table__middle')[0]?.clientHeight; |
|
|
|
// 判断是否有数据,没数据修改 middleHeight |
|
|
|
if ((table.rows && table.rows.length > 0) || attrs['hide-bottom']) { |
|
|
|
state.refHeightWidth.middleHeight = tableRef.value.$el.getElementsByClassName('q-table__middle')[0]?.clientHeight; |
|
|
@ -1728,11 +1751,15 @@ const refreshStyle = (time = 500) => { |
|
|
|
column1Width + column2Width + column3Width + column4Width + column5Width + column6Width + column7Width + column8Width + column9Width + 'px', |
|
|
|
); |
|
|
|
} |
|
|
|
let titleTotalHeight = tableDom.getElementsByTagName('thead')[0].offsetHeight; |
|
|
|
let titleTotalHeight = tableDom.getElementsByTagName('thead')[0]?.offsetHeight; |
|
|
|
// 无数据时列头会增加一行,多表头的top距离计算会出错,需减掉多出来的提示行。 |
|
|
|
if (table.rows.length === 0) { |
|
|
|
const noDataTrHeight = tableRef.value.$el.getElementsByClassName('noDataTr')[0].offsetHeight; |
|
|
|
titleTotalHeight = titleTotalHeight - noDataTrHeight; |
|
|
|
const noDataTrHeight = tableRef.value.$el.getElementsByClassName('noDataTr')[0]?.offsetHeight; |
|
|
|
if (titleTotalHeight && titleTotalHeight > 0) { |
|
|
|
titleTotalHeight = titleTotalHeight - noDataTrHeight; |
|
|
|
} else { |
|
|
|
titleTotalHeight = noDataTrHeight; |
|
|
|
} |
|
|
|
} |
|
|
|
state.refHeightWidth.titleTotalHeight = titleTotalHeight; |
|
|
|
} |
|
|
|