<template>
<AuiGrid
ref="viewTree"
:data="data"
:tree-config="{
children: 'children',
renderIcon
}"
:show-header="false"
:stripe="false"
row-id="oid"
height="auto"
:auto-resize="true"
:sync-resize="true"
highlight-current-row
@toggle-tree-change="handTreeExpand"
>
<AuiGridColumn field="label" tree-node show-overflow>
<template #default="data">
<div>
<AuiCheckbox
v-model="data.row.checked"
class="checkbox"
:indeterminate="data.row.indeterminate"
@change="checkboxChangeEvent($event, data.row)"
></AuiCheckbox>
<IconLoading v-if="data.row.isLoading" class="loading-folder"></IconLoading>
<span class="item_icon_new" :class="$util.getClassesExt(data.row)"></span>
<span class="label">{{ data.row.label }}</span>
</div>
</template>
</AuiGridColumn>
<template #empty></template>
</AuiGrid>
</template>
<script lang="jsx">
import { Grid, GridColumn, Checkbox } from '@aurora/vue3';
import { IconPlusSquare, IconMinusSquare, IconLoading } from '@aurora/vue3-icon';
import DBoxUtil from '../../common/utils/DBoxUtil';
import ShellItemHelper from '../../common/Helper/ShellItemHelper';
import ConstantParams from '../../common/ConstantParams';
import StringUtil from '../../common/utils/StringUtil';
import ViewExpandTree from './ViewExpandTree.vue';
import NodeFactory from '../../common/NodeFactory';
import UrlHelper from '../../common/Helper/UrlHelper';
import FileManager from '../../common/FileBrowser/FileManager';
export default {
name: 'ViewDepthExpandTree',
components: {
AuiGrid: Grid,
AuiGridColumn: GridColumn,
AuiCheckbox: Checkbox,
IconLoading: IconLoading()
},
extends: ViewExpandTree,
props: {
rootNode: Object,
sysConfig: Object,
viewConfig: Object,
defaultCheckedKeyItems: {
type: Array,
default: () => {
return [];
}
},
defaultExpandedKeyItems: {
type: Array,
default: () => {
return [];
}
},
serverCreateNodes: {
type: Array,
default: () => {
return [];
}
},
isUpdate: {
type: Boolean,
default: false
},
isSelectAll: {
type: String,
default: '0'
}
},
emits: {'cancelSelectAll': null, 'emptyDir': null},
methods: {
renderIcon(h, { row, active }) {
if (!row.isFolder) {
return;
}
const expandIcon = IconMinusSquare();
const closeIcon = IconPlusSquare();
return active ? <expandIcon></expandIcon> : <closeIcon></closeIcon>;
},
// 动态加载文件夹内容
async handTreeExpand({ row }) {
if (row.loaded) {
return;
}
row.children = [];
if (!row.isFolder) {
return;
}
row.isLoading = true;
try {
let res = await this.getServerData({ data: row });
row.isLoading = false;
row.loaded = true;
row.children = res;
if (this.isUpdate) {
this.setCheckedForLocal(row);
} else {
this.setChecked(row.children, row.checked);
}
} catch (e) {
row.isLoading = false;
row.loaded = true;
}
},
// 文件夹展开后根据本地节点设置选中
setCheckedForLocal(row) {
if (this.isSelectAll === '1') {
row.children.forEach(item => {
item.checked = true;
});
return;
}
if (this.isSelectAll === '2') {
row.children.forEach(item => {
item.checked = false;
});
return;
}
if (!row.checked) {
return;
}
let viewNodeDAL = NodeFactory.GetDAL(this.viewConfig.viewname);
viewNodeDAL.getChildViewNodesByOid(row.oid).then(viewNodes => {
let selectedNum = 0;
row.children.forEach(item => {
if (viewNodes.find(n => item.oid.includes(n.oid) || item.label === n.name)) {
selectedNum++;
item.checked = true;
} else {
item.checked = false;
}
});
if (selectedNum < row.children.length) {
row.checked = false;
row.indeterminate = true;
row.isSelectChild = true;
}
});
},
// 复选框change事件
checkboxChangeEvent(checked, row) {
if (!checked) {
this.$emit('cancelSelectAll');
}
if (!row.isFolder || !row.loaded) {
this.setParentChecked(row);
return;
}
const isExpand = this.$refs.viewTree.hasTreeExpand(row);
if (isExpand) {
if (!checked) {
// 第二次点击选中子
if (row.isSelectChild) {
row.checked = true;
row.indeterminate = false;
row.isSelectChild = false;
this.setChecked(row.children, true);
this.setParentChecked(row);
return;
}
// 取消所有选中
row.isSelectChild = false;
this.setChecked(row.children, false);
} else if (row.isSelectChild && row.indeterminate) {
row.checked = true;
row.indeterminate = false;
row.isSelectChild = false;
this.setChecked(row.children, true);
} else if (row.children.length) {
row.checked = false;
row.indeterminate = true;
row.isSelectChild = true;
}
this.setParentChecked(row);
return;
}
if (!checked) {
row.isSelectChild = false;
this.setChecked(row.children, false);
this.setParentChecked(row);
} else {
row.isSelectChild = false;
row.indeterminate = false;
this.setChecked(row.children, true);
this.setParentChecked(row);
}
},
// 递归设置子节点选中
setChecked(children, checked) {
children.forEach(item => {
item.checked = checked;
item.indeterminate = false;
if (item.isFolder) {
this.setChecked(item.children, checked);
}
});
},
// 设置父节点选中
setParentChecked(row) {
const findRes = this.getParents(row);
if (!findRes.isFind || !findRes.parents.length) {
return;
}
for (let i = findRes.parents.length - 1; i >= 0; i--) {
let cur = findRes.parents[i];
let isSelectAll = true;
for (let item of cur.children) {
if (!item.checked) {
isSelectAll = false;
}
}
if (isSelectAll) {
cur.checked = true;
cur.indeterminate = false;
cur.isSelectChild = false;
} else {
cur.checked = false;
cur.indeterminate = true;
cur.isSelectChild = true;
}
}
},
// 获取所有祖先节点
getParents(row, childs, result = []) {
if (!childs) {
childs = this.$refs.viewTree.getData();
}
for (const item of childs) {
if (item.label === row.label && item.oid === row.oid) {
return { isFind: true, parents: result };
}
if (item.isFolder && item.loaded) {
result.push(item);
const findRes = this.getParents(row, item.children);
if (!findRes.isFind) {
result.pop();
continue;
}
result = result.concat(findRes.parents);
return { isFind: true, parents: result };
}
}
return { isFind: false, parents: result };
},
// 请求文件夹内容
getTreeData(dirNode, resolve) {
if (!this.sysConfig) {
return;
}
if (dirNode.level === 0) {
resolve(this.data);
return;
}
if (dirNode.data.oid.includes('wt.doc.WTDocument')) {
resolve([]);
return;
}
this.getServerData(dirNode).then(children => {
if (this.data.length === 0) {
this.$util.showDBoxMessage(this.$t('reminder'), this.$t('directoryIsNull'), 'warning', {
onConfirm: () => {
this.$emit('emptyDir');
}
});
}
resolve(children);
this.$nextTick(() => {
// 设置子节点选中
let firstItem;
this.data.forEach(item => {
const isFind = this.defaultCheckedKeyItems.find(c => c.oid === item.oid || DBoxUtil.fillORStr(c.oid) === item.oid || c.name === item.label);
if (isFind) {
item.checked = true;
firstItem = item;
}
});
if (this.defaultCheckedKeyItems.length === 1 && firstItem) {
setTimeout(() => {
this.$refs.viewTree.scrollToRow(firstItem);
}, 300);
}
this.locateNode();
});
});
},
// 智能地址栏新增节点选中
async locateNode() {
if (!this.serverCreateNodes || this.serverCreateNodes.length <= 1) {
return;
}
const firstData = this.data.find(item => item.name.toLowerCase() === this.serverCreateNodes[0].toLowerCase());
if (!firstData) {
return;
}
let firstNode = this.$refs.viewTree.getRowById(UrlHelper.UrlEncode(DBoxUtil.fillORStr(firstData.oid)));
if (!firstNode) {
firstNode = this.$refs.viewTree.getRowById(UrlHelper.UrlEncode(DBoxUtil.GetSimpleOid(firstData.oid)));
if (!firstNode) {
return;
}
}
this.$refs.viewTree.scrollToRow(firstNode);
await this.handTreeExpand({ row: firstNode });
this.$refs.viewTree.setTreeExpansion([firstData], true);
const expandNodes = this.serverCreateNodes.slice(1);
let curNode = firstNode;
for (let i = 0; i < expandNodes.length; i++) {
const nodeName = expandNodes[i];
let nextNode = curNode.children.find(n => {
if (n.name.toLowerCase() === nodeName.toLowerCase()) {
return true;
}
if (!n.isFolder && n.name.includes('.')) {
const nameNoExt = n.name.substring(0, n.name.lastIndexOf('.'));
return nameNoExt.toLowerCase() === nodeName.toLowerCase();
}
});
if (!nextNode) {
return;
}
await this.handTreeExpand({ row: nextNode });
this.$refs.viewTree.setTreeExpansion([nextNode], true);
const rowEle = document.querySelector(`[data-rowid="${UrlHelper.UrlEncode(nextNode.oid)}"]`);
if (rowEle) {
rowEle.scrollIntoView();
}
curNode = nextNode;
if (i === expandNodes.length - 1) {
curNode.checked = true;
this.setParentChecked(curNode);
}
}
},
createTreeDataByFolderVO(folderVO, parentPath) {
let nd = {
label: folderVO.name,
oid: folderVO.oid,
checked: false,
isFolder: true,
selectType: 0,
oldUpdateType: 0,
docNumber: null,
oldNdOid: null,
children: [
{
label: ''
}
],
loaded: false,
isLoading: false,
isSelectChild: false,
fullPath: parentPath + '\\' + folderVO.name,
...folderVO
};
return nd;
},
createFileViewNode(node, treeNode) {
let viewNode = {
name: node.label,
localrelpath: this.rootNode.localrelpath,
oid: DBoxUtil.fillORStr(StringUtil.isNullOrEmpty(node.oldNdOid) ? node.oid : node.oldNdOid),
viewid: this.viewConfig ? this.viewConfig.viewid : 0,
type: 'file',
fileSize: 0,
state: ConstantParams.STATE.NormalState,
md5: '',
updatetype: ShellItemHelper.UpdateType.folderAllSelectType,
primaryoid: '',
oidpath: this.getOidPath(node),
viewConfig: ShellItemHelper.getNodeRoot(this.rootNode),
parentrelpath: treeNode.parent.level < 1 ? this.rootNode.localrelpath : FileManager.pathJoin(this.rootNode.localrelpath, treeNode.parent.data.fullPath)
};
return viewNode;
},
createFolderViewNode(node, treeNode, isHalfChecked) {
let viewNode = {
name: node.label,
localrelpath: this.rootNode.localrelpath,
parentrelpath: treeNode.parent.level < 1 ? this.rootNode.localrelpath : FileManager.pathJoin(this.rootNode.localrelpath, treeNode.parent.data.fullPath),
oid: node.oid,
viewid: this.viewConfig ? this.viewConfig.viewid : 0,
type: 'folder',
fileSize: 0,
state: ConstantParams.STATE.NormalState,
md5: '',
updatetype: isHalfChecked ? ShellItemHelper.UpdateType.currentFolderOnly : ShellItemHelper.UpdateType.folderAllSelectType,
primaryoid: '',
oidpath: this.getOidPath(node),
viewConfig: ShellItemHelper.getNodeRoot(this.rootNode)
};
return viewNode;
},
getTreeNodes(tableData = this.$refs.viewTree.getData(), parent = { level: 0 }) {
let treeData = [];
tableData.forEach(item => {
let treeItem = {
checked: item.checked,
indeterminate: item.indeterminate,
data: item,
loaded: item.loaded,
childNodes: [],
parent,
level: parent.level + 1
};
if (item.isFolder) {
treeItem.childNodes = this.getTreeNodes(item.children, treeItem);
}
treeData.push(treeItem);
});
return treeData;
},
getSelectedTreeNodes(tableData = this.$refs.viewTree.getData(), parent = { level: 0 }) {
let halfChecked = [];
let checked = [];
tableData.forEach(item => {
if (!item.checked && !item.indeterminate) {
return;
}
let treeItem = {
checked: item.checked,
indeterminate: item.indeterminate,
data: item,
loaded: item.loaded,
childNodes: [],
parent,
level: parent.level + 1
};
if (item.isFolder) {
treeItem.childNodes = this.getTreeNodes(item.children, treeItem);
}
item.indeterminate ? halfChecked.push(treeItem) : checked.push(treeItem);
});
return { halfChecked, checked };
},
// 获取选中节点
getSelectedData() {
let lstFullUpdateNode = [];
let lstOneFldUpdateNode = [];
let lstOneFileUpdateNode = [];
let { checked, halfChecked } = this.getSelectedTreeNodes();
checked.forEach(f => {
if (f.isFolder) {
lstFullUpdateNode.push(this.createFolderViewNode(f.data, f));
} else {
lstOneFileUpdateNode.push(this.createFileViewNode(f.data, f));
}
});
halfChecked.forEach(f => {
lstOneFldUpdateNode.push(this.createFolderViewNode(f.data, f, true));
});
let isFullSelected = halfChecked.length === 0 && checked.length === this.data.length;
isFullSelected = this.isFullSelected && isFullSelected;
let isFullUnSelected = this.isFullUnSelected && halfChecked.length === 0 && checked.length === 0;
return {
checkedTreeNode: checked,
halfCheckTreeNode: halfChecked,
lstFullUpdateNode,
lstOneFldUpdateNode,
lstOneFileUpdateNode,
isFullSelected,
isFullUnSelected
};
},
selectAll() {
const treeData = this.$refs.viewTree.getData();
this.setChecked(treeData, true);
this.isFullSelected = true;
this.isFullUnSelected = false;
},
deselectAll() {
const treeData = this.$refs.viewTree.getData();
this.setChecked(treeData, false);
this.isFullSelected = false;
this.isFullUnSelected = true;
}
}
};
</script>
<style scoped>
:deep(.aui-grid .aui-grid-body__row.row__current),
:deep(.aui-grid .row__selected) {
background-color: #bae7ff !important;
}
.loading-folder {
font-size: 14px;
margin-right: 5px;
}
.label {
position: absolute;
vertical-align: middle;
display: inline-block;
width: 85%;
text-overflow: ellipsis;
overflow: hidden;
}
:deep(.aui-grid .aui-grid-body__column.col__treenode .aui-grid-cell .aui-grid-tree-wrapper) {
flex-shrink: 0;
}
.checkbox {
margin-right: 5px;
}
:deep(.aui-grid-body__row:hover) {
background-color: #e6f7ff;
}
:deep(.aui-grid-body__column .col__treenode) {
padding: 0px 8px;
}
:deep(.aui-grid.size__mini .aui-grid-body__column.col__ellipsis),
:deep(.aui-grid.size__mini .aui-grid-footer__column.col__ellipsis),
:deep(.aui-grid.size__mini .aui-grid-header__column.col__ellipsis) {
height: 22px;
}
.unknown {
background: url('../../assets/image/unknown-circle.svg') no-repeat 100% / cover;
}
</style>
这是客户端ViewDepthExpandTree.vue的代码下边是ViewDepthUpdateDialog.vue的代码:
<template>
<div style="z-index: 9999">
<DialogBase
:title="$t('expandViewFolder')"
:width="`${624}px`"
:box-visibility="true"
:is-can-drag="true"
:show-max="true"
:drag-event="dragEvent"
@close="close"
@confirm="confirm"
@open="open"
@maximize="setMaxStyle"
>
<template #content>
<div class="tree-panel-content">
<div class="tree-panel">
<img v-if="isLoading" src="../../assets/image/loading.gif" />
<ViewDepthExpandTree
ref="viewTree"
:root-node="rootNode"
:default-checked-key-items="defaultCheckedKeyList"
:default-expanded-key-items="defaultExpandedKeyList"
:server-create-nodes="options.serverCreateNodes"
:sys-config="sysConfig"
:view-config="viewConfig"
:is-update="true"
:is-select-all="isSelectAll"
@tree-loaded="treeLoaded"
@empty-dir="close"
@permission="showPermissionDialog"
@cancel-select-all="isSelectAll = '0'"
></ViewDepthExpandTree>
</div>
</div>
</template>
<template #footer>
<div>
<AuiRadio v-model="isSelectAll" label="1">{{ $t('selectAll') }}</AuiRadio>
<AuiRadio v-model="isSelectAll" label="2">{{ $t('deselectAll') }}</AuiRadio>
<AuiButton type="primary" @click="confirm">{{ $t('ok') }}</AuiButton>
<AuiButton @click="close">{{ $t('cancel') }}</AuiButton>
</div>
</template>
</DialogBase>
<!--权限申请弹窗-->
<PermissionApplicationDialog v-if="permission.isVisible" :options="permission" @close="closePermissionApplicationDialog"></PermissionApplicationDialog
>
</div>
</template>
<script>
import DialogBase from './DialogBase';
import { Button, Radio } from '@aurora/vue3';
import { IconPlusSquare, IconMinusSquare, IconFolderClosed } from '@aurora/vue3-icon';
import ViewDepthExpandTree from './ViewDepthExpandTree';
import EnumConst from '../../common/EnumConst';
import DBoxUtil from '../../common/utils/DBoxUtil';
import ShellItemHelper from '../../common/Helper/ShellItemHelper';
import LogUtil from '../../common/utils/LogUtil';
import NodeFactory from '../../common/NodeFactory';
import PermissionApplicationDialog from './PermissionApplicationDialog';
import CustomTreeDataBase from './CustomTreeDataBase';
import $ from 'jquery';
export default {
name: 'ViewDepthUpdateDialog',
components: {
AuiButton: Button,
AuiRadio: Radio,
ViewDepthExpandTree,
DialogBase,
PermissionApplicationDialog
},
mixins: [CustomTreeDataBase],
props: {
options: {
isVisible: Boolean,
sysConfig: Object,
viewConfig: Object,
rootNode: Object,
defaultCheckedKeyList: Array,
defaultExpandedKeyList: Array,
serverCreateNodes: Array,
closeCallBack: Function
}
},
emits: ['close'],
data() {
return {
IconPlusSquare: IconPlusSquare(),
IconMinusSquare: IconMinusSquare(),
IconFolderClosed: IconFolderClosed(),
isLoading: true,
viewFolder: null,
sysConfig: null,
viewConfig: null,
rootNode: null,
data: [],
localNodes: [],
defaultCheckedKeyList: [],
defaultExpandedKeyList: [],
selectedNode: null,
isSelectAll: '0',
radioLabel: ['1', '2'],
folderView: null,
permission: {
isVisible: false,
permInfo: null
}
};
},
watch: {
isSelectAll: {
handler(newVal, oldVal) {
if (newVal === this.radioLabel[0]) {
this.$refs.viewTree.selectAll();
} else if (newVal === this.radioLabel[1]) {
this.$refs.viewTree.deselectAll();
}
}
},
item: {
handler(val, oldVal) {
this.folderView = val;
}
}
},
created() {
this.sysConfig = this.options.sysConfig;
this.viewConfig = this.options.viewConfig;
this.rootNode = this.options.rootNode;
this.rootNode.oid = DBoxUtil.IsBookmarkEntity(this.rootNode.oid) ? this.rootNode.primaryoid : this.rootNode.oid;
this.rootNode.selectType = ShellItemHelper.UpdateType.customerType;
this.defaultCheckedKeyList = this.options.defaultCheckedKeys;
this.defaultExpandedKeyList = this.options.defaultExpandedKeyList;
this.open();
},
methods: {
open() {
this.isLoading = true;
let viewname = this.viewConfig.viewname;
this.$util.uemTrack('PA86C41B814DB84', this.sysConfig.username);
LogUtil.info('ViewDepthUpdate Operation: ' + this.sysConfig.username + ' ' + viewname);
let viewNodeDAL = NodeFactory.GetDAL(this.viewConfig.viewname);
viewNodeDAL.findByPaths([this.viewConfig.viewname]).then(res => {
this.localNodes = res;
});
},
showPermissionDialog(permParams) {
this.isLoading = false;
this.permission.permInfo = permParams;
this.permission.userConfig = this.sysConfig;
this.permission.isVisible = true;
},
treeLoaded(isLoading) {
this.isLoading = isLoading;
},
closePermissionApplicationDialog() {
this.permission.isVisible = false;
this.$emit('close');
},
confirm() {
this.parseInfo(this.rootNode.oid, this.$refs.viewTree.getTreeNodes(), this.localNodes);
let serverParameters = {
customOnlyFolderOids: this.customOnlyFolderOids,
oids: this.oids,
onlyFolderOids: this.onlyFolderOids,
updateType: EnumConst.ViewUpdateType.Custom,
parentNode: {},
...this.rootNode
};
let viewNode = {};
viewNode.oid = this.rootNode.oid;
viewNode.localrelpath = this.rootNode.localrelpath;
serverParameters.parentNode = viewNode;
// 全选时使用全递归
if (this.isSelectAll === this.radioLabel[0] || this.isSelectAll === '1') {
serverParameters.updateType = EnumConst.ViewUpdateType.Recursion;
serverParameters.oids = [this.rootNode.oid];
}
this.options.closeCallBack({
isOpenUpdate: true,
serverParameters,
isDepthUpdate: true
});
this.$store.commit('setIsClickDialogConfirm', true);
this.$emit('close');
},
close() {
this.$emit('close');
},
// 树节点点击事件
handleItemClick(data, node, vm) {
LogUtil.info(node);
},
dragEvent() {
const container = $('.tree-panel', this.$el)[0];
const rect = container.parentNode.getBoundingClientRect();
const MIN_HEIGHT = 465;
// 边框余量
const MARGIN = 5;
if (rect.height - MARGIN < MIN_HEIGHT) {
return;
}
container.style.height = rect.height - MARGIN + 'px';
},
setMaxStyle(isMaximize) {
const container = $('.tree-panel', this.$el)[0];
const rect = container.parentNode.getBoundingClientRect();
const MIN_HEIGHT = 465;
// 边框余量
const MARGIN = 5;
if (isMaximize) {
if (rect.height - MARGIN < MIN_HEIGHT) {
return;
}
container.style.height = rect.height - MARGIN + 'px';
} else {
// 原始高度
const ORIGIN_HEIGHT = 465;
container.style.height = ORIGIN_HEIGHT + 'px';
this.messageHeight = ORIGIN_HEIGHT;
}
}
}
};
</script>
<style scoped>
:deep(.content) {
border: none;
}
.tree-content {
width: calc(100%-15px);
min-height: 285px;
background: white;
border: 1px solid #666;
margin: 0 auto;
margin-top: 3px;
padding: 7px;
}
.tree-panel {
border: 1px solid #666;
width: 99.5%;
height: 465px;
overflow: auto;
}
.tree-panel img {
display: table-cell;
vertical-align: middle;
margin: 0 auto;
margin-top: 20%;
}
:deep(.aui-radio__inner::after) {
width: 7px;
height: 7px;
background: #333;
}
:deep(.tree-panel::-webkit-scrollbar-thumb) {
border-radius: 0;
}
:deep(.aui-radio) {
float: left;
line-height: 26px;
margin-right: 20px;
}
.tree-panel-content {
height: 100%;
overflow: auto;
}
</style>
现在问题是,当我点开弹窗后,里边的table表格总是和弹窗底部有空白距离,当我放大和缩小弹窗时空白距离会自动被表格中的突然出现的数据填补,当我快速上下拖动弹窗下方时,空白距离又会时不时的显现,我怎么才能让打开弹窗时没有空白距离且表格填满弹窗?
最新发布