Files
sk_fems_ui/components/common/Grid.vue
2025-07-22 09:58:38 +07:00

720 lines
20 KiB
Vue

<template>
<tui-grid
:ref="['tuigrid' + gridName]"
:data="chkGridData"
:columns="chkGridColumns"
:options="chkGridOptions"
@focusChange="focusChangeEvt"
@click="startEditing"
@editingFinish="editingFinish"
@dblclick="dblClick"
@mouseover="mouseoverEvent"
@mouseout="mouseoutEvent"
/>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
gridName: {
type: String,
require: true,
},
dataPath: {
type: Object,
require: false,
default: null,
},
editorGrid: {
type: Boolean,
default: false,
require: false,
},
innerTabGridInfo: {
type: Object,
default: null,
},
selectedRowDataWatchFlag: {
type: Boolean,
require: false,
default: false,
},
preventFocusChangeEventFlag: {
type: Boolean,
require: false,
default: false,
},
// gridInstance Array
preventFocusChangeEventTargetGridList: {
type: Array,
require: false,
default: null,
},
columnClickEventFlag: {
type: Boolean,
require: false,
default: false,
},
mouseoverEvent: {
type: Function,
default() {
return 'Default Function';
},
},
mouseoutEvent: {
type: Function,
default() {
return 'Default Function';
},
},
},
data() {
return {
gridInstance: null,
gridHeight: null,
selecrRowKey: null,
originData: [],
editorStartKey: null,
editorEndKey: null,
scrollBody: null,
gridScrollTop: 0,
gridScrollLeft: 0,
};
},
computed: {
...mapState({
pageData: state => state.pageData,
gridData(state) {
return this.dataPath
? this.dataPath[this.gridName]
: state.pageData[this.parentPrgmId][this.gridName];
},
drawer: state => state.drawer,
activePrgmId(state) {
return state.activeMenuInfo.prgmId;
},
}),
chkGridData() {
// return this.pageData[this.parentPrgmId][this.gridName].data;
return this.gridData.data;
},
chkGridColumns() {
return this.gridData.column;
},
chkGridOptions() {
const options = {
// bodyHeight: 'fitToContent',
scrollX: false,
scrollY: false,
...this.gridData.option,
useIcon: false,
};
options.treeColumnOptions = {
useIcon: false,
...options.treeColumnOptions,
};
return options;
},
defaultRow() {
return this.gridData.defaultRow;
},
},
watch: {
chkGridData(val) {
this.$refs['tuigrid' + this.gridName].invoke('resetData', val);
},
innerTabGridInfo(val) {
const _this = this;
setTimeout(() => {
_this.refreshLayout();
}, 500);
},
activePrgmId(val) {
const _this = this;
setTimeout(() => {
_this.refreshLayout();
}, 700);
if (val == this.parentPrgmId) {
setTimeout(() => {
if (!_this.innerTabGridInfo) {
//_this.refreshLayout();
_this.scrollBody.scrollTop = _this.gridScrollTop;
_this.scrollBody.scrollLeft = _this.gridScrollLeft;
} else {
if (_this.innerTabGridInfo.tab == _this.innerTabGridInfo.idx) {
//_this.refreshLayout();
_this.scrollBody.scrollTop = _this.gridScrollTop;
_this.scrollBody.scrollLeft = _this.gridScrollLeft;
}
}
}, 1000);
}
},
drawer() {
const _this = this;
setTimeout(() => {
_this.refreshLayout();
}, 500);
},
},
created() {},
async mounted() {
console.log('--------------DEBUG----gridData: ', this.gridData);
if (this.gridName) {
this.gridInstance = this.$refs['tuigrid' + this.gridName];
this.scrollBody = document
.getElementsByClassName('tui-grid-rside-area')
[
document.getElementsByClassName('tui-grid-rside-area').length - 1
].getElementsByClassName('tui-grid-body-area')[0];
this.scrollBody.addEventListener('scroll', e => {
this.gridScrollTop = e.target.scrollTop;
this.gridScrollLeft = e.target.scrollLeft;
});
}
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
}),
// true : 현재 행 혹은 연결된 그리드가 수정중인 상태
checkGridState() {
var rowStatList = ['I', 'U', 'D'];
var row = this.gridInstance.invoke('getFocusedCell');
if (row) {
var rowData = this.gridInstance.invoke('getRow', row.rowKey);
if (rowData) {
var rowStat = rowData['rowStat'];
if (rowStatList.includes(rowStat)) {
return true;
}
}
}
if (this.preventFocusChangeEventTargetGridList) {
for (var gridInstance of this.preventFocusChangeEventTargetGridList) {
var dataArr = gridInstance.save();
if (dataArr.length > 0) {
return true;
}
}
}
return false;
},
preventFocusChangeEvent(e) {
var result = false;
if (this.preventFocusChangeEventFlag) {
if (this.checkGridState()) {
e.stop();
return true;
}
}
return result;
},
columnClickEvent(e) {
var result = false;
if (this.columnClickEventFlag) {
return true;
}
return result;
},
getCheckedRowsEvt() {
const checkedRowDataList = this.gridInstance.invoke('getCheckedRows');
return checkedRowDataList;
},
dblClick(nativeEvent) {
if (this.preventFocusChangeEvent(nativeEvent)) {
return;
}
this.$emit(
'dblClick',
this.gridInstance.invoke('dblclick'),
nativeEvent,
this.gridName,
);
},
uncheckEvt(rowData, instance) {
this.gridInstance.invoke('uncheck', rowData.rowKey, instance);
},
checkEvt(rowData, instance) {
this.gridInstance.invoke('check', rowData.rowKey, instance);
},
setSelectionRange(rowKey) {
const rowDatas = this.gridInstance.invoke('getData');
rowDatas.forEach(item => {
if (item.rowKey == rowKey) {
this.gridInstance.invoke(
'addRowClassName',
item.rowKey,
'row-selected',
);
} else {
this.gridInstance.invoke(
'removeRowClassName',
item.rowKey,
'row-selected',
);
}
});
},
focusChangeEvt(e) {
// console.log('focusChangeEvt1...')
if (this.preventFocusChangeEvent(e)) {
// console.log('prevent focusChangeEvt')
return;
}
// console.log('focusChangeEvt2...')
// cell 선택시 row 선택 method
if (e.rowKey >= 0) {
this.$emit(
'getRowsData',
this.gridInstance.invoke('getRow', e.rowKey),
this.gridName,
e.columnName,
);
this.selecrRowKey = e.rowKey;
this.setSelectionRange(e.rowKey);
}
this.sendSelectedRowData(e.rowKey);
},
startEditing(e) {
// console.log('startEditing1...')
if (this.preventFocusChangeEvent(e)) {
// console.log('prevent startEditing')
return;
}
if (this.columnClickEvent(e)) {
this.$emit('columnClick', e, this.gridName);
return;
}
// console.log('startEditing2...')
if (this.editorGrid && e.rowKey >= 0) {
this.editorStartKey = e.rowKey;
// console.log("E::", this.gridInstance.invoke("getRow", e.rowKey));
this.gridInstance.invoke('startEditing', e.rowKey, e.columnName);
this.$emit(
'getRowsData',
this.gridInstance.invoke('getRow', e.rowKey),
this.gridName,
e.columnName,
);
this.setSelectionRange(e.rowKey);
}
},
async editingFinish(e) {
// console.log("Editing END E::", e);
// editor 간 이동시 수정되는 문제 수정
// e.rowEditingFg: grid의 한 row를 한번에 수정할 시 각각의 cell 마다 click 이벤트가 발생하지 않아 this.editorStartKey값이 제대로 입력 되지 않는 경우를 대비하여 만든 Fg
if (this.editorGrid) {
this.editorEndKey = Number.isInteger(e.rowKey) ? e.rowKey : null;
if (e.rowEditingFg == undefined && this.editorStartKey >= 0) {
if (this.editorStartKey != this.editorEndKey) {
this.editorStartKey = null;
this.editorEndKey = null;
return false;
}
}
}
const rowIdxKey = this.editorGrid ? this.editorEndKey : this.gridInstance.invoke('getFocusedCell').rowKey
// editor 간 이동시 수정되는 문제 수정 끝
const columnName = e.columnName;
const value = e.value;
const editingData = {
...e,
rowKey: rowIdxKey,
};
const isBaseRow = this.isBaseDataRow(rowIdxKey);
// console.log("END E::", rowIdxKey, e);
const rowStat = this.gridInstance.invoke('getRow', rowIdxKey).rowStat;
if (rowStat == 'D') {
this.gridInstance.invoke(
'removeRowClassName',
rowIdxKey,
'row-removed',
);
}
await this.gridInstance.invoke(
e.rowEditingFg != undefined ? 'setValue' : this.editorGrid ? 'finishEditing' : 'setValue',
rowIdxKey,
columnName,
value,
);
if (isBaseRow) {
const isSameData = await this.compareData(editingData);
if (isSameData) {
this.gridInstance.invoke(
'removeRowClassName',
rowIdxKey,
'row-modify',
);
this.updateData('clear', rowIdxKey);
} else {
this.gridInstance.invoke('addRowClassName', rowIdxKey, 'row-modify');
this.updateData('modify', rowIdxKey);
}
}
if (
e.ignoreUpdateDataInfoFlag === undefined ||
e.ignoreUpdateDataInfoFlag === false
) {
this.$emit('updateDataInfo', {
rowIdxKey: rowIdxKey,
rowStat: rowStat,
columnName: columnName,
value: value,
rowData: this.gridInstance.invoke('getRow', rowIdxKey),
});
}
this.sendSelectedRowData();
},
async addRow(setData, argRowKey) {
// 그리드가 수정중인 상태면 addRow를 하지 않음
if (this.preventFocusChangeEventFlag) {
if (this.checkGridState()) {
return true;
}
}
const addData = !setData
? this.defaultRow
: Object.assign(this.defaultRow, setData);
// 열 앞에 데이터 추가
// if (argRowKey != undefined && argRowKey != null) {
this.gridInstance.invoke('appendRow', addData, {
focus: true,
});
// } else {
// this.gridInstance.invoke('prependRow', addData, {
// focus: true,
// });
// }
// this.gridInstance.invoke('prependRow', addData, {
// focus: true,
// });
this.$nextTick(() => {
var addRowKey = this.gridInstance.invoke('getFocusedCell').rowKey;
if (argRowKey) {
addRowKey = argRowKey;
}
this.gridInstance.invoke(
'removeRowClassName',
addRowKey,
'row-removed',
);
this.gridInstance.invoke('addRowClassName', addRowKey, 'row-insert');
this.updateData('insert', addRowKey);
});
},
async appendRow() {
this.gridInstance.invoke('appendRow', {
focus: true,
});
},
async addTreeRow(setData) {
// tree append의 경우 무한루프가 발행하는 버그현상으로 appendRows로 추가
const addData = !setData
? this.defaultRow
: Object.assign(this.defaultRow, setData);
this.gridInstance.invoke('appendRows', [addData]);
this.$nextTick(() => {
const rowDatas = this.gridInstance.invoke('getData');
const addRowKey = rowDatas[rowDatas.length - 1].rowKey;
this.gridInstance.invoke(
'removeRowClassName',
addRowKey,
'row-removed',
);
this.gridInstance.invoke('addRowClassName', addRowKey, 'row-insert');
this.updateData('insert', addRowKey);
this.gridInstance.invoke('focus', addRowKey);
});
},
async removeRow(delType, argRowKey) {
var rowIdxKey = this.gridInstance.invoke('getFocusedCell').rowKey;
if (typeof argRowKey == 'number') {
rowIdxKey = argRowKey;
}
const rowStat = this.gridInstance.invoke('getRow', rowIdxKey).rowStat;
if (rowStat === 'D') {
this.gridInstance.invoke(
'removeRowClassName',
rowIdxKey,
'row-removed',
);
this.updateData('clear', rowIdxKey);
} else {
if (!this.isBaseDataRow(rowIdxKey)) {
this.gridInstance.invoke('removeRow', rowIdxKey);
let nextFocus = Number(rowIdxKey) - 1;
if (!this.isBaseDataRow(nextFocus)) nextFocus = 0;
this.gridInstance.invoke('focus', nextFocus);
} else {
this.gridInstance.invoke('addRowClassName', rowIdxKey, 'row-removed');
this.updateData('delete', rowIdxKey);
if (delType == 'immediately')
this.gridInstance.invoke('removeRow', rowIdxKey);
}
}
},
async removeTreeRow(delType) {
const rowIdxKey = this.gridInstance.invoke('getFocusedCell').rowKey;
const rowStat = this.gridInstance.invoke('getRow', rowIdxKey).rowStat;
if (rowStat === 'D') {
this.gridInstance.invoke(
'removeRowClassName',
rowIdxKey,
'row-removed',
);
this.updateData('clear', rowIdxKey);
} else {
if (!this.isBaseDataRow(rowIdxKey)) {
this.updateData('clear', rowIdxKey);
this.gridInstance.invoke('removeRow', rowIdxKey);
let nextFocus = Number(rowIdxKey) - 1;
if (!this.isBaseDataRow(nextFocus)) nextFocus = 0;
this.gridInstance.invoke('focus', nextFocus);
} else {
this.gridInstance.invoke('addRowClassName', rowIdxKey, 'row-removed');
this.updateData('delete', rowIdxKey);
if (delType == 'immediately')
this.gridInstance.invoke('removeRow', rowIdxKey);
}
}
},
isBaseDataRow(rowKey) {
// 기존데이터 여부 확인 (추가된 데이터 X)
const findRow = this.gridInstance.invoke('findRows', { rowKey: rowKey });
return findRow && findRow[0] && findRow[0].rowStat != 'I' ? true : false;
},
compareData(data) {
// rowStat key값 제거
const dataKeyArr = Object.keys(this.defaultRow);
const rowStatIdx = dataKeyArr.indexOf('rowStat');
dataKeyArr.splice(rowStatIdx, 1);
// rowStat key값 제거 끝
const selectedRowData = this.gridInstance.invoke('getRow', data.rowKey);
this.getOriginData();
const rowData = this.originData.find(item => {
return item.rowKey == data.rowKey;
});
let count = 0;
// console.log("dataKeyArr", dataKeyArr);
// console.log("selectedRowData", selectedRowData);
for (let i = 0; i < dataKeyArr.length; i++) {
// console.log(dataKeyArr[i], selectedRowData[dataKeyArr[i]], rowData[dataKeyArr[i]]);
if (selectedRowData[dataKeyArr[i]] == rowData[dataKeyArr[i]]) {
count++;
}
}
return dataKeyArr.length == count ? true : false;
},
getOriginData() {
this.chkGridData.forEach(item => {
this.originData.push(item);
if (item._children) {
this.getChildrenData(item._children);
}
});
},
getChildrenData(children) {
children.forEach(item => {
this.originData.push(item);
if (item._children) {
this.getChildrenData(item._children);
}
});
},
updateData(updateType, rowIdxKey) {
let type = '';
switch (updateType) {
case 'insert':
type = 'I';
break;
case 'modify':
type = 'U';
break;
case 'delete':
type = 'D';
break;
case 'clear':
type = null;
break;
}
this.gridInstance.invoke('setValue', rowIdxKey, 'rowStat', type);
},
// 지정 로우 선택상태
focus(rowInfo) {
this.gridInstance.invoke(
'focus',
rowInfo.rowKey,
rowInfo.columnName,
rowInfo.setScroll,
);
},
// 트리 전체 접기
expandAll() {
this.gridInstance.invoke('expandAll');
},
// 트리 전체 펼치기
collapseAll() {
this.gridInstance.invoke('collapseAll');
},
save() {
const saveTargetRows = this.gridInstance.invoke('getModifiedRows');
// createdRows | deletedRows | updatedRows
const createdRows = saveTargetRows.createdRows;
const deletedRows = saveTargetRows.deletedRows;
const updatedRows = saveTargetRows.updatedRows;
const dataArr = [...createdRows, ...deletedRows, ...updatedRows]
.filter(item => item.rowStat)
.map(item => {
delete item.rowKey;
return item;
});
// console.log("dataArr::", dataArr, saveTargetRows);
return dataArr;
},
getData() {
return this.gridInstance.invoke('getData');
},
getCheckedRows() {
return this.gridInstance.invoke('getCheckedRows');
},
getCheckedRowKeys() {
return this.gridInstance.invoke('getCheckedRowKeys');
},
setCheck(list) {
// console.log("setCheck:: ", list);
list.map(item => this.gridInstance.invoke('check', item));
},
refreshLayout() {
this.gridInstance.invoke('refreshLayout');
},
refreshGrid(){
// console.log("refreshLayout",this.$refs['tuigrid' + this.gridName])
var store = this.$refs['tuigrid' + this.gridName].gridInstance.store;
var containerEl = this.$refs['tuigrid' + this.gridName].$el;
// var containerEl = document.querySelector('.tui-grid-container')
var parentEl = containerEl.parentElement;
// console.log("containerEl : ",containerEl);
// console.log('parentEl : ', parentEl)
// function refreshLayout(store, containerEl, parentEl) {
var dimension = store.dimension;
var autoWidth = dimension.autoWidth, fitToParentHeight = dimension.fitToParentHeight;
var clientHeight = containerEl.clientHeight, clientWidth = containerEl.clientWidth, scrollTop = containerEl.scrollTop, scrollLeft = containerEl.scrollLeft;
var _a = containerEl.getBoundingClientRect(), top = _a.top, left = _a.left;
this.setOffsetTop(store, top + scrollTop);
// store.dimension.setOffsetTop = top + scrollTop;
this.setOffsetLeft(store, left + scrollLeft);
// store.dimension.headerHeight = left + scrollLeft;
this.setWidth(store, clientWidth, autoWidth);
// store.dimension.autoWidth = autoWidth;
// store.dimension.width = clientWidth;
// console.log("###",getComputedStyle(parentEl));
// console.log("fitToParentHeight : ",fitToParentHeight);
// console.log("parentEl : ",parentEl)
// console.log("parentEl.clientHeight" , parentEl.clientHeight)
// console.log("clientHeight : ",clientHeight);
if (parentEl && parentEl.clientHeight !== clientHeight) {
var _b = getComputedStyle(parentEl), paddingTop = _b.paddingTop, paddingBottom = _b.paddingBottom;
this.setHeight(store, parentEl.clientHeight - (parseFloat(paddingTop) + parseFloat(paddingBottom)));
}
// }
},
setOffsetTop(store, offsetTop) {
// console.log("setOffsetTop");
store.dimension.offsetTop = offsetTop;
},
setWidth(_a, width, autoWidth) {
// console.log("setWidth");
var dimension = _a.dimension;
dimension.autoWidth = autoWidth;
dimension.width = width;
},
setHeaderHeight(store, height) {
// console.log("setHeaderHeight")
store.dimension.headerHeight = height;
},
setOffsetLeft(store, offsetLeft) {
// console.log("setOffsetLeft")
store.dimension.offsetLeft = offsetLeft;
},
setHeight(_a,height){
// console.log("setHeight");
var dimension = _a.dimension;
var headerHeight = dimension.headerHeight, summaryHeight = dimension.summaryHeight, tableBorderWidth = dimension.tableBorderWidth;
dimension.bodyHeight = height - headerHeight - summaryHeight - tableBorderWidth;
},
sendSelectedRowData(eventRowKey) {
if (this.selectedRowDataWatchFlag) {
var rowKey =
eventRowKey === undefined
? this.gridInstance.invoke('getFocusedCell').rowKey
: eventRowKey;
var rowData = this.gridInstance.invoke('getRow', rowKey);
this.$emit('sendSelectedRowStatInfo', rowData);
}
},
disableRow(rowKey, withCheckBox = false) {
this.gridInstance.invoke('disableRow', rowKey, withCheckBox);
},
async disabledRow(addRowKey) {
this.$nextTick(() => {
this.gridInstance.invoke(
'removeRowClassName',
addRowKey,
'row-removed',
);
this.gridInstance.invoke('addRowClassName', addRowKey, 'row-disabled');
});
},
// resetData() {
// // console.log("resetData = ", this.tuigridProps.data);
// this.$refs.tuigrid.invoke("resetData", this.tuigridProps.data);
// }
},
};
</script>
<style scoped lang="scss">
::v-deep .tui-grid-container {
// .tui-grid-body-area {
// overflow: hidden !important;
// }
.tui-grid-content-area {
.tui-grid-cell-content {
input[type='number'] {
width: 100%;
}
}
}
}
</style>