HcTreeData.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <template>
  2. <ElTree class="hc-tree-node tree-line" ref="ElTreeRef" :props="ElTreeProps" :data="treeDatas" highlight-current accordion node-key="primaryKeyId"
  3. :default-expanded-keys="TreeExpandKey" @node-click="ElTreeClick" @node-contextmenu="ElTreeLabelContextMenu" :indent="0">
  4. <template #default="{ node, data }">
  5. <div class="data-custom-tree-node" :id="`${idPrefix}${data['primaryKeyId']}`">
  6. <!--树组件,节点名称-->
  7. <div class="label">{{ node.label }}</div>
  8. <!--树组件,操作菜单-->
  9. <div class="menu-icon" :class="node.showTreeMenu?'show':''" v-if="menusData.length > 0" @click.stop>
  10. <div class="cu-tree-node-popover-menu-icon" @click.prevent.stop="ElTreeLabelContextMenu($event,data,node)">
  11. <HcIcon name="menu" ui="text-2xl"/>
  12. </div>
  13. </div>
  14. <!--树组件,操作菜单 END-->
  15. </div>
  16. </template>
  17. </ElTree>
  18. <!--右键菜单-->
  19. <HcContextMenu ref="contextMenuRef" :datas="menusData" @item-click="handleMenuSelect" v-if="menusData.length > 0">
  20. <template #sort="{item}">
  21. <HcIcon :name="item.icon" :line="false" class="menu-item-icon"/>
  22. <span class="menu-item-name">{{item.label}}</span>
  23. </template>
  24. </HcContextMenu>
  25. <!--新增/编辑 节点-->
  26. <HcDialog :show="nodeFormModal" :title="`${nodeFormModel.id?'编辑':'新增'}节点`" widths="30rem" :loading="nodeFormLoading" @save="nodeFormModalSave" @close="nodeFormModalClose">
  27. <el-form ref="nodeFormRef" :model="nodeFormModel" :rules="nodeFormRules" label-width="auto" label-position="top" size="large">
  28. <el-form-item class="mb-0" label="节点名称">
  29. <el-input v-model="nodeFormModel.nodeName" placeholder="请输入节点名称"/>
  30. </el-form-item>
  31. </el-form>
  32. </HcDialog>
  33. </template>
  34. <script setup>
  35. import {onMounted, ref, watch} from "vue";
  36. import {HcIsButton} from "~src/plugins/IsButtons";
  37. import {formValidate, getArrValue} from "vue-utils-plus"
  38. import {getTreeAll, submitTree, removeTree} from "~api/tentative/detect"
  39. import {delMessage} from "~uti/tools";
  40. //参数
  41. const props = defineProps({
  42. autoExpandKeys: {
  43. type: Array,
  44. default: () => ([])
  45. },
  46. projectId: {
  47. type: [String,Number],
  48. default: ''
  49. },
  50. contractId: {
  51. type: [String,Number],
  52. default: ''
  53. },
  54. type: {
  55. type: String,
  56. default: 'leftTree'
  57. },
  58. })
  59. //变量
  60. const ElTreeRef = ref(null)
  61. const idPrefix = ref('detect-tree-data-')
  62. const TreeExpandKey = ref(props.autoExpandKeys)
  63. const projectId = ref(props.projectId)
  64. const contractId = ref(props.contractId)
  65. const dataType = ref(props.type)
  66. const ElTreeProps = ref({
  67. label: 'nodeName',
  68. children: 'children',
  69. isLeaf: 'hasChildren'
  70. })
  71. //监听
  72. watch(() => [
  73. props.projectId,
  74. props.contractId,
  75. props.type,
  76. props.autoExpandKeys
  77. ], ([pid, cid, type, expandKeys]) => {
  78. projectId.value = pid
  79. contractId.value = cid
  80. dataType.value = type
  81. TreeExpandKey.value = expandKeys
  82. })
  83. //渲染完成
  84. onMounted(() => {
  85. setElTreeMenu()
  86. getTreeDatas()
  87. })
  88. //树菜单配置
  89. const menusData = ref([])
  90. const setElTreeMenu = () => {
  91. let newArr = [];
  92. if (HcIsButton('tentative_detect_third_tree_add')) {
  93. newArr.push({icon: 'add-circle', label: '新增节点', key: "add"})
  94. }
  95. if (HcIsButton('tentative_detect_third_tree_edit')) {
  96. newArr.push({icon: 'draft', label: '修改节点', key: "edit"})
  97. }
  98. if (HcIsButton('tentative_detect_third_tree_del')) {
  99. newArr.push({icon: 'delete-bin', label: '删除节点', key: "del"})
  100. }
  101. menusData.value = newArr
  102. }
  103. //获取树数据
  104. const treeDatas = ref([])
  105. const getTreeDatas = async () => {
  106. const { error, code, data } = await getTreeAll({
  107. projectId: projectId.value,
  108. contractId: contractId.value
  109. })
  110. if (!error && code === 200) {
  111. treeDatas.value = getArrValue(data[dataType.value])
  112. } else {
  113. treeDatas.value = []
  114. }
  115. }
  116. //事件
  117. const emit = defineEmits(['menuTap','nodeTap'])
  118. //节点被点击
  119. const ElTreeClick = async (data,node) => {
  120. emit('nodeTap', {node, data, keys: [data.id]})
  121. }
  122. //鼠标右键事件
  123. const treeRefNode = ref(null)
  124. const treeRefData = ref(null)
  125. const contextMenuRef = ref(null)
  126. const ElTreeLabelContextMenu = (e,data,node) => {
  127. const rows = menusData.value || [];
  128. if (rows.length > 0) {
  129. e.preventDefault();
  130. treeRefNode.value = node;
  131. treeRefData.value = data;
  132. //展开菜单
  133. contextMenuRef.value?.showMenu(e)
  134. }
  135. }
  136. //鼠标右键菜单被点击
  137. const handleMenuSelect = ({key}) => {
  138. const data = treeRefData.value;
  139. if (key === 'add') {
  140. nodeFormModel.value = {
  141. parentId: data.id,
  142. nodeType: data.nodeType,
  143. nodeName: ''
  144. }
  145. nodeFormModal.value = true
  146. } else if (key === 'edit') {
  147. nodeFormModel.value = data
  148. nodeFormModal.value = true
  149. } else if (key === 'del') {
  150. delMessage(() => {
  151. treeRemoveData(data.id)
  152. })
  153. }
  154. }
  155. //新增/编辑 节点
  156. const nodeFormModal = ref(false)
  157. const nodeFormRef = ref(null)
  158. const nodeFormModel = ref({
  159. nodeName: ''
  160. })
  161. const nodeFormRules = {
  162. nodeName: {
  163. required: true,
  164. trigger: 'blur',
  165. message: "请输入节点名称"
  166. },
  167. }
  168. //保存节点信息
  169. const nodeFormLoading = ref(false)
  170. const nodeFormModalSave = async () => {
  171. const validate = await formValidate(nodeFormRef.value)
  172. if (validate) {
  173. //发起请求
  174. const { error, code } = await submitTree({
  175. ...nodeFormModel.value,
  176. projectId: projectId.value,
  177. contractId: contractId.value
  178. })
  179. //处理数据
  180. if (!error && code === 200) {
  181. window?.$message?.success('操作成功')
  182. nodeFormModal.value = false
  183. await getTreeDatas()
  184. }
  185. }
  186. }
  187. //关闭节点编辑弹窗
  188. const nodeFormModalClose = () => {
  189. nodeFormModal.value = false
  190. }
  191. //删除节点
  192. const treeRemoveData = async (id) => {
  193. const { error, code } = await removeTree({
  194. projectId: projectId.value,
  195. contractId: contractId.value,
  196. id: id
  197. })
  198. //处理数据
  199. if (!error && code === 200) {
  200. window?.$message?.success('操作成功')
  201. await getTreeDatas()
  202. }
  203. }
  204. </script>
  205. <style lang="scss" scoped>
  206. @import "../../../../styles/app/tree.scss";
  207. .data-custom-tree-node {
  208. .menu-icon {
  209. position: relative;
  210. font-size: 20px;
  211. opacity: 0;
  212. pointer-events: none;
  213. transition: opacity 0.2s;
  214. .cu-tree-node-popover-menu-icon {
  215. display: flex;
  216. align-items: center;
  217. justify-content: center;
  218. }
  219. }
  220. &:hover {
  221. .menu-icon {
  222. opacity: 1;
  223. pointer-events: all;
  224. cursor: context-menu;
  225. }
  226. }
  227. .menu-icon.show {
  228. opacity: 1;
  229. pointer-events: all;
  230. cursor: context-menu;
  231. }
  232. }
  233. </style>