UEquipmentTreeDrag.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. <template>
  2. <div id="dragBox" ref="dragBoxRef" class="u-tree-drag">
  3. <!-- 左侧树 -->
  4. <div id="leftTree" class="left-tree">
  5. <!-- 标题 -->
  6. <div class="top-title u-flex-jab">
  7. <div class="title">{{ treeTitle }}</div>
  8. <div class="refresh" @click="handleRefresh"></div>
  9. </div>
  10. <div class="interlock-tree-container">
  11. <!-- 搜索+新增 -->
  12. <div class="tree-search">
  13. <a-button v-if="hasHandleBtn && isSysManage" type="primary" icon="plus" @click="handleAdd"/>
  14. <!-- <a-button v-if="hasHandleBtn" type="primary" icon="plus" @click="handleAdd" v-has="'add:tree'"/> -->
  15. <a-input-search allow-clear placeholder="请输入" @change="onChange" :class="hasHandleBtn?'has-btn':'noHas-btn'"/>
  16. </div>
  17. <!-- 树列表 -->
  18. <div class="interlock-tree-content">
  19. <a-tree
  20. v-if="tpmTreeData.length > 0"
  21. :tree-data="tpmTreeData"
  22. :replace-fields="replaceFields"
  23. autoExpandParent
  24. :expandedKeys="expandedKeys"
  25. :selectedKeys="selectedKeys"
  26. @expand="onExpand"
  27. @select="selectNode"
  28. blockNode
  29. >
  30. <template v-slot:title="nodeData">
  31. <div class="item-node-container">
  32. <div>
  33. <a-icon slot="icon" :type="nodeData.interlockType==='0'?'cluster':'project'" />
  34. <!-- carry-out apartment cluster -->
  35. <span class="item-node-name">{{nodeData.interlockName}}</span>
  36. </div>
  37. <template v-if="hasHandleBtn">
  38. <!-- <div v-if="hasHandleBtn" v-has="'edit:tree'"> -->
  39. <!-- 系统管理员:全部权限 -->
  40. <template v-if="isSysManage">
  41. <a-dropdown>
  42. <a-icon type="more" />
  43. <a-menu slot="overlay">
  44. <a-menu-item>
  45. <a @click="handleEdit(nodeData)">修改</a>
  46. </a-menu-item>
  47. <a-menu-item>
  48. <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(nodeData.id)">
  49. <a>删除</a>
  50. </a-popconfirm>
  51. </a-menu-item>
  52. </a-menu>
  53. </a-dropdown>
  54. </template>
  55. <template v-if="!isSysManage">
  56. <!-- 非系统管理员:装置--不能增删改(装置不能操作);系统--不能新增删除,只能修改有权限的系统名称和对应配置 -->
  57. <a-dropdown v-if="nodeData.interlockType === '1' && nodeData.limitType === '0'">
  58. <a-icon type="more" />
  59. <a-menu slot="overlay">
  60. <a-menu-item>
  61. <a @click="handleEdit(nodeData)">修改</a>
  62. </a-menu-item>
  63. <!-- <a-menu-item v-if="isSysManage">
  64. <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(nodeData.id)">
  65. <a>删除</a>
  66. </a-popconfirm>
  67. </a-menu-item> -->
  68. </a-menu>
  69. </a-dropdown>
  70. </template>
  71. </template>
  72. </div>
  73. </template>
  74. <!-- :filter-tree-node="filterTreeNode" -->
  75. </a-tree>
  76. </div>
  77. </div>
  78. </div>
  79. <!-- 拖拽盒子 -->
  80. <div class="resize" id="resize" title="收缩侧边栏">
  81. <span class="resize-btn"></span>
  82. <!-- <span class="resize-btn">⋮</span> -->
  83. </div>
  84. <!-- 右侧slot -->
  85. <div id="rightSlot" class="right-content">
  86. <slot></slot>
  87. </div>
  88. <!-- 新增修改弹框 -->
  89. <base-InterLock-modal ref="modalForm" @ok="modalFormOk"></base-InterLock-modal>
  90. </div>
  91. </template>
  92. <script>
  93. import { getAction,deleteAction } from '@api/manage'
  94. import BaseInterLockModal from '@/views/module_interLock/baseInterLock/modules/BaseInterLockModal.vue'
  95. import cookie from 'js-cookie'
  96. export default({
  97. name: 'UEquipmentTree',
  98. components: {
  99. BaseInterLockModal
  100. },
  101. props: {
  102. treeTitle: {
  103. type: String,
  104. default: '列表'
  105. },
  106. // treeData: {
  107. // type: Array,
  108. // default: function(){
  109. // return [] // 使用工厂函数返回默认值
  110. // }
  111. // },
  112. hasHandleBtn: {
  113. type: Boolean,
  114. default: true
  115. }
  116. },
  117. data () {
  118. return {
  119. searchValue: '',
  120. // autoExpandParent: true,
  121. tpmListData: [], // 原始数据
  122. tpmTreeData: [], // 树形列表使用数据
  123. replaceFields: {
  124. key: 'id',
  125. children: 'children',
  126. title: 'interlockName',
  127. },
  128. expandedKeys: ['1808684817591234562'],
  129. selectedKeys: [], // 设置再次点击不仍然高亮
  130. url: {
  131. // list: '/base/interlockBase/list', // 修改权限前接口
  132. list: '/base/interlockBase/listByUser',
  133. // delete: "/base/interlockBase/delete",
  134. delete: "/iotedgeCollectData/iotedgeCollectData/deleteGroup",
  135. },
  136. }
  137. },
  138. computed: {
  139. treeSelectKeys() {
  140. return this.$store.getters.treeSelectKeys
  141. },
  142. treeExpandedKeys() {
  143. return this.$store.getters.treeExpandedKeys
  144. },
  145. isSysManage(){
  146. return cookie.get('SSORole') === 'globalAdmin'
  147. },
  148. },
  149. created() {
  150. this.getTpmTreeData()
  151. },
  152. mounted() {
  153. this.dragControllerDiv()
  154. },
  155. methods: {
  156. getTpmTreeData(){
  157. // 现版本
  158. // getAction(`/base/interlockBase/lever12`).then(res=>{
  159. // 原版本
  160. getAction(this.url.list).then(res=>{
  161. // if (res.success) {
  162. // 防止res.result对tpmListData造成地址赋值的问题
  163. this.tpmListData = JSON.parse(JSON.stringify(res))
  164. // 现版本
  165. // this.tpmTreeData = this.tpmListData
  166. // 原版本
  167. this.tpmTreeData = this.handleTree(res, "id", "pid")
  168. // console.log(this.tpmTreeData)
  169. // } else {
  170. // }
  171. })
  172. this.selectedKeys = this.treeSelectKeys
  173. this.expandedKeys = this.treeExpandedKeys
  174. },
  175. filterTreeNode(node) {
  176. // console.log(node)
  177. // if (!inputValue) return true;
  178. return node.title.indexOf('设备') !== -1;
  179. },
  180. onExpand(expandedKeys) {
  181. console.log(expandedKeys)
  182. this.expandedKeys = expandedKeys;
  183. // this.autoExpandParent = false;
  184. this.$store.commit('SET_TREEEXPANDEKEYS', expandedKeys);
  185. },
  186. onChange(e) {
  187. const value = e.target.value;
  188. // 筛选后数据
  189. var filterData = []
  190. // 筛选符合条件的数据:包含当前搜索的项
  191. console.log('原数据',this.tpmListData)
  192. filterData = this.tpmListData.filter(item => (item.interlockName.indexOf(value) !== -1))
  193. // var data = []
  194. // filterData.forEach(item => {
  195. // var arr = this.tpmListData.filter(data => item.pid === data.id)
  196. // console.log('父级', arr)
  197. // // filterData = [...filterData, ...arr]
  198. // })
  199. // 循环寻找父级
  200. // console.log(this.findParents(this.tpmTreeData, '287813167808513'))
  201. // 原版本
  202. this.tpmTreeData = this.handleTree(filterData, "id", "pid")
  203. // 现版本
  204. // this.tpmTreeData = filterData
  205. // const expandedKeys = dataList.map(item => {
  206. // if (item.name.indexOf(value) > -1) {
  207. // // return getParentKey(item.key, gData);
  208. // return this.filterNode(item.key, gData);
  209. // }
  210. // return null;
  211. // }).filter((item, i, self) => item && self.indexOf(item) === i);
  212. // Object.assign(this, {
  213. // expandedKeys,
  214. // searchValue: value,
  215. // autoExpandParent: true,
  216. // });
  217. },
  218. // 树节点选择操作
  219. selectNode(selectedKeys, e){
  220. if (!e.selected){
  221. // 再次点击节点时,仍然高亮
  222. return
  223. }
  224. this.selectedKeys = selectedKeys
  225. let selectNode = e.selectedNodes[0].data.props
  226. var selectData = {
  227. id: selectNode.id,
  228. pid: selectNode.pid,
  229. interlockType: selectNode.interlockType,
  230. limitType: selectNode.limitType,
  231. }
  232. this.$store.commit('SET_CLICKSYSTEMNODE', selectData);
  233. this.$store.commit('SET_TREESELECTKEYS', selectedKeys);
  234. this.$emit('select')
  235. },
  236. // 树重置/刷新操作
  237. handleRefresh(){
  238. this.selectedKeys = []
  239. this.$store.commit('SET_CLICKSYSTEMNODE', {});
  240. this.$emit('select')
  241. },
  242. // findParents(treeData,id){
  243. // let allparents = []
  244. // if(treeData.length==0){
  245. // return
  246. // }
  247. // let findele = (data,id) => {
  248. // if(!id) return
  249. // data.forEach((item,index) => {
  250. // if(item.id == id){
  251. // allparents.unshift(item.id)
  252. // findele(treeData,item.parentid)
  253. // }else{
  254. // if(!!item.children){
  255. // findele(item.children,id)
  256. // }
  257. // }
  258. // })
  259. // }
  260. // findele(treeData,id)
  261. // return allparents
  262. // },
  263. handleAdd: function () {
  264. this.$refs.modalForm.add();
  265. this.$refs.modalForm.title = "新增";
  266. this.$refs.modalForm.disableSubmit = false;
  267. this.$refs.modalForm.disableEdit = false;
  268. },
  269. handleEdit: function (record) {
  270. this.$refs.modalForm.edit(record);
  271. this.$refs.modalForm.title = "编辑";
  272. this.$refs.modalForm.disableSubmit = false;
  273. this.$refs.modalForm.disableEdit = true;
  274. },
  275. handleDelete: function (id) {
  276. if(!this.url.delete){
  277. this.$message.error("请设置url.delete属性!")
  278. return
  279. }
  280. var that = this;
  281. deleteAction(that.url.delete, {id: id}).then((res) => {
  282. if (res.success) {
  283. that.getTpmTreeData();
  284. that.$message.success(res.message);
  285. } else {
  286. that.$message.warning(res.message);
  287. }
  288. });
  289. },
  290. modalFormOk() {
  291. // 新增/修改 成功时,重载列表
  292. this.getTpmTreeData();
  293. },
  294. // 拖拽事件
  295. dragControllerDiv(){
  296. let resize = document.getElementById("resize");
  297. let leftTree = document.getElementById("leftTree");
  298. let rightSlot = document.getElementById("rightSlot");
  299. let dragBox = document.getElementById("dragBox");
  300. // 鼠标按下事件
  301. resize.onmousedown = function (e) {
  302. // 记录坐标起始位置
  303. let startX = e.clientX;
  304. // 左边元素起始宽度
  305. resize.left = leftTree.offsetWidth;
  306. // console.log("宽度:", resize.left);
  307. // 鼠标拖动事件
  308. document.onmousemove = function (e) {
  309. // 鼠标拖动的终止位置
  310. let endX = e.clientX;
  311. // (endx-startx)= 移动的距离
  312. // resize.left + 移动的距离 = 左边区域最后的宽度
  313. let moveLen = resize.left + (endX - startX);
  314. // console.log(moveLen);
  315. // 左右两边区域的总宽度 = 大容器宽度 - 中间区域拖拉框的宽度
  316. let maxWidth = dragBox.clientWidth - resize.offsetWidth;
  317. // 限制左边区域的最小宽度为220px
  318. if (moveLen < 220) moveLen = 220;
  319. // 右边区域最小宽度为 150px 限制左边区域到150后不能再拉宽
  320. if (moveLen > maxWidth - 420) moveLen = maxWidth - 420;
  321. // 设置左边区域的宽度,通过换算为百分比的形式,实现窗体放大缩小自适应
  322. // console.log((moveLen / maxWidth) * 100);
  323. // leftTree.style.width =(moveLen / maxWidth * 100) + '%';
  324. leftTree.style.width = moveLen + "px";
  325. // 右边区域即是总大小 - 左边宽度 - 拖动条宽度
  326. // console.log(((maxWidth - moveLen) / maxWidth) * 100);
  327. rightSlot.style.width = maxWidth - moveLen + "px";
  328. // console.log(moveLen);
  329. };
  330. // 鼠标松开事件
  331. document.onmouseup = function (evt) {
  332. // console.log(11);
  333. document.onmousemove = null;
  334. document.onmouseup = null;
  335. resize.releaseCapture && resize.releaseCapture(); //当你不在需要继续获得鼠标消息就要应该调用ReleaseCapture()释放掉
  336. };
  337. resize.setCapture && resize.setCapture(); //该函数在属于当前线程的指定窗口里设置鼠标捕获
  338. return false;
  339. };
  340. },
  341. },
  342. })
  343. </script>
  344. <style lang="less">
  345. .u-tree-drag{
  346. height: 100%;
  347. width: 100%;
  348. display: flex;
  349. overflow: hidden;
  350. /** 样式设置开始 */
  351. // 左侧树
  352. .left-tree{
  353. height: 100%;
  354. width: 300px;
  355. overflow: hidden;
  356. }
  357. /*拖拽区div样式*/
  358. .resize {
  359. width: 1px;
  360. height: 100%;
  361. background-color: #c8c8c8;
  362. position: relative;
  363. .resize-btn{
  364. width: 16px;
  365. height: 32px;
  366. cursor: col-resize;
  367. z-index: 99;
  368. position: absolute;
  369. top: 8px;
  370. left: -8px;
  371. background: url('../../../assets/drag.svg') no-repeat;
  372. background-size: 16px 32px;
  373. // width: 11px;
  374. // height: 50px;
  375. // font-size: 32px;
  376. // text-align: center;
  377. // color: #d6d6d6;
  378. // border-radius: 10px;
  379. // background-color: #ffffff;
  380. // background-size: cover;
  381. // background-position: center;
  382. }
  383. }
  384. /*拖拽区鼠标悬停样式*/
  385. .resize:hover {
  386. color: #444444;
  387. }
  388. /* 右侧 */
  389. .right-content{
  390. width: calc(100% - 301px);
  391. height: 100%;
  392. overflow: hidden;
  393. }
  394. /** 样式设置结束 */
  395. .top-title{
  396. height: 48px;
  397. line-height: 24px;
  398. padding: 12px 24px;
  399. border-bottom: 1px solid #e1e1e1;
  400. .title{
  401. color: #323233;
  402. font-size: 16px;
  403. font-weight: 700;
  404. }
  405. .refresh{
  406. width: 24px;
  407. height: 24px;
  408. background: url('../../../assets/refresh.svg') no-repeat;
  409. background-size: 24px 24px;
  410. cursor: pointer;
  411. }
  412. .refresh:hover{
  413. background: url('../../../assets/refresh-hover.svg') no-repeat;
  414. background-size: 24px 24px;
  415. }
  416. }
  417. /** 树区域设置 */
  418. .interlock-tree-container{
  419. width: 100%;
  420. height: calc(100% - 48px);
  421. background-color: transparent;
  422. overflow: auto;
  423. // border: 1px solid #CADAE6;
  424. // box-shadow: 0px 5px 10px 0 #CADAE6;
  425. .tree-search{
  426. padding: 8px 15px;
  427. .ant-btn{
  428. width: 32px;
  429. height: 32px;
  430. margin-right: 8px;
  431. }
  432. .has-btn{
  433. width: calc(100% - 40px);
  434. }
  435. .noHas-btn{
  436. width: 100%;
  437. }
  438. }
  439. .interlock-tree-content{
  440. width: 100%;
  441. // height: calc(100% - 40px);
  442. overflow: auto;
  443. padding: 0 15px 10px;
  444. .ant-tree{
  445. li{
  446. padding: 0;
  447. span.ant-tree-switcher{
  448. height: 40px;
  449. line-height: 40px;
  450. }
  451. .ant-tree-node-content-wrapper{
  452. height: 40px;
  453. }
  454. .ant-tree-node-content-wrapper:hover{
  455. background: linear-gradient(315deg,rgba(11,76,217,.05) 0%,rgba(11,76,217,.05) 0%,rgba(0,140,214,.05) 100%),#ffffff;
  456. }
  457. }
  458. .ant-tree-title{
  459. .item-node-container{
  460. width: 100%;
  461. display: flex;
  462. justify-content: space-between;
  463. align-items: center;
  464. font-size: 16px;
  465. color: #323233;
  466. height: 40px;
  467. }
  468. .item-node-name{
  469. padding-left: 8px;
  470. }
  471. }
  472. // 节点折叠时
  473. .ant-tree-treenode-switcher-close{
  474. }
  475. // 节点打开时
  476. .ant-tree-treenode-switcher-open{
  477. }
  478. // 节点行被选择时
  479. .ant-tree-treenode-selected{
  480. // 节点文字
  481. .ant-tree-node-selected{
  482. background: linear-gradient(to right,#a1c4fd8a 0%,#c2e9fb8a 100%)!important;
  483. // background: linear-gradient(to right,#a1c4fd 0%,#c2e9fb 100%)!important;
  484. // background: transparent;
  485. .item-node-container{
  486. // color: #008cd6;
  487. // font-weight: 700;
  488. }
  489. }
  490. }
  491. }
  492. }
  493. }
  494. }
  495. </style>