|
@@ -1,121 +1,131 @@
|
|
|
<template>
|
|
|
-
|
|
|
- <ElTree :key="treeKey" ref="ElTreeRef"
|
|
|
- :class="[ui,submitCounts?'tree-line1':'']" :default-expanded-keys="defaultExpandedCids" :indent="0"
|
|
|
- :load="ElTreeLoadNode"
|
|
|
- :props="ElTreeProps" accordion
|
|
|
- class="hc-tree-node tree-line el-radio-group" highlight-current
|
|
|
- lazy node-key="primaryKeyId" @node-click="ElTreeClick"
|
|
|
- @node-contextmenu="ElTreeLabelContextMenu">
|
|
|
+ <ElTree
|
|
|
+ :key="treeKey" ref="ElTreeRef"
|
|
|
+ :class="[ui, submitCounts ? 'tree-line1' : '']" :default-expanded-keys="defaultExpandedCids" :indent="0"
|
|
|
+ :load="ElTreeLoadNode"
|
|
|
+ :props="ElTreeProps" accordion
|
|
|
+ class="hc-tree-node tree-line el-radio-group" highlight-current
|
|
|
+ lazy node-key="primaryKeyId" @node-click="ElTreeClick"
|
|
|
+ @node-contextmenu="ElTreeLabelContextMenu"
|
|
|
+ >
|
|
|
<template #default="{ node, data }">
|
|
|
- <div :id="`${idPrefix}${data['primaryKeyId']}`" class="data-custom-tree-node">
|
|
|
- <!--树组件,节点名称-->
|
|
|
- <div :class="node.level === 1?'level-name':''" class="label">
|
|
|
+ <div :id="`${idPrefix}${data.primaryKeyId}`" class="data-custom-tree-node">
|
|
|
+ <!-- 树组件,节点名称 -->
|
|
|
+ <div :class="node.level === 1 ? 'level-name' : ''" class="label">
|
|
|
<span
|
|
|
- v-if="(data['type'] > 0 && data['majorDataType'] > 0) || (data['type'] > 0 && data['majorDataType'] <= 0)"
|
|
|
- class="hc-tree-node-type">{{
|
|
|
- getTreeNodeType(data['type'], data['majorDataType'])
|
|
|
- }}</span>
|
|
|
+ v-if="(data.type > 0 && data.majorDataType > 0) || (data.type > 0 && data.majorDataType <= 0)"
|
|
|
+ class="hc-tree-node-type"
|
|
|
+ >{{
|
|
|
+ getTreeNodeType(data.type, data.majorDataType)
|
|
|
+ }}</span>
|
|
|
<span
|
|
|
v-if="isColor"
|
|
|
- :class="data?.colorStatus === 2?'text-blue':data?.colorStatus === 3?'text-orange':data?.colorStatus === 4?'text-green':''">{{
|
|
|
- node.label
|
|
|
- }}</span>
|
|
|
+ :class="data?.colorStatus === 2 ? 'text-blue' : data?.colorStatus === 3 ? 'text-orange' : data?.colorStatus === 4 ? 'text-green' : ''"
|
|
|
+ >{{
|
|
|
+ node.label
|
|
|
+ }}</span>
|
|
|
<span v-else>{{ node.label }}</span>
|
|
|
</div>
|
|
|
|
|
|
- <!--树组件,统计数量-->
|
|
|
- <div v-if="isSubmitCounts" class="text-blue submit-counts">
|
|
|
+ <!-- 树组件,统计数量 -->
|
|
|
+ <div v-if="isSubmitCounts" class="submit-counts text-blue">
|
|
|
【{{ data.submitCounts ?? 0 }}】
|
|
|
</div>
|
|
|
|
|
|
- <!--树组件,操作菜单-->
|
|
|
- <div v-if="node.level !== 1 && menusData.length > 0" :class="node.showTreeMenu?'show':''"
|
|
|
- class="menu-icon1">
|
|
|
- <div class="cu-tree-node-popover-menu-icon"
|
|
|
- @click.prevent.stop="ElTreeLabelContextMenu($event,data,node)">
|
|
|
- <HcIcon name="apps" ui="text-2xl"/>
|
|
|
+ <!-- 树组件,操作菜单 -->
|
|
|
+ <div
|
|
|
+ v-if="node.level !== 1 && menusData.length > 0" :class="node.showTreeMenu ? 'show' : ''"
|
|
|
+ class="menu-icon1"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="cu-tree-node-popover-menu-icon"
|
|
|
+ @click.prevent.stop="ElTreeLabelContextMenu($event, data, node)"
|
|
|
+ >
|
|
|
+ <HcIcon name="apps" ui="text-2xl" />
|
|
|
</div>
|
|
|
</div>
|
|
|
- <!--树组件,操作菜单 END-->
|
|
|
+ <!-- 树组件,操作菜单 END -->
|
|
|
</div>
|
|
|
-
|
|
|
</template>
|
|
|
</ElTree>
|
|
|
- <!--右键菜单-->
|
|
|
- <HcContextMenu v-if="menusData.length > 0" ref="contextMenuRef" :datas="menusData" @closed="handleMenuClosed"
|
|
|
- @item-click="handleMenuSelect">
|
|
|
- <template #mark="{item}">
|
|
|
- <HcIcon :fill="treeRefData?.isFirst" :name="item.icon" class="menu-item-icon"/>
|
|
|
+ <!-- 右键菜单 -->
|
|
|
+ <HcContextMenu
|
|
|
+ v-if="menusData.length > 0" ref="contextMenuRef" :datas="menusData" @closed="handleMenuClosed"
|
|
|
+ @item-click="handleMenuSelect"
|
|
|
+ >
|
|
|
+ <template #mark="{ item }">
|
|
|
+ <HcIcon :fill="treeRefData?.isFirst" :name="item.icon" class="menu-item-icon" />
|
|
|
<span class="menu-item-name">{{ treeRefData?.isFirst ? '取消标记为首件' : '标记为首件' }}</span>
|
|
|
</template>
|
|
|
- <template #sort="{item}">
|
|
|
- <HcIcon :line="false" :name="item.icon" class="menu-item-icon"/>
|
|
|
+ <template #sort="{ item }">
|
|
|
+ <HcIcon :line="false" :name="item.icon" class="menu-item-icon" />
|
|
|
<span class="menu-item-name">{{ item.label }}</span>
|
|
|
</template>
|
|
|
</HcContextMenu>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import {ref, nextTick, watch} from "vue";
|
|
|
-import dataFillQuery from '~api/data-fill/query';
|
|
|
-import {getTreeNodeType} from '~uti/utils';
|
|
|
-import {getArrValue, getObjValue, isNullES, isArrItem} from "js-fast-way"
|
|
|
+import { nextTick, ref, watch } from 'vue'
|
|
|
+import dataFillQuery from '~api/data-fill/query'
|
|
|
+import { getTreeNodeType } from '~uti/utils'
|
|
|
+import { getArrValue, getObjValue, isArrItem, isNullES } from 'js-fast-way'
|
|
|
|
|
|
//参数
|
|
|
const props = defineProps({
|
|
|
menus: {
|
|
|
type: Array,
|
|
|
- default: () => ([])
|
|
|
+ default: () => ([]),
|
|
|
},
|
|
|
projectId: {
|
|
|
type: [String, Number],
|
|
|
- default: ''
|
|
|
+ default: '',
|
|
|
},
|
|
|
contractId: {
|
|
|
type: [String, Number],
|
|
|
- default: ''
|
|
|
+ default: '',
|
|
|
},
|
|
|
autoExpandKeys: {
|
|
|
type: Array,
|
|
|
- default: () => ([])
|
|
|
+ default: () => ([]),
|
|
|
},
|
|
|
isMark: {
|
|
|
type: Boolean,
|
|
|
- default: false
|
|
|
+ default: false,
|
|
|
},
|
|
|
idPrefix: {
|
|
|
type: String,
|
|
|
- default: 'wbs-tree-'
|
|
|
+ default: 'wbs-tree-',
|
|
|
},
|
|
|
isAutoKeys: {
|
|
|
type: Boolean,
|
|
|
- default: true
|
|
|
+ default: true,
|
|
|
},
|
|
|
isAutoClick: {
|
|
|
type: Boolean,
|
|
|
- default: true
|
|
|
+ default: true,
|
|
|
},
|
|
|
isColor: {
|
|
|
type: Boolean,
|
|
|
- default: false
|
|
|
+ default: false,
|
|
|
},
|
|
|
ui: {
|
|
|
type: String,
|
|
|
- default: ''
|
|
|
+ default: '',
|
|
|
},
|
|
|
submitCounts: {
|
|
|
type: Boolean,
|
|
|
- default: false
|
|
|
+ default: false,
|
|
|
},
|
|
|
classifyType: {
|
|
|
type: [String, Number],
|
|
|
},
|
|
|
treeKey: {
|
|
|
type: [String, Number],
|
|
|
- }
|
|
|
+ },
|
|
|
})
|
|
|
|
|
|
+//事件
|
|
|
+const emit = defineEmits(['menuTap', 'nodeTap', 'nodeLoading'])
|
|
|
//变量
|
|
|
const ElTreeRef = ref(null)
|
|
|
const treeRefNode = ref(null)
|
|
@@ -123,17 +133,17 @@ const treeRefData = ref(null)
|
|
|
const ElTreeProps = ref({
|
|
|
label: 'title',
|
|
|
children: 'children',
|
|
|
- isLeaf: 'notExsitChild'
|
|
|
+ isLeaf: 'notExsitChild',
|
|
|
})
|
|
|
const menusData = ref(props.menus)
|
|
|
const menuMark = ref(props.isMark)
|
|
|
const isAutoKeys = ref(props.isAutoKeys)
|
|
|
const TreeExpandKey = ref(props.autoExpandKeys)
|
|
|
-const projectId = ref(props.projectId);
|
|
|
-const contractId = ref(props.contractId);
|
|
|
-const idPrefix = ref(props.idPrefix);
|
|
|
-const isSubmitCounts = ref(props.submitCounts);
|
|
|
-const classifyTypedata = ref(props.classifyType);
|
|
|
+const projectId = ref(props.projectId)
|
|
|
+const contractId = ref(props.contractId)
|
|
|
+const idPrefix = ref(props.idPrefix)
|
|
|
+const isSubmitCounts = ref(props.submitCounts)
|
|
|
+const classifyTypedata = ref(props.classifyType)
|
|
|
const treeKeyData = ref(props.treeKey)
|
|
|
|
|
|
//监听
|
|
@@ -166,41 +176,39 @@ watch(classifyTypedata, (val) => {
|
|
|
classifyTypedata.value = val
|
|
|
}
|
|
|
},
|
|
|
- {immediate: true}
|
|
|
+ { immediate: true },
|
|
|
)
|
|
|
|
|
|
-//事件
|
|
|
-const emit = defineEmits(['menuTap', 'nodeTap', 'nodeLoading'])
|
|
|
-
|
|
|
//树形结构异步加载数据
|
|
|
const defaultExpandedCids = ref([])
|
|
|
const rootNode = ref({})
|
|
|
const rootResolve = ref(null)
|
|
|
const ElTreeLoadNode = async (node, resolve) => {
|
|
|
- let contractIdRelation = '', parentId = '', primaryKeyId = '';
|
|
|
+ let contractIdRelation = '', parentId = '', primaryKeyId = ''
|
|
|
if (node.level !== 0) {
|
|
|
rootNode.value = node
|
|
|
rootResolve.value = resolve
|
|
|
- const nodeData = getObjValue(node?.data);
|
|
|
+ const nodeData = getObjValue(node?.data)
|
|
|
contractIdRelation = nodeData?.contractIdRelation || ''
|
|
|
parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
|
|
|
primaryKeyId = nodeData?.id || ''
|
|
|
}
|
|
|
//获取数据
|
|
|
- const {error, code, data} = await dataFillQuery.queryWbsTreeData({
|
|
|
+ const { error, code, data } = await dataFillQuery.queryWbsTreeData({
|
|
|
contractId: contractId.value || '',
|
|
|
contractIdRelation,
|
|
|
primaryKeyId,
|
|
|
parentId,
|
|
|
- classifyType: classifyTypedata.value
|
|
|
+ classifyType: classifyTypedata.value,
|
|
|
+ dataTime:new Date(),
|
|
|
})
|
|
|
//处理数据
|
|
|
if (!error && code === 200) {
|
|
|
- let clickKey = '', defaultExpandedArr = [];
|
|
|
+ let clickKey = '', defaultExpandedArr = []
|
|
|
const keys = TreeExpandKey.value || []
|
|
|
const resData = getArrValue(data)
|
|
|
if (keys.length > 0) {
|
|
|
- let lastKey = keys[keys.length - 1];
|
|
|
+ let lastKey = keys[keys.length - 1]
|
|
|
for (const item of resData) {
|
|
|
//自动展开
|
|
|
if (isArrItem(keys, item?.primaryKeyId)) {
|
|
@@ -240,9 +248,9 @@ const ElTreeClick = async (data, node) => {
|
|
|
let autoKeysArr = []
|
|
|
await getNodeExpandKeys(node, autoKeysArr)
|
|
|
const autoKeys = autoKeysArr.reverse()
|
|
|
- emit('nodeTap', {node, data, keys: autoKeys})
|
|
|
+ emit('nodeTap', { node, data, keys: autoKeys })
|
|
|
} else {
|
|
|
- emit('nodeTap', {node, data, keys: []})
|
|
|
+ emit('nodeTap', { node, data, keys: [] })
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -259,11 +267,11 @@ const getNodeExpandKeys = async (node, newKeys) => {
|
|
|
//鼠标右键事件
|
|
|
const contextMenuRef = ref(null)
|
|
|
const ElTreeLabelContextMenu = (e, data, node) => {
|
|
|
- const rows = menusData.value || [];
|
|
|
+ const rows = menusData.value || []
|
|
|
if (node.level !== 1 && rows.length > 0) {
|
|
|
- e.preventDefault();
|
|
|
- treeRefNode.value = node;
|
|
|
- treeRefData.value = data;
|
|
|
+ e.preventDefault()
|
|
|
+ treeRefNode.value = node
|
|
|
+ treeRefData.value = data
|
|
|
node.showTreeMenu = true
|
|
|
//展开菜单
|
|
|
contextMenuRef.value?.showMenu(e)
|
|
@@ -271,30 +279,30 @@ const ElTreeLabelContextMenu = (e, data, node) => {
|
|
|
}
|
|
|
|
|
|
//鼠标右键菜单被点击
|
|
|
-const handleMenuSelect = async ({key}) => {
|
|
|
- const node = treeRefNode.value;
|
|
|
- const data = treeRefData.value;
|
|
|
+const handleMenuSelect = async ({ key }) => {
|
|
|
+ const node = treeRefNode.value
|
|
|
+ const data = treeRefData.value
|
|
|
|
|
|
//如果为标记菜单
|
|
|
if (key === 'mark' && menuMark.value) {
|
|
|
if (data.isFirst === true) {
|
|
|
- emit('menuTap', {key: 'cancel_mark', node, data})
|
|
|
+ emit('menuTap', { key: 'cancel_mark', node, data })
|
|
|
} else {
|
|
|
- emit('menuTap', {key: 'mark', node, data})
|
|
|
+ emit('menuTap', { key: 'mark', node, data })
|
|
|
}
|
|
|
} else {
|
|
|
if (isAutoKeys.value) {
|
|
|
let autoKeysArr = []
|
|
|
await getNodeExpandKeys(node, autoKeysArr)
|
|
|
const autoKeys = autoKeysArr.reverse()
|
|
|
- emit('menuTap', {key, node, data, keys: autoKeys})
|
|
|
+ emit('menuTap', { key, node, data, keys: autoKeys })
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const handleMenuClosed = () => {
|
|
|
- const node = treeRefNode.value;
|
|
|
+ const node = treeRefNode.value
|
|
|
if (!isNullES(node)) {
|
|
|
treeRefNode.value['showTreeMenu'] = false
|
|
|
}
|
|
@@ -305,7 +313,7 @@ const setElTreeMenuMark = (keys, isFirst) => {
|
|
|
keys.forEach(item => {
|
|
|
//根据 data 或者 key 拿到 Tree 组件中的 node
|
|
|
let node = ElTreeRef.value.getNode(item)
|
|
|
- if (!!node) node.data.isFirst = isFirst;
|
|
|
+ if (node) node.data.isFirst = isFirst
|
|
|
})
|
|
|
}
|
|
|
|